From b9965077e51bb9952c4fd161164e796e5fc66fbf Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 24 Dec 2014 02:06:02 +0100 Subject: [PATCH 001/256] Start 1.24.0 development cycle Signed-off-by: Denys Vlasenko --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index b487f0457..cd42ca37b 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 1 -PATCHLEVEL = 23 +PATCHLEVEL = 24 SUBLEVEL = 0 -EXTRAVERSION = +EXTRAVERSION = .git NAME = Unnamed # *DOCUMENTATION* From 8074a6ca4dc4e30e38570b52529b87c547c41b1b Mon Sep 17 00:00:00 2001 From: John Schroeder Date: Thu, 25 Dec 2014 21:12:51 +0100 Subject: [PATCH 002/256] udhcpd: account for script delay in lease Prevent nasty surprises if script runs longer than lease time / 2. Signed-off-by: John Schroeder Signed-off-by: Denys Vlasenko --- networking/udhcp/dhcpc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index a34829c3a..9d3d1a31c 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -1752,7 +1752,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) } #endif /* enter bound state */ - timeout = lease_seconds / 2; temp_addr.s_addr = packet.yiaddr; bb_info_msg("Lease of %s obtained, lease time %u", inet_ntoa(temp_addr), (unsigned)lease_seconds); @@ -1761,6 +1760,11 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) start = monotonic_sec(); udhcp_run_script(&packet, state == REQUESTING ? "bound" : "renew"); already_waited_sec = (unsigned)monotonic_sec() - start; + timeout = lease_seconds / 2; + if ((unsigned)timeout < already_waited_sec) { + /* Something went wrong. Back to discover state */ + timeout = already_waited_sec = 0; + } state = BOUND; change_listen_mode(LISTEN_NONE); From c76236fd7d980822a647914c9ff6a3fabdec2390 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 29 Dec 2014 00:04:18 +0100 Subject: [PATCH 003/256] ash: fix a SEGV in ${#1} function old new delta varvalue 760 805 +45 evalvar 648 603 -45 Signed-off-by: Denys Vlasenko --- shell/ash.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 90fb00fbd..c5ad96909 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -6746,6 +6746,14 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list) len = strlen(p); if (!(subtype == VSPLUS || subtype == VSLENGTH)) memtodest(p, len, syntax, quotes); +#if ENABLE_UNICODE_SUPPORT + if (subtype == VSLENGTH && len > 0) { + reinit_unicode_for_ash(); + if (unicode_status == UNICODE_ON) { + len = unicode_strlen(p); + } + } +#endif return len; } @@ -6829,15 +6837,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list) varunset(p, var, 0, 0); if (subtype == VSLENGTH) { - ssize_t n = varlen; - if (n > 0) { - reinit_unicode_for_ash(); - if (unicode_status == UNICODE_ON) { - const char *val = lookupvar(var); - n = unicode_strlen(val); - } - } - cvtnum(n > 0 ? n : 0); + cvtnum(varlen > 0 ? varlen : 0); goto record; } From 6c19d35f689c911b83073ab1faeffb8040c4b3d9 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 17 Dec 2014 17:58:23 +0100 Subject: [PATCH 004/256] Makefile: fix cscope target This target doesn't work with current directory layout. Just make cscope index all .c and .h files. While we're at it: add cscope output files to .gitignore. Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- .gitignore | 8 ++++++++ Makefile | 19 +------------------ 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index 73e88fb5b..be1d46199 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,11 @@ core /busybox.links /runtest-tempdir-links /testsuite/echo-ne + +# +# cscope output +# +cscope.files +cscope.in.out +cscope.out +cscope.po.out diff --git a/Makefile b/Makefile index cd42ca37b..e0888578f 100644 --- a/Makefile +++ b/Makefile @@ -1165,24 +1165,7 @@ endif ALLSOURCE_ARCHS := $(ARCH) define all-sources - ( find $(__srctree) $(RCS_FIND_IGNORE) \ - \( -name include -o -name arch \) -prune -o \ - -name '*.[chS]' -print; \ - for ARCH in $(ALLSOURCE_ARCHS) ; do \ - find $(__srctree)arch/$${ARCH} $(RCS_FIND_IGNORE) \ - -name '*.[chS]' -print; \ - done ; \ - find $(__srctree)security/selinux/include $(RCS_FIND_IGNORE) \ - -name '*.[chS]' -print; \ - find $(__srctree)include $(RCS_FIND_IGNORE) \ - \( -name config -o -name 'asm-*' \) -prune \ - -o -name '*.[chS]' -print; \ - for ARCH in $(ALLINCLUDE_ARCHS) ; do \ - find $(__srctree)include/asm-$${ARCH} $(RCS_FIND_IGNORE) \ - -name '*.[chS]' -print; \ - done ; \ - find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \ - -name '*.[chS]' -print ) + ( find -regex '.*\.[ch]$$' ) endef quiet_cmd_cscope-file = FILELST cscope.files From 78854520ebecfd24d5c80a266d6779bd1e069016 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 1 Jan 2015 19:02:40 +0100 Subject: [PATCH 005/256] modprobe: revert checking for /, stop doing basename() on modprobe args function old new delta process_module 726 719 -7 filename2modname 81 67 -14 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-21) Total: -21 bytes Signed-off-by: Denys Vlasenko --- modutils/modprobe-small.c | 8 ++++++-- modutils/modprobe.c | 11 ----------- modutils/modutils.c | 8 ++++++-- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index b7990bff1..dafe91ed7 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c @@ -149,9 +149,13 @@ static void replace(char *s, char what, char with) static char *filename2modname(const char *filename, char *modname) { int i; - char *from; + const char *from; - from = bb_get_last_path_component_nostrip(filename); + // Disabled since otherwise "modprobe dir/name" would work + // as if it is "modprobe name". It is unclear why + // 'basenamization' was here in the first place. + //from = bb_get_last_path_component_nostrip(filename); + from = filename; for (i = 0; i < (MODULE_NAME_LEN-1) && from[i] != '\0' && from[i] != '.'; i++) modname[i] = (from[i] == '-') ? '_' : from[i]; modname[i] = '\0'; diff --git a/modutils/modprobe.c b/modutils/modprobe.c index f0904285b..f08f0850d 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c @@ -238,17 +238,6 @@ static void add_probe(const char *name) { struct module_entry *m; - /* - * get_or_add_modentry() strips path from name and works - * on remaining basename. - * This would make "rmmod dir/name" and "modprobe dir/name" - * to work like "rmmod name" and "modprobe name", - * which is wrong, and can be abused via implicit modprobing: - * "ifconfig /usbserial up" tries to modprobe netdev-/usbserial. - */ - if (strchr(name, '/')) - bb_error_msg_and_die("malformed module name '%s'", name); - m = get_or_add_modentry(name); if (!(option_mask32 & (OPT_REMOVE | OPT_SHOW_DEPS)) && (m->flags & MODULE_FLAG_LOADED) diff --git a/modutils/modutils.c b/modutils/modutils.c index 6187ca72f..ff79d3fac 100644 --- a/modutils/modutils.c +++ b/modutils/modutils.c @@ -48,13 +48,17 @@ int FAST_FUNC string_to_llist(char *string, llist_t **llist, const char *delim) char* FAST_FUNC filename2modname(const char *filename, char *modname) { int i; - char *from; + const char *from; if (filename == NULL) return NULL; if (modname == NULL) modname = xmalloc(MODULE_NAME_LEN); - from = bb_get_last_path_component_nostrip(filename); + // Disabled since otherwise "modprobe dir/name" would work + // as if it is "modprobe name". It is unclear why + // 'basenamization' was here in the first place. + //from = bb_get_last_path_component_nostrip(filename); + from = filename; for (i = 0; i < (MODULE_NAME_LEN-1) && from[i] != '\0' && from[i] != '.'; i++) modname[i] = (from[i] == '-') ? '_' : from[i]; modname[i] = '\0'; From 1da09cfacf1c4789cc74322857a098c2ddb06e31 Mon Sep 17 00:00:00 2001 From: Tito Ragusa Date: Fri, 2 Jan 2015 21:37:59 +0100 Subject: [PATCH 006/256] libpwdgrp: rewritten to use malloced implementation This removed buffer size limitations. function old new delta convert_to_struct - 269 +269 getXXnam_r - 204 +204 parse_common - 185 +185 getXXnam - 164 +164 tokenize - 126 +126 bb_internal_getpwent_r 102 167 +65 get_S 30 88 +58 getgrouplist_internal 195 240 +45 const_sp_db - 20 +20 const_pw_db - 20 +20 const_gr_db - 20 +20 bb_internal_endpwent 27 36 +9 bb_internal_endgrent 27 36 +9 decode_one_format 726 734 +8 bb_internal_setpwent 17 24 +7 volume_id_probe_iso9660 319 322 +3 scriptreplay_main 204 207 +3 mkfs_minix_main 2684 2687 +3 id_main 478 480 +2 hash_find 233 235 +2 pstree_main 321 322 +1 gr_off 3 4 +1 expand_one_var 1579 1578 -1 pwf 4 - -4 grf 4 - -4 pack_gzip 1787 1780 -7 addattr32 67 56 -11 buffer_fill_and_print 191 178 -13 dpkg_main 2944 2927 -17 bb_internal_setgrent 17 - -17 bb_internal_getpwuid 38 19 -19 bb_internal_getgrgid 44 19 -25 bb_internal_getpwnam 38 11 -27 bb_internal_getgrnam 44 14 -30 bb_internal_fgetpwent_r 51 - -51 bb_internal_fgetgrent_r 51 - -51 bb_internal_getspnam_r 121 42 -79 bb_internal_getpwnam_r 121 39 -82 bb_internal_getgrent_r 102 - -102 bb__parsepwent 110 - -110 bb_internal_getpwuid_r 113 - -113 bb_internal_getgrgid_r 113 - -113 bb__parsespent 120 - -120 bb_internal_getgrnam_r 121 - -121 bb__pgsreader 213 - -213 bb__parsegrent 226 - -226 ------------------------------------------------------------------------------ (add/remove: 8/13 grow/shrink: 14/11 up/down: 1224/-1556) Total: -332 bytes text data bss dec hex filename 923471 928 17684 942083 e6003 busybox_old 923167 928 17676 941771 e5ecb busybox_unstripped Signed-off-by: Tito Ragusa Signed-off-by: Denys Vlasenko Signed-off-by: Denys Vlasenko --- include/grp_.h | 54 +- include/pwd_.h | 25 - libbb/bb_pwd.c | 48 -- libpwdgrp/pwd_grp.c | 1308 ++++++++++------------------------ libpwdgrp/pwd_grp_internal.c | 61 -- 5 files changed, 394 insertions(+), 1102 deletions(-) delete mode 100644 libpwdgrp/pwd_grp_internal.c diff --git a/include/grp_.h b/include/grp_.h index e5075e5a0..f7b8d836f 100644 --- a/include/grp_.h +++ b/include/grp_.h @@ -30,17 +30,9 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN * so that function calls are directed to bb_internal_XXX replacements */ #undef endgrent -#define setgrent bb_internal_setgrent #define endgrent bb_internal_endgrent -#define getgrent bb_internal_getgrent -#define fgetgrent bb_internal_fgetgrent -#define putgrent bb_internal_putgrent #define getgrgid bb_internal_getgrgid #define getgrnam bb_internal_getgrnam -#define getgrent_r bb_internal_getgrent_r -#define getgrgid_r bb_internal_getgrgid_r -#define getgrnam_r bb_internal_getgrnam_r -#define fgetgrent_r bb_internal_fgetgrent_r #define getgrouplist bb_internal_getgrouplist #define initgroups bb_internal_initgroups @@ -48,60 +40,16 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN /* All function names below should be remapped by #defines above * in order to not collide with libc names. */ - -/* Rewind the group-file stream. */ -extern void setgrent(void); - /* Close the group-file stream. */ extern void endgrent(void); -#ifdef UNUSED_SINCE_WE_AVOID_STATIC_BUFS -/* Read an entry from the group-file stream, opening it if necessary. */ -extern struct group *getgrent(void); - -/* Read a group entry from STREAM. */ -extern struct group *fgetgrent(FILE *__stream); - -/* Write the given entry onto the given stream. */ -extern int putgrent(const struct group *__restrict __p, - FILE *__restrict __f); -#endif - /* Search for an entry with a matching group ID. */ extern struct group *getgrgid(gid_t __gid); /* Search for an entry with a matching group name. */ extern struct group *getgrnam(const char *__name); -/* Reentrant versions of some of the functions above. - - PLEASE NOTE: the `getgrent_r' function is not (yet) standardized. - The interface may change in later versions of this library. But - the interface is designed following the principals used for the - other reentrant functions so the chances are good this is what the - POSIX people would choose. */ - -extern int getgrent_r(struct group *__restrict __resultbuf, - char *__restrict __buffer, size_t __buflen, - struct group **__restrict __result); - -/* Search for an entry with a matching group ID. */ -extern int getgrgid_r(gid_t __gid, struct group *__restrict __resultbuf, - char *__restrict __buffer, size_t __buflen, - struct group **__restrict __result); - -/* Search for an entry with a matching group name. */ -extern int getgrnam_r(const char *__restrict __name, - struct group *__restrict __resultbuf, - char *__restrict __buffer, size_t __buflen, - struct group **__restrict __result); - -/* Read a group entry from STREAM. This function is not standardized - an probably never will. */ -extern int fgetgrent_r(FILE *__restrict __stream, - struct group *__restrict __resultbuf, - char *__restrict __buffer, size_t __buflen, - struct group **__restrict __result); +/* Reentrant versions of some of the functions above. */ /* Store at most *NGROUPS members of the group set for USER into *GROUPS. Also include GROUP. The actual number of groups found is diff --git a/include/pwd_.h b/include/pwd_.h index 625b6f5a2..d086f86e3 100644 --- a/include/pwd_.h +++ b/include/pwd_.h @@ -34,20 +34,14 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN #define setpwent bb_internal_setpwent #define endpwent bb_internal_endpwent #define getpwent bb_internal_getpwent -#define fgetpwent bb_internal_fgetpwent -#define putpwent bb_internal_putpwent #define getpwuid bb_internal_getpwuid #define getpwnam bb_internal_getpwnam #define getpwent_r bb_internal_getpwent_r -#define getpwuid_r bb_internal_getpwuid_r #define getpwnam_r bb_internal_getpwnam_r -#define fgetpwent_r bb_internal_fgetpwent_r - /* All function names below should be remapped by #defines above * in order to not collide with libc names. */ - /* Rewind the password-file stream. */ extern void setpwent(void); @@ -57,13 +51,6 @@ extern void endpwent(void); #ifdef UNUSED_SINCE_WE_AVOID_STATIC_BUFS /* Read an entry from the password-file stream, opening it if necessary. */ extern struct passwd *getpwent(void); - -/* Read an entry from STREAM. */ -extern struct passwd *fgetpwent(FILE *__stream); - -/* Write the given entry onto the given stream. */ -extern int putpwent(const struct passwd *__restrict __p, - FILE *__restrict __f); #endif /* Search for an entry with a matching user ID. */ @@ -84,23 +71,11 @@ extern int getpwent_r(struct passwd *__restrict __resultbuf, char *__restrict __buffer, size_t __buflen, struct passwd **__restrict __result); -extern int getpwuid_r(uid_t __uid, - struct passwd *__restrict __resultbuf, - char *__restrict __buffer, size_t __buflen, - struct passwd **__restrict __result); - extern int getpwnam_r(const char *__restrict __name, struct passwd *__restrict __resultbuf, char *__restrict __buffer, size_t __buflen, struct passwd **__restrict __result); -/* Read an entry from STREAM. This function is not standardized and - probably never will. */ -extern int fgetpwent_r(FILE *__restrict __stream, - struct passwd *__restrict __resultbuf, - char *__restrict __buffer, size_t __buflen, - struct passwd **__restrict __result); - POP_SAVED_FUNCTION_VISIBILITY #endif diff --git a/libbb/bb_pwd.c b/libbb/bb_pwd.c index 8250cd446..4829b723a 100644 --- a/libbb/bb_pwd.c +++ b/libbb/bb_pwd.c @@ -110,51 +110,3 @@ unsigned long FAST_FUNC get_ug_id(const char *s, return xname2id(s); return r; } - -/* Experimental "mallocing" API. - * The goal is nice: "we want to support a case when "guests" group is very large" - * but the code is butt-ugly. - */ -#if 0 -static char *find_latest(char last, char *cp) -{ - if (!cp) - return last; - cp += strlen(cp) + 1; - if (last < cp) - last = cp; - return last; -} - -struct group* FAST_FUNC xmalloc_getgrnam(const char *name) -{ - struct { - struct group gr; - // May still be not enough! - char buf[64*1024 - sizeof(struct group) - 16]; - } *s; - struct group *grp; - int r; - char *last; - char **gr_mem; - - s = xmalloc(sizeof(*s)); - r = getgrnam_r(name, &s->gr, s->buf, sizeof(s->buf), &grp); - if (!grp) { - free(s); - return grp; - } - last = find_latest(s->buf, grp->gr_name); - last = find_latest(last, grp->gr_passwd); - gr_mem = grp->gr_mem; - while (*gr_mem) - last = find_latest(last, *gr_mem++); - gr_mem++; /* points past NULL */ - if (last < (char*)gr_mem) - last = (char*)gr_mem; -//FIXME: what if we get not only truncated, but also moved here? -// grp->gr_name pointer and friends are invalid now!!! - s = xrealloc(s, last - (char*)s); - return grp; -} -#endif diff --git a/libpwdgrp/pwd_grp.c b/libpwdgrp/pwd_grp.c index 2060d7811..ed8370124 100644 --- a/libpwdgrp/pwd_grp.c +++ b/libpwdgrp/pwd_grp.c @@ -1,598 +1,480 @@ /* vi: set sw=4 ts=4: */ -/* Copyright (C) 2003 Manuel Novoa III +/* Copyright (C) 2014 Tito Ragusa * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ - -/* Nov 6, 2003 Initial version. +/* This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY!! * - * NOTE: This implementation is quite strict about requiring all - * field seperators. It also does not allow leading whitespace - * except when processing the numeric fields. glibc is more - * lenient. See the various glibc difference comments below. + * Rewrite of some parts. Main differences are: * - * TODO: - * Move to dynamic allocation of (currently statically allocated) - * buffers; especially for the group-related functions since - * large group member lists will cause error returns. + * 1) the buffer for getpwuid, getgrgid, getpwnam, getgrnam is dynamically + * allocated and reused by later calls. if ERANGE error pops up it is + * reallocated to the size of the longest line found so far in the + * passwd/group files and reused for later calls. + * If ENABLE_FEATURE_CLEAN_UP is set the buffers are freed at program + * exit using the atexit function to make valgrind happy. + * 2) the passwd/group files: + * a) must contain the expected number of fields (as per count of field + * delimeters ":") or we will complain with a error message. + * b) leading or trailing whitespace in fields is allowed and handled. + * c) some fields are not allowed to be empty (e.g. username, uid/gid, + * homedir, shell) and in this case NULL is returned and errno is + * set to EINVAL. This behaviour could be easily changed by + * modifying PW_DEF, GR_DEF, SP_DEF strings (uppercase + * makes a field mandatory). + * d) the string representing uid/gid must be convertible by strtoXX + * functions or NULL is returned and errno is set to EINVAL. + * e) leading or trailing whitespaces in member names and empty members + * are allowed and handled. + * 3) the internal function for getgrouplist uses a dynamically allocated + * buffer and retries with a bigger one in case it is too small; + * 4) the _r functions use the user supplied buffers that are never reallocated + * but use mostly the same common code as the other functions. + * 5) at the moment only the functions really used by busybox code are + * implemented, if you need a particular missing function it should be + * easy to write it by using the internal common code. */ #include "libbb.h" -#include -/**********************************************************************/ -/* Sizes for statically allocated buffers. */ +/* S = string not empty, s = string maybe empty, */ +/* I = uid,gid, l = long maybe empty, m = members,*/ +/* r = reserved */ +#define PW_DEF "SsIIsSS" +#define GR_DEF "SsIm" +#define SP_DEF "Ssllllllr" -#define PWD_BUFFER_SIZE 256 -#define GRP_BUFFER_SIZE 256 - -/**********************************************************************/ -/* Prototypes for internal functions. */ - -static int bb__pgsreader( - int FAST_FUNC (*parserfunc)(void *d, char *line), - void *data, - char *__restrict line_buff, - size_t buflen, - FILE *f); - -static int FAST_FUNC bb__parsepwent(void *pw, char *line); -static int FAST_FUNC bb__parsegrent(void *gr, char *line); +static const uint8_t pw_off[] ALIGN1 = { + offsetof(struct passwd, pw_name), /* 0 S */ + offsetof(struct passwd, pw_passwd), /* 1 s */ + offsetof(struct passwd, pw_uid), /* 2 I */ + offsetof(struct passwd, pw_gid), /* 3 I */ + offsetof(struct passwd, pw_gecos), /* 4 s */ + offsetof(struct passwd, pw_dir), /* 5 S */ + offsetof(struct passwd, pw_shell) /* 6 S */ +}; +static const uint8_t gr_off[] ALIGN1 = { + offsetof(struct group, gr_name), /* 0 S */ + offsetof(struct group, gr_passwd), /* 1 s */ + offsetof(struct group, gr_gid), /* 2 I */ + offsetof(struct group, gr_mem) /* 3 m (char **) */ +}; #if ENABLE_USE_BB_SHADOW -static int FAST_FUNC bb__parsespent(void *sp, char *line); +static const uint8_t sp_off[] ALIGN1 = { + offsetof(struct spwd, sp_namp), /* 0 S Login name */ + offsetof(struct spwd, sp_pwdp), /* 1 s Encrypted password */ + offsetof(struct spwd, sp_lstchg), /* 2 l */ + offsetof(struct spwd, sp_min), /* 3 l */ + offsetof(struct spwd, sp_max), /* 4 l */ + offsetof(struct spwd, sp_warn), /* 5 l */ + offsetof(struct spwd, sp_inact), /* 6 l */ + offsetof(struct spwd, sp_expire), /* 7 l */ + offsetof(struct spwd, sp_flag) /* 8 r Reserved */ +}; #endif -/**********************************************************************/ -/* We avoid having big global data. */ +struct const_passdb { + const char *filename; + const uint8_t *off; + const char def[10]; + uint8_t numfields; + uint8_t size_of; +}; +struct passdb { + const char *filename; + const uint8_t *off; + const char def[10]; + uint8_t numfields; + uint8_t size_of; + FILE *fp; + void *malloced; +}; +static const struct const_passdb const_pw_db = { _PATH_PASSWD, pw_off, PW_DEF, sizeof(PW_DEF)-1, sizeof(struct passwd) }; +static const struct const_passdb const_gr_db = { _PATH_GROUP , gr_off, GR_DEF, sizeof(GR_DEF)-1, sizeof(struct group) }; +#if ENABLE_USE_BB_SHADOW +static const struct const_passdb const_sp_db = { _PATH_SHADOW, sp_off, SP_DEF, sizeof(SP_DEF)-1, sizeof(struct spwd) }; +#endif + +/* We avoid having big global data. */ struct statics { - /* Smaller things first */ /* It's ok to use one buffer for getpwuid and getpwnam. Manpage says: * "The return value may point to a static area, and may be overwritten * by subsequent calls to getpwent(), getpwnam(), or getpwuid()." */ - struct passwd getpw_resultbuf; - struct group getgr_resultbuf; - - char getpw_buffer[PWD_BUFFER_SIZE]; - char getgr_buffer[GRP_BUFFER_SIZE]; -#if 0 //ENABLE_USE_BB_SHADOW - struct spwd getsp_resultbuf; - char getsp_buffer[PWD_BUFFER_SIZE]; -#endif -// Not converted - too small to bother -//pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; -//FILE *pwf /*= NULL*/; -//FILE *grf /*= NULL*/; -//FILE *spf /*= NULL*/; + struct passdb db[2 + ENABLE_USE_BB_SHADOW]; + char *tokenize_end; }; static struct statics *ptr_to_statics; +#define S (*ptr_to_statics) +#define has_S (ptr_to_statics) static struct statics *get_S(void) { - if (!ptr_to_statics) - ptr_to_statics = xzalloc(sizeof(*ptr_to_statics)); + if (!ptr_to_statics) { + ptr_to_statics = xzalloc(sizeof(S)); + memcpy(&S.db[0], &const_pw_db, sizeof(const_pw_db)); + memcpy(&S.db[1], &const_gr_db, sizeof(const_gr_db)); +#if ENABLE_USE_BB_SHADOW + memcpy(&S.db[2], &const_sp_db, sizeof(const_sp_db)); +#endif + } return ptr_to_statics; } -/* Always use in this order, get_S() must be called first */ -#define RESULTBUF(name) &((S = get_S())->name##_resultbuf) -#define BUFFER(name) (S->name##_buffer) - /**********************************************************************/ -/* For the various fget??ent_r funcs, return - * - * 0: success - * ENOENT: end-of-file encountered - * ERANGE: buflen too small - * other error values possible. See bb__pgsreader. - * - * Also, *result == resultbuf on success and NULL on failure. - * - * NOTE: glibc difference - For the ENOENT case, glibc also sets errno. - * We do not, as it really isn't an error if we reach the end-of-file. - * Doing so is analogous to having fgetc() set errno on EOF. +/* Internal functions */ +/**********************************************************************/ + +/* Divide the passwd/group/shadow record in fields + * by substituting the given delimeter + * e.g. ':' or ',' with '\0'. + * Returns the number of fields found. + * Strips leading and trailing whitespace in fields. */ -/**********************************************************************/ - -int fgetpwent_r(FILE *__restrict stream, struct passwd *__restrict resultbuf, - char *__restrict buffer, size_t buflen, - struct passwd **__restrict result) +static int tokenize(char *buffer, int ch) { - int rv; + char *p = buffer; + char *s = p; + int num_fields = 0; - *result = NULL; - - rv = bb__pgsreader(bb__parsepwent, resultbuf, buffer, buflen, stream); - if (!rv) { - *result = resultbuf; - } - - return rv; -} - -int fgetgrent_r(FILE *__restrict stream, struct group *__restrict resultbuf, - char *__restrict buffer, size_t buflen, - struct group **__restrict result) -{ - int rv; - - *result = NULL; - - rv = bb__pgsreader(bb__parsegrent, resultbuf, buffer, buflen, stream); - if (!rv) { - *result = resultbuf; - } - - return rv; -} - -#if ENABLE_USE_BB_SHADOW -#ifdef UNUSED_FOR_NOW -int fgetspent_r(FILE *__restrict stream, struct spwd *__restrict resultbuf, - char *__restrict buffer, size_t buflen, - struct spwd **__restrict result) -{ - int rv; - - *result = NULL; - - rv = bb__pgsreader(bb__parsespent, resultbuf, buffer, buflen, stream); - if (!rv) { - *result = resultbuf; - } - - return rv; -} -#endif -#endif - -/**********************************************************************/ -/* For the various fget??ent funcs, return NULL on failure and a - * pointer to the appropriate struct (statically allocated) on success. - * TODO: audit & stop using these in bbox, they pull in static buffers */ -/**********************************************************************/ - -#ifdef UNUSED_SINCE_WE_AVOID_STATIC_BUFS -struct passwd *fgetpwent(FILE *stream) -{ - struct statics *S; - struct passwd *resultbuf = RESULTBUF(getpw); - char *buffer = BUFFER(getpw); - struct passwd *result; - - fgetpwent_r(stream, resultbuf, buffer, sizeof(BUFFER(getpw)), &result); - return result; -} - -struct group *fgetgrent(FILE *stream) -{ - struct statics *S; - struct group *resultbuf = RESULTBUF(getgr); - char *buffer = BUFFER(getgr); - struct group *result; - - fgetgrent_r(stream, resultbuf, buffer, sizeof(BUFFER(getgr)), &result); - return result; -} -#endif - -#if ENABLE_USE_BB_SHADOW -#ifdef UNUSED_SINCE_WE_AVOID_STATIC_BUFS -struct spwd *fgetspent(FILE *stream) -{ - struct statics *S; - struct spwd *resultbuf = RESULTBUF(getsp); - char *buffer = BUFFER(getsp); - struct spwd *result; - - fgetspent_r(stream, resultbuf, buffer, sizeof(BUFFER(getsp)), &result); - return result; -} -#endif - -#ifdef UNUSED_FOR_NOW -int sgetspent_r(const char *string, struct spwd *result_buf, - char *buffer, size_t buflen, struct spwd **result) -{ - int rv = ERANGE; - - *result = NULL; - - if (buflen < PWD_BUFFER_SIZE) { - DO_ERANGE: - errno = rv; - goto DONE; - } - - if (string != buffer) { - if (strlen(string) >= buflen) { - goto DO_ERANGE; + for (;;) { + if (isblank(*s)) { + overlapping_strcpy(s, skip_whitespace(s)); } - strcpy(buffer, string); + if (*p == ch || *p == '\0') { + char *end = p; + while (p != s && isblank(p[-1])) + p--; + if (p != end) + overlapping_strcpy(p, end); + num_fields++; + if (*end == '\0') { + S.tokenize_end = p + 1; + return num_fields; + } + *p = '\0'; + s = p + 1; + } + p++; } - - rv = bb__parsespent(result_buf, buffer); - if (!rv) { - *result = result_buf; - } - - DONE: - return rv; } -#endif -#endif /* ENABLE_USE_BB_SHADOW */ -/**********************************************************************/ +/* Returns !NULL on success and matching line broken up in fields by '\0' in buf. + * We require the expected number of fields to be found. + */ +static char *parse_common(FILE *fp, const char *filename, + int n_fields, + const char *key, int field_pos) +{ + int count = 0; + char *buf; -#define GETXXKEY_R_FUNC getpwnam_r -#define GETXXKEY_R_PARSER bb__parsepwent -#define GETXXKEY_R_ENTTYPE struct passwd -#define GETXXKEY_R_TEST(ENT) (!strcmp((ENT)->pw_name, key)) -#define GETXXKEY_R_KEYTYPE const char *__restrict -#define GETXXKEY_R_PATHNAME _PATH_PASSWD -#include "pwd_grp_internal.c" + while ((buf = xmalloc_fgetline(fp)) != NULL) { + count++; + /* Skip empty lines, comment lines */ + if (buf[0] == '\0' || buf[0] == '#') + goto free_and_next; + if (tokenize(buf, ':') != n_fields) { + /* number of fields is wrong */ + bb_error_msg("bad record at %s:%u", filename, count); + goto free_and_next; + } -#define GETXXKEY_R_FUNC getgrnam_r -#define GETXXKEY_R_PARSER bb__parsegrent -#define GETXXKEY_R_ENTTYPE struct group -#define GETXXKEY_R_TEST(ENT) (!strcmp((ENT)->gr_name, key)) -#define GETXXKEY_R_KEYTYPE const char *__restrict -#define GETXXKEY_R_PATHNAME _PATH_GROUP -#include "pwd_grp_internal.c" +/* Ugly hack: group db requires aqdditional buffer space + * for members[] array. If there is only one group, we need space + * for 3 pointers: alignment padding, group name, NULL. + * +1 for every additional group. + */ + if (n_fields == sizeof(GR_DEF)-1) { /* if we read group file */ + int resize = 3; + char *p = buf; + while (*p) + if (*p++ == ',') + resize++; + resize *= sizeof(char**); + resize += S.tokenize_end - buf; + buf = xrealloc(buf, resize); + } + if (!key) { + /* no key specified: sequential read, return a record */ + break; + } + if (strcmp(key, nth_string(buf, field_pos)) == 0) { + /* record found */ + break; + } + free_and_next: + free(buf); + } + + return buf; +} + +static char *parse_file(const char *filename, + int n_fields, + const char *key, int field_pos) +{ + char *buf = NULL; + FILE *fp = fopen_for_read(filename); + + if (fp) { + buf = parse_common(fp, filename, n_fields, key, field_pos); + fclose(fp); + } + return buf; +} + +/* Convert passwd/group/shadow file record in buffer to a struct */ +static void *convert_to_struct(const char *def, const unsigned char *off, + char *buffer, void *result) +{ + for (;;) { + void *member = (char*)result + (*off++); + + if ((*def | 0x20) == 's') { /* s or S */ + *(char **)member = (char*)buffer; + if (!buffer[0] && (*def == 'S')) { + errno = EINVAL; + } + } + if (*def == 'I') { + *(int *)member = bb_strtou(buffer, NULL, 10); + } #if ENABLE_USE_BB_SHADOW -#define GETXXKEY_R_FUNC getspnam_r -#define GETXXKEY_R_PARSER bb__parsespent -#define GETXXKEY_R_ENTTYPE struct spwd -#define GETXXKEY_R_TEST(ENT) (!strcmp((ENT)->sp_namp, key)) -#define GETXXKEY_R_KEYTYPE const char *__restrict -#define GETXXKEY_R_PATHNAME _PATH_SHADOW -#include "pwd_grp_internal.c" + if (*def == 'l') { + long n = -1; + if (buffer[0]) + n = bb_strtol(buffer, NULL, 10); + *(long *)member = n; + } #endif + if (*def == 'm') { + char **members; + int i = tokenize(buffer, ','); -#define GETXXKEY_R_FUNC getpwuid_r -#define GETXXKEY_R_PARSER bb__parsepwent -#define GETXXKEY_R_ENTTYPE struct passwd -#define GETXXKEY_R_TEST(ENT) ((ENT)->pw_uid == key) -#define GETXXKEY_R_KEYTYPE uid_t -#define GETXXKEY_R_PATHNAME _PATH_PASSWD -#include "pwd_grp_internal.c" + /* Store members[] after buffer's end. + * This is safe ONLY because there is a hack + * in parse_common() which allocates additional space + * at the end of malloced buffer! + */ + members = (char **) + ( ((intptr_t)S.tokenize_end + sizeof(char**)) + & -(intptr_t)sizeof(char**) + ); -#define GETXXKEY_R_FUNC getgrgid_r -#define GETXXKEY_R_PARSER bb__parsegrent -#define GETXXKEY_R_ENTTYPE struct group -#define GETXXKEY_R_TEST(ENT) ((ENT)->gr_gid == key) -#define GETXXKEY_R_KEYTYPE gid_t -#define GETXXKEY_R_PATHNAME _PATH_GROUP -#include "pwd_grp_internal.c" + ((struct group *)result)->gr_mem = members; + while (--i >= 0) { + *members++ = buffer; + buffer += strlen(buffer) + 1; + } + *members = NULL; + } + /* def "r" does nothing */ -/**********************************************************************/ -/* TODO: audit & stop using these in bbox, they pull in static buffers */ - -/* This one has many users */ -struct passwd *getpwuid(uid_t uid) -{ - struct statics *S; - struct passwd *resultbuf = RESULTBUF(getpw); - char *buffer = BUFFER(getpw); - struct passwd *result; - - getpwuid_r(uid, resultbuf, buffer, sizeof(BUFFER(getpw)), &result); - return result; -} - -/* This one has many users */ -struct group *getgrgid(gid_t gid) -{ - struct statics *S; - struct group *resultbuf = RESULTBUF(getgr); - char *buffer = BUFFER(getgr); - struct group *result; - - getgrgid_r(gid, resultbuf, buffer, sizeof(BUFFER(getgr)), &result); - return result; -} - -#if 0 //ENABLE_USE_BB_SHADOW -/* This function is non-standard and is currently not built. It seems - * to have been created as a reentrant version of the non-standard - * functions getspuid. Why getspuid was added, I do not know. */ -int getspuid_r(uid_t uid, struct spwd *__restrict resultbuf, - char *__restrict buffer, size_t buflen, - struct spwd **__restrict result) -{ - int rv; - struct passwd *pp; - struct passwd password; - char pwd_buff[PWD_BUFFER_SIZE]; - - *result = NULL; - rv = getpwuid_r(uid, &password, pwd_buff, sizeof(pwd_buff), &pp); - if (!rv) { - rv = getspnam_r(password.pw_name, resultbuf, buffer, buflen, result); + def++; + if (*def == '\0') + break; + buffer += strlen(buffer) + 1; } - return rv; + if (errno) + result = NULL; + return result; } -/* This function is non-standard and is currently not built. - * Why it was added, I do not know. */ -struct spwd *getspuid(uid_t uid) -{ - struct statics *S; - struct spwd *resultbuf = RESULTBUF(getsp); - char *buffer = BUFFER(getsp); - struct spwd *result; +/****** getXXnam/id_r */ - getspuid_r(uid, resultbuf, buffer, sizeof(BUFFER(getsp)), &result); - return result; +static int getXXnam_r(const char *name, uintptr_t db_and_field_pos, char *buffer, size_t buflen, + void *result) +{ + void *struct_buf = *(void**)result; + char *buf; + struct passdb *db; + get_S(); + db = &S.db[db_and_field_pos >> 2]; + + *(void**)result = NULL; + buf = parse_file(db->filename, db->numfields, name, db_and_field_pos & 3); + if (buf) { + size_t size = S.tokenize_end - buf; + if (size > buflen) { + errno = ERANGE; + } else { + memcpy(buffer, buf, size); + *(void**)result = convert_to_struct(db->def, db->off, buffer, struct_buf); + } + free(buf); + } + /* "The reentrant functions return zero on success. + * In case of error, an error number is returned." + * NB: not finding the record is also a "success" here: + */ + return errno; +} + +int getpwnam_r(const char *name, struct passwd *struct_buf, char *buffer, size_t buflen, + struct passwd **result) +{ + /* Why the "store buffer address in result" trick? + * This way, getXXnam_r has the same ABI signature as getpwnam_r, + * hopefully compiler can optimize tall call better in this case. + */ + *result = struct_buf; + return getXXnam_r(name, (0 << 2) + 0, buffer, buflen, result); +} +#if ENABLE_USE_BB_SHADOW +int getspnam_r(const char *name, struct spwd *struct_buf, char *buffer, size_t buflen, + struct spwd **result) +{ + *result = struct_buf; + return getXXnam_r(name, (2 << 2) + 0, buffer, buflen, result); } #endif -/* This one has many users */ +/****** getXXent_r */ + +static int getXXent_r(void *struct_buf, char *buffer, size_t buflen, + void *result, + unsigned db_idx) +{ + char *buf; + struct passdb *db; + get_S(); + db = &S.db[db_idx]; + + *(void**)result = NULL; + + if (!db->fp) { + db->fp = fopen_for_read(db->filename); + if (!db->fp) { + return errno; + } + close_on_exec_on(fileno(db->fp)); + } + + buf = parse_common(db->fp, db->filename, db->numfields, /*no search key:*/ NULL, 0); + if (buf) { + size_t size = S.tokenize_end - buf; + if (size > buflen) { + errno = ERANGE; + } else { + memcpy(buffer, buf, size); + *(void**)result = convert_to_struct(db->def, db->off, buffer, struct_buf); + } + free(buf); + } + /* "The reentrant functions return zero on success. + * In case of error, an error number is returned." + * NB: not finding the record is also a "success" here: + */ + return errno; +} + +int getpwent_r(struct passwd *struct_buf, char *buffer, size_t buflen, struct passwd **result) +{ + return getXXent_r(struct_buf, buffer, buflen, result, 0); +} + +/****** getXXnam/id */ + +static void *getXXnam(const char *name, unsigned db_and_field_pos) +{ + char *buf; + void *result; + struct passdb *db; + get_S(); + db = &S.db[db_and_field_pos >> 2]; + + result = NULL; + + if (!db->fp) { + db->fp = fopen_for_read(db->filename); + if (!db->fp) { + return NULL; + } + close_on_exec_on(fileno(db->fp)); + } + + free(db->malloced); + db->malloced = NULL; + buf = parse_common(db->fp, db->filename, db->numfields, name, db_and_field_pos & 3); + if (buf) { + db->malloced = xzalloc(db->size_of); + result = convert_to_struct(db->def, db->off, buf, db->malloced); + } + return result; +} + struct passwd *getpwnam(const char *name) { - struct statics *S; - struct passwd *resultbuf = RESULTBUF(getpw); - char *buffer = BUFFER(getpw); - struct passwd *result; - - getpwnam_r(name, resultbuf, buffer, sizeof(BUFFER(getpw)), &result); - return result; + return getXXnam(name, (0 << 2) + 0); } - -/* This one has many users */ struct group *getgrnam(const char *name) { - struct statics *S; - struct group *resultbuf = RESULTBUF(getgr); - char *buffer = BUFFER(getgr); - struct group *result; - - getgrnam_r(name, resultbuf, buffer, sizeof(BUFFER(getgr)), &result); - return result; + return getXXnam(name, (1 << 2) + 0); } - -#if 0 //ENABLE_USE_BB_SHADOW -struct spwd *getspnam(const char *name) +struct passwd *getpwuid(uid_t id) { - struct statics *S; - struct spwd *resultbuf = RESULTBUF(getsp); - char *buffer = BUFFER(getsp); - struct spwd *result; - - getspnam_r(name, resultbuf, buffer, sizeof(BUFFER(getsp)), &result); - return result; + return getXXnam(utoa(id), (0 << 2) + 2); } -#endif - -/**********************************************************************/ - -/* FIXME: we don't have such CONFIG_xx - ?! */ - -#if defined CONFIG_USE_BB_THREADSAFE_SHADOW && defined PTHREAD_MUTEX_INITIALIZER -static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; -# define LOCK pthread_mutex_lock(&mylock) -# define UNLOCK pthread_mutex_unlock(&mylock); -#else -# define LOCK ((void) 0) -# define UNLOCK ((void) 0) -#endif - -static FILE *pwf /*= NULL*/; -void setpwent(void) +struct group *getgrgid(gid_t id) { - LOCK; - if (pwf) { - rewind(pwf); - } - UNLOCK; + return getXXnam(utoa(id), (1 << 2) + 2); } +/****** end/setXXend */ + void endpwent(void) { - LOCK; - if (pwf) { - fclose(pwf); - pwf = NULL; + if (has_S && S.db[0].fp) { + fclose(S.db[0].fp); + S.db[0].fp = NULL; } - UNLOCK; } - - -int getpwent_r(struct passwd *__restrict resultbuf, - char *__restrict buffer, size_t buflen, - struct passwd **__restrict result) +void setpwent(void) { - int rv; - - LOCK; - *result = NULL; /* In case of error... */ - - if (!pwf) { - pwf = fopen_for_read(_PATH_PASSWD); - if (!pwf) { - rv = errno; - goto ERR; - } - close_on_exec_on(fileno(pwf)); + if (has_S && S.db[0].fp) { + rewind(S.db[0].fp); } - - rv = bb__pgsreader(bb__parsepwent, resultbuf, buffer, buflen, pwf); - if (!rv) { - *result = resultbuf; - } - - ERR: - UNLOCK; - return rv; } - -static FILE *grf /*= NULL*/; -void setgrent(void) -{ - LOCK; - if (grf) { - rewind(grf); - } - UNLOCK; -} - void endgrent(void) { - LOCK; - if (grf) { - fclose(grf); - grf = NULL; + if (has_S && S.db[1].fp) { + fclose(S.db[1].fp); + S.db[1].fp = NULL; } - UNLOCK; } -int getgrent_r(struct group *__restrict resultbuf, - char *__restrict buffer, size_t buflen, - struct group **__restrict result) +/****** initgroups and getgrouplist */ + +static gid_t* FAST_FUNC getgrouplist_internal(int *ngroups_ptr, + const char *user, gid_t gid) { - int rv; - - LOCK; - *result = NULL; /* In case of error... */ - - if (!grf) { - grf = fopen_for_read(_PATH_GROUP); - if (!grf) { - rv = errno; - goto ERR; - } - close_on_exec_on(fileno(grf)); - } - - rv = bb__pgsreader(bb__parsegrent, resultbuf, buffer, buflen, grf); - if (!rv) { - *result = resultbuf; - } - - ERR: - UNLOCK; - return rv; -} - -#ifdef UNUSED_FOR_NOW -#if ENABLE_USE_BB_SHADOW -static FILE *spf /*= NULL*/; -void setspent(void) -{ - LOCK; - if (spf) { - rewind(spf); - } - UNLOCK; -} - -void endspent(void) -{ - LOCK; - if (spf) { - fclose(spf); - spf = NULL; - } - UNLOCK; -} - -int getspent_r(struct spwd *resultbuf, char *buffer, - size_t buflen, struct spwd **result) -{ - int rv; - - LOCK; - *result = NULL; /* In case of error... */ - - if (!spf) { - spf = fopen_for_read(_PATH_SHADOW); - if (!spf) { - rv = errno; - goto ERR; - } - close_on_exec_on(fileno(spf)); - } - - rv = bb__pgsreader(bb__parsespent, resultbuf, buffer, buflen, spf); - if (!rv) { - *result = resultbuf; - } - - ERR: - UNLOCK; - return rv; -} -#endif -#endif /* UNUSED_FOR_NOW */ - -#ifdef UNUSED_SINCE_WE_AVOID_STATIC_BUFS -struct passwd *getpwent(void) -{ - static char line_buff[PWD_BUFFER_SIZE]; - static struct passwd pwd; - struct passwd *result; - - getpwent_r(&pwd, line_buff, sizeof(line_buff), &result); - return result; -} - -struct group *getgrent(void) -{ - static char line_buff[GRP_BUFFER_SIZE]; - static struct group gr; - struct group *result; - - getgrent_r(&gr, line_buff, sizeof(line_buff), &result); - return result; -} - -#if ENABLE_USE_BB_SHADOW -struct spwd *getspent(void) -{ - static char line_buff[PWD_BUFFER_SIZE]; - static struct spwd spwd; - struct spwd *result; - - getspent_r(&spwd, line_buff, sizeof(line_buff), &result); - return result; -} - -struct spwd *sgetspent(const char *string) -{ - static char line_buff[PWD_BUFFER_SIZE]; - static struct spwd spwd; - struct spwd *result; - - sgetspent_r(string, &spwd, line_buff, sizeof(line_buff), &result); - return result; -} -#endif -#endif /* UNUSED_SINCE_WE_AVOID_STATIC_BUFS */ - -static gid_t *getgrouplist_internal(int *ngroups_ptr, const char *user, gid_t gid) -{ - FILE *grfile; + FILE *fp; gid_t *group_list; int ngroups; - struct group group; - char buff[PWD_BUFFER_SIZE]; + + get_S(); /* We alloc space for 8 gids at a time. */ group_list = xmalloc(8 * sizeof(group_list[0])); group_list[0] = gid; ngroups = 1; - grfile = fopen_for_read(_PATH_GROUP); - if (grfile) { - while (!bb__pgsreader(bb__parsegrent, &group, buff, sizeof(buff), grfile)) { + fp = fopen_for_read(_PATH_GROUP); + if (fp) { + char *buf; + while ((buf = parse_common(fp, _PATH_GROUP, sizeof(GR_DEF)-1, NULL, 0)) != NULL) { char **m; - assert(group.gr_mem); /* Must have at least a NULL terminator. */ + struct group group; + if (!convert_to_struct(GR_DEF, gr_off, buf, &group)) + goto next; if (group.gr_gid == gid) - continue; + goto next; for (m = group.gr_mem; *m; m++) { if (strcmp(*m, user) != 0) continue; @@ -600,8 +482,10 @@ static gid_t *getgrouplist_internal(int *ngroups_ptr, const char *user, gid_t gi group_list[ngroups++] = group.gr_gid; break; } + next: + free(buf); } - fclose(grfile); + fclose(fp); } *ngroups_ptr = ngroups; return group_list; @@ -631,409 +515,3 @@ int getgrouplist(const char *user, gid_t gid, gid_t *groups, int *ngroups) free(group_list); return ngroups_old; } - -#ifdef UNUSED_SINCE_WE_AVOID_STATIC_BUFS -int putpwent(const struct passwd *__restrict p, FILE *__restrict f) -{ - int rv = -1; - -#if 0 - /* glibc does this check */ - if (!p || !f) { - errno = EINVAL; - return rv; - } -#endif - - /* No extra thread locking is needed above what fprintf does. */ - if (fprintf(f, "%s:%s:%lu:%lu:%s:%s:%s\n", - p->pw_name, p->pw_passwd, - (unsigned long)(p->pw_uid), - (unsigned long)(p->pw_gid), - p->pw_gecos, p->pw_dir, p->pw_shell) >= 0 - ) { - rv = 0; - } - - return rv; -} - -int putgrent(const struct group *__restrict p, FILE *__restrict f) -{ - int rv = -1; - -#if 0 - /* glibc does this check */ - if (!p || !f) { - errno = EINVAL; - return rv; - } -#endif - - if (fprintf(f, "%s:%s:%lu:", - p->gr_name, p->gr_passwd, - (unsigned long)(p->gr_gid)) >= 0 - ) { - static const char format[] ALIGN1 = ",%s"; - - char **m; - const char *fmt; - - fmt = format + 1; - - assert(p->gr_mem); - m = p->gr_mem; - - while (1) { - if (!*m) { - if (fputc('\n', f) >= 0) { - rv = 0; - } - break; - } - if (fprintf(f, fmt, *m) < 0) { - break; - } - m++; - fmt = format; - } - } - - return rv; -} -#endif - -#if ENABLE_USE_BB_SHADOW -#ifdef UNUSED_FOR_NOW -static const unsigned char put_sp_off[] ALIGN1 = { - offsetof(struct spwd, sp_lstchg), /* 2 - not a char ptr */ - offsetof(struct spwd, sp_min), /* 3 - not a char ptr */ - offsetof(struct spwd, sp_max), /* 4 - not a char ptr */ - offsetof(struct spwd, sp_warn), /* 5 - not a char ptr */ - offsetof(struct spwd, sp_inact), /* 6 - not a char ptr */ - offsetof(struct spwd, sp_expire) /* 7 - not a char ptr */ -}; - -int putspent(const struct spwd *p, FILE *stream) -{ - const char *fmt; - long x; - int i; - int rv = -1; - - /* Unlike putpwent and putgrent, glibc does not check the args. */ - if (fprintf(stream, "%s:%s:", p->sp_namp, - (p->sp_pwdp ? p->sp_pwdp : "")) < 0 - ) { - goto DO_UNLOCK; - } - - for (i = 0; i < sizeof(put_sp_off); i++) { - fmt = "%ld:"; - x = *(long *)((char *)p + put_sp_off[i]); - if (x == -1) { - fmt += 3; - } - if (fprintf(stream, fmt, x) < 0) { - goto DO_UNLOCK; - } - } - - if ((p->sp_flag != ~0UL) && (fprintf(stream, "%lu", p->sp_flag) < 0)) { - goto DO_UNLOCK; - } - - if (fputc('\n', stream) > 0) { - rv = 0; - } - - DO_UNLOCK: - return rv; -} -#endif -#endif /* USE_BB_SHADOW */ - -/**********************************************************************/ -/* Internal functions */ -/**********************************************************************/ - -static const unsigned char pw_off[] ALIGN1 = { - offsetof(struct passwd, pw_name), /* 0 */ - offsetof(struct passwd, pw_passwd), /* 1 */ - offsetof(struct passwd, pw_uid), /* 2 - not a char ptr */ - offsetof(struct passwd, pw_gid), /* 3 - not a char ptr */ - offsetof(struct passwd, pw_gecos), /* 4 */ - offsetof(struct passwd, pw_dir), /* 5 */ - offsetof(struct passwd, pw_shell) /* 6 */ -}; - -static int FAST_FUNC bb__parsepwent(void *data, char *line) -{ - char *endptr; - char *p; - int i; - - i = 0; - while (1) { - p = (char *) data + pw_off[i]; - - if (i < 2 || i > 3) { - *((char **) p) = line; - if (i == 6) { - return 0; - } - /* NOTE: glibc difference - glibc allows omission of - * ':' seperators after the gid field if all remaining - * entries are empty. We require all separators. */ - line = strchr(line, ':'); - if (!line) { - break; - } - } else { - unsigned long t = strtoul(line, &endptr, 10); - /* Make sure we had at least one digit, and that the - * failing char is the next field seperator ':'. See - * glibc difference note above. */ - /* TODO: Also check for leading whitespace? */ - if ((endptr == line) || (*endptr != ':')) { - break; - } - line = endptr; - if (i & 1) { /* i == 3 -- gid */ - *((gid_t *) p) = t; - } else { /* i == 2 -- uid */ - *((uid_t *) p) = t; - } - } - - *line++ = '\0'; - i++; - } /* while (1) */ - - return -1; -} - -/**********************************************************************/ - -static const unsigned char gr_off[] ALIGN1 = { - offsetof(struct group, gr_name), /* 0 */ - offsetof(struct group, gr_passwd), /* 1 */ - offsetof(struct group, gr_gid) /* 2 - not a char ptr */ -}; - -static int FAST_FUNC bb__parsegrent(void *data, char *line) -{ - char *endptr; - char *p; - int i; - char **members; - char *end_of_buf; - - end_of_buf = ((struct group *) data)->gr_name; /* Evil hack! */ - i = 0; - while (1) { - p = (char *) data + gr_off[i]; - - if (i < 2) { - *((char **) p) = line; - line = strchr(line, ':'); - if (!line) { - break; - } - *line++ = '\0'; - i++; - } else { - *((gid_t *) p) = strtoul(line, &endptr, 10); - - /* NOTE: glibc difference - glibc allows omission of the - * trailing colon when there is no member list. We treat - * this as an error. */ - - /* Make sure we had at least one digit, and that the - * failing char is the next field seperator ':'. See - * glibc difference note above. */ - if ((endptr == line) || (*endptr != ':')) { - break; - } - - i = 1; /* Count terminating NULL ptr. */ - p = endptr; - - if (p[1]) { /* We have a member list to process. */ - /* Overwrite the last ':' with a ',' before counting. - * This allows us to (1) test for initial ',' - * and (2) adds one ',' so that the number of commas - * equals the member count. */ - *p = ','; - do { - /* NOTE: glibc difference - glibc allows and trims leading - * (but not trailing) space. We treat this as an error. */ - /* NOTE: glibc difference - glibc allows consecutive and - * trailing commas, and ignores "empty string" users. We - * treat this as an error. */ - if (*p == ',') { - ++i; - *p = 0; /* nul-terminate each member string. */ - if (!*++p || (*p == ',') || isspace(*p)) { - goto ERR; - } - } - } while (*++p); - } - - /* Now align (p+1), rounding up. */ - /* Assumes sizeof(char **) is a power of 2. */ - members = (char **)( (((intptr_t) p) + sizeof(char **)) - & ~((intptr_t)(sizeof(char **) - 1)) ); - - if (((char *)(members + i)) > end_of_buf) { /* No space. */ - break; - } - - ((struct group *) data)->gr_mem = members; - - if (--i) { - p = endptr; /* Pointing to char prior to first member. */ - while (1) { - *members++ = ++p; - if (!--i) - break; - while (*++p) - continue; - } - } - *members = NULL; - - return 0; - } - } /* while (1) */ - - ERR: - return -1; -} - -/**********************************************************************/ - -#if ENABLE_USE_BB_SHADOW -static const unsigned char sp_off[] ALIGN1 = { - offsetof(struct spwd, sp_namp), /* 0: char* */ - offsetof(struct spwd, sp_pwdp), /* 1: char* */ - offsetof(struct spwd, sp_lstchg), /* 2: long */ - offsetof(struct spwd, sp_min), /* 3: long */ - offsetof(struct spwd, sp_max), /* 4: long */ - offsetof(struct spwd, sp_warn), /* 5: long */ - offsetof(struct spwd, sp_inact), /* 6: long */ - offsetof(struct spwd, sp_expire), /* 7: long */ - offsetof(struct spwd, sp_flag) /* 8: unsigned long */ -}; - -static int FAST_FUNC bb__parsespent(void *data, char *line) -{ - char *endptr; - char *p; - int i; - - i = 0; - while (1) { - p = (char *) data + sp_off[i]; - if (i < 2) { - *((char **) p) = line; - line = strchr(line, ':'); - if (!line) { - break; /* error */ - } - } else { - *((long *) p) = strtoul(line, &endptr, 10); - if (endptr == line) { - *((long *) p) = -1L; - } - line = endptr; - if (i == 8) { - if (*line != '\0') { - break; /* error */ - } - return 0; /* all ok */ - } - if (*line != ':') { - break; /* error */ - } - } - *line++ = '\0'; - i++; - } - - return EINVAL; -} -#endif - -/**********************************************************************/ - -/* Reads until EOF, or until it finds a line which fits in the buffer - * and for which the parser function succeeds. - * - * Returns 0 on success and ENOENT for end-of-file (glibc convention). - */ -static int bb__pgsreader( - int FAST_FUNC (*parserfunc)(void *d, char *line), - void *data, - char *__restrict line_buff, - size_t buflen, - FILE *f) -{ - int skip; - int rv = ERANGE; - - if (buflen < PWD_BUFFER_SIZE) { - errno = rv; - return rv; - } - - skip = 0; - while (1) { - if (!fgets(line_buff, buflen, f)) { - if (feof(f)) { - rv = ENOENT; - } - break; - } - - { - int line_len = strlen(line_buff) - 1; - if (line_len >= 0 && line_buff[line_len] == '\n') { - line_buff[line_len] = '\0'; - } else - if (line_len + 2 == buflen) { - /* A start (or continuation) of overlong line */ - skip = 1; - continue; - } /* else: a last line in the file, and it has no '\n' */ - } - - if (skip) { - /* This "line" is a remainder of overlong line, ignore */ - skip = 0; - continue; - } - - /* NOTE: glibc difference - glibc strips leading whitespace from - * records. We do not allow leading whitespace. */ - - /* Skip empty lines, comment lines, and lines with leading - * whitespace. */ - if (line_buff[0] != '\0' && line_buff[0] != '#' && !isspace(line_buff[0])) { - if (parserfunc == bb__parsegrent) { - /* Do evil group hack: - * The group entry parsing function needs to know where - * the end of the buffer is so that it can construct the - * group member ptr table. */ - ((struct group *) data)->gr_name = line_buff + buflen; - } - if (parserfunc(data, line_buff) == 0) { - rv = 0; - break; - } - } - } /* while (1) */ - - return rv; -} diff --git a/libpwdgrp/pwd_grp_internal.c b/libpwdgrp/pwd_grp_internal.c deleted file mode 100644 index d6483be84..000000000 --- a/libpwdgrp/pwd_grp_internal.c +++ /dev/null @@ -1,61 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* Copyright (C) 2003 Manuel Novoa III - * - * Licensed under GPLv2 or later, see file LICENSE in this source tree. - */ - -/* Nov 6, 2003 Initial version. - * - * NOTE: This implementation is quite strict about requiring all - * field seperators. It also does not allow leading whitespace - * except when processing the numeric fields. glibc is more - * lenient. See the various glibc difference comments below. - * - * TODO: - * Move to dynamic allocation of (currently statically allocated) - * buffers; especially for the group-related functions since - * large group member lists will cause error returns. - */ - -#ifndef GETXXKEY_R_FUNC -#error GETXXKEY_R_FUNC is not defined! -#endif - -int GETXXKEY_R_FUNC(GETXXKEY_R_KEYTYPE key, - GETXXKEY_R_ENTTYPE *__restrict resultbuf, - char *__restrict buffer, size_t buflen, - GETXXKEY_R_ENTTYPE **__restrict result) -{ - FILE *stream; - int rv; - - *result = NULL; - - stream = fopen_for_read(GETXXKEY_R_PATHNAME); - if (!stream) - return errno; - while (1) { - rv = bb__pgsreader(GETXXKEY_R_PARSER, resultbuf, buffer, buflen, stream); - if (!rv) { - if (GETXXKEY_R_TEST(resultbuf)) { /* found key? */ - *result = resultbuf; - break; - } - } else { - if (rv == ENOENT) { /* EOF encountered */ - rv = 0; - } - break; - } - } - fclose(stream); - - return rv; -} - -#undef GETXXKEY_R_FUNC -#undef GETXXKEY_R_PARSER -#undef GETXXKEY_R_ENTTYPE -#undef GETXXKEY_R_TEST -#undef GETXXKEY_R_KEYTYPE -#undef GETXXKEY_R_PATHNAME From 908b6e5dfdbc81322680ce939e5415161c637bb4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 2 Jan 2015 22:31:07 +0100 Subject: [PATCH 007/256] libpwdgrp: use FAST_FUNC to make "matching ABI" optimization more likely to succeed See bb_internal_get*nam_r size reduction: function old new delta bb_internal_getpwent_r 167 176 +9 getXXnam_r 204 206 +2 sulogin_main 326 325 -1 su_main 471 470 -1 read_line_input 3832 3831 -1 print_stat 865 864 -1 prepare_socket_fd 283 282 -1 load_crontab 777 776 -1 fork_job 456 455 -1 do_shm 884 883 -1 do_sem 637 636 -1 do_msg 783 782 -1 complete_username 124 123 -1 bb_internal_getgrouplist 71 70 -1 xgetpwuid 27 25 -2 xgetpwnam 27 25 -2 xgetgrnam 27 25 -2 xgetgrgid 27 25 -2 uid2uname 18 16 -2 login_main 980 978 -2 gid2group 18 16 -2 get_shell_name 54 52 -2 change_identity 50 48 -2 bb_internal_initgroups 50 48 -2 argstr 1261 1259 -2 print_perms 177 174 -3 inetd_main 2077 2074 -3 run_applet_no_and_exit 446 442 -4 fileaction_setowngrp 89 85 -4 deluser_main 312 308 -4 bb_internal_getpwuid 19 15 -4 bb_internal_getpwnam 11 7 -4 bb_internal_getgrnam 14 10 -4 bb_internal_getgrgid 19 15 -4 adduser_main 865 861 -4 passwd_main 989 984 -5 get_passwd 97 92 -5 data_extract_all 887 882 -5 check_user_passwd 490 485 -5 get_groups 81 75 -6 ftpd_main 2178 2171 -7 bb_internal_getspnam_r 42 18 -24 bb_internal_getpwnam_r 39 15 -24 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/41 up/down: 11/-153) Total: -142 bytes text data bss dec hex filename 923167 928 17676 941771 e5ecb busybox_old 923023 928 17676 941627 e5e3b busybox_unstripped Signed-off-by: Denys Vlasenko --- include/grp_.h | 11 +++++------ include/pwd_.h | 14 +++++++------- include/shadow_.h | 26 +++++++++++++------------- libpwdgrp/pwd_grp.c | 32 ++++++++++++++++---------------- 4 files changed, 41 insertions(+), 42 deletions(-) diff --git a/include/grp_.h b/include/grp_.h index f7b8d836f..db13ce3b4 100644 --- a/include/grp_.h +++ b/include/grp_.h @@ -36,31 +36,30 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN #define getgrouplist bb_internal_getgrouplist #define initgroups bb_internal_initgroups - /* All function names below should be remapped by #defines above * in order to not collide with libc names. */ /* Close the group-file stream. */ -extern void endgrent(void); +void FAST_FUNC endgrent(void); /* Search for an entry with a matching group ID. */ -extern struct group *getgrgid(gid_t __gid); +struct group* FAST_FUNC getgrgid(gid_t __gid); /* Search for an entry with a matching group name. */ -extern struct group *getgrnam(const char *__name); +struct group* FAST_FUNC getgrnam(const char *__name); /* Reentrant versions of some of the functions above. */ /* Store at most *NGROUPS members of the group set for USER into *GROUPS. Also include GROUP. The actual number of groups found is returned in *NGROUPS. Return -1 if the if *NGROUPS is too small. */ -extern int getgrouplist(const char *__user, gid_t __group, +int FAST_FUNC getgrouplist(const char *__user, gid_t __group, gid_t *__groups, int *__ngroups); /* Initialize the group set for the current user by reading the group database and using all groups of which USER is a member. Also include GROUP. */ -extern int initgroups(const char *__user, gid_t __group); +int FAST_FUNC initgroups(const char *__user, gid_t __group); POP_SAVED_FUNCTION_VISIBILITY diff --git a/include/pwd_.h b/include/pwd_.h index d086f86e3..32b5b366e 100644 --- a/include/pwd_.h +++ b/include/pwd_.h @@ -43,21 +43,21 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN * in order to not collide with libc names. */ /* Rewind the password-file stream. */ -extern void setpwent(void); +void FAST_FUNC setpwent(void); /* Close the password-file stream. */ -extern void endpwent(void); +void FAST_FUNC endpwent(void); #ifdef UNUSED_SINCE_WE_AVOID_STATIC_BUFS /* Read an entry from the password-file stream, opening it if necessary. */ -extern struct passwd *getpwent(void); +struct passwd* FAST_FUNC getpwent(void); #endif /* Search for an entry with a matching user ID. */ -extern struct passwd *getpwuid(uid_t __uid); +struct passwd* FAST_FUNC getpwuid(uid_t __uid); /* Search for an entry with a matching username. */ -extern struct passwd *getpwnam(const char *__name); +struct passwd* FAST_FUNC getpwnam(const char *__name); /* Reentrant versions of some of the functions above. @@ -67,11 +67,11 @@ extern struct passwd *getpwnam(const char *__name); other reentrant functions so the chances are good this is what the POSIX people would choose. */ -extern int getpwent_r(struct passwd *__restrict __resultbuf, +int FAST_FUNC getpwent_r(struct passwd *__restrict __resultbuf, char *__restrict __buffer, size_t __buflen, struct passwd **__restrict __result); -extern int getpwnam_r(const char *__restrict __name, +int FAST_FUNC getpwnam_r(const char *__restrict __name, struct passwd *__restrict __resultbuf, char *__restrict __buffer, size_t __buflen, struct passwd **__restrict __result); diff --git a/include/shadow_.h b/include/shadow_.h index 7babe4f30..8e2581e7c 100644 --- a/include/shadow_.h +++ b/include/shadow_.h @@ -57,48 +57,48 @@ struct spwd { #ifdef UNUSED_FOR_NOW /* Open database for reading */ -extern void setspent(void); +void FAST_FUNC setspent(void); /* Close database */ -extern void endspent(void); +void FAST_FUNC endspent(void); /* Get next entry from database, perhaps after opening the file */ -extern struct spwd *getspent(void); +struct spwd* FAST_FUNC getspent(void); /* Get shadow entry matching NAME */ -extern struct spwd *getspnam(const char *__name); +struct spwd* FAST_FUNC getspnam(const char *__name); /* Read shadow entry from STRING */ -extern struct spwd *sgetspent(const char *__string); +struct spwd* FAST_FUNC sgetspent(const char *__string); /* Read next shadow entry from STREAM */ -extern struct spwd *fgetspent(FILE *__stream); +struct spwd* FAST_FUNC fgetspent(FILE *__stream); /* Write line containing shadow password entry to stream */ -extern int putspent(const struct spwd *__p, FILE *__stream); +int FAST_FUNC putspent(const struct spwd *__p, FILE *__stream); /* Reentrant versions of some of the functions above */ -extern int getspent_r(struct spwd *__result_buf, char *__buffer, +int FAST_FUNC getspent_r(struct spwd *__result_buf, char *__buffer, size_t __buflen, struct spwd **__result); #endif -extern int getspnam_r(const char *__name, struct spwd *__result_buf, +int FAST_FUNC getspnam_r(const char *__name, struct spwd *__result_buf, char *__buffer, size_t __buflen, struct spwd **__result); #ifdef UNUSED_FOR_NOW -extern int sgetspent_r(const char *__string, struct spwd *__result_buf, +int FAST_FUNC sgetspent_r(const char *__string, struct spwd *__result_buf, char *__buffer, size_t __buflen, struct spwd **__result); -extern int fgetspent_r(FILE *__stream, struct spwd *__result_buf, +int FAST_FUNC fgetspent_r(FILE *__stream, struct spwd *__result_buf, char *__buffer, size_t __buflen, struct spwd **__result); /* Protect password file against multi writers */ -extern int lckpwdf(void); +int FAST_FUNC lckpwdf(void); /* Unlock password file */ -extern int ulckpwdf(void); +int FAST_FUNC ulckpwdf(void); #endif POP_SAVED_FUNCTION_VISIBILITY diff --git a/libpwdgrp/pwd_grp.c b/libpwdgrp/pwd_grp.c index ed8370124..0d8e2bb5c 100644 --- a/libpwdgrp/pwd_grp.c +++ b/libpwdgrp/pwd_grp.c @@ -288,7 +288,7 @@ static void *convert_to_struct(const char *def, const unsigned char *off, /****** getXXnam/id_r */ -static int getXXnam_r(const char *name, uintptr_t db_and_field_pos, char *buffer, size_t buflen, +static int FAST_FUNC getXXnam_r(const char *name, uintptr_t db_and_field_pos, char *buffer, size_t buflen, void *result) { void *struct_buf = *(void**)result; @@ -316,18 +316,18 @@ static int getXXnam_r(const char *name, uintptr_t db_and_field_pos, char *buffer return errno; } -int getpwnam_r(const char *name, struct passwd *struct_buf, char *buffer, size_t buflen, +int FAST_FUNC getpwnam_r(const char *name, struct passwd *struct_buf, char *buffer, size_t buflen, struct passwd **result) { /* Why the "store buffer address in result" trick? * This way, getXXnam_r has the same ABI signature as getpwnam_r, - * hopefully compiler can optimize tall call better in this case. + * hopefully compiler can optimize tail call better in this case. */ *result = struct_buf; return getXXnam_r(name, (0 << 2) + 0, buffer, buflen, result); } #if ENABLE_USE_BB_SHADOW -int getspnam_r(const char *name, struct spwd *struct_buf, char *buffer, size_t buflen, +int FAST_FUNC getspnam_r(const char *name, struct spwd *struct_buf, char *buffer, size_t buflen, struct spwd **result) { *result = struct_buf; @@ -337,7 +337,7 @@ int getspnam_r(const char *name, struct spwd *struct_buf, char *buffer, size_t b /****** getXXent_r */ -static int getXXent_r(void *struct_buf, char *buffer, size_t buflen, +static int FAST_FUNC getXXent_r(void *struct_buf, char *buffer, size_t buflen, void *result, unsigned db_idx) { @@ -374,14 +374,14 @@ static int getXXent_r(void *struct_buf, char *buffer, size_t buflen, return errno; } -int getpwent_r(struct passwd *struct_buf, char *buffer, size_t buflen, struct passwd **result) +int FAST_FUNC getpwent_r(struct passwd *struct_buf, char *buffer, size_t buflen, struct passwd **result) { return getXXent_r(struct_buf, buffer, buflen, result, 0); } /****** getXXnam/id */ -static void *getXXnam(const char *name, unsigned db_and_field_pos) +static void* FAST_FUNC getXXnam(const char *name, unsigned db_and_field_pos) { char *buf; void *result; @@ -409,39 +409,39 @@ static void *getXXnam(const char *name, unsigned db_and_field_pos) return result; } -struct passwd *getpwnam(const char *name) +struct passwd* FAST_FUNC getpwnam(const char *name) { return getXXnam(name, (0 << 2) + 0); } -struct group *getgrnam(const char *name) +struct group* FAST_FUNC getgrnam(const char *name) { return getXXnam(name, (1 << 2) + 0); } -struct passwd *getpwuid(uid_t id) +struct passwd* FAST_FUNC getpwuid(uid_t id) { return getXXnam(utoa(id), (0 << 2) + 2); } -struct group *getgrgid(gid_t id) +struct group* FAST_FUNC getgrgid(gid_t id) { return getXXnam(utoa(id), (1 << 2) + 2); } /****** end/setXXend */ -void endpwent(void) +void FAST_FUNC endpwent(void) { if (has_S && S.db[0].fp) { fclose(S.db[0].fp); S.db[0].fp = NULL; } } -void setpwent(void) +void FAST_FUNC setpwent(void) { if (has_S && S.db[0].fp) { rewind(S.db[0].fp); } } -void endgrent(void) +void FAST_FUNC endgrent(void) { if (has_S && S.db[1].fp) { fclose(S.db[1].fp); @@ -491,7 +491,7 @@ static gid_t* FAST_FUNC getgrouplist_internal(int *ngroups_ptr, return group_list; } -int initgroups(const char *user, gid_t gid) +int FAST_FUNC initgroups(const char *user, gid_t gid) { int ngroups; gid_t *group_list = getgrouplist_internal(&ngroups, user, gid); @@ -501,7 +501,7 @@ int initgroups(const char *user, gid_t gid) return ngroups; } -int getgrouplist(const char *user, gid_t gid, gid_t *groups, int *ngroups) +int FAST_FUNC getgrouplist(const char *user, gid_t gid, gid_t *groups, int *ngroups) { int ngroups_old = *ngroups; gid_t *group_list = getgrouplist_internal(ngroups, user, gid); From 31d6734457b9cafeeaa862750c2afa80aa67816c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Jan 2015 15:15:47 +0100 Subject: [PATCH 008/256] libpwdgrp: tweak comments, replace one xmalloc with xzalloc Signed-off-by: Denys Vlasenko --- libpwdgrp/pwd_grp.c | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/libpwdgrp/pwd_grp.c b/libpwdgrp/pwd_grp.c index 0d8e2bb5c..823884edc 100644 --- a/libpwdgrp/pwd_grp.c +++ b/libpwdgrp/pwd_grp.c @@ -1,5 +1,5 @@ /* vi: set sw=4 ts=4: */ -/* Copyright (C) 2014 Tito Ragusa +/* Copyright (C) 2014 Tito Ragusa * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ @@ -9,38 +9,33 @@ * Rewrite of some parts. Main differences are: * * 1) the buffer for getpwuid, getgrgid, getpwnam, getgrnam is dynamically - * allocated and reused by later calls. if ERANGE error pops up it is - * reallocated to the size of the longest line found so far in the - * passwd/group files and reused for later calls. + * allocated and reused by later calls. * If ENABLE_FEATURE_CLEAN_UP is set the buffers are freed at program * exit using the atexit function to make valgrind happy. * 2) the passwd/group files: * a) must contain the expected number of fields (as per count of field * delimeters ":") or we will complain with a error message. - * b) leading or trailing whitespace in fields is allowed and handled. + * b) leading or trailing whitespace in fields is stripped. * c) some fields are not allowed to be empty (e.g. username, uid/gid, * homedir, shell) and in this case NULL is returned and errno is * set to EINVAL. This behaviour could be easily changed by * modifying PW_DEF, GR_DEF, SP_DEF strings (uppercase * makes a field mandatory). * d) the string representing uid/gid must be convertible by strtoXX - * functions or NULL is returned and errno is set to EINVAL. - * e) leading or trailing whitespaces in member names and empty members - * are allowed and handled. - * 3) the internal function for getgrouplist uses a dynamically allocated - * buffer and retries with a bigger one in case it is too small; - * 4) the _r functions use the user supplied buffers that are never reallocated - * but use mostly the same common code as the other functions. - * 5) at the moment only the functions really used by busybox code are + * functions, or errno is set to EINVAL. + * e) leading or trailing whitespace in group member names are stripped. + * 3) the internal function for getgrouplist uses dynamically allocated buffer. + * 4) at the moment only the functions really used by busybox code are * implemented, if you need a particular missing function it should be * easy to write it by using the internal common code. */ #include "libbb.h" -/* S = string not empty, s = string maybe empty, */ -/* I = uid,gid, l = long maybe empty, m = members,*/ -/* r = reserved */ +/* S = string not empty, s = string maybe empty, + * I = uid,gid, l = long maybe empty, m = members, + * r = reserved + */ #define PW_DEF "SsIIsSS" #define GR_DEF "SsIm" #define SP_DEF "Ssllllllr" @@ -99,7 +94,8 @@ static const struct const_passdb const_sp_db = { _PATH_SHADOW, sp_off, SP_DEF, s /* We avoid having big global data. */ struct statics { - /* It's ok to use one buffer for getpwuid and getpwnam. Manpage says: + /* It's ok to use same buffer (db[0].malloced) for getpwuid and getpwnam. + * Manpage says: * "The return value may point to a static area, and may be overwritten * by subsequent calls to getpwent(), getpwnam(), or getpwuid()." */ @@ -124,14 +120,12 @@ static struct statics *get_S(void) return ptr_to_statics; } -/**********************************************************************/ -/* Internal functions */ -/**********************************************************************/ +/* Internal functions */ /* Divide the passwd/group/shadow record in fields * by substituting the given delimeter * e.g. ':' or ',' with '\0'. - * Returns the number of fields found. + * Returns the number of fields found. * Strips leading and trailing whitespace in fields. */ static int tokenize(char *buffer, int ch) @@ -328,7 +322,7 @@ int FAST_FUNC getpwnam_r(const char *name, struct passwd *struct_buf, char *buff } #if ENABLE_USE_BB_SHADOW int FAST_FUNC getspnam_r(const char *name, struct spwd *struct_buf, char *buffer, size_t buflen, - struct spwd **result) + struct spwd **result) { *result = struct_buf; return getXXnam_r(name, (2 << 2) + 0, buffer, buflen, result); @@ -461,7 +455,7 @@ static gid_t* FAST_FUNC getgrouplist_internal(int *ngroups_ptr, get_S(); /* We alloc space for 8 gids at a time. */ - group_list = xmalloc(8 * sizeof(group_list[0])); + group_list = xzalloc(8 * sizeof(group_list[0])); group_list[0] = gid; ngroups = 1; From 8d547aca75f8b096976a472714241acd4328be46 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Jan 2015 15:54:04 +0100 Subject: [PATCH 009/256] libpwdgrp: fix a memory leak in getXXnam (we did not save address of string buf) function old new delta convert_to_struct 261 269 +8 const_sp_db 20 24 +4 const_pw_db 20 24 +4 const_gr_db 20 24 +4 tokenize 144 147 +3 parse_common 185 188 +3 get_S 82 85 +3 bb_internal_getpwent_r 188 185 -3 gr_off 4 - -4 getXXnam 171 165 -6 pw_off 7 - -7 getgrouplist_internal 237 229 -8 getXXnam_r 215 207 -8 sp_off 9 - -9 ------------------------------------------------------------------------------ (add/remove: 0/3 grow/shrink: 7/4 up/down: 29/-45) Total: -16 bytes Signed-off-by: Denys Vlasenko --- libpwdgrp/pwd_grp.c | 133 +++++++++++++++++++++++++------------------- 1 file changed, 75 insertions(+), 58 deletions(-) diff --git a/libpwdgrp/pwd_grp.c b/libpwdgrp/pwd_grp.c index 823884edc..6d938f621 100644 --- a/libpwdgrp/pwd_grp.c +++ b/libpwdgrp/pwd_grp.c @@ -32,6 +32,27 @@ #include "libbb.h" +struct const_passdb { + const char *filename; + const char def[10]; + const uint8_t off[9]; + uint8_t numfields; +}; +struct passdb { + const char *filename; + const char def[10]; + const uint8_t off[9]; + uint8_t numfields; + FILE *fp; + char *malloced; + char struct_result[0 + | sizeof(struct passwd) + | sizeof(struct group) + IF_USE_BB_SHADOW( | sizeof(struct spwd) ) + /* bitwise OR above is poor man's max(a,b,c) */ + ]; +}; + /* S = string not empty, s = string maybe empty, * I = uid,gid, l = long maybe empty, m = members, * r = reserved @@ -40,61 +61,50 @@ #define GR_DEF "SsIm" #define SP_DEF "Ssllllllr" -static const uint8_t pw_off[] ALIGN1 = { - offsetof(struct passwd, pw_name), /* 0 S */ - offsetof(struct passwd, pw_passwd), /* 1 s */ - offsetof(struct passwd, pw_uid), /* 2 I */ - offsetof(struct passwd, pw_gid), /* 3 I */ - offsetof(struct passwd, pw_gecos), /* 4 s */ - offsetof(struct passwd, pw_dir), /* 5 S */ - offsetof(struct passwd, pw_shell) /* 6 S */ +static const struct const_passdb const_pw_db = { + _PATH_PASSWD, PW_DEF, + { + offsetof(struct passwd, pw_name), /* 0 S */ + offsetof(struct passwd, pw_passwd), /* 1 s */ + offsetof(struct passwd, pw_uid), /* 2 I */ + offsetof(struct passwd, pw_gid), /* 3 I */ + offsetof(struct passwd, pw_gecos), /* 4 s */ + offsetof(struct passwd, pw_dir), /* 5 S */ + offsetof(struct passwd, pw_shell) /* 6 S */ + }, + sizeof(PW_DEF)-1 }; -static const uint8_t gr_off[] ALIGN1 = { - offsetof(struct group, gr_name), /* 0 S */ - offsetof(struct group, gr_passwd), /* 1 s */ - offsetof(struct group, gr_gid), /* 2 I */ - offsetof(struct group, gr_mem) /* 3 m (char **) */ +static const struct const_passdb const_gr_db = { + _PATH_GROUP, GR_DEF, + { + offsetof(struct group, gr_name), /* 0 S */ + offsetof(struct group, gr_passwd), /* 1 s */ + offsetof(struct group, gr_gid), /* 2 I */ + offsetof(struct group, gr_mem) /* 3 m (char **) */ + }, + sizeof(GR_DEF)-1 }; #if ENABLE_USE_BB_SHADOW -static const uint8_t sp_off[] ALIGN1 = { - offsetof(struct spwd, sp_namp), /* 0 S Login name */ - offsetof(struct spwd, sp_pwdp), /* 1 s Encrypted password */ - offsetof(struct spwd, sp_lstchg), /* 2 l */ - offsetof(struct spwd, sp_min), /* 3 l */ - offsetof(struct spwd, sp_max), /* 4 l */ - offsetof(struct spwd, sp_warn), /* 5 l */ - offsetof(struct spwd, sp_inact), /* 6 l */ - offsetof(struct spwd, sp_expire), /* 7 l */ - offsetof(struct spwd, sp_flag) /* 8 r Reserved */ +static const struct const_passdb const_sp_db = { + _PATH_SHADOW, SP_DEF, + { + offsetof(struct spwd, sp_namp), /* 0 S Login name */ + offsetof(struct spwd, sp_pwdp), /* 1 s Encrypted password */ + offsetof(struct spwd, sp_lstchg), /* 2 l */ + offsetof(struct spwd, sp_min), /* 3 l */ + offsetof(struct spwd, sp_max), /* 4 l */ + offsetof(struct spwd, sp_warn), /* 5 l */ + offsetof(struct spwd, sp_inact), /* 6 l */ + offsetof(struct spwd, sp_expire), /* 7 l */ + offsetof(struct spwd, sp_flag) /* 8 r Reserved */ + }, + sizeof(SP_DEF)-1 }; #endif -struct const_passdb { - const char *filename; - const uint8_t *off; - const char def[10]; - uint8_t numfields; - uint8_t size_of; -}; -struct passdb { - const char *filename; - const uint8_t *off; - const char def[10]; - uint8_t numfields; - uint8_t size_of; - FILE *fp; - void *malloced; -}; - -static const struct const_passdb const_pw_db = { _PATH_PASSWD, pw_off, PW_DEF, sizeof(PW_DEF)-1, sizeof(struct passwd) }; -static const struct const_passdb const_gr_db = { _PATH_GROUP , gr_off, GR_DEF, sizeof(GR_DEF)-1, sizeof(struct group) }; -#if ENABLE_USE_BB_SHADOW -static const struct const_passdb const_sp_db = { _PATH_SHADOW, sp_off, SP_DEF, sizeof(SP_DEF)-1, sizeof(struct spwd) }; -#endif - /* We avoid having big global data. */ struct statics { - /* It's ok to use same buffer (db[0].malloced) for getpwuid and getpwnam. + /* It's ok to use same buffer (db[0].struct_result) for getpwuid and getpwnam. * Manpage says: * "The return value may point to a static area, and may be overwritten * by subsequent calls to getpwent(), getpwnam(), or getpwuid()." @@ -223,9 +233,15 @@ static char *parse_file(const char *filename, } /* Convert passwd/group/shadow file record in buffer to a struct */ -static void *convert_to_struct(const char *def, const unsigned char *off, +static void *convert_to_struct(struct passdb *db, char *buffer, void *result) { + const char *def = db->def; + const uint8_t *off = db->off; + +/* TODO? for consistency, zero out all fields */ +/* memset(result, 0, size_of_result);*/ + for (;;) { void *member = (char*)result + (*off++); @@ -282,7 +298,8 @@ static void *convert_to_struct(const char *def, const unsigned char *off, /****** getXXnam/id_r */ -static int FAST_FUNC getXXnam_r(const char *name, uintptr_t db_and_field_pos, char *buffer, size_t buflen, +static int FAST_FUNC getXXnam_r(const char *name, uintptr_t db_and_field_pos, + char *buffer, size_t buflen, void *result) { void *struct_buf = *(void**)result; @@ -299,7 +316,7 @@ static int FAST_FUNC getXXnam_r(const char *name, uintptr_t db_and_field_pos, ch errno = ERANGE; } else { memcpy(buffer, buf, size); - *(void**)result = convert_to_struct(db->def, db->off, buffer, struct_buf); + *(void**)result = convert_to_struct(db, buffer, struct_buf); } free(buf); } @@ -310,8 +327,9 @@ static int FAST_FUNC getXXnam_r(const char *name, uintptr_t db_and_field_pos, ch return errno; } -int FAST_FUNC getpwnam_r(const char *name, struct passwd *struct_buf, char *buffer, size_t buflen, - struct passwd **result) +int FAST_FUNC getpwnam_r(const char *name, struct passwd *struct_buf, + char *buffer, size_t buflen, + struct passwd **result) { /* Why the "store buffer address in result" trick? * This way, getXXnam_r has the same ABI signature as getpwnam_r, @@ -357,7 +375,7 @@ static int FAST_FUNC getXXent_r(void *struct_buf, char *buffer, size_t buflen, errno = ERANGE; } else { memcpy(buffer, buf, size); - *(void**)result = convert_to_struct(db->def, db->off, buffer, struct_buf); + *(void**)result = convert_to_struct(db, buffer, struct_buf); } free(buf); } @@ -393,12 +411,11 @@ static void* FAST_FUNC getXXnam(const char *name, unsigned db_and_field_pos) close_on_exec_on(fileno(db->fp)); } - free(db->malloced); - db->malloced = NULL; buf = parse_common(db->fp, db->filename, db->numfields, name, db_and_field_pos & 3); if (buf) { - db->malloced = xzalloc(db->size_of); - result = convert_to_struct(db->def, db->off, buf, db->malloced); + free(db->malloced); + db->malloced = buf; + result = convert_to_struct(db, buf, db->struct_result); } return result; } @@ -465,7 +482,7 @@ static gid_t* FAST_FUNC getgrouplist_internal(int *ngroups_ptr, while ((buf = parse_common(fp, _PATH_GROUP, sizeof(GR_DEF)-1, NULL, 0)) != NULL) { char **m; struct group group; - if (!convert_to_struct(GR_DEF, gr_off, buf, &group)) + if (!convert_to_struct(&S.db[1], buf, &group)) goto next; if (group.gr_gid == gid) goto next; From 9dca6acaac3a49f1ff8ba9d3ca78853da6f59ae1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Jan 2015 16:09:05 +0100 Subject: [PATCH 010/256] libpwdgrp: reinstate Tito's optional atexit freeing Signed-off-by: Denys Vlasenko --- libpwdgrp/pwd_grp.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/libpwdgrp/pwd_grp.c b/libpwdgrp/pwd_grp.c index 6d938f621..539d2b01f 100644 --- a/libpwdgrp/pwd_grp.c +++ b/libpwdgrp/pwd_grp.c @@ -117,6 +117,18 @@ static struct statics *ptr_to_statics; #define S (*ptr_to_statics) #define has_S (ptr_to_statics) +#if ENABLE_FEATURE_CLEAN_UP +static void free_static(void) +{ + free(S.db[0].malloced); + free(S.db[1].malloced); +# if ENABLE_USE_BB_SHADOW + S.db[2].malloced); +# endif + free(ptr_to_statics); +} +#endif + static struct statics *get_S(void) { if (!ptr_to_statics) { @@ -125,6 +137,9 @@ static struct statics *get_S(void) memcpy(&S.db[1], &const_gr_db, sizeof(const_gr_db)); #if ENABLE_USE_BB_SHADOW memcpy(&S.db[2], &const_sp_db, sizeof(const_sp_db)); +#endif +#if ENABLE_FEATURE_CLEAN_UP + atexit(free_static); #endif } return ptr_to_statics; From 5e62a3d016633d4d97906f0f73298dc8e8b6a42b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Jan 2015 17:53:49 +0100 Subject: [PATCH 011/256] libpwdgrp: use a better estimate of max struct size Previous code's trick with bitwise OR was giving this on 32-bit x86: sizeof(struct passwd):28 sizeof(struct group):16 sizeof(struct spwd):36 sizeof(struct_result):60 Signed-off-by: Denys Vlasenko --- libpwdgrp/pwd_grp.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libpwdgrp/pwd_grp.c b/libpwdgrp/pwd_grp.c index 539d2b01f..f3fcec859 100644 --- a/libpwdgrp/pwd_grp.c +++ b/libpwdgrp/pwd_grp.c @@ -45,11 +45,10 @@ struct passdb { uint8_t numfields; FILE *fp; char *malloced; - char struct_result[0 - | sizeof(struct passwd) - | sizeof(struct group) - IF_USE_BB_SHADOW( | sizeof(struct spwd) ) - /* bitwise OR above is poor man's max(a,b,c) */ + char struct_result[ + /* Should be max(sizeof passwd,group,spwd), but this will do: */ + IF_NOT_USE_BB_SHADOW(sizeof(struct passwd)) + IF_USE_BB_SHADOW(sizeof(struct spwd)) ]; }; From 20c0a16334e96493077eaaad6f4c5690af0aa6e8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Jan 2015 19:12:49 +0100 Subject: [PATCH 012/256] libpwdgrp: make db->def[] one byte shorter In the future I will need another uint8_t, want to fit it w/o using another word on 32 bits. Signed-off-by: Denys Vlasenko --- libpwdgrp/pwd_grp.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/libpwdgrp/pwd_grp.c b/libpwdgrp/pwd_grp.c index f3fcec859..1b2418a8d 100644 --- a/libpwdgrp/pwd_grp.c +++ b/libpwdgrp/pwd_grp.c @@ -34,13 +34,13 @@ struct const_passdb { const char *filename; - const char def[10]; + const char def[9]; const uint8_t off[9]; uint8_t numfields; }; struct passdb { const char *filename; - const char def[10]; + const char def[9]; const uint8_t off[9]; uint8_t numfields; FILE *fp; @@ -51,6 +51,11 @@ struct passdb { IF_USE_BB_SHADOW(sizeof(struct spwd)) ]; }; +/* Note: for shadow db, def[9] will not contain terminating NUL, + * but convert_to_struct() logic detects def[] end by "less than SP?", + * not by "is it NUL?" condition; and off[0] happens to be zero + * for every db anyway, so there _is_ in fact a terminating NUL there. + */ /* S = string not empty, s = string maybe empty, * I = uid,gid, l = long maybe empty, m = members, @@ -122,7 +127,7 @@ static void free_static(void) free(S.db[0].malloced); free(S.db[1].malloced); # if ENABLE_USE_BB_SHADOW - S.db[2].malloced); + free(S.db[2].malloced); # endif free(ptr_to_statics); } @@ -286,8 +291,8 @@ static void *convert_to_struct(struct passdb *db, * at the end of malloced buffer! */ members = (char **) - ( ((intptr_t)S.tokenize_end + sizeof(char**)) - & -(intptr_t)sizeof(char**) + ( ((intptr_t)S.tokenize_end + sizeof(members[0])) + & -(intptr_t)sizeof(members[0]) ); ((struct group *)result)->gr_mem = members; @@ -300,7 +305,7 @@ static void *convert_to_struct(struct passdb *db, /* def "r" does nothing */ def++; - if (*def == '\0') + if ((unsigned char)*def < (unsigned char)' ') break; buffer += strlen(buffer) + 1; } From 134c53098bdcbf7a0c34b60b97c46280d86eb48f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Jan 2015 20:47:47 +0100 Subject: [PATCH 013/256] libpwdgrp: store getXXnam result in a single malloc block This saves a bit of memory but more importantly, allows to create xmalloc_getpwnam() API where result can be deleted simply using free(). function old new delta getXXnam 134 173 +39 parse_common 188 212 +24 convert_to_struct 277 290 +13 get_S 90 88 -2 tokenize 129 126 -3 bb_internal_getpwent_r 175 172 -3 getXXnam_r 208 198 -10 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/4 up/down: 76/-18) Total: 58 bytes Signed-off-by: Denys Vlasenko --- libpwdgrp/pwd_grp.c | 58 +++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/libpwdgrp/pwd_grp.c b/libpwdgrp/pwd_grp.c index 1b2418a8d..4b61b61d2 100644 --- a/libpwdgrp/pwd_grp.c +++ b/libpwdgrp/pwd_grp.c @@ -34,24 +34,21 @@ struct const_passdb { const char *filename; - const char def[9]; - const uint8_t off[9]; + const char def[7 + 2*ENABLE_USE_BB_SHADOW]; + const uint8_t off[7 + 2*ENABLE_USE_BB_SHADOW]; uint8_t numfields; + uint8_t size_of; }; struct passdb { const char *filename; - const char def[9]; - const uint8_t off[9]; + const char def[7 + 2*ENABLE_USE_BB_SHADOW]; + const uint8_t off[7 + 2*ENABLE_USE_BB_SHADOW]; uint8_t numfields; + uint8_t size_of; FILE *fp; char *malloced; - char struct_result[ - /* Should be max(sizeof passwd,group,spwd), but this will do: */ - IF_NOT_USE_BB_SHADOW(sizeof(struct passwd)) - IF_USE_BB_SHADOW(sizeof(struct spwd)) - ]; }; -/* Note: for shadow db, def[9] will not contain terminating NUL, +/* Note: for shadow db, def[] will not contain terminating NUL, * but convert_to_struct() logic detects def[] end by "less than SP?", * not by "is it NUL?" condition; and off[0] happens to be zero * for every db anyway, so there _is_ in fact a terminating NUL there. @@ -76,7 +73,7 @@ static const struct const_passdb const_pw_db = { offsetof(struct passwd, pw_dir), /* 5 S */ offsetof(struct passwd, pw_shell) /* 6 S */ }, - sizeof(PW_DEF)-1 + sizeof(PW_DEF)-1, sizeof(struct passwd) }; static const struct const_passdb const_gr_db = { _PATH_GROUP, GR_DEF, @@ -86,7 +83,7 @@ static const struct const_passdb const_gr_db = { offsetof(struct group, gr_gid), /* 2 I */ offsetof(struct group, gr_mem) /* 3 m (char **) */ }, - sizeof(GR_DEF)-1 + sizeof(GR_DEF)-1, sizeof(struct group) }; #if ENABLE_USE_BB_SHADOW static const struct const_passdb const_sp_db = { @@ -102,19 +99,20 @@ static const struct const_passdb const_sp_db = { offsetof(struct spwd, sp_expire), /* 7 l */ offsetof(struct spwd, sp_flag) /* 8 r Reserved */ }, - sizeof(SP_DEF)-1 + sizeof(SP_DEF)-1, sizeof(struct spwd) }; #endif /* We avoid having big global data. */ struct statics { - /* It's ok to use same buffer (db[0].struct_result) for getpwuid and getpwnam. + /* It's ok to use same buffer (db[0].malloced) for getpwuid and getpwnam. * Manpage says: * "The return value may point to a static area, and may be overwritten * by subsequent calls to getpwent(), getpwnam(), or getpwuid()." */ struct passdb db[2 + ENABLE_USE_BB_SHADOW]; char *tokenize_end; + unsigned string_size; }; static struct statics *ptr_to_statics; @@ -205,21 +203,21 @@ static char *parse_common(FILE *fp, const char *filename, bb_error_msg("bad record at %s:%u", filename, count); goto free_and_next; } + S.string_size = S.tokenize_end - buf; -/* Ugly hack: group db requires aqdditional buffer space +/* Ugly hack: group db requires additional buffer space * for members[] array. If there is only one group, we need space * for 3 pointers: alignment padding, group name, NULL. * +1 for every additional group. */ if (n_fields == sizeof(GR_DEF)-1) { /* if we read group file */ - int resize = 3; + int cnt = 3; char *p = buf; while (*p) if (*p++ == ',') - resize++; - resize *= sizeof(char**); - resize += S.tokenize_end - buf; - buf = xrealloc(buf, resize); + cnt++; + S.string_size += cnt * sizeof(char*); + buf = xrealloc(buf, S.string_size); } if (!key) { @@ -258,8 +256,8 @@ static void *convert_to_struct(struct passdb *db, const char *def = db->def; const uint8_t *off = db->off; -/* TODO? for consistency, zero out all fields */ -/* memset(result, 0, size_of_result);*/ + /* For consistency, zero out all fields */ + memset(result, 0, db->size_of); for (;;) { void *member = (char*)result + (*off++); @@ -305,7 +303,7 @@ static void *convert_to_struct(struct passdb *db, /* def "r" does nothing */ def++; - if ((unsigned char)*def < (unsigned char)' ') + if ((unsigned char)*def <= (unsigned char)' ') break; buffer += strlen(buffer) + 1; } @@ -328,7 +326,9 @@ static int FAST_FUNC getXXnam_r(const char *name, uintptr_t db_and_field_pos, db = &S.db[db_and_field_pos >> 2]; *(void**)result = NULL; - buf = parse_file(db->filename, db->numfields, name, db_and_field_pos & 3); + buf = parse_file(db->filename, db->numfields, name, 0 /*db_and_field_pos & 3*/); + /* "db_and_field_pos & 3" is commented out since so far we don't implement + * getXXXid_r() functions which would use that to pass 2 here */ if (buf) { size_t size = S.tokenize_end - buf; if (size > buflen) { @@ -433,8 +433,14 @@ static void* FAST_FUNC getXXnam(const char *name, unsigned db_and_field_pos) buf = parse_common(db->fp, db->filename, db->numfields, name, db_and_field_pos & 3); if (buf) { free(db->malloced); - db->malloced = buf; - result = convert_to_struct(db, buf, db->struct_result); + /* We enlarge buf and move string data up, freeing space + * for struct passwd/group/spwd at the beginning. This way, + * entire result of getXXnam is in a single malloced block. + * This enables easy creation of xmalloc_getpwnam() API. + */ + db->malloced = buf = xrealloc(buf, db->size_of + S.string_size); + memmove(buf + db->size_of, buf, S.string_size); + result = convert_to_struct(db, buf + db->size_of, buf); } return result; } From f9936676bb7fd57ea2256af2247c970d1ed3f906 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Jan 2015 21:03:39 +0100 Subject: [PATCH 014/256] libpwdgrp: fix counting of commas in group list Signed-off-by: Denys Vlasenko --- libpwdgrp/pwd_grp.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/libpwdgrp/pwd_grp.c b/libpwdgrp/pwd_grp.c index 4b61b61d2..01058d3a1 100644 --- a/libpwdgrp/pwd_grp.c +++ b/libpwdgrp/pwd_grp.c @@ -203,22 +203,6 @@ static char *parse_common(FILE *fp, const char *filename, bb_error_msg("bad record at %s:%u", filename, count); goto free_and_next; } - S.string_size = S.tokenize_end - buf; - -/* Ugly hack: group db requires additional buffer space - * for members[] array. If there is only one group, we need space - * for 3 pointers: alignment padding, group name, NULL. - * +1 for every additional group. - */ - if (n_fields == sizeof(GR_DEF)-1) { /* if we read group file */ - int cnt = 3; - char *p = buf; - while (*p) - if (*p++ == ',') - cnt++; - S.string_size += cnt * sizeof(char*); - buf = xrealloc(buf, S.string_size); - } if (!key) { /* no key specified: sequential read, return a record */ @@ -232,6 +216,24 @@ static char *parse_common(FILE *fp, const char *filename, free(buf); } + S.string_size = S.tokenize_end - buf; +/* + * Ugly hack: group db requires additional buffer space + * for members[] array. If there is only one group, we need space + * for 3 pointers: alignment padding, group name, NULL. + * +1 for every additional group. + */ + if (n_fields == sizeof(GR_DEF)-1) { /* if we read group file... */ + int cnt = 3; + char *p = buf; + while (p < S.tokenize_end) + if (*p++ == ',') + cnt++; + S.string_size += cnt * sizeof(char*); +//bb_error_msg("+%d words = %u key:%s buf:'%s'", cnt, S.string_size, key, buf); + buf = xrealloc(buf, S.string_size); + } + return buf; } From 402451aa19521908125c9aeeb52e91fd4032948b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Jan 2015 21:11:27 +0100 Subject: [PATCH 015/256] fix a SEGV in previous commit Signed-off-by: Denys Vlasenko --- libpwdgrp/pwd_grp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libpwdgrp/pwd_grp.c b/libpwdgrp/pwd_grp.c index 01058d3a1..2392e7d22 100644 --- a/libpwdgrp/pwd_grp.c +++ b/libpwdgrp/pwd_grp.c @@ -223,7 +223,7 @@ static char *parse_common(FILE *fp, const char *filename, * for 3 pointers: alignment padding, group name, NULL. * +1 for every additional group. */ - if (n_fields == sizeof(GR_DEF)-1) { /* if we read group file... */ + if (buf && n_fields == sizeof(GR_DEF)-1) { /* if we read group file... */ int cnt = 3; char *p = buf; while (p < S.tokenize_end) From 12fc86956057ac3e679dd276ba3897260b95157e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 3 Jan 2015 21:16:18 +0100 Subject: [PATCH 016/256] libpwdgrp: getgrXXX: empty string is not a member name, do not store it Signed-off-by: Denys Vlasenko --- libpwdgrp/pwd_grp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libpwdgrp/pwd_grp.c b/libpwdgrp/pwd_grp.c index 2392e7d22..65fd5261d 100644 --- a/libpwdgrp/pwd_grp.c +++ b/libpwdgrp/pwd_grp.c @@ -297,7 +297,10 @@ static void *convert_to_struct(struct passdb *db, ((struct group *)result)->gr_mem = members; while (--i >= 0) { - *members++ = buffer; + if (buffer[0]) { + *members++ = buffer; + // bb_error_msg("member[]='%s'", buffer); + } buffer += strlen(buffer) + 1; } *members = NULL; From 5acf1346b463a41373f5a8c1df424c5f1646a4f9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 4 Jan 2015 02:02:39 +0100 Subject: [PATCH 017/256] libpwdgrp: code shrink function old new delta parse_common 206 205 -1 getgrouplist_internal 229 225 -4 bb_internal_getpwent_r 182 173 -9 getXXnam 232 222 -10 getXXnam_r 216 176 -40 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/5 up/down: 0/-64) Total: -64 bytes Signed-off-by: Denys Vlasenko --- libpwdgrp/pwd_grp.c | 41 ++++++++++++++++------------------------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/libpwdgrp/pwd_grp.c b/libpwdgrp/pwd_grp.c index 65fd5261d..0fd458fdc 100644 --- a/libpwdgrp/pwd_grp.c +++ b/libpwdgrp/pwd_grp.c @@ -186,8 +186,7 @@ static int tokenize(char *buffer, int ch) /* Returns !NULL on success and matching line broken up in fields by '\0' in buf. * We require the expected number of fields to be found. */ -static char *parse_common(FILE *fp, const char *filename, - int n_fields, +static char *parse_common(FILE *fp, struct passdb *db, const char *key, int field_pos) { int count = 0; @@ -198,9 +197,9 @@ static char *parse_common(FILE *fp, const char *filename, /* Skip empty lines, comment lines */ if (buf[0] == '\0' || buf[0] == '#') goto free_and_next; - if (tokenize(buf, ':') != n_fields) { + if (tokenize(buf, ':') != db->numfields) { /* number of fields is wrong */ - bb_error_msg("bad record at %s:%u", filename, count); + bb_error_msg("bad record at %s:%u", db->filename, count); goto free_and_next; } @@ -223,7 +222,7 @@ static char *parse_common(FILE *fp, const char *filename, * for 3 pointers: alignment padding, group name, NULL. * +1 for every additional group. */ - if (buf && n_fields == sizeof(GR_DEF)-1) { /* if we read group file... */ + if (buf && db->numfields == sizeof(GR_DEF)-1) { /* if we read group file... */ int cnt = 3; char *p = buf; while (p < S.tokenize_end) @@ -237,15 +236,14 @@ static char *parse_common(FILE *fp, const char *filename, return buf; } -static char *parse_file(const char *filename, - int n_fields, +static char *parse_file(struct passdb *db, const char *key, int field_pos) { char *buf = NULL; - FILE *fp = fopen_for_read(filename); + FILE *fp = fopen_for_read(db->filename); if (fp) { - buf = parse_common(fp, filename, n_fields, key, field_pos); + buf = parse_common(fp, db, key, field_pos); fclose(fp); } return buf; @@ -326,12 +324,10 @@ static int FAST_FUNC getXXnam_r(const char *name, uintptr_t db_and_field_pos, { void *struct_buf = *(void**)result; char *buf; - struct passdb *db; - get_S(); - db = &S.db[db_and_field_pos >> 2]; + struct passdb *db = &get_S()->db[db_and_field_pos >> 2]; *(void**)result = NULL; - buf = parse_file(db->filename, db->numfields, name, 0 /*db_and_field_pos & 3*/); + buf = parse_file(db, name, 0 /*db_and_field_pos & 3*/); /* "db_and_field_pos & 3" is commented out since so far we don't implement * getXXXid_r() functions which would use that to pass 2 here */ if (buf) { @@ -378,9 +374,7 @@ static int FAST_FUNC getXXent_r(void *struct_buf, char *buffer, size_t buflen, unsigned db_idx) { char *buf; - struct passdb *db; - get_S(); - db = &S.db[db_idx]; + struct passdb *db = &get_S()->db[db_idx]; *(void**)result = NULL; @@ -392,7 +386,7 @@ static int FAST_FUNC getXXent_r(void *struct_buf, char *buffer, size_t buflen, close_on_exec_on(fileno(db->fp)); } - buf = parse_common(db->fp, db->filename, db->numfields, /*no search key:*/ NULL, 0); + buf = parse_common(db->fp, db, /*no search key:*/ NULL, 0); if (buf) { size_t size = S.tokenize_end - buf; if (size > buflen) { @@ -421,9 +415,7 @@ static void* FAST_FUNC getXXnam(const char *name, unsigned db_and_field_pos) { char *buf; void *result; - struct passdb *db; - get_S(); - db = &S.db[db_and_field_pos >> 2]; + struct passdb *db = &get_S()->db[db_and_field_pos >> 2]; result = NULL; @@ -435,7 +427,7 @@ static void* FAST_FUNC getXXnam(const char *name, unsigned db_and_field_pos) close_on_exec_on(fileno(db->fp)); } - buf = parse_common(db->fp, db->filename, db->numfields, name, db_and_field_pos & 3); + buf = parse_common(db->fp, db, name, db_and_field_pos & 3); if (buf) { free(db->malloced); /* We enlarge buf and move string data up, freeing space @@ -499,8 +491,6 @@ static gid_t* FAST_FUNC getgrouplist_internal(int *ngroups_ptr, gid_t *group_list; int ngroups; - get_S(); - /* We alloc space for 8 gids at a time. */ group_list = xzalloc(8 * sizeof(group_list[0])); group_list[0] = gid; @@ -508,11 +498,12 @@ static gid_t* FAST_FUNC getgrouplist_internal(int *ngroups_ptr, fp = fopen_for_read(_PATH_GROUP); if (fp) { + struct passdb *db = &get_S()->db[1]; char *buf; - while ((buf = parse_common(fp, _PATH_GROUP, sizeof(GR_DEF)-1, NULL, 0)) != NULL) { + while ((buf = parse_common(fp, db, NULL, 0)) != NULL) { char **m; struct group group; - if (!convert_to_struct(&S.db[1], buf, &group)) + if (!convert_to_struct(db, buf, &group)) goto next; if (group.gr_gid == gid) goto next; From db4d1051ca5e9b4cc1fd2d1872194874f09e3b35 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 4 Jan 2015 02:34:52 +0100 Subject: [PATCH 018/256] libpwdgrp: another code shrink function old new delta massage_data_for_r_func - 110 +110 bb_internal_getpwent_r 173 100 -73 getXXnam_r 176 95 -81 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/2 up/down: 110/-154) Total: -44 bytes Signed-off-by: Denys Vlasenko --- libpwdgrp/pwd_grp.c | 69 ++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 38 deletions(-) diff --git a/libpwdgrp/pwd_grp.c b/libpwdgrp/pwd_grp.c index 0fd458fdc..3b96cc4d6 100644 --- a/libpwdgrp/pwd_grp.c +++ b/libpwdgrp/pwd_grp.c @@ -316,27 +316,19 @@ static void *convert_to_struct(struct passdb *db, return result; } -/****** getXXnam/id_r */ - -static int FAST_FUNC getXXnam_r(const char *name, uintptr_t db_and_field_pos, +static int massage_data_for_r_func(struct passdb *db, char *buffer, size_t buflen, - void *result) + void **result, + char *buf) { - void *struct_buf = *(void**)result; - char *buf; - struct passdb *db = &get_S()->db[db_and_field_pos >> 2]; - - *(void**)result = NULL; - buf = parse_file(db, name, 0 /*db_and_field_pos & 3*/); - /* "db_and_field_pos & 3" is commented out since so far we don't implement - * getXXXid_r() functions which would use that to pass 2 here */ + void *result_buf = *result; + *result = NULL; if (buf) { - size_t size = S.tokenize_end - buf; - if (size > buflen) { + if (S.string_size > buflen) { errno = ERANGE; } else { - memcpy(buffer, buf, size); - *(void**)result = convert_to_struct(db, buffer, struct_buf); + memcpy(buffer, buf, S.string_size); + *result = convert_to_struct(db, buffer, result_buf); } free(buf); } @@ -347,6 +339,22 @@ static int FAST_FUNC getXXnam_r(const char *name, uintptr_t db_and_field_pos, return errno; } +/****** getXXnam/id_r */ + +static int FAST_FUNC getXXnam_r(const char *name, uintptr_t db_and_field_pos, + char *buffer, size_t buflen, + void *result) +{ + char *buf; + struct passdb *db = &get_S()->db[db_and_field_pos >> 2]; + + buf = parse_file(db, name, 0 /*db_and_field_pos & 3*/); + /* "db_and_field_pos & 3" is commented out since so far we don't implement + * getXXXid_r() functions which would use that to pass 2 here */ + + return massage_data_for_r_func(db, buffer, buflen, result, buf); +} + int FAST_FUNC getpwnam_r(const char *name, struct passwd *struct_buf, char *buffer, size_t buflen, struct passwd **result) @@ -369,15 +377,12 @@ int FAST_FUNC getspnam_r(const char *name, struct spwd *struct_buf, char *buffer /****** getXXent_r */ -static int FAST_FUNC getXXent_r(void *struct_buf, char *buffer, size_t buflen, - void *result, - unsigned db_idx) +static int FAST_FUNC getXXent_r(uintptr_t db_idx, char *buffer, size_t buflen, + void *result) { char *buf; struct passdb *db = &get_S()->db[db_idx]; - *(void**)result = NULL; - if (!db->fp) { db->fp = fopen_for_read(db->filename); if (!db->fp) { @@ -387,26 +392,14 @@ static int FAST_FUNC getXXent_r(void *struct_buf, char *buffer, size_t buflen, } buf = parse_common(db->fp, db, /*no search key:*/ NULL, 0); - if (buf) { - size_t size = S.tokenize_end - buf; - if (size > buflen) { - errno = ERANGE; - } else { - memcpy(buffer, buf, size); - *(void**)result = convert_to_struct(db, buffer, struct_buf); - } - free(buf); - } - /* "The reentrant functions return zero on success. - * In case of error, an error number is returned." - * NB: not finding the record is also a "success" here: - */ - return errno; + return massage_data_for_r_func(db, buffer, buflen, result, buf); } -int FAST_FUNC getpwent_r(struct passwd *struct_buf, char *buffer, size_t buflen, struct passwd **result) +int FAST_FUNC getpwent_r(struct passwd *struct_buf, char *buffer, size_t buflen, + struct passwd **result) { - return getXXent_r(struct_buf, buffer, buflen, result, 0); + *result = struct_buf; + return getXXent_r(0, buffer, buflen, result); } /****** getXXnam/id */ From 4bf88d9094fd208672ba48c809cbcc2753a7d726 Mon Sep 17 00:00:00 2001 From: Adam Tkac Date: Sun, 4 Jan 2015 17:46:08 +0100 Subject: [PATCH 019/256] ntpd: relicense ntpd applet to ISC-style license OpenNTPd is licensed under ISC-style license so it's good idea to keep ntpd applet under same license to avoid mess, instead of having our changes to be under GPL. Names of original code's authors are added. Signed-off-by: Adam Tkac Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 51 +++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index 2d4f076d9..33cb1dcb1 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -1,30 +1,43 @@ /* * NTP client/server, based on OpenNTPD 3.9p1 * - * Author: Adam Tkac + * Busybox port author: Adam Tkac (C) 2009 * - * Licensed under GPLv2, see file LICENSE in this source tree. + * OpenNTPd 3.9p1 copyright holders: + * Copyright (c) 2003, 2004 Henning Brauer + * Copyright (c) 2004 Alexander Guy + * + * OpenNTPd code is licensed under ISC-style licence: + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *********************************************************************** * * Parts of OpenNTPD clock syncronization code is replaced by - * code which is based on ntp-4.2.6, whuch carries the following + * code which is based on ntp-4.2.6, which carries the following * copyright notice: * - *********************************************************************** - * * - * Copyright (c) University of Delaware 1992-2009 * - * * - * Permission to use, copy, modify, and distribute this software and * - * its documentation for any purpose with or without fee is hereby * - * granted, provided that the above copyright notice appears in all * - * copies and that both the copyright notice and this permission * - * notice appear in supporting documentation, and that the name * - * University of Delaware not be used in advertising or publicity * - * pertaining to distribution of the software without specific, * - * written prior permission. The University of Delaware makes no * - * representations about the suitability this software for any * - * purpose. It is provided "as is" without express or implied * - * warranty. * - * * + * Copyright (c) University of Delaware 1992-2009 + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose with or without fee is hereby + * granted, provided that the above copyright notice appears in all + * copies and that both the copyright notice and this permission + * notice appear in supporting documentation, and that the name + * University of Delaware not be used in advertising or publicity + * pertaining to distribution of the software without specific, + * written prior permission. The University of Delaware makes no + * representations about the suitability this software for any + * purpose. It is provided "as is" without express or implied warranty. *********************************************************************** */ From c5d4a04e450b961e354e985058bd69a0f7b7bc2d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 5 Jan 2015 15:09:04 +0100 Subject: [PATCH 020/256] libpwdgrp: fixes suggested by Tito, comment tweaks function old new delta bb_internal_getpwent_r 100 121 +21 parse_common 202 203 +1 Signed-off-by: Denys Vlasenko --- libpwdgrp/pwd_grp.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/libpwdgrp/pwd_grp.c b/libpwdgrp/pwd_grp.c index 3b96cc4d6..524acfeab 100644 --- a/libpwdgrp/pwd_grp.c +++ b/libpwdgrp/pwd_grp.c @@ -9,13 +9,13 @@ * Rewrite of some parts. Main differences are: * * 1) the buffer for getpwuid, getgrgid, getpwnam, getgrnam is dynamically - * allocated and reused by later calls. + * allocated. * If ENABLE_FEATURE_CLEAN_UP is set the buffers are freed at program * exit using the atexit function to make valgrind happy. * 2) the passwd/group files: * a) must contain the expected number of fields (as per count of field * delimeters ":") or we will complain with a error message. - * b) leading or trailing whitespace in fields is stripped. + * b) leading and trailing whitespace in fields is stripped. * c) some fields are not allowed to be empty (e.g. username, uid/gid, * homedir, shell) and in this case NULL is returned and errno is * set to EINVAL. This behaviour could be easily changed by @@ -23,7 +23,7 @@ * makes a field mandatory). * d) the string representing uid/gid must be convertible by strtoXX * functions, or errno is set to EINVAL. - * e) leading or trailing whitespace in group member names are stripped. + * e) leading and trailing whitespace in group member names is stripped. * 3) the internal function for getgrouplist uses dynamically allocated buffer. * 4) at the moment only the functions really used by busybox code are * implemented, if you need a particular missing function it should be @@ -34,15 +34,15 @@ struct const_passdb { const char *filename; - const char def[7 + 2*ENABLE_USE_BB_SHADOW]; - const uint8_t off[7 + 2*ENABLE_USE_BB_SHADOW]; + char def[7 + 2*ENABLE_USE_BB_SHADOW]; + uint8_t off[7 + 2*ENABLE_USE_BB_SHADOW]; uint8_t numfields; uint8_t size_of; }; struct passdb { const char *filename; - const char def[7 + 2*ENABLE_USE_BB_SHADOW]; - const uint8_t off[7 + 2*ENABLE_USE_BB_SHADOW]; + char def[7 + 2*ENABLE_USE_BB_SHADOW]; + uint8_t off[7 + 2*ENABLE_USE_BB_SHADOW]; uint8_t numfields; uint8_t size_of; FILE *fp; @@ -105,7 +105,7 @@ static const struct const_passdb const_sp_db = { /* We avoid having big global data. */ struct statics { - /* It's ok to use same buffer (db[0].malloced) for getpwuid and getpwnam. + /* We use same buffer (db[0].malloced) for getpwuid and getpwnam. * Manpage says: * "The return value may point to a static area, and may be overwritten * by subsequent calls to getpwent(), getpwnam(), or getpwuid()." @@ -203,7 +203,7 @@ static char *parse_common(FILE *fp, struct passdb *db, goto free_and_next; } - if (!key) { + if (field_pos == -1) { /* no key specified: sequential read, return a record */ break; } @@ -292,7 +292,6 @@ static void *convert_to_struct(struct passdb *db, ( ((intptr_t)S.tokenize_end + sizeof(members[0])) & -(intptr_t)sizeof(members[0]) ); - ((struct group *)result)->gr_mem = members; while (--i >= 0) { if (buffer[0]) { @@ -391,7 +390,9 @@ static int FAST_FUNC getXXent_r(uintptr_t db_idx, char *buffer, size_t buflen, close_on_exec_on(fileno(db->fp)); } - buf = parse_common(db->fp, db, /*no search key:*/ NULL, 0); + buf = parse_common(db->fp, db, /*no search key:*/ NULL, -1); + if (!buf && !errno) + errno = ENOENT; return massage_data_for_r_func(db, buffer, buflen, result, buf); } @@ -493,7 +494,7 @@ static gid_t* FAST_FUNC getgrouplist_internal(int *ngroups_ptr, if (fp) { struct passdb *db = &get_S()->db[1]; char *buf; - while ((buf = parse_common(fp, db, NULL, 0)) != NULL) { + while ((buf = parse_common(fp, db, NULL, -1)) != NULL) { char **m; struct group group; if (!convert_to_struct(db, buf, &group)) @@ -505,7 +506,7 @@ static gid_t* FAST_FUNC getgrouplist_internal(int *ngroups_ptr, continue; group_list = xrealloc_vector(group_list, /*8=2^3:*/ 3, ngroups); group_list[ngroups++] = group.gr_gid; - break; + goto next; } next: free(buf); From 08b90a9d10f2f712c6e16c118328d85930762b92 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 5 Jan 2015 15:12:37 +0100 Subject: [PATCH 021/256] deleting unused ntpd_simple.c Signed-off-by: Denys Vlasenko --- networking/ntpd_simple.c | 1005 -------------------------------------- 1 file changed, 1005 deletions(-) delete mode 100644 networking/ntpd_simple.c diff --git a/networking/ntpd_simple.c b/networking/ntpd_simple.c deleted file mode 100644 index 2cfbd55d4..000000000 --- a/networking/ntpd_simple.c +++ /dev/null @@ -1,1005 +0,0 @@ -/* - * NTP client/server, based on OpenNTPD 3.9p1 - * - * Author: Adam Tkac - * - * Licensed under GPLv2, see file LICENSE in this source tree. - */ -#include "libbb.h" -#include /* For IPTOS_LOWDELAY definition */ -#include /* setpriority */ -#ifndef IPTOS_LOWDELAY -# define IPTOS_LOWDELAY 0x10 -#endif - - -/* Sync to peers every N secs */ -#define INTERVAL_QUERY_NORMAL 30 -#define INTERVAL_QUERY_PATHETIC 60 -#define INTERVAL_QUERY_AGRESSIVE 5 - -/* Bad if *less than* TRUSTLEVEL_BADPEER */ -#define TRUSTLEVEL_BADPEER 6 -#define TRUSTLEVEL_PATHETIC 2 -#define TRUSTLEVEL_AGRESSIVE 8 -#define TRUSTLEVEL_MAX 10 - -#define QSCALE_OFF_MIN 0.05 -#define QSCALE_OFF_MAX 0.50 - -/* Single query might take N secs max */ -#define QUERYTIME_MAX 15 -/* Min offset for settime at start. "man ntpd" says it's 128 ms */ -#define STEPTIME_MIN_OFFSET 0.128 - -typedef struct { - uint32_t int_partl; - uint32_t fractionl; -} l_fixedpt_t; - -typedef struct { - uint16_t int_parts; - uint16_t fractions; -} s_fixedpt_t; - -enum { - NTP_DIGESTSIZE = 16, - NTP_MSGSIZE_NOAUTH = 48, - NTP_MSGSIZE = (NTP_MSGSIZE_NOAUTH + 4 + NTP_DIGESTSIZE), -}; - -typedef struct { - uint8_t m_status; /* status of local clock and leap info */ - uint8_t m_stratum; /* stratum level */ - uint8_t m_ppoll; /* poll value */ - int8_t m_precision_exp; - s_fixedpt_t m_rootdelay; - s_fixedpt_t m_dispersion; - uint32_t m_refid; - l_fixedpt_t m_reftime; - l_fixedpt_t m_orgtime; - l_fixedpt_t m_rectime; - l_fixedpt_t m_xmttime; - uint32_t m_keyid; - uint8_t m_digest[NTP_DIGESTSIZE]; -} msg_t; - -enum { - NTP_VERSION = 4, - NTP_MAXSTRATUM = 15, - - /* Status Masks */ - MODE_MASK = (7 << 0), - VERSION_MASK = (7 << 3), - VERSION_SHIFT = 3, - LI_MASK = (3 << 6), - - /* Leap Second Codes (high order two bits of m_status) */ - LI_NOWARNING = (0 << 6), /* no warning */ - LI_PLUSSEC = (1 << 6), /* add a second (61 seconds) */ - LI_MINUSSEC = (2 << 6), /* minus a second (59 seconds) */ - LI_ALARM = (3 << 6), /* alarm condition */ - - /* Mode values */ - MODE_RES0 = 0, /* reserved */ - MODE_SYM_ACT = 1, /* symmetric active */ - MODE_SYM_PAS = 2, /* symmetric passive */ - MODE_CLIENT = 3, /* client */ - MODE_SERVER = 4, /* server */ - MODE_BROADCAST = 5, /* broadcast */ - MODE_RES1 = 6, /* reserved for NTP control message */ - MODE_RES2 = 7, /* reserved for private use */ -}; - -#define OFFSET_1900_1970 2208988800UL /* 1970 - 1900 in seconds */ - -typedef struct { - double d_offset; - double d_delay; - //UNUSED: double d_error; - time_t d_rcv_time; - uint32_t d_refid4; - uint8_t d_leap; - uint8_t d_stratum; - uint8_t d_good; -} datapoint_t; - -#define NUM_DATAPOINTS 8 -typedef struct { - len_and_sockaddr *p_lsa; - char *p_dotted; - /* When to send new query (if p_fd == -1) - * or when receive times out (if p_fd >= 0): */ - time_t next_action_time; - int p_fd; - uint8_t p_datapoint_idx; - uint8_t p_trustlevel; - double p_xmttime; - datapoint_t update; - datapoint_t p_datapoint[NUM_DATAPOINTS]; - msg_t p_xmt_msg; -} peer_t; - -enum { - OPT_n = (1 << 0), - OPT_q = (1 << 1), - OPT_N = (1 << 2), - OPT_x = (1 << 3), - /* Insert new options above this line. */ - /* Non-compat options: */ - OPT_p = (1 << 4), - OPT_l = (1 << 5) * ENABLE_FEATURE_NTPD_SERVER, -}; - - -struct globals { - /* total round trip delay to currently selected reference clock */ - double rootdelay; - /* reference timestamp: time when the system clock was last set or corrected */ - double reftime; - llist_t *ntp_peers; -#if ENABLE_FEATURE_NTPD_SERVER - int listen_fd; -#endif - unsigned verbose; - unsigned peer_cnt; - unsigned scale; - uint32_t refid; - uint32_t refid4; - uint8_t synced; - uint8_t leap; -#define G_precision_exp -6 -// int8_t precision_exp; - uint8_t stratum; - uint8_t time_was_stepped; - uint8_t first_adj_done; -}; -#define G (*ptr_to_globals) - -static const int const_IPTOS_LOWDELAY = IPTOS_LOWDELAY; - - -static void -set_next(peer_t *p, unsigned t) -{ - p->next_action_time = time(NULL) + t; -} - -static void -add_peers(char *s) -{ - peer_t *p; - - p = xzalloc(sizeof(*p)); - p->p_lsa = xhost2sockaddr(s, 123); - p->p_dotted = xmalloc_sockaddr2dotted_noport(&p->p_lsa->u.sa); - p->p_fd = -1; - p->p_xmt_msg.m_status = MODE_CLIENT | (NTP_VERSION << 3); - p->p_trustlevel = TRUSTLEVEL_PATHETIC; - p->next_action_time = time(NULL); /* = set_next(p, 0); */ - - llist_add_to(&G.ntp_peers, p); - G.peer_cnt++; -} - -static double -gettime1900d(void) -{ - struct timeval tv; - gettimeofday(&tv, NULL); /* never fails */ - return (tv.tv_sec + 1.0e-6 * tv.tv_usec + OFFSET_1900_1970); -} - -static void -d_to_tv(double d, struct timeval *tv) -{ - tv->tv_sec = (long)d; - tv->tv_usec = (d - tv->tv_sec) * 1000000; -} - -static double -lfp_to_d(l_fixedpt_t lfp) -{ - double ret; - lfp.int_partl = ntohl(lfp.int_partl); - lfp.fractionl = ntohl(lfp.fractionl); - ret = (double)lfp.int_partl + ((double)lfp.fractionl / UINT_MAX); - return ret; -} - -#if 0 //UNUSED -static double -sfp_to_d(s_fixedpt_t sfp) -{ - double ret; - sfp.int_parts = ntohs(sfp.int_parts); - sfp.fractions = ntohs(sfp.fractions); - ret = (double)sfp.int_parts + ((double)sfp.fractions / USHRT_MAX); - return ret; -} -#endif - -#if ENABLE_FEATURE_NTPD_SERVER -static l_fixedpt_t -d_to_lfp(double d) -{ - l_fixedpt_t lfp; - lfp.int_partl = (uint32_t)d; - lfp.fractionl = (uint32_t)((d - lfp.int_partl) * UINT_MAX); - lfp.int_partl = htonl(lfp.int_partl); - lfp.fractionl = htonl(lfp.fractionl); - return lfp; -} - -static s_fixedpt_t -d_to_sfp(double d) -{ - s_fixedpt_t sfp; - sfp.int_parts = (uint16_t)d; - sfp.fractions = (uint16_t)((d - sfp.int_parts) * USHRT_MAX); - sfp.int_parts = htons(sfp.int_parts); - sfp.fractions = htons(sfp.fractions); - return sfp; -} -#endif - -static unsigned -error_interval(void) -{ - unsigned interval, r; - interval = INTERVAL_QUERY_PATHETIC * QSCALE_OFF_MAX / QSCALE_OFF_MIN; - r = (unsigned)rand() % (unsigned)(interval / 10); - return (interval + r); -} - -static int -do_sendto(int fd, - const struct sockaddr *from, const struct sockaddr *to, socklen_t addrlen, - msg_t *msg, ssize_t len) -{ - ssize_t ret; - - errno = 0; - if (!from) { - ret = sendto(fd, msg, len, MSG_DONTWAIT, to, addrlen); - } else { - ret = send_to_from(fd, msg, len, MSG_DONTWAIT, to, from, addrlen); - } - if (ret != len) { - bb_perror_msg("send failed"); - return -1; - } - return 0; -} - -static int -send_query_to_peer(peer_t *p) -{ - // Why do we need to bind()? - // See what happens when we don't bind: - // - // socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 3 - // setsockopt(3, SOL_IP, IP_TOS, [16], 4) = 0 - // gettimeofday({1259071266, 327885}, NULL) = 0 - // sendto(3, "xxx", 48, MSG_DONTWAIT, {sa_family=AF_INET, sin_port=htons(123), sin_addr=inet_addr("10.34.32.125")}, 16) = 48 - // ^^^ we sent it from some source port picked by kernel. - // time(NULL) = 1259071266 - // write(2, "ntpd: entering poll 15 secs\n", 28) = 28 - // poll([{fd=3, events=POLLIN}], 1, 15000) = 1 ([{fd=3, revents=POLLIN}]) - // recv(3, "yyy", 68, MSG_DONTWAIT) = 48 - // ^^^ this recv will receive packets to any local port! - // - // Uncomment this and use strace to see it in action: -#define PROBE_LOCAL_ADDR // { len_and_sockaddr lsa; lsa.len = LSA_SIZEOF_SA; getsockname(p->query.fd, &lsa.u.sa, &lsa.len); } - - if (p->p_fd == -1) { - int fd, family; - len_and_sockaddr *local_lsa; - - family = p->p_lsa->u.sa.sa_family; - p->p_fd = fd = xsocket_type(&local_lsa, family, SOCK_DGRAM); - /* local_lsa has "null" address and port 0 now. - * bind() ensures we have a *particular port* selected by kernel - * and remembered in p->p_fd, thus later recv(p->p_fd) - * receives only packets sent to this port. - */ - PROBE_LOCAL_ADDR - xbind(fd, &local_lsa->u.sa, local_lsa->len); - PROBE_LOCAL_ADDR -#if ENABLE_FEATURE_IPV6 - if (family == AF_INET) -#endif - setsockopt(fd, IPPROTO_IP, IP_TOS, &const_IPTOS_LOWDELAY, sizeof(const_IPTOS_LOWDELAY)); - free(local_lsa); - } - - /* - * Send out a random 64-bit number as our transmit time. The NTP - * server will copy said number into the originate field on the - * response that it sends us. This is totally legal per the SNTP spec. - * - * The impact of this is two fold: we no longer send out the current - * system time for the world to see (which may aid an attacker), and - * it gives us a (not very secure) way of knowing that we're not - * getting spoofed by an attacker that can't capture our traffic - * but can spoof packets from the NTP server we're communicating with. - * - * Save the real transmit timestamp locally. - */ - p->p_xmt_msg.m_xmttime.int_partl = rand(); - p->p_xmt_msg.m_xmttime.fractionl = rand(); - p->p_xmttime = gettime1900d(); - - if (do_sendto(p->p_fd, /*from:*/ NULL, /*to:*/ &p->p_lsa->u.sa, /*addrlen:*/ p->p_lsa->len, - &p->p_xmt_msg, NTP_MSGSIZE_NOAUTH) == -1 - ) { - close(p->p_fd); - p->p_fd = -1; - set_next(p, INTERVAL_QUERY_PATHETIC); - return -1; - } - - if (G.verbose) - bb_error_msg("sent query to %s", p->p_dotted); - set_next(p, QUERYTIME_MAX); - - return 0; -} - - -/* Time is stepped only once, when the first packet from a peer is received. - */ -static void -step_time_once(double offset) -{ - double dtime; - llist_t *item; - struct timeval tv; - char buf[80]; - time_t tval; - - if (G.time_was_stepped) - goto bail; - G.time_was_stepped = 1; - - /* if the offset is small, don't step, slew (later) */ - if (offset < STEPTIME_MIN_OFFSET && offset > -STEPTIME_MIN_OFFSET) - goto bail; - - gettimeofday(&tv, NULL); /* never fails */ - dtime = offset + tv.tv_sec; - dtime += 1.0e-6 * tv.tv_usec; - d_to_tv(dtime, &tv); - - if (settimeofday(&tv, NULL) == -1) - bb_perror_msg_and_die("settimeofday"); - - tval = tv.tv_sec; - strftime_YYYYMMDDHHMMSS(buf, sizeof(buf), &tval); - - bb_error_msg("setting clock to %s (offset %fs)", buf, offset); - - for (item = G.ntp_peers; item != NULL; item = item->link) { - peer_t *p = (peer_t *) item->data; - p->next_action_time -= (time_t)offset; - } - - bail: - if (option_mask32 & OPT_q) - exit(0); -} - - -/* Time is periodically slewed when we collect enough - * good data points. - */ -static int -compare_offsets(const void *aa, const void *bb) -{ - const peer_t *const *a = aa; - const peer_t *const *b = bb; - if ((*a)->update.d_offset < (*b)->update.d_offset) - return -1; - return ((*a)->update.d_offset > (*b)->update.d_offset); -} -static unsigned -updated_scale(double offset) -{ - if (offset < 0) - offset = -offset; - if (offset > QSCALE_OFF_MAX) - return 1; - if (offset < QSCALE_OFF_MIN) - return QSCALE_OFF_MAX / QSCALE_OFF_MIN; - return QSCALE_OFF_MAX / offset; -} -static void -slew_time(void) -{ - llist_t *item; - double offset_median; - struct timeval tv; - - { - peer_t **peers = xzalloc(sizeof(peers[0]) * G.peer_cnt); - unsigned goodpeer_cnt = 0; - unsigned middle; - - for (item = G.ntp_peers; item != NULL; item = item->link) { - peer_t *p = (peer_t *) item->data; - if (p->p_trustlevel < TRUSTLEVEL_BADPEER) - continue; - if (!p->update.d_good) { - free(peers); - return; - } - peers[goodpeer_cnt++] = p; - } - - if (goodpeer_cnt == 0) { - free(peers); - goto clear_good; - } - - qsort(peers, goodpeer_cnt, sizeof(peers[0]), compare_offsets); - - middle = goodpeer_cnt / 2; - if (middle != 0 && (goodpeer_cnt & 1) == 0) { - offset_median = (peers[middle-1]->update.d_offset + peers[middle]->update.d_offset) / 2; - G.rootdelay = (peers[middle-1]->update.d_delay + peers[middle]->update.d_delay) / 2; - G.stratum = 1 + MAX(peers[middle-1]->update.d_stratum, peers[middle]->update.d_stratum); - } else { - offset_median = peers[middle]->update.d_offset; - G.rootdelay = peers[middle]->update.d_delay; - G.stratum = 1 + peers[middle]->update.d_stratum; - } - G.leap = peers[middle]->update.d_leap; - G.refid4 = peers[middle]->update.d_refid4; - G.refid = -#if ENABLE_FEATURE_IPV6 - peers[middle]->p_lsa->u.sa.sa_family != AF_INET ? - G.refid4 : -#endif - peers[middle]->p_lsa->u.sin.sin_addr.s_addr; - free(peers); - } -//TODO: if (offset_median > BIG) step_time(offset_median)? - - G.scale = updated_scale(offset_median); - - bb_error_msg("adjusting clock by %fs, our stratum is %u, time scale %u", - offset_median, G.stratum, G.scale); - - errno = 0; - d_to_tv(offset_median, &tv); - if (adjtime(&tv, &tv) == -1) - bb_perror_msg_and_die("adjtime failed"); - if (G.verbose >= 2) - bb_error_msg("old adjust: %d.%06u", (int)tv.tv_sec, (unsigned)tv.tv_usec); - - if (G.first_adj_done) { - uint8_t synced = (tv.tv_sec == 0 && tv.tv_usec == 0); - if (synced != G.synced) { - G.synced = synced; - bb_error_msg("clock is %ssynced", synced ? "" : "un"); - } - } - G.first_adj_done = 1; - - G.reftime = gettime1900d(); - - clear_good: - for (item = G.ntp_peers; item != NULL; item = item->link) { - peer_t *p = (peer_t *) item->data; - p->update.d_good = 0; - } -} - -static void -update_peer_data(peer_t *p) -{ - /* Clock filter. - * Find the datapoint with the lowest delay. - * Use that as the peer update. - * Invalidate it and all older ones. - */ - int i; - int best = -1; - int good = 0; - - for (i = 0; i < NUM_DATAPOINTS; i++) { - if (p->p_datapoint[i].d_good) { - good++; - if (best < 0 || p->p_datapoint[i].d_delay < p->p_datapoint[best].d_delay) - best = i; - } - } - - if (good < 8) //FIXME: was it meant to be NUM_DATAPOINTS, not 8? - return; - - p->update = p->p_datapoint[best]; /* struct copy */ - slew_time(); - - for (i = 0; i < NUM_DATAPOINTS; i++) - if (p->p_datapoint[i].d_rcv_time <= p->p_datapoint[best].d_rcv_time) - p->p_datapoint[i].d_good = 0; -} - -static unsigned -scale_interval(unsigned requested) -{ - unsigned interval, r; - interval = requested * G.scale; - r = (unsigned)rand() % (unsigned)(MAX(5, interval / 10)); - return (interval + r); -} -static void -recv_and_process_peer_pkt(peer_t *p) -{ - ssize_t size; - msg_t msg; - double T1, T2, T3, T4; - unsigned interval; - datapoint_t *datapoint; - - /* We can recvfrom here and check from.IP, but some multihomed - * ntp servers reply from their *other IP*. - * TODO: maybe we should check at least what we can: from.port == 123? - */ - size = recv(p->p_fd, &msg, sizeof(msg), MSG_DONTWAIT); - if (size == -1) { - bb_perror_msg("recv(%s) error", p->p_dotted); - if (errno == EHOSTUNREACH || errno == EHOSTDOWN - || errno == ENETUNREACH || errno == ENETDOWN - || errno == ECONNREFUSED || errno == EADDRNOTAVAIL - || errno == EAGAIN - ) { -//TODO: always do this? - set_next(p, error_interval()); - goto close_sock; - } - xfunc_die(); - } - - if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) { - bb_error_msg("malformed packet received from %s", p->p_dotted); - goto bail; - } - - if (msg.m_orgtime.int_partl != p->p_xmt_msg.m_xmttime.int_partl - || msg.m_orgtime.fractionl != p->p_xmt_msg.m_xmttime.fractionl - ) { - goto bail; - } - - if ((msg.m_status & LI_ALARM) == LI_ALARM - || msg.m_stratum == 0 - || msg.m_stratum > NTP_MAXSTRATUM - ) { -// TODO: stratum 0 responses may have commands in 32-bit m_refid field: -// "DENY", "RSTR" - peer does not like us at all -// "RATE" - peer is overloaded, reduce polling freq - interval = error_interval(); - bb_error_msg("reply from %s: not synced, next query in %us", p->p_dotted, interval); - goto close_sock; - } - - /* - * From RFC 2030 (with a correction to the delay math): - * - * Timestamp Name ID When Generated - * ------------------------------------------------------------ - * Originate Timestamp T1 time request sent by client - * Receive Timestamp T2 time request received by server - * Transmit Timestamp T3 time reply sent by server - * Destination Timestamp T4 time reply received by client - * - * The roundtrip delay and local clock offset are defined as - * - * delay = (T4 - T1) - (T3 - T2); offset = ((T2 - T1) + (T3 - T4)) / 2 - */ - T1 = p->p_xmttime; - T2 = lfp_to_d(msg.m_rectime); - T3 = lfp_to_d(msg.m_xmttime); - T4 = gettime1900d(); - - datapoint = &p->p_datapoint[p->p_datapoint_idx]; - - datapoint->d_offset = ((T2 - T1) + (T3 - T4)) / 2; - datapoint->d_delay = (T4 - T1) - (T3 - T2); - if (datapoint->d_delay < 0) { - bb_error_msg("reply from %s: negative delay %f", p->p_dotted, datapoint->d_delay); - interval = error_interval(); - set_next(p, interval); - goto close_sock; - } - //UNUSED: datapoint->d_error = (T2 - T1) - (T3 - T4); - datapoint->d_rcv_time = (time_t)(T4 - OFFSET_1900_1970); /* = time(NULL); */ - datapoint->d_good = 1; - - datapoint->d_leap = (msg.m_status & LI_MASK); - //UNUSED: datapoint->o_precision = msg.m_precision_exp; - //UNUSED: datapoint->o_rootdelay = sfp_to_d(msg.m_rootdelay); - //UNUSED: datapoint->o_rootdispersion = sfp_to_d(msg.m_dispersion); - //UNUSED: datapoint->d_refid = ntohl(msg.m_refid); - datapoint->d_refid4 = msg.m_xmttime.fractionl; - //UNUSED: datapoint->o_reftime = lfp_to_d(msg.m_reftime); - //UNUSED: datapoint->o_poll = msg.m_ppoll; - datapoint->d_stratum = msg.m_stratum; - - if (p->p_trustlevel < TRUSTLEVEL_PATHETIC) - interval = scale_interval(INTERVAL_QUERY_PATHETIC); - else if (p->p_trustlevel < TRUSTLEVEL_AGRESSIVE) - interval = scale_interval(INTERVAL_QUERY_AGRESSIVE); - else - interval = scale_interval(INTERVAL_QUERY_NORMAL); - - set_next(p, interval); - - /* Every received reply which we do not discard increases trust */ - if (p->p_trustlevel < TRUSTLEVEL_MAX) { - p->p_trustlevel++; - if (p->p_trustlevel == TRUSTLEVEL_BADPEER) - bb_error_msg("peer %s now valid", p->p_dotted); - } - - if (G.verbose) - bb_error_msg("reply from %s: offset %f delay %f, next query in %us", p->p_dotted, - datapoint->d_offset, datapoint->d_delay, interval); - - update_peer_data(p); -//TODO: do it after all peers had a chance to return at least one reply? - step_time_once(datapoint->d_offset); - - p->p_datapoint_idx++; - if (p->p_datapoint_idx >= NUM_DATAPOINTS) - p->p_datapoint_idx = 0; - - close_sock: - /* We do not expect any more packets from this peer for now. - * Closing the socket informs kernel about it. - * We open a new socket when we send a new query. - */ - close(p->p_fd); - p->p_fd = -1; - bail: - return; -} - -#if ENABLE_FEATURE_NTPD_SERVER -static void -recv_and_process_client_pkt(void /*int fd*/) -{ - ssize_t size; - uint8_t version; - double rectime; - len_and_sockaddr *to; - struct sockaddr *from; - msg_t msg; - uint8_t query_status; - uint8_t query_ppoll; - l_fixedpt_t query_xmttime; - - to = get_sock_lsa(G.listen_fd); - from = xzalloc(to->len); - - size = recv_from_to(G.listen_fd, &msg, sizeof(msg), MSG_DONTWAIT, from, &to->u.sa, to->len); - if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) { - char *addr; - if (size < 0) { - if (errno == EAGAIN) - goto bail; - bb_perror_msg_and_die("recv"); - } - addr = xmalloc_sockaddr2dotted_noport(from); - bb_error_msg("malformed packet received from %s: size %u", addr, (int)size); - free(addr); - goto bail; - } - - query_status = msg.m_status; - query_ppoll = msg.m_ppoll; - query_xmttime = msg.m_xmttime; - - /* Build a reply packet */ - memset(&msg, 0, sizeof(msg)); - msg.m_status = G.synced ? G.leap : LI_ALARM; - msg.m_status |= (query_status & VERSION_MASK); - msg.m_status |= ((query_status & MODE_MASK) == MODE_CLIENT) ? - MODE_SERVER : MODE_SYM_PAS; - msg.m_stratum = G.stratum; - msg.m_ppoll = query_ppoll; - msg.m_precision_exp = G_precision_exp; - rectime = gettime1900d(); - msg.m_xmttime = msg.m_rectime = d_to_lfp(rectime); - msg.m_reftime = d_to_lfp(G.reftime); - //msg.m_xmttime = d_to_lfp(gettime1900d()); // = msg.m_rectime - msg.m_orgtime = query_xmttime; - msg.m_rootdelay = d_to_sfp(G.rootdelay); - version = (query_status & VERSION_MASK); /* ... >> VERSION_SHIFT - done below instead */ - msg.m_refid = (version > (3 << VERSION_SHIFT)) ? G.refid4 : G.refid; - - /* We reply from the local address packet was sent to, - * this makes to/from look swapped here: */ - do_sendto(G.listen_fd, - /*from:*/ &to->u.sa, /*to:*/ from, /*addrlen:*/ to->len, - &msg, size); - - bail: - free(to); - free(from); -} -#endif - -/* Upstream ntpd's options: - * - * -4 Force DNS resolution of host names to the IPv4 namespace. - * -6 Force DNS resolution of host names to the IPv6 namespace. - * -a Require cryptographic authentication for broadcast client, - * multicast client and symmetric passive associations. - * This is the default. - * -A Do not require cryptographic authentication for broadcast client, - * multicast client and symmetric passive associations. - * This is almost never a good idea. - * -b Enable the client to synchronize to broadcast servers. - * -c conffile - * Specify the name and path of the configuration file, - * default /etc/ntp.conf - * -d Specify debugging mode. This option may occur more than once, - * with each occurrence indicating greater detail of display. - * -D level - * Specify debugging level directly. - * -f driftfile - * Specify the name and path of the frequency file. - * This is the same operation as the "driftfile FILE" - * configuration command. - * -g Normally, ntpd exits with a message to the system log - * if the offset exceeds the panic threshold, which is 1000 s - * by default. This option allows the time to be set to any value - * without restriction; however, this can happen only once. - * If the threshold is exceeded after that, ntpd will exit - * with a message to the system log. This option can be used - * with the -q and -x options. See the tinker command for other options. - * -i jaildir - * Chroot the server to the directory jaildir. This option also implies - * that the server attempts to drop root privileges at startup - * (otherwise, chroot gives very little additional security). - * You may need to also specify a -u option. - * -k keyfile - * Specify the name and path of the symmetric key file, - * default /etc/ntp/keys. This is the same operation - * as the "keys FILE" configuration command. - * -l logfile - * Specify the name and path of the log file. The default - * is the system log file. This is the same operation as - * the "logfile FILE" configuration command. - * -L Do not listen to virtual IPs. The default is to listen. - * -n Don't fork. - * -N To the extent permitted by the operating system, - * run the ntpd at the highest priority. - * -p pidfile - * Specify the name and path of the file used to record the ntpd - * process ID. This is the same operation as the "pidfile FILE" - * configuration command. - * -P priority - * To the extent permitted by the operating system, - * run the ntpd at the specified priority. - * -q Exit the ntpd just after the first time the clock is set. - * This behavior mimics that of the ntpdate program, which is - * to be retired. The -g and -x options can be used with this option. - * Note: The kernel time discipline is disabled with this option. - * -r broadcastdelay - * Specify the default propagation delay from the broadcast/multicast - * server to this client. This is necessary only if the delay - * cannot be computed automatically by the protocol. - * -s statsdir - * Specify the directory path for files created by the statistics - * facility. This is the same operation as the "statsdir DIR" - * configuration command. - * -t key - * Add a key number to the trusted key list. This option can occur - * more than once. - * -u user[:group] - * Specify a user, and optionally a group, to switch to. - * -v variable - * -V variable - * Add a system variable listed by default. - * -x Normally, the time is slewed if the offset is less than the step - * threshold, which is 128 ms by default, and stepped if above - * the threshold. This option sets the threshold to 600 s, which is - * well within the accuracy window to set the clock manually. - * Note: since the slew rate of typical Unix kernels is limited - * to 0.5 ms/s, each second of adjustment requires an amortization - * interval of 2000 s. Thus, an adjustment as much as 600 s - * will take almost 14 days to complete. This option can be used - * with the -g and -q options. See the tinker command for other options. - * Note: The kernel time discipline is disabled with this option. - */ - -/* By doing init in a separate function we decrease stack usage - * in main loop. - */ -static NOINLINE void ntp_init(char **argv) -{ - unsigned opts; - llist_t *peers; - - srand(getpid()); - - if (getuid()) - bb_error_msg_and_die(bb_msg_you_must_be_root); - - peers = NULL; - opt_complementary = "dd:p::"; /* d: counter, p: list */ - opts = getopt32(argv, - "nqNx" /* compat */ - "p:"IF_FEATURE_NTPD_SERVER("l") /* NOT compat */ - "d" /* compat */ - "46aAbgL", /* compat, ignored */ - &peers, &G.verbose); - if (!(opts & (OPT_p|OPT_l))) - bb_show_usage(); - if (opts & OPT_x) /* disable stepping, only slew is allowed */ - G.time_was_stepped = 1; - while (peers) - add_peers(llist_pop(&peers)); - if (!(opts & OPT_n)) { - bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO, argv); - logmode = LOGMODE_NONE; - } -#if ENABLE_FEATURE_NTPD_SERVER - G.listen_fd = -1; - if (opts & OPT_l) { - G.listen_fd = create_and_bind_dgram_or_die(NULL, 123); - socket_want_pktinfo(G.listen_fd); - setsockopt(G.listen_fd, IPPROTO_IP, IP_TOS, &const_IPTOS_LOWDELAY, sizeof(const_IPTOS_LOWDELAY)); - } -#endif - /* I hesitate to set -20 prio. -15 should be high enough for timekeeping */ - if (opts & OPT_N) - setpriority(PRIO_PROCESS, 0, -15); - - /* Set some globals */ -#if 0 - /* With constant b = 100, G.precision_exp is also constant -6. - * Uncomment this and you'll see */ - { - int prec = 0; - int b; -# if 0 - struct timespec tp; - /* We can use sys_clock_getres but assuming 10ms tick should be fine */ - clock_getres(CLOCK_REALTIME, &tp); - tp.tv_sec = 0; - tp.tv_nsec = 10000000; - b = 1000000000 / tp.tv_nsec; /* convert to Hz */ -# else - b = 100; /* b = 1000000000/10000000 = 100 */ -# endif - while (b > 1) - prec--, b >>= 1; - //G.precision_exp = prec; - bb_error_msg("G.precision_exp:%d", prec); /* -6 */ - } -#endif - G.scale = 1; - - bb_signals((1 << SIGTERM) | (1 << SIGINT), record_signo); - bb_signals((1 << SIGPIPE) | (1 << SIGHUP), SIG_IGN); -} - -int ntpd_main(int argc UNUSED_PARAM, char **argv) MAIN_EXTERNALLY_VISIBLE; -int ntpd_main(int argc UNUSED_PARAM, char **argv) -{ - struct globals g; - struct pollfd *pfd; - peer_t **idx2peer; - - memset(&g, 0, sizeof(g)); - SET_PTR_TO_GLOBALS(&g); - - ntp_init(argv); - - { - /* if ENABLE_FEATURE_NTPD_SERVER, + 1 for listen_fd: */ - unsigned cnt = g.peer_cnt + ENABLE_FEATURE_NTPD_SERVER; - idx2peer = xzalloc(sizeof(idx2peer[0]) * cnt); - pfd = xzalloc(sizeof(pfd[0]) * cnt); - } - - while (!bb_got_signal) { - llist_t *item; - unsigned i, j; - unsigned sent_cnt, trial_cnt; - int nfds, timeout; - time_t cur_time, nextaction; - - /* Nothing between here and poll() blocks for any significant time */ - - cur_time = time(NULL); - nextaction = cur_time + 3600; - - i = 0; -#if ENABLE_FEATURE_NTPD_SERVER - if (g.listen_fd != -1) { - pfd[0].fd = g.listen_fd; - pfd[0].events = POLLIN; - i++; - } -#endif - /* Pass over peer list, send requests, time out on receives */ - sent_cnt = trial_cnt = 0; - for (item = g.ntp_peers; item != NULL; item = item->link) { - peer_t *p = (peer_t *) item->data; - - /* Overflow-safe "if (p->next_action_time <= cur_time) ..." */ - if ((int)(cur_time - p->next_action_time) >= 0) { - if (p->p_fd == -1) { - /* Time to send new req */ - trial_cnt++; - if (send_query_to_peer(p) == 0) - sent_cnt++; - } else { - /* Timed out waiting for reply */ - close(p->p_fd); - p->p_fd = -1; - timeout = error_interval(); - bb_error_msg("timed out waiting for %s, " - "next query in %us", p->p_dotted, timeout); - if (p->p_trustlevel >= TRUSTLEVEL_BADPEER) { - p->p_trustlevel /= 2; - if (p->p_trustlevel < TRUSTLEVEL_BADPEER) - bb_error_msg("peer %s now invalid", p->p_dotted); - } - set_next(p, timeout); - } - } - - if (p->next_action_time < nextaction) - nextaction = p->next_action_time; - - if (p->p_fd >= 0) { - /* Wait for reply from this peer */ - pfd[i].fd = p->p_fd; - pfd[i].events = POLLIN; - idx2peer[i] = p; - i++; - } - } - - if ((trial_cnt > 0 && sent_cnt == 0) || g.peer_cnt == 0) - step_time_once(0); /* no good peers, don't wait */ - - timeout = nextaction - cur_time; - if (timeout < 1) - timeout = 1; - - /* Here we may block */ - if (g.verbose >= 2) - bb_error_msg("poll %us, sockets:%u", timeout, i); - nfds = poll(pfd, i, timeout * 1000); - if (nfds <= 0) - continue; - - /* Process any received packets */ - j = 0; -#if ENABLE_FEATURE_NTPD_SERVER - if (g.listen_fd != -1) { - if (pfd[0].revents /* & (POLLIN|POLLERR)*/) { - nfds--; - recv_and_process_client_pkt(/*g.listen_fd*/); - } - j = 1; - } -#endif - for (; nfds != 0 && j < i; j++) { - if (pfd[j].revents /* & (POLLIN|POLLERR)*/) { - nfds--; - recv_and_process_peer_pkt(idx2peer[j]); - } - } - } /* while (!bb_got_signal) */ - - kill_myself_with_sig(bb_got_signal); -} From da9212667c99f2f2121747c4715d067deb7c155b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 5 Jan 2015 15:37:58 +0100 Subject: [PATCH 022/256] libbb: code shrink by factoring out common update_utmp_DEAD_PROCESS function old new delta update_utmp_DEAD_PROCESS - 17 +17 telnetd_main 1685 1674 -11 mark_terminated 56 45 -11 handle_sigchld 74 63 -11 Signed-off-by: Denys Vlasenko --- include/libbb.h | 2 ++ init/init.c | 6 +----- libbb/utmp.c | 14 ++++++++++++++ loginutils/login.c | 2 +- networking/telnetd.c | 12 ++---------- 5 files changed, 20 insertions(+), 16 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index 68a7cf002..be792d6b2 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -921,9 +921,11 @@ void die_if_bad_username(const char* name) FAST_FUNC; #if ENABLE_FEATURE_UTMP void FAST_FUNC write_new_utmp(pid_t pid, int new_type, const char *tty_name, const char *username, const char *hostname); void FAST_FUNC update_utmp(pid_t pid, int new_type, const char *tty_name, const char *username, const char *hostname); +void FAST_FUNC update_utmp_DEAD_PROCESS(pid_t pid); #else # define write_new_utmp(pid, new_type, tty_name, username, hostname) ((void)0) # define update_utmp(pid, new_type, tty_name, username, hostname) ((void)0) +# define update_utmp_DEAD_PROCESS(pid) ((void)0) #endif diff --git a/init/init.c b/init/init.c index d99d68ce4..b2fe85635 100644 --- a/init/init.c +++ b/init/init.c @@ -538,11 +538,7 @@ static struct init_action *mark_terminated(pid_t pid) struct init_action *a; if (pid > 0) { - update_utmp(pid, DEAD_PROCESS, - /*tty_name:*/ NULL, - /*username:*/ NULL, - /*hostname:*/ NULL - ); + update_utmp_DEAD_PROCESS(pid); for (a = init_action_list; a; a = a->next) { if (a->pid == pid) { a->pid = 0; diff --git a/libbb/utmp.c b/libbb/utmp.c index 09443fb6c..8ad9ba27e 100644 --- a/libbb/utmp.c +++ b/libbb/utmp.c @@ -130,3 +130,17 @@ void FAST_FUNC update_utmp(pid_t pid, int new_type, const char *tty_name, const updwtmp(bb_path_wtmp_file, &utent); #endif } + +/* man utmp: + * When init(8) finds that a process has exited, it locates its utmp entry + * by ut_pid, sets ut_type to DEAD_PROCESS, and clears ut_user, ut_host + * and ut_time with null bytes. + * [same applies to other processes which maintain utmp entries, like telnetd] + * + * We do not bother actually clearing fields: + * it might be interesting to know who was logged in and from where + */ +void FAST_FUNC update_utmp_DEAD_PROCESS(pid_t pid) +{ + update_utmp(pid, DEAD_PROCESS, NULL, NULL, NULL); +} diff --git a/loginutils/login.c b/loginutils/login.c index a4b19ccfc..b9d910331 100644 --- a/loginutils/login.c +++ b/loginutils/login.c @@ -454,7 +454,7 @@ int login_main(int argc UNUSED_PARAM, char **argv) else { if (safe_waitpid(child_pid, NULL, 0) == -1) bb_perror_msg("waitpid"); - update_utmp(child_pid, DEAD_PROCESS, NULL, NULL, NULL); + update_utmp_DEAD_PROCESS(child_pid); } IF_PAM(login_pam_end(pamh);) return 0; diff --git a/networking/telnetd.c b/networking/telnetd.c index 9e7a84cce..6aee95871 100644 --- a/networking/telnetd.c +++ b/networking/telnetd.c @@ -462,15 +462,7 @@ static void handle_sigchld(int sig UNUSED_PARAM) while (ts) { if (ts->shell_pid == pid) { ts->shell_pid = -1; -// man utmp: -// When init(8) finds that a process has exited, it locates its utmp entry -// by ut_pid, sets ut_type to DEAD_PROCESS, and clears ut_user, ut_host -// and ut_time with null bytes. -// [same applies to other processes which maintain utmp entries, like telnetd] -// -// We do not bother actually clearing fields: -// it might be interesting to know who was logged in and from where - update_utmp(pid, DEAD_PROCESS, /*tty_name:*/ NULL, /*username:*/ NULL, /*hostname:*/ NULL); + update_utmp_DEAD_PROCESS(pid); break; } ts = ts->next; @@ -739,7 +731,7 @@ int telnetd_main(int argc UNUSED_PARAM, char **argv) continue; kill_session: if (ts->shell_pid > 0) - update_utmp(ts->shell_pid, DEAD_PROCESS, /*tty_name:*/ NULL, /*username:*/ NULL, /*hostname:*/ NULL); + update_utmp_DEAD_PROCESS(ts->shell_pid); free_session(ts); ts = next; } From 75a1403f266098bc4a498140473e1007075f459d Mon Sep 17 00:00:00 2001 From: Guillermo Rodriguez Date: Mon, 5 Jan 2015 18:34:53 +0100 Subject: [PATCH 023/256] free: handle "cached" value too function old new delta free_main 356 481 +125 Signed-off-by: Guillermo Rodriguez Signed-off-by: Denys Vlasenko --- procps/free.c | 77 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 31 deletions(-) diff --git a/procps/free.c b/procps/free.c index 47f2fc3b2..0d023f740 100644 --- a/procps/free.c +++ b/procps/free.c @@ -44,11 +44,28 @@ static unsigned long long scale(unsigned long d) return ((unsigned long long)d * G.mem_unit) >> G_unit_steps; } +static unsigned long parse_cached_kb(void) +{ + char buf[60]; /* actual lines we expect are ~30 chars or less */ + FILE *fp; + unsigned long cached = 0; + + fp = xfopen_for_read("/proc/meminfo"); + while (fgets(buf, sizeof(buf), fp) != NULL) { + if (sscanf(buf, "Cached: %lu %*s\n", &cached) == 1) + break; + } + if (ENABLE_FEATURE_CLEAN_UP) + fclose(fp); + + return cached; +} int free_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) { struct sysinfo info; + unsigned long long cached; INIT_G(); @@ -73,49 +90,47 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) } } #endif - - sysinfo(&info); - - /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */ - G.mem_unit = (info.mem_unit ? info.mem_unit : 1); - - printf(" %13s%13s%13s%13s%13s\n", + printf(" %11s%11s%11s%11s%11s%11s\n" + "Mem: ", "total", "used", "free", - "shared", "buffers" /* swap and total don't have these columns */ - /* procps version 3.2.8 also shows "cached" column, but - * sysinfo() does not provide this value, need to parse - * /proc/meminfo instead and get "Cached: NNN kB" from there. - */ + "shared", "buffers", "cached" /* swap and total don't have these columns */ ); -#define FIELDS_5 "%13llu%13llu%13llu%13llu%13llu\n" -#define FIELDS_3 (FIELDS_5 + 2*6) -#define FIELDS_2 (FIELDS_5 + 3*6) + sysinfo(&info); + /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */ + G.mem_unit = (info.mem_unit ? info.mem_unit : 1); + /* Extract cached from /proc/meminfo and convert to mem_units */ + cached = ((unsigned long long) parse_cached_kb() * 1024) / G.mem_unit; - printf("Mem: "); - printf(FIELDS_5, - scale(info.totalram), - scale(info.totalram - info.freeram), - scale(info.freeram), - scale(info.sharedram), - scale(info.bufferram) +#define FIELDS_6 "%11llu%11llu%11llu%11llu%11llu%11llu\n" +#define FIELDS_3 (FIELDS_6 + 3*6) +#define FIELDS_2 (FIELDS_6 + 4*6) + + printf(FIELDS_6, + scale(info.totalram), //total + scale(info.totalram - info.freeram), //used + scale(info.freeram), //free + scale(info.sharedram), //shared + scale(info.bufferram), //buffers + scale(cached) //cached ); /* Show alternate, more meaningful busy/free numbers by counting - * buffer cache as free memory (make it "-/+ buffers/cache" - * if/when we add support for "cached" column): */ - printf("-/+ buffers: "); + * buffer cache as free memory. */ + printf("-/+ buffers/cache:"); + cached += info.freeram; + cached += info.bufferram; printf(FIELDS_2, - scale(info.totalram - info.freeram - info.bufferram), - scale(info.freeram + info.bufferram) + scale(info.totalram - cached), //used + scale(cached) //free ); #if BB_MMU - printf("Swap:"); + printf("Swap: "); printf(FIELDS_3, - scale(info.totalswap), - scale(info.totalswap - info.freeswap), - scale(info.freeswap) + scale(info.totalswap), //total + scale(info.totalswap - info.freeswap), //used + scale(info.freeswap) //free ); #endif return EXIT_SUCCESS; From 1ec49732e2b477c45599f1a33953b4390e8c43e5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 5 Jan 2015 18:39:23 +0100 Subject: [PATCH 024/256] mpstat: code shrink function old new delta get_uptime 134 129 -5 get_irqs_from_stat 110 103 -7 Signed-off-by: Denys Vlasenko --- procps/mpstat.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/procps/mpstat.c b/procps/mpstat.c index c628d6215..af3263d67 100644 --- a/procps/mpstat.c +++ b/procps/mpstat.c @@ -522,9 +522,7 @@ static void get_irqs_from_stat(struct stats_irq *irq) FILE *fp; char buf[1024]; - fp = fopen_for_read(PROCFS_STAT); - if (!fp) - return; + fp = xfopen_for_read(PROCFS_STAT); while (fgets(buf, sizeof(buf), fp)) { //bb_error_msg("/proc/stat:'%s'", buf); @@ -644,9 +642,7 @@ static void get_uptime(data_t *uptime) char buf[sizeof(long)*3 * 2 + 4]; /* enough for long.long */ unsigned long uptime_sec, decimal; - fp = fopen_for_read(PROCFS_UPTIME); - if (!fp) - return; + fp = xfopen_for_read(PROCFS_UPTIME); if (fgets(buf, sizeof(buf), fp)) { if (sscanf(buf, "%lu.%lu", &uptime_sec, &decimal) == 2) { *uptime = (data_t)uptime_sec * G.hz + decimal * G.hz / 100; From e76957708b6a158fd25f7298a4bf2cc5583a974a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Rh=C3=A9aume?= Date: Mon, 5 Jan 2015 20:35:00 +0100 Subject: [PATCH 025/256] swaponoff: add support for -e MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: René Rhéaume Signed-off-by: Denys Vlasenko --- util-linux/swaponoff.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/util-linux/swaponoff.c b/util-linux/swaponoff.c index 75487267b..5cd1fbe70 100644 --- a/util-linux/swaponoff.c +++ b/util-linux/swaponoff.c @@ -8,7 +8,7 @@ */ //usage:#define swapon_trivial_usage -//usage: "[-a]" IF_FEATURE_SWAPON_DISCARD(" [-d[POL]]") IF_FEATURE_SWAPON_PRI(" [-p PRI]") " [DEVICE]" +//usage: "[-a] [-e]" IF_FEATURE_SWAPON_DISCARD(" [-d[POL]]") IF_FEATURE_SWAPON_PRI(" [-p PRI]") " [DEVICE]" //usage:#define swapon_full_usage "\n\n" //usage: "Start swapping on DEVICE\n" //usage: "\n -a Start swapping on all swap devices" @@ -16,15 +16,17 @@ //usage: "\n -d[POL] Discard blocks at swapon (POL=once)," //usage: "\n as freed (POL=pages), or both (POL omitted)" //usage: ) +//usage: "\n -e Silently skip devices that do not exist" //usage: IF_FEATURE_SWAPON_PRI( //usage: "\n -p PRI Set swap device priority" //usage: ) //usage: //usage:#define swapoff_trivial_usage -//usage: "[-a] [DEVICE]" +//usage: "[-a] [-e] [DEVICE]" //usage:#define swapoff_full_usage "\n\n" //usage: "Stop swapping on DEVICE\n" //usage: "\n -a Stop swapping on all swap devices" +//usage: "\n -e Silently skip devices that do not exist" #include "libbb.h" #include @@ -77,15 +79,18 @@ struct globals { /* Command line options */ enum { OPTBIT_a, /* -a all */ + OPTBIT_e, /* -e ifexists */ IF_FEATURE_SWAPON_DISCARD( OPTBIT_d ,) /* -d discard */ IF_FEATURE_SWAPON_PRI ( OPTBIT_p ,) /* -p priority */ OPT_a = 1 << OPTBIT_a, + OPT_e = 1 << OPTBIT_e, OPT_d = IF_FEATURE_SWAPON_DISCARD((1 << OPTBIT_d)) + 0, OPT_p = IF_FEATURE_SWAPON_PRI ((1 << OPTBIT_p)) + 0, }; #define OPT_ALL (option_mask32 & OPT_a) #define OPT_DISCARD (option_mask32 & OPT_d) +#define OPT_IFEXISTS (option_mask32 & OPT_e) #define OPT_PRIO (option_mask32 & OPT_p) static int swap_enable_disable(char *device) @@ -95,6 +100,8 @@ static int swap_enable_disable(char *device) struct stat st; resolve_mount_spec(&device); + if (!OPT_IFEXISTS) + xstat(device, &st); if (do_swapoff) { err = swapoff(device); @@ -112,7 +119,8 @@ static int swap_enable_disable(char *device) } err = swapon(device, g_flags); /* Don't complain on swapon -a if device is already in use */ - quiet = (OPT_ALL && errno == EBUSY); + /* Don't complain if file does not exist with -e option */ + quiet = (OPT_ALL && errno == EBUSY) || (OPT_IFEXISTS && errno == ENOENT); } } @@ -229,7 +237,7 @@ static int do_all_in_proc_swaps(void) return err; } -#define OPTSTR_SWAPON "a" \ +#define OPTSTR_SWAPON "ae" \ IF_FEATURE_SWAPON_DISCARD("d::") \ IF_FEATURE_SWAPON_PRI("p:") @@ -242,7 +250,7 @@ int swap_on_off_main(int argc UNUSED_PARAM, char **argv) INIT_G(); - getopt32(argv, do_swapoff ? "a" : OPTSTR_SWAPON + getopt32(argv, do_swapoff ? "ae" : OPTSTR_SWAPON IF_FEATURE_SWAPON_DISCARD(, &discard) IF_FEATURE_SWAPON_PRI(, &prio) ); From e5cae08f1232e66daca8f47f0f257a83a0cca9fa Mon Sep 17 00:00:00 2001 From: Tito Ragusa Date: Tue, 6 Jan 2015 01:22:36 +0100 Subject: [PATCH 026/256] libpwdgrp: line counting in error meesages is broken, remove it Signed-off-by: Tito Ragusa Signed-off-by: Denys Vlasenko --- libpwdgrp/pwd_grp.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libpwdgrp/pwd_grp.c b/libpwdgrp/pwd_grp.c index 524acfeab..90647e9d3 100644 --- a/libpwdgrp/pwd_grp.c +++ b/libpwdgrp/pwd_grp.c @@ -189,17 +189,15 @@ static int tokenize(char *buffer, int ch) static char *parse_common(FILE *fp, struct passdb *db, const char *key, int field_pos) { - int count = 0; char *buf; while ((buf = xmalloc_fgetline(fp)) != NULL) { - count++; /* Skip empty lines, comment lines */ if (buf[0] == '\0' || buf[0] == '#') goto free_and_next; if (tokenize(buf, ':') != db->numfields) { /* number of fields is wrong */ - bb_error_msg("bad record at %s:%u", db->filename, count); + bb_error_msg("%s: bad record", db->filename); goto free_and_next; } From 08364dab752e752ba3b7da30f64d09b72d9da0ad Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 7 Jan 2015 14:39:01 +0100 Subject: [PATCH 027/256] depmod: fix recent breakage in modules.dep generation Signed-off-by: Denys Vlasenko --- modutils/depmod.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/modutils/depmod.c b/modutils/depmod.c index aa228ec85..a41b3e440 100644 --- a/modutils/depmod.c +++ b/modutils/depmod.c @@ -51,7 +51,11 @@ static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARA info->dnext = info->dprev = info; info->name = xstrdup(fname + 2); /* skip "./" */ - info->modname = xstrdup(filename2modname(fname, modname)); + info->modname = xstrdup( + filename2modname( + bb_get_last_path_component_nostrip(fname), + modname + )); for (ptr = image; ptr < image + len - 10; ptr++) { if (strncmp(ptr, "depends=", 8) == 0) { char *u; @@ -242,17 +246,18 @@ int depmod_main(int argc UNUSED_PARAM, char **argv) if (!(option_mask32 & OPT_n)) xfreopen_write("modules.alias", stdout); for (m = modules; m != NULL; m = m->next) { + char modname[MODULE_NAME_LEN]; const char *fname = bb_basename(m->name); - int fnlen = strchrnul(fname, '.') - fname; + filename2modname(fname, modname); while (m->aliases) { /* Last word can well be m->modname instead, * but depmod from module-init-tools 3.4 * uses module basename, i.e., no s/-/_/g. * (pathname and .ko.* are still stripped) * Mimicking that... */ - printf("alias %s %.*s\n", + printf("alias %s %s\n", (char*)llist_pop(&m->aliases), - fnlen, fname); + modname); } } #endif @@ -260,12 +265,13 @@ int depmod_main(int argc UNUSED_PARAM, char **argv) if (!(option_mask32 & OPT_n)) xfreopen_write("modules.symbols", stdout); for (m = modules; m != NULL; m = m->next) { + char modname[MODULE_NAME_LEN]; const char *fname = bb_basename(m->name); - int fnlen = strchrnul(fname, '.') - fname; + filename2modname(fname, modname); while (m->symbols) { - printf("alias symbol:%s %.*s\n", + printf("alias symbol:%s %s\n", (char*)llist_pop(&m->symbols), - fnlen, fname); + modname); } } #endif From e5213cee3833a88397cb5e73428efb9a1b886db3 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Sun, 30 Nov 2014 20:39:25 +0000 Subject: [PATCH 028/256] vi: failure to open file is not an error when initialising buffer Commit 32afd3a introduced these regressions on the master branch: Starting vi with no filename on the command line gives the status message "'(null)' Bad address" instead of "- No file 1/1 100%". Starting vi with a non-existent file on the command line gives the status message "'new.txt' No such file or directory" instead of "- new.txt 1/1 100%" Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- editors/vi.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/editors/vi.c b/editors/vi.c index 70bdbab07..7b88e8e17 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -542,9 +542,6 @@ static void cookmode(void); // return to "cooked" mode on tty static int mysleep(int); static int readit(void); // read (maybe cursor) key from stdin static int get_one_char(void); // read 1 char from stdin -#if !ENABLE_FEATURE_VI_READONLY -#define file_insert(fn, p, update_ro_status) file_insert(fn, p) -#endif // file_insert might reallocate text[]! static int file_insert(const char *, char *, int); static int file_write(char *, char *, char *); @@ -1325,7 +1322,7 @@ static void colon(char *buf) q = next_line(q); { // dance around potentially-reallocated text[] uintptr_t ofs = q - text; - size = file_insert(fn, q, /*update_ro:*/ 0); + size = file_insert(fn, q, 0); q = text + ofs; } if (size < 0) @@ -2905,7 +2902,7 @@ static char *get_input_line(const char *prompt) } // might reallocate text[]! -static int file_insert(const char *fn, char *p, int update_ro_status) +static int file_insert(const char *fn, char *p, int initial) { int cnt = -1; int fd, size; @@ -2918,7 +2915,8 @@ static int file_insert(const char *fn, char *p, int update_ro_status) fd = open(fn, O_RDONLY); if (fd < 0) { - status_line_bold_errno(fn); + if (!initial) + status_line_bold_errno(fn); return cnt; } @@ -2946,7 +2944,7 @@ static int file_insert(const char *fn, char *p, int update_ro_status) close(fd); #if ENABLE_FEATURE_VI_READONLY - if (update_ro_status + if (initial && ((access(fn, W_OK) < 0) || /* root will always have access() * so we check fileperms too */ From 70f4320b40b7af83525cebabab2bc437a22c41d2 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Sun, 30 Nov 2014 20:39:53 +0000 Subject: [PATCH 029/256] vi: fix reading of file after last line If the :r command is used to read a file after the last line of the buffer the last line of the buffer and the first line of the file are joined. An extra blank line appears at the end of the buffer. file 1 file 1 file 1file 2 file 2 file 2 ~ ~ The insertion point is normally at the start of the line following the specified line. When the specified line is the last one the next_line function baulks at moving to the non-existent following line. Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- editors/vi.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/editors/vi.c b/editors/vi.c index 7b88e8e17..77535be92 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -1318,8 +1318,12 @@ static void colon(char *buf) q = begin_line(dot); // assume "dot" } // read after current line- unless user said ":0r foo" - if (b != 0) + if (b != 0) { q = next_line(q); + // read after last line + if (q == end-1) + ++q; + } { // dance around potentially-reallocated text[] uintptr_t ofs = q - text; size = file_insert(fn, q, 0); From 39f017293a047ac1063c84263d4d855b86c62ba1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 11 Jan 2015 16:41:54 +0100 Subject: [PATCH 030/256] diff: fix a bug in diffing against stdin. Closes 7784 Signed-off-by: Denys Vlasenko --- editors/diff.c | 3 ++- testsuite/diff.tests | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/editors/diff.c b/editors/diff.c index a78a0ee28..c3ad31bf3 100644 --- a/editors/diff.c +++ b/editors/diff.c @@ -740,9 +740,10 @@ static int diffreg(char *file[2]) unlink(name); if (bb_copyfd_eof(fd, fd_tmp) < 0) xfunc_die(); - if (fd) /* Prevents closing of stdin */ + if (fd != STDIN_FILENO) close(fd); fd = fd_tmp; + xlseek(fd, 0, SEEK_SET); } fp[i] = fdopen(fd, "r"); } diff --git a/testsuite/diff.tests b/testsuite/diff.tests index 6de46483b..84d853852 100755 --- a/testsuite/diff.tests +++ b/testsuite/diff.tests @@ -44,6 +44,17 @@ testing "diff of stdin, twice" \ "" \ "stdin" +testing "diff of empty file against stdin" \ + "diff -u - input | $TRIM_TAB" \ +"\ +--- - ++++ input +@@ -1 +0,0 @@ +-a +" \ + "" \ + "a\n" + testing "diff of empty file against nonempty one" \ "diff -u - input | $TRIM_TAB" \ "\ From 3c75b1c34e56e89aacacc781a97c70eff37bc63d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 11 Jan 2015 17:40:30 +0100 Subject: [PATCH 031/256] modprobe-small: fix recent breakage: modprobe -r was using full path "modprobe -r MODNAME", after it found the full module pathname, should strip dirpath before trying to remove the module. Signed-off-by: Denys Vlasenko --- modutils/modprobe-small.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index dafe91ed7..cf8a3f0fe 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c @@ -635,6 +635,14 @@ static void process_module(char *name, const char *cmdline_options) infovec = find_alias(name); } + if (!infovec) { + /* both dirscan and find_alias found nothing */ + if (!is_rmmod && applet_name[0] != 'd') /* it wasn't rmmod or depmod */ + bb_error_msg("module '%s' not found", name); +//TODO: _and_die()? or should we continue (un)loading modules listed on cmdline? + goto ret; + } + /* There can be more than one module for the given alias. For example, * "pci:v00008086d00007010sv00000000sd00000000bc01sc01i80" matches * ata_piix because it has alias "pci:v00008086d00007010sv*sd*bc*sc*i*" @@ -650,7 +658,8 @@ static void process_module(char *name, const char *cmdline_options) int r; char modname[MODULE_NAME_LEN]; - filename2modname(info->pathname, modname); + filename2modname( + bb_get_last_path_component_nostrip(info->pathname), modname); r = delete_module(modname, O_NONBLOCK | O_EXCL); dbg1_error_msg("delete_module('%s', O_NONBLOCK | O_EXCL):%d", modname, r); if (r != 0) { @@ -673,14 +682,6 @@ static void process_module(char *name, const char *cmdline_options) */ } - if (!infovec) { - /* both dirscan and find_alias found nothing */ - if (!is_rmmod && applet_name[0] != 'd') /* it wasn't rmmod or depmod */ - bb_error_msg("module '%s' not found", name); -//TODO: _and_die()? or should we continue (un)loading modules listed on cmdline? - goto ret; - } - infoidx = 0; while ((info = infovec[infoidx++]) != NULL) { /* Iterate thru dependencies, trying to (un)load them */ From 1b6715345f2ad026482c336d2844c2d7fe64a25c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 11 Jan 2015 17:46:56 +0100 Subject: [PATCH 032/256] modprobe-small: code shrink function old new delta pathname_matches_modname 80 42 -38 Signed-off-by: Denys Vlasenko --- modutils/modprobe-small.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index cf8a3f0fe..cafbdc0b2 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c @@ -163,6 +163,15 @@ static char *filename2modname(const char *filename, char *modname) return modname; } +static int pathname_matches_modname(const char *pathname, const char *modname) +{ + int r; + char name[MODULE_NAME_LEN]; + filename2modname(bb_get_last_path_component_nostrip(pathname), name); + r = (strcmp(name, modname) == 0); + return r; +} + /* Take "word word", return malloced "word",NUL,"word",NUL,NUL */ static char* str_2_list(const char *str) { @@ -295,18 +304,6 @@ static void parse_module(module_info *info, const char *pathname) free(module_image); } -static int pathname_matches_modname(const char *pathname, const char *modname) -{ - int r; - char name[MODULE_NAME_LEN]; - const char *fname = bb_get_last_path_component_nostrip(pathname); - const char *suffix = strrstr(fname, ".ko"); - safe_strncpy(name, fname, suffix - fname + 1); - replace(name, '-', '_'); - r = (strcmp(name, modname) == 0); - return r; -} - static FAST_FUNC int fileAction(const char *pathname, struct stat *sb UNUSED_PARAM, void *modname_to_match, From e998b08f118a0e485fffaa513bac133df2e3843b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 15 Jan 2015 02:48:36 +0100 Subject: [PATCH 033/256] modprobe: fix recent breakage: modules.dep reading code needs to strip dirname Signed-off-by: Denys Vlasenko --- modutils/modprobe.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/modutils/modprobe.c b/modutils/modprobe.c index f08f0850d..d1adaf8e1 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c @@ -15,8 +15,11 @@ #include #include -//#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__) +#if 1 #define DBG(...) ((void)0) +#else +#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__) +#endif /* Note that unlike older versions of modules.dep/depmod (busybox and m-i-t), * we expect the full dependency list to be specified in modules.dep. @@ -204,7 +207,7 @@ static struct module_entry *helper_get_module(const char *module, int create) unsigned i; unsigned hash; - filename2modname(module, modname); + filename2modname(bb_get_last_path_component_nostrip(module), modname); hash = 0; for (i = 0; modname[i]; i++) @@ -546,7 +549,6 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) if (opt & OPT_LIST_ONLY) { int i; - char name[MODULE_NAME_LEN]; char *colon, *tokens[2]; parser_t *p = config_open2(CONFIG_DEFAULT_DEPMOD_FILE, xfopen_for_read); @@ -558,10 +560,14 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) if (!colon) continue; *colon = '\0'; - filename2modname(tokens[0], name); if (!argv[0]) puts(tokens[0]); else { + char name[MODULE_NAME_LEN]; + filename2modname( + bb_get_last_path_component_nostrip(tokens[0]), + name + ); for (i = 0; argv[i]; i++) { if (fnmatch(argv[i], name, 0) == 0) { puts(tokens[0]); From 76b2262b9b911e1741b9b6d04ed15fcf076b8d2d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 15 Jan 2015 03:04:23 +0100 Subject: [PATCH 034/256] modprobe: fix "modprobe devname:snd/timer" case (alias with a slash) Signed-off-by: Denys Vlasenko --- modutils/modprobe.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/modutils/modprobe.c b/modutils/modprobe.c index d1adaf8e1..ce8b0b886 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c @@ -207,7 +207,7 @@ static struct module_entry *helper_get_module(const char *module, int create) unsigned i; unsigned hash; - filename2modname(bb_get_last_path_component_nostrip(module), modname); + filename2modname(module, modname); hash = 0; for (i = 0; modname[i]; i++) @@ -232,9 +232,14 @@ static ALWAYS_INLINE struct module_entry *get_or_add_modentry(const char *module { return helper_get_module(module, 1); } -static ALWAYS_INLINE struct module_entry *get_modentry(const char *module) +/* So far this function always gets a module pathname, never an alias name. + * The crucial difference is that pathname needs dirname stripping, + * while alias name must NOT do it! + * Testcase where dirname stripping is likely to go wrong: "modprobe devname:snd/timer" + */ +static ALWAYS_INLINE struct module_entry *get_modentry(const char *pathname) { - return helper_get_module(module, 0); + return helper_get_module(bb_get_last_path_component_nostrip(pathname), 0); } static void add_probe(const char *name) @@ -502,7 +507,7 @@ static void load_modules_dep(void) colon = last_char_is(tokens[0], ':'); if (colon == NULL) continue; - *colon = 0; + *colon = '\0'; m = get_modentry(tokens[0]); if (m == NULL) From 9de69c024c7c47f3f8733dbc7c9522966fcd73a9 Mon Sep 17 00:00:00 2001 From: Natanael Copa Date: Fri, 16 Jan 2015 13:53:05 +0100 Subject: [PATCH 035/256] modprobe: fix modprobe -r and parsing of /etc/modprobe.d This fixes a regression introduced with commit 78854520 (modprobe: revert checking for /, stop doing basename() on modprobe args, 2015-01-01) that broke modprobe options stored in /etc/modprobe.conf and /etc/modprobe.d/*.conf. This also fixes modprobe -r Signed-off-by: Natanael Copa Signed-off-by: Denys Vlasenko --- modutils/modprobe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modutils/modprobe.c b/modutils/modprobe.c index ce8b0b886..0e8aa9e85 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c @@ -425,7 +425,7 @@ static int do_modprobe(struct module_entry *m) rc = 0; fn = llist_pop(&m->deps); /* we leak it */ - m2 = get_or_add_modentry(fn); + m2 = get_or_add_modentry(bb_get_last_path_component_nostrip(fn)); if (option_mask32 & OPT_REMOVE) { /* modprobe -r */ From 86031a5ffd106b8128f5763d32c273b96875f707 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 24 Jan 2015 19:46:45 +0100 Subject: [PATCH 036/256] trim extra newlines in help texts Signed-off-by: Denys Vlasenko --- console-tools/loadkmap.c | 5 +++-- coreutils/basename.c | 2 +- procps/powertop.c | 2 +- procps/pwdx.c | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/console-tools/loadkmap.c b/console-tools/loadkmap.c index 66ec3b043..6dcf8133f 100644 --- a/console-tools/loadkmap.c +++ b/console-tools/loadkmap.c @@ -10,8 +10,9 @@ //usage:#define loadkmap_trivial_usage //usage: "< keymap" //usage:#define loadkmap_full_usage "\n\n" -//usage: "Load a binary keyboard translation table from stdin\n" -/* //usage: "\n -C TTY Affect TTY instead of /dev/tty" */ +//usage: "Load a binary keyboard translation table from stdin" +////usage: "\n" +////usage: "\n -C TTY Affect TTY instead of /dev/tty" //usage: //usage:#define loadkmap_example_usage //usage: "$ loadkmap < /etc/i18n/lang-keymap\n" diff --git a/coreutils/basename.c b/coreutils/basename.c index 1f7a13713..ab0c972ed 100644 --- a/coreutils/basename.c +++ b/coreutils/basename.c @@ -31,7 +31,7 @@ //usage:#define basename_trivial_usage //usage: "FILE [SUFFIX]" //usage:#define basename_full_usage "\n\n" -//usage: "Strip directory path and .SUFFIX from FILE\n" +//usage: "Strip directory path and .SUFFIX from FILE" //usage: //usage:#define basename_example_usage //usage: "$ basename /usr/local/bin/foo\n" diff --git a/procps/powertop.c b/procps/powertop.c index e3c29d1c3..ddda5bd93 100644 --- a/procps/powertop.c +++ b/procps/powertop.c @@ -674,7 +674,7 @@ static void show_timerstats(void) //usage:#define powertop_trivial_usage //usage: "" //usage:#define powertop_full_usage "\n\n" -//usage: "Analyze power consumption on Intel-based laptops\n" +//usage: "Analyze power consumption on Intel-based laptops" int powertop_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int powertop_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv) diff --git a/procps/pwdx.c b/procps/pwdx.c index 781810488..22b892275 100644 --- a/procps/pwdx.c +++ b/procps/pwdx.c @@ -21,7 +21,7 @@ //usage:#define pwdx_trivial_usage //usage: "PID..." //usage:#define pwdx_full_usage "\n\n" -//usage: "Show current directory for PIDs\n" +//usage: "Show current directory for PIDs" #include "libbb.h" From cc70b6f8b6c6441e1c48690c7885700a2d389946 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 24 Jan 2015 22:30:30 +0100 Subject: [PATCH 037/256] depmod: simple memory optimization function old new delta filename2modname 67 86 +19 parse_module 374 351 -23 Signed-off-by: Denys Vlasenko --- modutils/depmod.c | 19 +++++++++---------- modutils/modutils.c | 6 +++++- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/modutils/depmod.c b/modutils/depmod.c index a41b3e440..37a8482d9 100644 --- a/modutils/depmod.c +++ b/modutils/depmod.c @@ -33,7 +33,6 @@ typedef struct module_info { static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARAM, void *data, int depth UNUSED_PARAM) { - char modname[MODULE_NAME_LEN]; module_info **first = (module_info **) data; char *image, *ptr; module_info *info; @@ -51,11 +50,10 @@ static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARA info->dnext = info->dprev = info; info->name = xstrdup(fname + 2); /* skip "./" */ - info->modname = xstrdup( - filename2modname( + info->modname = filename2modname( bb_get_last_path_component_nostrip(fname), - modname - )); + NULL + ); for (ptr = image; ptr < image + len - 10; ptr++) { if (strncmp(ptr, "depends=", 8) == 0) { char *u; @@ -250,11 +248,12 @@ int depmod_main(int argc UNUSED_PARAM, char **argv) const char *fname = bb_basename(m->name); filename2modname(fname, modname); while (m->aliases) { - /* Last word can well be m->modname instead, - * but depmod from module-init-tools 3.4 - * uses module basename, i.e., no s/-/_/g. - * (pathname and .ko.* are still stripped) - * Mimicking that... */ + /* + * Last word used to be a basename + * (filename with path and .ko.* stripped) + * at the time of module-init-tools 3.4. + * kmod v.12 uses module name, i.e., s/-/_/g. + */ printf("alias %s %s\n", (char*)llist_pop(&m->aliases), modname); diff --git a/modutils/modutils.c b/modutils/modutils.c index ff79d3fac..84300d931 100644 --- a/modutils/modutils.c +++ b/modutils/modutils.c @@ -47,13 +47,14 @@ int FAST_FUNC string_to_llist(char *string, llist_t **llist, const char *delim) char* FAST_FUNC filename2modname(const char *filename, char *modname) { + char local_modname[MODULE_NAME_LEN]; int i; const char *from; if (filename == NULL) return NULL; if (modname == NULL) - modname = xmalloc(MODULE_NAME_LEN); + modname = local_modname; // Disabled since otherwise "modprobe dir/name" would work // as if it is "modprobe name". It is unclear why // 'basenamization' was here in the first place. @@ -63,6 +64,9 @@ char* FAST_FUNC filename2modname(const char *filename, char *modname) modname[i] = (from[i] == '-') ? '_' : from[i]; modname[i] = '\0'; + if (modname == local_modname) + return xstrdup(modname); + return modname; } From 50a6d86520b2c45a70a3d0e2d19fde37c49d8c90 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 25 Jan 2015 22:08:46 +0100 Subject: [PATCH 038/256] platform.h: add compat mempcpy Signed-off-by: Denys Vlasenko --- include/platform.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/platform.h b/include/platform.h index 09c7ccd9c..f00669695 100644 --- a/include/platform.h +++ b/include/platform.h @@ -370,6 +370,7 @@ typedef unsigned smalluint; #define HAVE_SETBIT 1 #define HAVE_SIGHANDLER_T 1 #define HAVE_STPCPY 1 +#define HAVE_MEMPCPY 1 #define HAVE_STRCASESTR 1 #define HAVE_STRCHRNUL 1 #define HAVE_STRSEP 1 @@ -450,6 +451,7 @@ typedef unsigned smalluint; #endif #if defined(__FreeBSD__) +//# undef HAVE_MEMPCPY - not yet confirmed # undef HAVE_CLEARENV # undef HAVE_FDATASYNC # undef HAVE_MNTENT_H @@ -513,6 +515,13 @@ typedef void (*sighandler_t)(int); extern char *stpcpy(char *p, const char *to_add) FAST_FUNC; #endif +#ifndef HAVE_MEMPCPY +static ALWAYS_INLINE void *mempcpy(void *dest, const void *src, size_t len) +{ + return memcpy(dest, src, len) + len; +} +#endif + #ifndef HAVE_STRCASESTR extern char *strcasestr(const char *s, const char *pattern) FAST_FUNC; #endif From 64b744997ef399809dc4c78ec45ddfbebde3e597 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 26 Jan 2015 15:45:48 +0100 Subject: [PATCH 039/256] ftpd: prevent zombies. closes 7832 Signed-off-by: Denys Vlasenko --- networking/ftpd.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/networking/ftpd.c b/networking/ftpd.c index 6adcb1dee..0c10e1f25 100644 --- a/networking/ftpd.c +++ b/networking/ftpd.c @@ -1174,8 +1174,13 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv) //umask(077); - admin can set umask before starting us - /* Signals. We'll always take -EPIPE rather than a rude signal, thanks */ - signal(SIGPIPE, SIG_IGN); + /* Signals */ + bb_signals(0 + /* We'll always take EPIPE rather than a rude signal, thanks */ + + (1 << SIGPIPE) + /* LIST command spawns chilren. Prevent zombies */ + + (1 << SIGCHLD) + , SIG_IGN); /* Set up options on the command socket (do we need these all? why?) */ setsockopt(STDIN_FILENO, IPPROTO_TCP, TCP_NODELAY, &const_int_1, sizeof(const_int_1)); From 936c401077cc68d9e3dd7f1b0b293ee03ce02bf5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 27 Jan 2015 21:59:40 +0100 Subject: [PATCH 040/256] dhcpd: fix an improper widening conversion We wanted to detect when tv_sec = unsigned1 - unsigned2 underflows by looking at tv_sec's sign. But if tv_sec is long and it is wider than unsigned, we get unsigned -> long conversion which is in this case never negative. Signed-off-by: Denys Vlasenko --- networking/udhcp/dhcpd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index 4b3ed240c..2de074f9b 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c @@ -413,7 +413,8 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) max_sock = udhcp_sp_fd_set(&rfds, server_socket); if (server_config.auto_time) { - tv.tv_sec = timeout_end - monotonic_sec(); + /* cast to signed is essential if tv_sec is wider than int */ + tv.tv_sec = (int)(timeout_end - monotonic_sec()); tv.tv_usec = 0; } retval = 0; From ff3f3accc68c84851d1ea8cd995f9491b32bedef Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 29 Jan 2015 16:31:36 +0100 Subject: [PATCH 041/256] ntpd: get rid of G.initial_poll_complete This speeds up syncing - now happens only just two replies from a peer. Especially useful for "ntpd -q". Shouldn't have ill effects: if we chose a bad peer, we will discover it later and switch to another one. The code is even smaller this way. Suggested by Miroslav Lichvar Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index 33cb1dcb1..c016bfc50 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -376,8 +376,6 @@ struct globals { */ #define G_precision_sec 0.002 uint8_t stratum; - /* Bool. After set to 1, never goes back to 0: */ - smallint initial_poll_complete; #define STATE_NSET 0 /* initial state, "nothing is set" */ //#define STATE_FSET 1 /* frequency set from file */ @@ -1084,7 +1082,7 @@ select_and_cluster(void) num_points = 0; item = G.ntp_peers; - if (G.initial_poll_complete) while (item != NULL) { + while (item != NULL) { double rd, offset; p = (peer_t *) item->data; @@ -1649,7 +1647,7 @@ update_local_clock(peer_t *p) if (G.ntp_status & LI_MINUSSEC) tmx.status |= STA_DEL; - tmx.constant = G.poll_exp - 4; + tmx.constant = (int)G.poll_exp - 4 > 0 ? (int)G.poll_exp - 4 : 0; /* EXPERIMENTAL. * The below if statement should be unnecessary, but... * It looks like Linux kernel's PLL is far too gentle in changing @@ -2285,7 +2283,6 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv) VERB4 bb_error_msg("disabling burst mode"); G.polladj_count = 0; G.poll_exp = MINPOLL; - G.initial_poll_complete = 1; } send_query_to_peer(p); } else { From 8c05a74f7efcda6ae5bd83e134edf44af12cb5e4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 29 Jan 2015 16:41:48 +0100 Subject: [PATCH 042/256] platform.h: mempcpy needs Signed-off-by: Denys Vlasenko --- include/platform.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/platform.h b/include/platform.h index f00669695..1168a34dc 100644 --- a/include/platform.h +++ b/include/platform.h @@ -516,6 +516,7 @@ extern char *stpcpy(char *p, const char *to_add) FAST_FUNC; #endif #ifndef HAVE_MEMPCPY +#include static ALWAYS_INLINE void *mempcpy(void *dest, const void *src, size_t len) { return memcpy(dest, src, len) + len; From 08f9ffc3f7503eb3dc94f16c615b20d2ae9a059c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 30 Jan 2015 15:15:38 +0100 Subject: [PATCH 043/256] dpkg: update supported compression methods Based on a patch by Ron Yorston function old new delta get_header_tar_xz - 60 +60 filter_accept_list_reassign 128 188 +60 unpack_package 585 621 +36 init_archive_deb_control 52 76 +24 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 3/0 up/down: 180/0) Total: 180 bytes Signed-off-by: Denys Vlasenko --- archival/dpkg.c | 11 ++++++++++ archival/dpkg_deb.c | 6 ++++++ archival/libarchive/Kbuild.src | 1 + .../libarchive/filter_accept_list_reassign.c | 10 +++++++++ archival/libarchive/get_header_tar_xz.c | 21 +++++++++++++++++++ include/bb_archive.h | 1 + 6 files changed, 50 insertions(+) create mode 100644 archival/libarchive/get_header_tar_xz.c diff --git a/archival/dpkg.c b/archival/dpkg.c index 2893cfc2d..151f0ca43 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c @@ -1472,12 +1472,16 @@ static void init_archive_deb_control(archive_handle_t *ar_handle) tar_handle->src_fd = ar_handle->src_fd; /* We don't care about data.tar.* or debian-binary, just control.tar.* */ + llist_add_to(&(ar_handle->accept), (char*)"control.tar"); #if ENABLE_FEATURE_SEAMLESS_GZ llist_add_to(&(ar_handle->accept), (char*)"control.tar.gz"); #endif #if ENABLE_FEATURE_SEAMLESS_BZ2 llist_add_to(&(ar_handle->accept), (char*)"control.tar.bz2"); #endif +#if ENABLE_FEATURE_SEAMLESS_XZ + llist_add_to(&(ar_handle->accept), (char*)"control.tar.xz"); +#endif /* Assign the tar handle as a subarchive of the ar handle */ ar_handle->dpkg__sub_archive = tar_handle; @@ -1492,12 +1496,19 @@ static void init_archive_deb_data(archive_handle_t *ar_handle) tar_handle->src_fd = ar_handle->src_fd; /* We don't care about control.tar.* or debian-binary, just data.tar.* */ + llist_add_to(&(ar_handle->accept), (char*)"data.tar"); #if ENABLE_FEATURE_SEAMLESS_GZ llist_add_to(&(ar_handle->accept), (char*)"data.tar.gz"); #endif #if ENABLE_FEATURE_SEAMLESS_BZ2 llist_add_to(&(ar_handle->accept), (char*)"data.tar.bz2"); #endif +#if ENABLE_FEATURE_SEAMLESS_LZMA + llist_add_to(&(ar_handle->accept), (char*)"data.tar.lzma"); +#endif +#if ENABLE_FEATURE_SEAMLESS_XZ + llist_add_to(&(ar_handle->accept), (char*)"data.tar.xz"); +#endif /* Assign the tar handle as a subarchive of the ar handle */ ar_handle->dpkg__sub_archive = tar_handle; diff --git a/archival/dpkg_deb.c b/archival/dpkg_deb.c index 13f9db991..0285273fe 100644 --- a/archival/dpkg_deb.c +++ b/archival/dpkg_deb.c @@ -70,6 +70,8 @@ int dpkg_deb_main(int argc, char **argv) ar_archive->dpkg__sub_archive = tar_archive; ar_archive->filter = filter_accept_list_reassign; + llist_add_to(&ar_archive->accept, (char*)"data.tar"); + llist_add_to(&control_tar_llist, (char*)"control.tar"); #if ENABLE_FEATURE_SEAMLESS_GZ llist_add_to(&ar_archive->accept, (char*)"data.tar.gz"); llist_add_to(&control_tar_llist, (char*)"control.tar.gz"); @@ -82,6 +84,10 @@ int dpkg_deb_main(int argc, char **argv) llist_add_to(&ar_archive->accept, (char*)"data.tar.lzma"); llist_add_to(&control_tar_llist, (char*)"control.tar.lzma"); #endif +#if ENABLE_FEATURE_SEAMLESS_XZ + llist_add_to(&ar_archive->accept, (char*)"data.tar.xz"); + llist_add_to(&control_tar_llist, (char*)"control.tar.xz"); +#endif opt_complementary = "c--efXx:e--cfXx:f--ceXx:X--cefx:x--cefX"; opt = getopt32(argv, "cefXx"); diff --git a/archival/libarchive/Kbuild.src b/archival/libarchive/Kbuild.src index 968fdf8ab..7e89e9e89 100644 --- a/archival/libarchive/Kbuild.src +++ b/archival/libarchive/Kbuild.src @@ -35,6 +35,7 @@ DPKG_FILES:= \ get_header_tar_gz.o \ get_header_tar_bz2.o \ get_header_tar_lzma.o \ + get_header_tar_xz.o \ INSERT diff --git a/archival/libarchive/filter_accept_list_reassign.c b/archival/libarchive/filter_accept_list_reassign.c index 3d19abe44..b9acfbc05 100644 --- a/archival/libarchive/filter_accept_list_reassign.c +++ b/archival/libarchive/filter_accept_list_reassign.c @@ -28,6 +28,10 @@ char FAST_FUNC filter_accept_list_reassign(archive_handle_t *archive_handle) name_ptr++; /* Modify the subarchive handler based on the extension */ + if (strcmp(name_ptr, "tar") == 0) { + archive_handle->dpkg__action_data_subarchive = get_header_tar; + return EXIT_SUCCESS; + } if (ENABLE_FEATURE_SEAMLESS_GZ && strcmp(name_ptr, "gz") == 0 ) { @@ -46,6 +50,12 @@ char FAST_FUNC filter_accept_list_reassign(archive_handle_t *archive_handle) archive_handle->dpkg__action_data_subarchive = get_header_tar_lzma; return EXIT_SUCCESS; } + if (ENABLE_FEATURE_SEAMLESS_XZ + && strcmp(name_ptr, "xz") == 0 + ) { + archive_handle->dpkg__action_data_subarchive = get_header_tar_xz; + return EXIT_SUCCESS; + } } return EXIT_FAILURE; } diff --git a/archival/libarchive/get_header_tar_xz.c b/archival/libarchive/get_header_tar_xz.c new file mode 100644 index 000000000..7bf3b3b56 --- /dev/null +++ b/archival/libarchive/get_header_tar_xz.c @@ -0,0 +1,21 @@ +/* vi: set sw=4 ts=4: */ +/* + * Licensed under GPLv2 or later, see file LICENSE in this source tree. + */ + +#include "libbb.h" +#include "bb_archive.h" + +char FAST_FUNC get_header_tar_xz(archive_handle_t *archive_handle) +{ + /* Can't lseek over pipes */ + archive_handle->seek = seek_by_read; + + fork_transformer_with_sig(archive_handle->src_fd, unpack_xz_stream, "unxz"); + archive_handle->offset = 0; + while (get_header_tar(archive_handle) == EXIT_SUCCESS) + continue; + + /* Can only do one file at a time */ + return EXIT_FAILURE; +} diff --git a/include/bb_archive.h b/include/bb_archive.h index a6b166fe3..5d9e24c17 100644 --- a/include/bb_archive.h +++ b/include/bb_archive.h @@ -184,6 +184,7 @@ char get_header_tar(archive_handle_t *archive_handle) FAST_FUNC; char get_header_tar_gz(archive_handle_t *archive_handle) FAST_FUNC; char get_header_tar_bz2(archive_handle_t *archive_handle) FAST_FUNC; char get_header_tar_lzma(archive_handle_t *archive_handle) FAST_FUNC; +char get_header_tar_xz(archive_handle_t *archive_handle) FAST_FUNC; void seek_by_jump(int fd, off_t amount) FAST_FUNC; void seek_by_read(int fd, off_t amount) FAST_FUNC; From 1cbe93cf4e4234629a15cc3038bdb379961ffc2e Mon Sep 17 00:00:00 2001 From: Martin Kaiser Date: Sun, 2 Nov 2014 23:23:16 +0100 Subject: [PATCH 044/256] telnetd: we only need CONFIG_UNIX98_PTYS from the Linux kernel (re-sending this as it got ignored completey and the format of the previous mail was probably not correct - please let me know if there's anything else I can do to get this trivial fix applied) for telnetd to work, we only need CONFIG_UNIX98_PTYS to be enabled in the Linux kernel - DEVPTS_FS has been obsolete for some time Signed-off-by: Martin Kaiser Signed-off-by: Denys Vlasenko --- networking/Config.src | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/networking/Config.src b/networking/Config.src index 15a696876..da36e8627 100644 --- a/networking/Config.src +++ b/networking/Config.src @@ -750,8 +750,7 @@ config TELNETD Note that for busybox telnetd to work you need several things: First of all, your kernel needs: - UNIX98_PTYS=y - DEVPTS_FS=y + CONFIG_UNIX98_PTYS=y Next, you need a /dev/pts directory on your root filesystem: From 07fa09a9527b7c9f864799c4c1cab86b49f232ce Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 2 Nov 2014 11:08:24 +0100 Subject: [PATCH 045/256] ubiattach: add option -O Some images do not have the default VID offset. The option -O must be used to attach such images. Signed-off-by: Micke Prag Signed-off-by: Denys Vlasenko --- miscutils/ubi_tools.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/miscutils/ubi_tools.c b/miscutils/ubi_tools.c index 6c09fe534..dd1bda300 100644 --- a/miscutils/ubi_tools.c +++ b/miscutils/ubi_tools.c @@ -105,6 +105,7 @@ int ubi_tools_main(int argc UNUSED_PARAM, char **argv) int mtd_num; int dev_num = UBI_DEV_NUM_AUTO; int vol_id = UBI_VOL_NUM_AUTO; + int vid_hdr_offset = 0; char *vol_name; unsigned long long size_bytes = size_bytes; /* for compiler */ char *size_bytes_str; @@ -133,10 +134,11 @@ int ubi_tools_main(int argc UNUSED_PARAM, char **argv) #define OPTION_a (1 << 5) #define OPTION_t (1 << 6) if (do_mkvol) { - opt_complementary = "-1:d+:n+:a+"; - opts = getopt32(argv, "md:n:N:s:a:t:", + opt_complementary = "-1:d+:n+:a+:O+"; + opts = getopt32(argv, "md:n:N:s:a:t:O:", &dev_num, &vol_id, - &vol_name, &size_bytes_str, &alignment, &type + &vol_name, &size_bytes_str, &alignment, &type, + &vid_hdr_offset ); } else if (do_update) { @@ -162,17 +164,19 @@ int ubi_tools_main(int argc UNUSED_PARAM, char **argv) // bb_error_msg_and_die("%s: not a char device", ubi_ctrl); //usage:#define ubiattach_trivial_usage -//usage: "-m MTD_NUM [-d UBI_NUM] UBI_CTRL_DEV" +//usage: "-m MTD_NUM [-d UBI_NUM] [-O VID_HDR_OFF] UBI_CTRL_DEV" //usage:#define ubiattach_full_usage "\n\n" //usage: "Attach MTD device to UBI\n" //usage: "\n -m MTD_NUM MTD device number to attach" //usage: "\n -d UBI_NUM UBI device number to assign" +//usage: "\n -O VID_HDR_OFF VID header offset" if (do_attach) { if (!(opts & OPTION_m)) bb_error_msg_and_die("%s device not specified", "MTD"); attach_req.mtd_num = mtd_num; attach_req.ubi_num = dev_num; + attach_req.vid_hdr_offset = vid_hdr_offset; xioctl(fd, UBI_IOCATT, &attach_req); } else From 5104645cf87f8cf37c42666c90bb259011cfac58 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 2 Feb 2015 03:51:47 +0100 Subject: [PATCH 046/256] platform.h: enable mempcpy for FreeBSD Signed-off-by: Denys Vlasenko --- include/platform.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/platform.h b/include/platform.h index 1168a34dc..0b0fce182 100644 --- a/include/platform.h +++ b/include/platform.h @@ -451,7 +451,8 @@ typedef unsigned smalluint; #endif #if defined(__FreeBSD__) -//# undef HAVE_MEMPCPY - not yet confirmed +/* users say mempcpy is not present in FreeBSD 9.x */ +# undef HAVE_MEMPCPY # undef HAVE_CLEARENV # undef HAVE_FDATASYNC # undef HAVE_MNTENT_H @@ -517,6 +518,10 @@ extern char *stpcpy(char *p, const char *to_add) FAST_FUNC; #ifndef HAVE_MEMPCPY #include +/* In case we are wrong about !HAVE_MEMPCPY, and toolchain _does_ have + * mempcpy(), avoid colliding with it: + */ +#define mempcpy bb__mempcpy static ALWAYS_INLINE void *mempcpy(void *dest, const void *src, size_t len) { return memcpy(dest, src, len) + len; From 7f7ade1964f61172125d9f4fe92f0b07ce8bc7a4 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Mon, 2 Feb 2015 16:01:16 +0100 Subject: [PATCH 047/256] gzip: do not store timestamp in gzip header Storing the original file's modification time in the output file is harmful (precludes deterministic results) and unlike official gzip, the busybox version provides no way to suppress this behavior; the -n option is silently ignored. Rather than trying to make -n work, this patch just removes the timestamp-storing functionality. It should be considered deprecated anyway; it's not Y2038-safe and gunzip ignores it by default. Per RFC 1952, 0 is the correct value to store to indicate that there is no timestamp. Signed-off-by: Rich Felker Signed-off-by: Denys Vlasenko --- archival/gzip.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/archival/gzip.c b/archival/gzip.c index a93d2175a..46367f9e6 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -2007,7 +2007,7 @@ static void ct_init(void) * IN assertions: the input and output buffers are cleared. */ -static void zip(ulg time_stamp) +static void zip(void) { ush deflate_flags = 0; /* pkzip -es, -en or -ex equivalent */ @@ -2018,7 +2018,7 @@ static void zip(ulg time_stamp) /* compression method: 8 (DEFLATED) */ /* general flags: 0 */ put_32bit(0x00088b1f); - put_32bit(time_stamp); + put_32bit(0); /* Unix timestamp */ /* Write deflated file to zip file */ G1.crc = ~0; @@ -2044,8 +2044,6 @@ static void zip(ulg time_stamp) static IF_DESKTOP(long long) int FAST_FUNC pack_gzip(transformer_state_t *xstate UNUSED_PARAM) { - struct stat s; - /* Clear input and output buffers */ G1.outcnt = 0; #ifdef DEBUG @@ -2077,9 +2075,23 @@ IF_DESKTOP(long long) int FAST_FUNC pack_gzip(transformer_state_t *xstate UNUSED G2.bl_desc.max_length = MAX_BL_BITS; //G2.bl_desc.max_code = 0; +#if 0 + /* Saving of timestamp is disabled. Why? + * - it is not Y2038-safe. + * - some people want deterministic results + * (normally they'd use -n, but our -n is a nop). + * - it's bloat. + * Per RFC 1952, gzfile.time=0 is "no timestamp". + * If users will demand this to be reinstated, + * implement -n "don't save timestamp". + */ + struct stat s; s.st_ctime = 0; fstat(STDIN_FILENO, &s); zip(s.st_ctime); +#else + zip(); +#endif return 0; } From f7f70bf1b3025550ea4ad8d13d977b846a868a06 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 2 Feb 2015 16:07:07 +0100 Subject: [PATCH 048/256] gzip: speed up and shrink put_16bit() function old new delta put_16bit 104 98 -6 Signed-off-by: Denys Vlasenko --- archival/gzip.c | 41 ++++++++++++++++++++++++++++++++++------- include/platform.h | 2 ++ 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/archival/gzip.c b/archival/gzip.c index 46367f9e6..18d795996 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -417,19 +417,46 @@ static void flush_outbuf(void) #define put_8bit(c) \ do { \ G1.outbuf[G1.outcnt++] = (c); \ - if (G1.outcnt == OUTBUFSIZ) flush_outbuf(); \ + if (G1.outcnt == OUTBUFSIZ) \ + flush_outbuf(); \ } while (0) /* Output a 16 bit value, lsb first */ static void put_16bit(ush w) { - if (G1.outcnt < OUTBUFSIZ - 2) { - G1.outbuf[G1.outcnt++] = w; - G1.outbuf[G1.outcnt++] = w >> 8; - } else { - put_8bit(w); - put_8bit(w >> 8); + /* GCC 4.2.1 won't optimize out redundant loads of G1.outcnt + * (probably because of fear of aliasing with G1.outbuf[] + * stores), do it explicitly: + */ + unsigned outcnt = G1.outcnt; + uch *dst = &G1.outbuf[outcnt]; + +#if BB_UNALIGNED_MEMACCESS_OK && BB_LITTLE_ENDIAN + if (outcnt < OUTBUFSIZ-2) { + /* Common case */ + ush *dst16 = (void*) dst; + *dst16 = w; /* unalinged LSB 16-bit store */ + G1.outcnt = outcnt + 2; + return; } + *dst = (uch)w; + w >>= 8; +#else + *dst++ = (uch)w; + w >>= 8; + if (outcnt < OUTBUFSIZ-2) { + /* Common case */ + *dst = w; + G1.outcnt = outcnt + 2; + return; + } +#endif + + /* Slowpath: we will need to do flush_outbuf() */ + G1.outcnt++; + if (G1.outcnt == OUTBUFSIZ) + flush_outbuf(); + put_8bit(w); } static void put_32bit(ulg n) diff --git a/include/platform.h b/include/platform.h index 0b0fce182..df9594507 100644 --- a/include/platform.h +++ b/include/platform.h @@ -217,6 +217,7 @@ typedef uint64_t bb__aliased_uint64_t FIX_ALIASING; * a lvalue. This makes it more likely to not swap them by mistake */ #if defined(i386) || defined(__x86_64__) || defined(__powerpc__) +# define BB_UNALIGNED_MEMACCESS_OK 1 # define move_from_unaligned_int(v, intp) ((v) = *(bb__aliased_int*)(intp)) # define move_from_unaligned_long(v, longp) ((v) = *(bb__aliased_long*)(longp)) # define move_from_unaligned16(v, u16p) ((v) = *(bb__aliased_uint16_t*)(u16p)) @@ -225,6 +226,7 @@ typedef uint64_t bb__aliased_uint64_t FIX_ALIASING; # define move_to_unaligned32(u32p, v) (*(bb__aliased_uint32_t*)(u32p) = (v)) /* #elif ... - add your favorite arch today! */ #else +# define BB_UNALIGNED_MEMACCESS_OK 0 /* performs reasonably well (gcc usually inlines memcpy here) */ # define move_from_unaligned_int(v, intp) (memcpy(&(v), (intp), sizeof(int))) # define move_from_unaligned_long(v, longp) (memcpy(&(v), (longp), sizeof(long))) From 8e74adab0107658e3dc04ed342206272a284f43e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 3 Feb 2015 12:07:40 +0100 Subject: [PATCH 049/256] libbb: make INET[6]_rresolve use sockaddr2{host,dotted}_noport function old new delta INET_rresolve 274 214 -60 INET6_rresolve 168 85 -83 Signed-off-by: Denys Vlasenko --- libbb/inet_common.c | 84 ++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 51 deletions(-) diff --git a/libbb/inet_common.c b/libbb/inet_common.c index b3e0802ee..5b4a4a10b 100644 --- a/libbb/inet_common.c +++ b/libbb/inet_common.c @@ -32,14 +32,12 @@ int FAST_FUNC INET_resolve(const char *name, struct sockaddr_in *s_in, int hostf return 0; } /* If we expect this to be a hostname, try hostname database first */ + if (hostfirst) { #ifdef DEBUG - if (hostfirst) { bb_error_msg("gethostbyname(%s)", name); - } #endif - if (hostfirst) { hp = gethostbyname(name); - if (hp != NULL) { + if (hp) { memcpy(&s_in->sin_addr, hp->h_addr_list[0], sizeof(struct in_addr)); return 0; @@ -51,7 +49,7 @@ int FAST_FUNC INET_resolve(const char *name, struct sockaddr_in *s_in, int hostf bb_error_msg("getnetbyname(%s)", name); #endif np = getnetbyname(name); - if (np != NULL) { + if (np) { s_in->sin_addr.s_addr = htonl(np->n_net); return 1; } @@ -66,7 +64,7 @@ int FAST_FUNC INET_resolve(const char *name, struct sockaddr_in *s_in, int hostf bb_error_msg("gethostbyname(%s)", name); #endif hp = gethostbyname(name); - if (hp == NULL) { + if (!hp) { return -1; } memcpy(&s_in->sin_addr, hp->h_addr_list[0], sizeof(struct in_addr)); @@ -74,7 +72,7 @@ int FAST_FUNC INET_resolve(const char *name, struct sockaddr_in *s_in, int hostf } -/* numeric: & 0x8000: default instead of *, +/* numeric: & 0x8000: "default" instead of "*", * & 0x4000: host instead of net, * & 0x0fff: don't resolve */ @@ -83,16 +81,16 @@ char* FAST_FUNC INET_rresolve(struct sockaddr_in *s_in, int numeric, uint32_t ne /* addr-to-name cache */ struct addr { struct addr *next; - struct sockaddr_in addr; - int host; + uint32_t nip; + smallint is_host; char name[1]; }; static struct addr *cache = NULL; struct addr *pn; char *name; - uint32_t ad, host_ad; - int host = 0; + uint32_t nip; + smallint is_host; if (s_in->sin_family != AF_INET) { #ifdef DEBUG @@ -102,61 +100,57 @@ char* FAST_FUNC INET_rresolve(struct sockaddr_in *s_in, int numeric, uint32_t ne errno = EAFNOSUPPORT; return NULL; } - ad = s_in->sin_addr.s_addr; + nip = s_in->sin_addr.s_addr; #ifdef DEBUG - bb_error_msg("rresolve: %08x, mask %08x, num %08x", (unsigned)ad, netmask, numeric); + bb_error_msg("rresolve: %08x mask:%08x num:%08x", (unsigned)nip, netmask, numeric); #endif - if (ad == INADDR_ANY) { - if ((numeric & 0x0FFF) == 0) { - if (numeric & 0x8000) - return xstrdup("default"); - return xstrdup("*"); - } - } if (numeric & 0x0FFF) - return xstrdup(inet_ntoa(s_in->sin_addr)); + return xmalloc_sockaddr2dotted_noport((void*)s_in); + if (nip == INADDR_ANY) { + if (numeric & 0x8000) + return xstrdup("default"); + return xstrdup("*"); + } + + is_host = ((nip & (~netmask)) != 0 || (numeric & 0x4000)); - if ((ad & (~netmask)) != 0 || (numeric & 0x4000)) - host = 1; pn = cache; while (pn) { - if (pn->addr.sin_addr.s_addr == ad && pn->host == host) { + if (pn->nip == nip && pn->is_host == is_host) { #ifdef DEBUG bb_error_msg("rresolve: found %s %08x in cache", - (host ? "host" : "net"), (unsigned)ad); + (is_host ? "host" : "net"), (unsigned)nip); #endif return xstrdup(pn->name); } pn = pn->next; } - host_ad = ntohl(ad); name = NULL; - if (host) { - struct hostent *ent; + if (is_host) { #ifdef DEBUG - bb_error_msg("gethostbyaddr (%08x)", (unsigned)ad); + bb_error_msg("sockaddr2host_noport(%08x)", (unsigned)nip); #endif - ent = gethostbyaddr((char *) &ad, 4, AF_INET); - if (ent) - name = xstrdup(ent->h_name); + name = xmalloc_sockaddr2host_noport((void*)s_in); } else if (ENABLE_FEATURE_ETC_NETWORKS) { struct netent *np; #ifdef DEBUG - bb_error_msg("getnetbyaddr (%08x)", (unsigned)host_ad); + bb_error_msg("getnetbyaddr(%08x)", (unsigned)ntohl(nip)); #endif - np = getnetbyaddr(host_ad, AF_INET); + np = getnetbyaddr(ntohl(nip), AF_INET); if (np) name = xstrdup(np->n_name); } if (!name) - name = xstrdup(inet_ntoa(s_in->sin_addr)); + name = xmalloc_sockaddr2dotted_noport((void*)s_in); + pn = xmalloc(sizeof(*pn) + strlen(name)); /* no '+ 1', it's already accounted for */ pn->next = cache; - pn->addr = *s_in; - pn->host = host; + pn->nip = nip; + pn->is_host = is_host; strcpy(pn->name, name); cache = pn; + return name; } @@ -188,9 +182,6 @@ int FAST_FUNC INET6_resolve(const char *name, struct sockaddr_in6 *sin6) char* FAST_FUNC INET6_rresolve(struct sockaddr_in6 *sin6, int numeric) { - char name[128]; - int s; - if (sin6->sin6_family != AF_INET6) { #ifdef DEBUG bb_error_msg("rresolve: unsupported address family %d!", @@ -200,8 +191,7 @@ char* FAST_FUNC INET6_rresolve(struct sockaddr_in6 *sin6, int numeric) return NULL; } if (numeric & 0x7FFF) { - inet_ntop(AF_INET6, &sin6->sin6_addr, name, sizeof(name)); - return xstrdup(name); + return xmalloc_sockaddr2dotted_noport((void*)sin6); } if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { if (numeric & 0x8000) @@ -209,15 +199,7 @@ char* FAST_FUNC INET6_rresolve(struct sockaddr_in6 *sin6, int numeric) return xstrdup("*"); } - s = getnameinfo((struct sockaddr *) sin6, sizeof(*sin6), - name, sizeof(name), - /*serv,servlen:*/ NULL, 0, - 0); - if (s != 0) { - bb_error_msg("getnameinfo failed"); - return NULL; - } - return xstrdup(name); + return xmalloc_sockaddr2host_noport((void*)sin6); } #endif /* CONFIG_FEATURE_IPV6 */ From a97777889328157bb7d06ec618bad16712a9c345 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 3 Feb 2015 12:11:30 +0100 Subject: [PATCH 050/256] ifconfig: fix double free fatal error in INET_sprint Based on the patch by Zheng Junling and Chen Gang Signed-off-by: Denys Vlasenko --- networking/interface.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/networking/interface.c b/networking/interface.c index bf7d2b1b4..b0572d04e 100644 --- a/networking/interface.c +++ b/networking/interface.c @@ -91,9 +91,9 @@ static const char* FAST_FUNC INET_sprint(struct sockaddr *sap, int numeric) { static char *buff; /* defaults to NULL */ - free(buff); if (sap->sa_family == 0xFFFF || sap->sa_family == 0) return "[NONE SET]"; + free(buff); buff = INET_rresolve((struct sockaddr_in *) sap, numeric, 0xffffff00); return buff; } @@ -173,9 +173,9 @@ static const char* FAST_FUNC INET6_sprint(struct sockaddr *sap, int numeric) { static char *buff; - free(buff); if (sap->sa_family == 0xFFFF || sap->sa_family == 0) return "[NONE SET]"; + free(buff); buff = INET6_rresolve((struct sockaddr_in6 *) sap, numeric); return buff; } From b62d4d9d5700d4931faac500fca11f440dacd610 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 3 Feb 2015 15:25:17 +0100 Subject: [PATCH 051/256] gzip: trivial code shrink -5 bytes Signed-off-by: Denys Vlasenko --- archival/gzip.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/archival/gzip.c b/archival/gzip.c index 18d795996..bc1f9c60b 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -442,19 +442,19 @@ static void put_16bit(ush w) *dst = (uch)w; w >>= 8; #else - *dst++ = (uch)w; + *dst = (uch)w; w >>= 8; if (outcnt < OUTBUFSIZ-2) { /* Common case */ - *dst = w; + dst[1] = w; G1.outcnt = outcnt + 2; return; } #endif /* Slowpath: we will need to do flush_outbuf() */ - G1.outcnt++; - if (G1.outcnt == OUTBUFSIZ) + G1.outcnt = ++outcnt; + if (outcnt == OUTBUFSIZ) flush_outbuf(); put_8bit(w); } From 09020b1aa891afaee865caf5fa46fa4ddb42f264 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 3 Feb 2015 19:32:44 +0100 Subject: [PATCH 052/256] route: improve -A inet6 Upstream route command shows non-up routes, it shows reject and nonexthop flags. And we had "ref" and "use" values mixed up... function old new delta flagvals 32 44 +12 flagchars 9 12 +3 INET_setroute 767 768 +1 INET6_setroute 495 496 +1 set_flags 43 39 -4 flags_ipvx 16 8 -8 route_main 632 623 -9 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/3 up/down: 17/-21) Total: -4 bytes Signed-off-by: Denys Vlasenko --- networking/route.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/networking/route.c b/networking/route.c index 24cc2eb5a..d82b0132a 100644 --- a/networking/route.c +++ b/networking/route.c @@ -55,6 +55,7 @@ #define RTF_WINDOW 0x0080 /* per route window clamping */ #define RTF_IRTT 0x0100 /* Initial round trip time */ #define RTF_REJECT 0x0200 /* Reject route */ +#define RTF_NONEXTHOP 0x00200000 /* route with no nexthop */ #endif #if defined(SIOCADDRTOLD) || defined(RTF_IRTT) /* route */ @@ -128,7 +129,7 @@ static const char tbl_ipvx[] ALIGN1 = "\013\043reinstate" /* Since last, we can save a byte. */ ; -static const int flags_ipvx[] = { /* MUST match tbl_ipvx[] values above. */ +static const uint16_t flags_ipvx[] = { /* MUST match tbl_ipvx[] values above. */ #ifdef RTF_REJECT RTF_REJECT, #endif @@ -449,7 +450,11 @@ static NOINLINE void INET6_setroute(int action, char **args) } #endif -static const unsigned flagvals[] = { /* Must agree with flagchars[]. */ +static const +IF_NOT_FEATURE_IPV6(uint16_t) +IF_FEATURE_IPV6(unsigned) +flagvals[] = { /* Must agree with flagchars[]. */ + RTF_UP, RTF_GATEWAY, RTF_HOST, RTF_REINSTATE, @@ -458,27 +463,25 @@ static const unsigned flagvals[] = { /* Must agree with flagchars[]. */ #if ENABLE_FEATURE_IPV6 RTF_DEFAULT, RTF_ADDRCONF, - RTF_CACHE + RTF_CACHE, + RTF_REJECT, + RTF_NONEXTHOP, /* this one doesn't fit into 16 bits */ #endif }; - -#define IPV4_MASK (RTF_GATEWAY|RTF_HOST|RTF_REINSTATE|RTF_DYNAMIC|RTF_MODIFIED) -#define IPV6_MASK (RTF_GATEWAY|RTF_HOST|RTF_DEFAULT|RTF_ADDRCONF|RTF_CACHE) - /* Must agree with flagvals[]. */ static const char flagchars[] ALIGN1 = - "GHRDM" + "UGHRDM" #if ENABLE_FEATURE_IPV6 - "DAC" + "DAC!n" #endif ; +#define IPV4_MASK (RTF_UP|RTF_GATEWAY|RTF_HOST|RTF_REINSTATE|RTF_DYNAMIC|RTF_MODIFIED) +#define IPV6_MASK (RTF_UP|RTF_GATEWAY|RTF_HOST|RTF_DEFAULT|RTF_ADDRCONF|RTF_CACHE|RTF_REJECT|RTF_NONEXTHOP) static void set_flags(char *flagstr, int flags) { int i; - *flagstr++ = 'U'; - for (i = 0; (*flagstr = flagchars[i]) != 0; i++) { if (flags & flagvals[i]) { ++flagstr; @@ -574,7 +577,7 @@ static void INET6_displayroutes(void) int r; r = fscanf(fp, "%32s%x%*s%x%32s%x%x%x%x%s\n", addr6x+14, &prefix_len, &slen, addr6x+40+7, - &metric, &use, &refcnt, &iflags, iface); + &metric, &refcnt, &use, &iflags, iface); if (r != 9) { if ((r < 0) && feof(fp)) { /* EOF with no (nonspace) chars read. */ break; @@ -606,10 +609,6 @@ static void INET6_displayroutes(void) } while (i < 40+28+7); } - if (!(iflags & RTF_UP)) { /* Skip interfaces that are down. */ - continue; - } - set_flags(flags, (iflags & IPV6_MASK)); r = 0; From a75dcd4353566f1a2d64baa642f1276f8ffd6ed4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 3 Feb 2015 19:42:28 +0100 Subject: [PATCH 053/256] route: fix bogus read error when route table is empty Signed-off-by: Denys Vlasenko --- networking/route.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/networking/route.c b/networking/route.c index d82b0132a..65c2fb7c8 100644 --- a/networking/route.c +++ b/networking/route.c @@ -494,6 +494,7 @@ void FAST_FUNC bb_displayroutes(int noresolve, int netstatfmt) { char devname[64], flags[16], *sdest, *sgw; unsigned long d, g, m; + int r; int flgs, ref, use, metric, mtu, win, ir; struct sockaddr_in s_addr; struct in_addr mask; @@ -504,20 +505,24 @@ void FAST_FUNC bb_displayroutes(int noresolve, int netstatfmt) "Destination Gateway Genmask Flags %s Iface\n", netstatfmt ? " MSS Window irtt" : "Metric Ref Use"); - if (fscanf(fp, "%*[^\n]\n") < 0) { /* Skip the first line. */ - goto ERROR; /* Empty or missing line, or read error. */ + /* Skip the first line. */ + r = fscanf(fp, "%*[^\n]\n"); + if (r < 0) { + /* Empty line, read error, or EOF. Yes, if routing table + * is completely empty, /proc/net/route has no header. + */ + goto ERROR; } while (1) { - int r; r = fscanf(fp, "%63s%lx%lx%X%d%d%d%lx%d%d%d\n", devname, &d, &g, &flgs, &ref, &use, &metric, &m, &mtu, &win, &ir); if (r != 11) { + ERROR: if ((r < 0) && feof(fp)) { /* EOF with no (nonspace) chars read. */ break; } - ERROR: - bb_error_msg_and_die("fscanf"); + bb_perror_msg_and_die(bb_msg_read_error); } if (!(flgs & RTF_UP)) { /* Skip interfaces that are down. */ @@ -583,7 +588,7 @@ static void INET6_displayroutes(void) break; } ERROR: - bb_error_msg_and_die("fscanf"); + bb_perror_msg_and_die(bb_msg_read_error); } /* Do the addr6x shift-and-insert changes to ':'-delimit addresses. From 3c5d133c7def0718e313928c69bde2e9784ce58e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 4 Feb 2015 15:19:38 +0100 Subject: [PATCH 054/256] fstrim: fix help text Signed-off-by: Denys Vlasenko --- util-linux/fstrim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util-linux/fstrim.c b/util-linux/fstrim.c index 675a02184..51400ef0b 100644 --- a/util-linux/fstrim.c +++ b/util-linux/fstrim.c @@ -32,7 +32,7 @@ //usage: " -o OFFSET Offset in bytes to discard from" //usage: "\n -l LEN Bytes to discard" //usage: "\n -m MIN Minimum extent length" -//usage: "\n -v, Print number of discarded bytes" +//usage: "\n -v Print number of discarded bytes" //usage: ) #include "libbb.h" From a14fa79592eadec0d5e296c66e79dfe36ce798c7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 5 Feb 2015 18:35:52 +0100 Subject: [PATCH 055/256] deluser: implement --remove-home function old new delta deluser_main 308 355 +47 packed_usage 30149 30156 +7 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 54/0) Total: 54 bytes Signed-off-by: Denys Vlasenko --- loginutils/deluser.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/loginutils/deluser.c b/loginutils/deluser.c index e39ac5506..2d98ecc58 100644 --- a/loginutils/deluser.c +++ b/loginutils/deluser.c @@ -11,9 +11,10 @@ */ //usage:#define deluser_trivial_usage -//usage: "USER" +//usage: IF_LONG_OPTS("[--remove-home] ") "USER" //usage:#define deluser_full_usage "\n\n" //usage: "Delete USER from the system" +// --remove-home is self-explanatory enough to put it in --help //usage:#define delgroup_trivial_usage //usage: IF_FEATURE_DEL_USER_FROM_GROUP("[USER] ")"GROUP" @@ -37,6 +38,19 @@ int deluser_main(int argc, char **argv) /* Are we deluser or delgroup? */ int do_deluser = (ENABLE_DELUSER && (!ENABLE_DELGROUP || applet_name[3] == 'u')); +#if !ENABLE_LONG_OPTS + const int opt_delhome = 0; +#else + int opt_delhome = 0; + if (do_deluser) { + applet_long_options = + "remove-home\0" No_argument "\xff"; + opt_delhome = getopt32(argv, ""); + argv += opt_delhome; + argc -= opt_delhome; + } +#endif + if (geteuid() != 0) bb_error_msg_and_die(bb_msg_perm_denied_are_you_root); @@ -55,10 +69,14 @@ int deluser_main(int argc, char **argv) case 2: if (do_deluser) { /* "deluser USER" */ - xgetpwnam(name); /* bail out if USER is wrong */ + struct passwd *pw; + + pw = xgetpwnam(name); /* bail out if USER is wrong */ pfile = bb_path_passwd_file; if (ENABLE_FEATURE_SHADOWPASSWDS) sfile = bb_path_shadow_file; + if (opt_delhome) + remove_file(pw->pw_dir, FILEUTILS_RECUR); } else { struct group *gr; do_delgroup: From 7e66102f762a7d80715f0c7e5925433256b78cee Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 5 Feb 2015 21:00:17 +0100 Subject: [PATCH 056/256] ash: fix a SEGV case in an invalid heredoc Signed-off-by: Denys Vlasenko --- shell/ash.c | 15 +++++++++++---- shell/ash_test/ash-heredoc/heredoc1.right | 1 + shell/ash_test/ash-heredoc/heredoc1.tests | 3 +++ 3 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 shell/ash_test/ash-heredoc/heredoc1.right create mode 100755 shell/ash_test/ash-heredoc/heredoc1.tests diff --git a/shell/ash.c b/shell/ash.c index c5ad96909..0f9f73ec3 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -10556,7 +10556,7 @@ static union node *andor(void); static union node *pipeline(void); static union node *parse_command(void); static void parseheredoc(void); -static char peektoken(void); +static char nexttoken_ends_list(void); static int readtoken(void); static union node * @@ -10566,7 +10566,7 @@ list(int nlflag) int tok; checkkwd = CHKNL | CHKKWD | CHKALIAS; - if (nlflag == 2 && peektoken()) + if (nlflag == 2 && nexttoken_ends_list()) return NULL; n1 = NULL; for (;;) { @@ -10608,8 +10608,15 @@ list(int nlflag) tokpushback = 1; } checkkwd = CHKNL | CHKKWD | CHKALIAS; - if (peektoken()) + if (nexttoken_ends_list()) { + /* Testcase: "< Date: Sat, 7 Feb 2015 01:41:22 +0100 Subject: [PATCH 057/256] dd: add optional support for status=noxfer/none While at it, added 'B' number suffixes, upstream compat function old new delta dd_main 1469 1543 +74 dd_suffixes 88 112 +24 packed_usage 30156 30176 +20 dd_output_status 372 388 +16 static.status_words - 13 +13 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 4/0 up/down: 147/0) Total: 147 bytes Signed-off-by: Ari Sundholm Signed-off-by: Denys Vlasenko --- coreutils/Config.src | 38 ------------ coreutils/dd.c | 143 +++++++++++++++++++++++++++++++++---------- 2 files changed, 111 insertions(+), 70 deletions(-) diff --git a/coreutils/Config.src b/coreutils/Config.src index 68c717883..1bbb91ee9 100644 --- a/coreutils/Config.src +++ b/coreutils/Config.src @@ -87,44 +87,6 @@ config CUT cut is used to print selected parts of lines from each file to stdout. -config DD - bool "dd" - default y - help - dd copies a file (from standard input to standard output, - by default) using specific input and output blocksizes, - while optionally performing conversions on it. - -config FEATURE_DD_SIGNAL_HANDLING - bool "Enable DD signal handling for status reporting" - default y - depends on DD - help - Sending a SIGUSR1 signal to a running `dd' process makes it - print to standard error the number of records read and written - so far, then to resume copying. - - $ dd if=/dev/zero of=/dev/null& - $ pid=$! kill -USR1 $pid; sleep 1; kill $pid - 10899206+0 records in - 10899206+0 records out - -config FEATURE_DD_THIRD_STATUS_LINE - bool "Enable the third status line upon signal" - default y - depends on DD && FEATURE_DD_SIGNAL_HANDLING - help - Displays a coreutils-like third status line with transferred bytes, - elapsed time and speed. - -config FEATURE_DD_IBS_OBS - bool "Enable ibs, obs and conv options" - default y - depends on DD - help - Enables support for writing a certain number of bytes in and out, - at a time, and performing conversions on the data stream. - config DF bool "df" default y diff --git a/coreutils/dd.c b/coreutils/dd.c index 2838f6341..302497074 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c @@ -8,6 +8,51 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ +//config:config DD +//config: bool "dd" +//config: default y +//config: help +//config: dd copies a file (from standard input to standard output, +//config: by default) using specific input and output blocksizes, +//config: while optionally performing conversions on it. +//config: +//config:config FEATURE_DD_SIGNAL_HANDLING +//config: bool "Enable signal handling for status reporting" +//config: default y +//config: depends on DD +//config: help +//config: Sending a SIGUSR1 signal to a running `dd' process makes it +//config: print to standard error the number of records read and written +//config: so far, then to resume copying. +//config: +//config: $ dd if=/dev/zero of=/dev/null & +//config: $ pid=$!; kill -USR1 $pid; sleep 1; kill $pid +//config: 10899206+0 records in +//config: 10899206+0 records out +//config: +//config:config FEATURE_DD_THIRD_STATUS_LINE +//config: bool "Enable the third status line upon signal" +//config: default y +//config: depends on DD && FEATURE_DD_SIGNAL_HANDLING +//config: help +//config: Displays a coreutils-like third status line with transferred bytes, +//config: elapsed time and speed. +//config: +//config:config FEATURE_DD_IBS_OBS +//config: bool "Enable ibs, obs and conv options" +//config: default y +//config: depends on DD +//config: help +//config: Enables support for writing a certain number of bytes in and out, +//config: at a time, and performing conversions on the data stream. +//config: +//config:config FEATURE_DD_STATUS +//config: bool "Enable status display options" +//config: default y +//config: depends on DD +//config: help +//config: Enables support for status=noxfer/none option. + //usage:#define dd_trivial_usage //usage: "[if=FILE] [of=FILE] " IF_FEATURE_DD_IBS_OBS("[ibs=N] [obs=N] ") "[bs=N] [count=N] [skip=N]\n" //usage: " [seek=N]" IF_FEATURE_DD_IBS_OBS(" [conv=notrunc|noerror|sync|fsync]") @@ -32,8 +77,12 @@ //usage: "\n conv=fsync Physically write data out before finishing" //usage: "\n conv=swab Swap every pair of bytes" //usage: ) +//usage: IF_FEATURE_DD_STATUS( +//usage: "\n status=noxfer Suppress rate output" +//usage: "\n status=none Suppress all output" +//usage: ) //usage: "\n" -//usage: "\nN may be suffixed by c (1), w (2), b (512), kD (1000), k (1024), MD, M, GD, G" +//usage: "\nN may be suffixed by c (1), w (2), b (512), kB (1000), k (1024), MB, M, GB, G" //usage: //usage:#define dd_example_usage //usage: "$ dd if=/dev/zero of=/dev/ram1 bs=1M count=4\n" @@ -54,13 +103,18 @@ static const struct suffix_mult dd_suffixes[] = { { "c", 1 }, { "w", 2 }, { "b", 512 }, + { "kB", 1000 }, { "kD", 1000 }, { "k", 1024 }, - { "K", 1024 }, /* compat with coreutils dd */ + { "K", 1024 }, /* compat with coreutils dd (it also accepts KB and KD, TODO?) */ + { "MB", 1000000 }, { "MD", 1000000 }, - { "M", 1048576 }, + { "M", 1024*1024 }, + { "GB", 1000000000 }, { "GD", 1000000000 }, - { "G", 1073741824 }, + { "G", 1024*1024*1024 }, + /* "D" suffix for decimal is not in coreutils manpage, looks like it's deprecated */ + /* coreutils also understands TPEZY suffixes for tera- and so on, with B suffix for decimal */ { "", 0 } }; @@ -70,6 +124,7 @@ struct globals { unsigned long long total_bytes; unsigned long long begin_time_us; #endif + int flags; } FIX_ALIASING; #define G (*(struct globals*)&bb_common_bufsiz1) #define INIT_G() do { \ @@ -77,6 +132,21 @@ struct globals { memset(&G, 0, sizeof(G)); \ } while (0) +enum { + /* Must be in the same order as OP_conv_XXX! */ + /* (see "flags |= (1 << what)" below) */ + FLAG_NOTRUNC = (1 << 0) * ENABLE_FEATURE_DD_IBS_OBS, + FLAG_SYNC = (1 << 1) * ENABLE_FEATURE_DD_IBS_OBS, + FLAG_NOERROR = (1 << 2) * ENABLE_FEATURE_DD_IBS_OBS, + FLAG_FSYNC = (1 << 3) * ENABLE_FEATURE_DD_IBS_OBS, + FLAG_SWAB = (1 << 4) * ENABLE_FEATURE_DD_IBS_OBS, + /* end of conv flags */ + FLAG_TWOBUFS = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS, + FLAG_COUNT = 1 << 6, + FLAG_STATUS = 1 << 7, + FLAG_STATUS_NONE = 1 << 7, + FLAG_STATUS_NOXFER = 1 << 8, +}; static void dd_output_status(int UNUSED_PARAM cur_signal) { @@ -93,6 +163,13 @@ static void dd_output_status(int UNUSED_PARAM cur_signal) G.out_full, G.out_part); #if ENABLE_FEATURE_DD_THIRD_STATUS_LINE +# if ENABLE_FEATURE_DD_STATUS + if (G.flags & FLAG_STATUS_NOXFER) /* status=noxfer active? */ + return; + //TODO: should status=none make dd stop reacting to USR1 entirely? + //So far we react to it (we print the stats), + //status=none only suppresses final, non-USR1 generated status message. +# endif fprintf(stderr, "%llu bytes (%sB) copied, ", G.total_bytes, /* show fractional digit, use suffixes */ @@ -148,20 +225,8 @@ static bool write_and_stats(const void *buf, size_t len, size_t obs, int dd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int dd_main(int argc UNUSED_PARAM, char **argv) { - enum { - /* Must be in the same order as OP_conv_XXX! */ - /* (see "flags |= (1 << what)" below) */ - FLAG_NOTRUNC = (1 << 0) * ENABLE_FEATURE_DD_IBS_OBS, - FLAG_SYNC = (1 << 1) * ENABLE_FEATURE_DD_IBS_OBS, - FLAG_NOERROR = (1 << 2) * ENABLE_FEATURE_DD_IBS_OBS, - FLAG_FSYNC = (1 << 3) * ENABLE_FEATURE_DD_IBS_OBS, - FLAG_SWAB = (1 << 4) * ENABLE_FEATURE_DD_IBS_OBS, - /* end of conv flags */ - FLAG_TWOBUFS = (1 << 5) * ENABLE_FEATURE_DD_IBS_OBS, - FLAG_COUNT = 1 << 6, - }; static const char keywords[] ALIGN1 = - "bs\0""count\0""seek\0""skip\0""if\0""of\0" + "bs\0""count\0""seek\0""skip\0""if\0""of\0"IF_FEATURE_DD_STATUS("status\0") #if ENABLE_FEATURE_DD_IBS_OBS "ibs\0""obs\0""conv\0" #endif @@ -169,6 +234,10 @@ int dd_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_FEATURE_DD_IBS_OBS static const char conv_words[] ALIGN1 = "notrunc\0""sync\0""noerror\0""fsync\0""swab\0"; +#endif +#if ENABLE_FEATURE_DD_STATUS + static const char status_words[] ALIGN1 = + "none\0""noxfer\0"; #endif enum { OP_bs = 0, @@ -177,6 +246,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) OP_skip, OP_if, OP_of, + IF_FEATURE_DD_STATUS(OP_status,) #if ENABLE_FEATURE_DD_IBS_OBS OP_ibs, OP_obs, @@ -215,14 +285,12 @@ int dd_main(int argc UNUSED_PARAM, char **argv) #endif /* These are all zeroed at once! */ struct { - int flags; size_t oc; ssize_t prev_read_size; /* for detecting swab failure */ off_t count; off_t seek, skip; const char *infile, *outfile; } Z; -#define flags (Z.flags ) #define oc (Z.oc ) #define prev_read_size (Z.prev_read_size) #define count (Z.count ) @@ -278,7 +346,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) n = index_in_strings(conv_words, val); if (n < 0) bb_error_msg_and_die(bb_msg_invalid_arg, val, "conv"); - flags |= (1 << n); + G.flags |= (1 << n); if (!arg) /* no ',' left, so this was the last specifier */ break; /* *arg = ','; - to preserve ps listing? */ @@ -294,7 +362,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) } /* These can be large: */ if (what == OP_count) { - flags |= FLAG_COUNT; + G.flags |= FLAG_COUNT; count = XATOU_SFX(val, dd_suffixes); /*continue;*/ } @@ -314,6 +382,16 @@ int dd_main(int argc UNUSED_PARAM, char **argv) outfile = val; /*continue;*/ } +#if ENABLE_FEATURE_DD_STATUS + if (what == OP_status) { + int n; + n = index_in_strings(status_words, val); + if (n < 0) + bb_error_msg_and_die(bb_msg_invalid_arg, val, "status"); + G.flags |= FLAG_STATUS << n; + /*continue;*/ + } +#endif } /* end of "for (argv[i])" */ //XXX:FIXME for huge ibs or obs, malloc'ing them isn't the brightest idea ever @@ -321,7 +399,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) obuf = ibuf; #if ENABLE_FEATURE_DD_IBS_OBS if (ibs != obs) { - flags |= FLAG_TWOBUFS; + G.flags |= FLAG_TWOBUFS; obuf = xmalloc(obs); } #endif @@ -341,12 +419,12 @@ int dd_main(int argc UNUSED_PARAM, char **argv) if (outfile) { int oflag = O_WRONLY | O_CREAT; - if (!seek && !(flags & FLAG_NOTRUNC)) + if (!seek && !(G.flags & FLAG_NOTRUNC)) oflag |= O_TRUNC; xmove_fd(xopen(outfile, oflag), ofd); - if (seek && !(flags & FLAG_NOTRUNC)) { + if (seek && !(G.flags & FLAG_NOTRUNC)) { if (ftruncate(ofd, seek * obs) < 0) { struct stat st; @@ -377,7 +455,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) goto die_outfile; } - while (!(flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) { + while (!(G.flags & FLAG_COUNT) || (G.in_full + G.in_part != count)) { ssize_t n; n = safe_read(ifd, ibuf, ibs); @@ -385,7 +463,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) break; if (n < 0) { /* "Bad block" */ - if (!(flags & FLAG_NOERROR)) + if (!(G.flags & FLAG_NOERROR)) goto die_infile; bb_simple_perror_msg(infile); /* GNU dd with conv=noerror skips over bad blocks */ @@ -394,7 +472,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) * conv=noerror just ignores input bad blocks */ n = 0; } - if (flags & FLAG_SWAB) { + if (G.flags & FLAG_SWAB) { uint16_t *p16; ssize_t n2; @@ -419,12 +497,12 @@ int dd_main(int argc UNUSED_PARAM, char **argv) G.in_full++; else { G.in_part++; - if (flags & FLAG_SYNC) { + if (G.flags & FLAG_SYNC) { memset(ibuf + n, 0, ibs - n); n = ibs; } } - if (flags & FLAG_TWOBUFS) { + if (G.flags & FLAG_TWOBUFS) { char *tmp = ibuf; while (n) { size_t d = obs - oc; @@ -446,7 +524,7 @@ int dd_main(int argc UNUSED_PARAM, char **argv) goto out_status; } - if (flags & FLAG_FSYNC) { + if (G.flags & FLAG_FSYNC) { if (fsync(ofd) < 0) goto die_outfile; } @@ -468,11 +546,12 @@ int dd_main(int argc UNUSED_PARAM, char **argv) exitcode = EXIT_SUCCESS; out_status: - dd_output_status(0); + if (!ENABLE_FEATURE_DD_STATUS || !(G.flags & FLAG_STATUS_NONE)) + dd_output_status(0); if (ENABLE_FEATURE_CLEAN_UP) { free(obuf); - if (flags & FLAG_TWOBUFS) + if (G.flags & FLAG_TWOBUFS) free(ibuf); } From a03195941b40f0d740f06d23648f672fe81d4ecf Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 7 Feb 2015 18:14:39 +0100 Subject: [PATCH 058/256] examples/mdev_fat.conf: document that newer mdev exposes path Signed-off-by: Denys Vlasenko --- examples/mdev_fat.conf | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/examples/mdev_fat.conf b/examples/mdev_fat.conf index f2a15f35d..630d2700a 100644 --- a/examples/mdev_fat.conf +++ b/examples/mdev_fat.conf @@ -19,7 +19,7 @@ # support module loading on hotplug $MODALIAS=.* root:root 660 @modprobe "$MODALIAS" -# null may already exist; therefore ownership has to be changed with command +# null may already exist; therefore mode has to be changed with command null root:root 666 @chmod 666 $MDEV zero root:root 666 full root:root 666 @@ -31,7 +31,7 @@ grsec root:root 660 kmem root:root 640 mem root:root 640 port root:root 640 -# console may already exist; therefore ownership has to be changed with command +# console may already exist; therefore mode has to be changed with command console root:tty 600 @chmod 600 $MDEV ptmx root:tty 666 pty.* root:tty 660 @@ -63,6 +63,12 @@ control.* root:audio 660 =snd/ midi.* root:audio 660 =snd/ seq root:audio 660 =snd/ timer root:audio 660 =snd/ +# for kernels/mdevs which expose full path of alsa devices: +snd/pcm.* root:audio 660 +snd/control.* root:audio 660 +snd/midi.* root:audio 660 +snd/seq root:audio 660 +snd/timer root:audio 660 adsp root:audio 660 >sound/ audio root:audio 660 >sound/ @@ -139,6 +145,6 @@ dahdi!(.*) root:dialout 660 =dahdi/%1 # We are hooking to the last events. To avoid having two scripts running, # we check for DISK_MEDIA_CHANGE=1 (prev to last event has it, # and it's the _only_ difference in env for these two events as of kernel 3.7.7) -# Unfortunately, there is no event for "user pressed [Turn USB storage] btn"! +# Unfortunately, there is no event for "user pressed [Turn USB storage on] btn"! # Script merely backgrounds and tries to rescan partition table for 1 minute: ACTION=change;SUBSYSTEM=block;DISK_MEDIA_CHANGE=1;.* 0:0 660 */etc/mdev.conf.change_blockdev.sh From 782ee2aa0e1646aebc96c8590ddc0a16405b8297 Mon Sep 17 00:00:00 2001 From: Kevin Wallace Date: Tue, 3 Feb 2015 16:17:29 -0800 Subject: [PATCH 059/256] libbb/loop: don't try to re-use existing loop device loopinfo.lo_file_name is not enough to uniquely identify a file on a system with multiple mount namespaces. We could conceivably change this to dedup on (lo_rdevice, lo_inode), but, as the comment above the deleted code notes, this whole approach of reusing devices is racy anyway, so it seems better to stop doing it entirely. Signed-off-by: Kevin Wallace Signed-off-by: Denys Vlasenko --- libbb/loop.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/libbb/loop.c b/libbb/loop.c index c96c5e070..d30b378d7 100644 --- a/libbb/loop.c +++ b/libbb/loop.c @@ -154,16 +154,7 @@ int FAST_FUNC set_loop(char **device, const char *file, unsigned long long offse else ioctl(dfd, LOOP_CLR_FD, 0); } - - /* If this block device already set up right, re-use it. - * (Yes this is racy, but associating two loop devices with the same - * file isn't pretty either. In general, mounting the same file twice - * without using losetup manually is problematic.) - */ - } else - if (strcmp(file, (char *)loopinfo.lo_file_name) != 0 - || offset != loopinfo.lo_offset - ) { + } else { rc = -1; } close(dfd); From 68c048fb23bd8b0831bbd02ec66900b12390cf19 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 7 Feb 2015 20:44:46 +0100 Subject: [PATCH 060/256] modprobe-small: fix and simplify rmmod "rmmod OUT_OF_TREE_MODULE" was not working, because module is not in depmod file. In general, rmmod doesn't need scanning, it simply unloads every argv[i]. function old new delta rmmod - 63 +63 modprobe_main 449 465 +16 process_module 705 667 -38 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/1 up/down: 79/-38) Total: 41 bytes Signed-off-by: Denys Vlasenko --- modutils/modprobe-small.c | 75 ++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 32 deletions(-) diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index cafbdc0b2..6b0a4400c 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c @@ -549,9 +549,23 @@ static int already_loaded(const char *name) return ret; } #else -#define already_loaded(name) is_rmmod +#define already_loaded(name) 0 #endif +static int rmmod(const char *filename) +{ + int r; + char modname[MODULE_NAME_LEN]; + + filename2modname(filename, modname); + r = delete_module(modname, O_NONBLOCK | O_EXCL); + dbg1_error_msg("delete_module('%s', O_NONBLOCK | O_EXCL):%d", modname, r); + if (r != 0 && !(option_mask32 & OPT_q)) { + bb_perror_msg("remove '%s'", modname); + } + return r; +} + /* * Given modules definition and module name (or alias, or symbol) * load/remove the module respecting dependencies. @@ -568,26 +582,36 @@ static void process_module(char *name, const char *cmdline_options) module_info **infovec; module_info *info; int infoidx; - int is_rmmod = (option_mask32 & OPT_r) != 0; + int is_remove = (option_mask32 & OPT_r) != 0; dbg1_error_msg("process_module('%s','%s')", name, cmdline_options); replace(name, '-', '_'); - dbg1_error_msg("already_loaded:%d is_rmmod:%d", already_loaded(name), is_rmmod); + dbg1_error_msg("already_loaded:%d is_remove:%d", already_loaded(name), is_remove); + + if (applet_name[0] == 'r') { + /* rmmod. + * Does not remove dependencies, no need to scan, just remove. + * (compat note: this allows and strips .ko suffix) + */ + rmmod(name); + return; + } + /* - * We used to have "is_rmmod != already_loaded(name)" check here, but + * We used to have "is_remove != already_loaded(name)" check here, but * modprobe -r pci:v00008086d00007010sv00000000sd00000000bc01sc01i80 * won't unload modules (there are more than one) * which have this alias. */ - if (!is_rmmod && already_loaded(name)) { + if (!is_remove && already_loaded(name)) { dbg1_error_msg("nothing to do for '%s'", name); return; } options = NULL; - if (!is_rmmod) { + if (!is_remove) { char *opt_filename = xasprintf("/etc/modules/%s", name); options = xmalloc_open_read_close(opt_filename, NULL); if (options) @@ -621,7 +645,7 @@ static void process_module(char *name, const char *cmdline_options) 0 /* depth */ ); dbg1_error_msg("dirscan complete"); - /* Module was not found, or load failed, or is_rmmod */ + /* Module was not found, or load failed, or is_remove */ if (module_found_idx >= 0) { /* module was found */ infovec = xzalloc(2 * sizeof(infovec[0])); infovec[0] = &modinfo[module_found_idx]; @@ -634,7 +658,7 @@ static void process_module(char *name, const char *cmdline_options) if (!infovec) { /* both dirscan and find_alias found nothing */ - if (!is_rmmod && applet_name[0] != 'd') /* it wasn't rmmod or depmod */ + if (!is_remove && applet_name[0] != 'd') /* it wasn't rmmod or depmod */ bb_error_msg("module '%s' not found", name); //TODO: _and_die()? or should we continue (un)loading modules listed on cmdline? goto ret; @@ -648,29 +672,15 @@ static void process_module(char *name, const char *cmdline_options) * a *list* of modinfo pointers from find_alias(). */ - /* rmmod or modprobe -r? unload module(s) */ - if (is_rmmod) { + /* modprobe -r? unload module(s) */ + if (is_remove) { infoidx = 0; while ((info = infovec[infoidx++]) != NULL) { - int r; - char modname[MODULE_NAME_LEN]; - - filename2modname( - bb_get_last_path_component_nostrip(info->pathname), modname); - r = delete_module(modname, O_NONBLOCK | O_EXCL); - dbg1_error_msg("delete_module('%s', O_NONBLOCK | O_EXCL):%d", modname, r); + int r = rmmod(bb_get_last_path_component_nostrip(info->pathname)); if (r != 0) { - if (!(option_mask32 & OPT_q)) - bb_perror_msg("remove '%s'", modname); - goto ret; + goto ret; /* error */ } } - - if (applet_name[0] == 'r') { - /* rmmod: do not remove dependencies, exit */ - goto ret; - } - /* modprobe -r: we do not stop here - * continue to unload modules on which the module depends: * "-r --remove: option causes modprobe to remove a module. @@ -691,7 +701,7 @@ static void process_module(char *name, const char *cmdline_options) } free(deps); - if (is_rmmod) + if (is_remove) continue; /* We are modprobe: load it */ @@ -894,10 +904,10 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) } #if ENABLE_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE - /* If not rmmod, parse possible module options given on command line. + /* If not rmmod/-r, parse possible module options given on command line. * insmod/modprobe takes one module name, the rest are parameters. */ options = NULL; - if ('r' != applet0) { + if (!(option_mask32 & OPT_r)) { char **arg = argv; while (*++arg) { /* Enclose options in quotes */ @@ -908,7 +918,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) } } #else - if ('r' != applet0) + if (!(option_mask32 & OPT_r)) argv[1] = NULL; #endif @@ -932,10 +942,11 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) } /* Try to load modprobe.dep.bb */ - load_dep_bb(); + if ('r' != applet0) /* not rmmod */ + load_dep_bb(); /* Load/remove modules. - * Only rmmod loops here, modprobe has only argv[0] */ + * Only rmmod/modprobe -r loops here, insmod/modprobe has only argv[0] */ do { process_module(*argv, options); } while (*++argv); From 23cfaab47de7392c1ba7d601a05fb36da3629b28 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 7 Feb 2015 21:21:02 +0100 Subject: [PATCH 061/256] libpwdgrp: use getpwent() instead of getpwent_r() function old new delta massage_data_for_non_r_func - 90 +90 bb_internal_getpwent - 69 +69 getXXnam_r 94 162 +68 fill_bounds 131 128 -3 deluser_main 355 310 -45 complete_username 123 78 -45 getXXnam 163 90 -73 massage_data_for_r_func 103 - -103 bb_internal_getpwent_r 121 - -121 ------------------------------------------------------------------------------ (add/remove: 2/2 grow/shrink: 1/5 up/down: 227/-407) Total: -163 bytes Signed-off-by: Denys Vlasenko --- include/pwd_.h | 16 +----------- libbb/lineedit.c | 13 ++++------ libpwdgrp/pwd_grp.c | 58 ++++++++++++++++++++++++++++++++------------ loginutils/deluser.c | 9 +++---- 4 files changed, 53 insertions(+), 43 deletions(-) diff --git a/include/pwd_.h b/include/pwd_.h index 32b5b366e..17348298a 100644 --- a/include/pwd_.h +++ b/include/pwd_.h @@ -36,7 +36,6 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN #define getpwent bb_internal_getpwent #define getpwuid bb_internal_getpwuid #define getpwnam bb_internal_getpwnam -#define getpwent_r bb_internal_getpwent_r #define getpwnam_r bb_internal_getpwnam_r /* All function names below should be remapped by #defines above @@ -48,10 +47,8 @@ void FAST_FUNC setpwent(void); /* Close the password-file stream. */ void FAST_FUNC endpwent(void); -#ifdef UNUSED_SINCE_WE_AVOID_STATIC_BUFS /* Read an entry from the password-file stream, opening it if necessary. */ struct passwd* FAST_FUNC getpwent(void); -#endif /* Search for an entry with a matching user ID. */ struct passwd* FAST_FUNC getpwuid(uid_t __uid); @@ -59,18 +56,7 @@ struct passwd* FAST_FUNC getpwuid(uid_t __uid); /* Search for an entry with a matching username. */ struct passwd* FAST_FUNC getpwnam(const char *__name); -/* Reentrant versions of some of the functions above. - - PLEASE NOTE: the `getpwent_r' function is not (yet) standardized. - The interface may change in later versions of this library. But - the interface is designed following the principals used for the - other reentrant functions so the chances are good this is what the - POSIX people would choose. */ - -int FAST_FUNC getpwent_r(struct passwd *__restrict __resultbuf, - char *__restrict __buffer, size_t __buflen, - struct passwd **__restrict __result); - +/* Reentrant versions of some of the functions above. */ int FAST_FUNC getpwnam_r(const char *__restrict __name, struct passwd *__restrict __resultbuf, char *__restrict __buffer, size_t __buflen, diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 720a4951e..249b401b4 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -672,23 +672,20 @@ static char *username_path_completion(char *ud) */ static NOINLINE unsigned complete_username(const char *ud) { - /* Using _r function to avoid pulling in static buffers */ - char line_buff[256]; - struct passwd pwd; - struct passwd *result; + struct passwd *pw; unsigned userlen; ud++; /* skip ~ */ userlen = strlen(ud); setpwent(); - while (!getpwent_r(&pwd, line_buff, sizeof(line_buff), &result)) { + while ((pw = getpwent()) != NULL) { /* Null usernames should result in all users as possible completions. */ - if (/*!userlen || */ strncmp(ud, pwd.pw_name, userlen) == 0) { - add_match(xasprintf("~%s/", pwd.pw_name)); + if (/*!userlen || */ strncmp(ud, pw->pw_name, userlen) == 0) { + add_match(xasprintf("~%s/", pw->pw_name)); } } - endpwent(); + endpwent(); /* don't keep password file open */ return 1 + userlen; } diff --git a/libpwdgrp/pwd_grp.c b/libpwdgrp/pwd_grp.c index 90647e9d3..7ec704ee4 100644 --- a/libpwdgrp/pwd_grp.c +++ b/libpwdgrp/pwd_grp.c @@ -336,6 +336,22 @@ static int massage_data_for_r_func(struct passdb *db, return errno; } +static void* massage_data_for_non_r_func(struct passdb *db, char *buf) +{ + if (!buf) + return NULL; + + free(db->malloced); + /* We enlarge buf and move string data up, freeing space + * for struct passwd/group/spwd at the beginning. This way, + * entire result of getXXnam is in a single malloced block. + * This enables easy creation of xmalloc_getpwnam() API. + */ + db->malloced = buf = xrealloc(buf, db->size_of + S.string_size); + memmove(buf + db->size_of, buf, S.string_size); + return convert_to_struct(db, buf + db->size_of, buf); +} + /****** getXXnam/id_r */ static int FAST_FUNC getXXnam_r(const char *name, uintptr_t db_and_field_pos, @@ -372,6 +388,7 @@ int FAST_FUNC getspnam_r(const char *name, struct spwd *struct_buf, char *buffer } #endif +#ifdef UNUSED /****** getXXent_r */ static int FAST_FUNC getXXent_r(uintptr_t db_idx, char *buffer, size_t buflen, @@ -400,17 +417,39 @@ int FAST_FUNC getpwent_r(struct passwd *struct_buf, char *buffer, size_t buflen, *result = struct_buf; return getXXent_r(0, buffer, buflen, result); } +#endif + +/****** getXXent */ + +static void* FAST_FUNC getXXent(uintptr_t db_idx) +{ + char *buf; + struct passdb *db = &get_S()->db[db_idx]; + + if (!db->fp) { + db->fp = fopen_for_read(db->filename); + if (!db->fp) { + return NULL; + } + close_on_exec_on(fileno(db->fp)); + } + + buf = parse_common(db->fp, db, /*no search key:*/ NULL, -1); + return massage_data_for_non_r_func(db, buf); +} + +struct passwd* FAST_FUNC getpwent(void) +{ + return getXXent(0); +} /****** getXXnam/id */ static void* FAST_FUNC getXXnam(const char *name, unsigned db_and_field_pos) { char *buf; - void *result; struct passdb *db = &get_S()->db[db_and_field_pos >> 2]; - result = NULL; - if (!db->fp) { db->fp = fopen_for_read(db->filename); if (!db->fp) { @@ -420,18 +459,7 @@ static void* FAST_FUNC getXXnam(const char *name, unsigned db_and_field_pos) } buf = parse_common(db->fp, db, name, db_and_field_pos & 3); - if (buf) { - free(db->malloced); - /* We enlarge buf and move string data up, freeing space - * for struct passwd/group/spwd at the beginning. This way, - * entire result of getXXnam is in a single malloced block. - * This enables easy creation of xmalloc_getpwnam() API. - */ - db->malloced = buf = xrealloc(buf, db->size_of + S.string_size); - memmove(buf + db->size_of, buf, S.string_size); - result = convert_to_struct(db, buf + db->size_of, buf); - } - return result; + return massage_data_for_non_r_func(db, buf); } struct passwd* FAST_FUNC getpwnam(const char *name) diff --git a/loginutils/deluser.c b/loginutils/deluser.c index 2d98ecc58..01a9386bc 100644 --- a/loginutils/deluser.c +++ b/loginutils/deluser.c @@ -91,12 +91,11 @@ int deluser_main(int argc, char **argv) if (!member) { /* "delgroup GROUP" */ struct passwd *pw; - struct passwd pwent; /* Check if the group is in use */ -#define passwd_buf bb_common_bufsiz1 - while (!getpwent_r(&pwent, passwd_buf, sizeof(passwd_buf), &pw)) { - if (pwent.pw_gid == gr->gr_gid) - bb_error_msg_and_die("'%s' still has '%s' as their primary group!", pwent.pw_name, name); + while ((pw = getpwent()) != NULL) { + if (pw->pw_gid == gr->gr_gid) + bb_error_msg_and_die("'%s' still has '%s' as their primary group!", + pw->pw_name, name); } //endpwent(); } From 8c06bc6ba14949d945eff0abcabab885f1ef7680 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 10 Feb 2015 01:30:43 +0100 Subject: [PATCH 062/256] unzip: prevent attacks via malicious filenames Signed-off-by: Denys Vlasenko --- archival/libarchive/Kbuild.src | 5 ++-- archival/libarchive/get_header_tar.c | 30 ----------------------- archival/libarchive/unsafe_prefix.c | 36 ++++++++++++++++++++++++++++ archival/unzip.c | 35 ++++++++++++++++++--------- 4 files changed, 63 insertions(+), 43 deletions(-) create mode 100644 archival/libarchive/unsafe_prefix.c diff --git a/archival/libarchive/Kbuild.src b/archival/libarchive/Kbuild.src index 7e89e9e89..b7faaf77f 100644 --- a/archival/libarchive/Kbuild.src +++ b/archival/libarchive/Kbuild.src @@ -30,6 +30,7 @@ COMMON_FILES:= \ DPKG_FILES:= \ unpack_ar_archive.o \ filter_accept_list_reassign.o \ + unsafe_prefix.o \ get_header_ar.o \ get_header_tar.o \ get_header_tar_gz.o \ @@ -44,7 +45,7 @@ lib-$(CONFIG_DPKG_DEB) += $(DPKG_FILES) lib-$(CONFIG_AR) += get_header_ar.o unpack_ar_archive.o lib-$(CONFIG_CPIO) += get_header_cpio.o -lib-$(CONFIG_TAR) += get_header_tar.o +lib-$(CONFIG_TAR) += get_header_tar.o unsafe_prefix.o lib-$(CONFIG_FEATURE_TAR_TO_COMMAND) += data_extract_to_command.o lib-$(CONFIG_LZOP) += lzo1x_1.o lzo1x_1o.o lzo1x_d.o lib-$(CONFIG_LZOP_COMPR_HIGH) += lzo1x_9x.o @@ -53,7 +54,7 @@ lib-$(CONFIG_UNLZMA) += open_transformer.o decompress_unlzma. lib-$(CONFIG_UNXZ) += open_transformer.o decompress_unxz.o lib-$(CONFIG_GUNZIP) += open_transformer.o decompress_gunzip.o lib-$(CONFIG_UNCOMPRESS) += open_transformer.o decompress_uncompress.o -lib-$(CONFIG_UNZIP) += open_transformer.o decompress_gunzip.o +lib-$(CONFIG_UNZIP) += open_transformer.o decompress_gunzip.o unsafe_prefix.o lib-$(CONFIG_RPM2CPIO) += open_transformer.o decompress_gunzip.o get_header_cpio.o lib-$(CONFIG_RPM) += open_transformer.o decompress_gunzip.o get_header_cpio.o diff --git a/archival/libarchive/get_header_tar.c b/archival/libarchive/get_header_tar.c index ba43bb073..0c663fbd7 100644 --- a/archival/libarchive/get_header_tar.c +++ b/archival/libarchive/get_header_tar.c @@ -17,36 +17,6 @@ typedef uint32_t aliased_uint32_t FIX_ALIASING; typedef off_t aliased_off_t FIX_ALIASING; - -const char* FAST_FUNC strip_unsafe_prefix(const char *str) -{ - const char *cp = str; - while (1) { - char *cp2; - if (*cp == '/') { - cp++; - continue; - } - if (strncmp(cp, "/../"+1, 3) == 0) { - cp += 3; - continue; - } - cp2 = strstr(cp, "/../"); - if (!cp2) - break; - cp = cp2 + 4; - } - if (cp != str) { - static smallint warned = 0; - if (!warned) { - warned = 1; - bb_error_msg("removing leading '%.*s' from member names", - (int)(cp - str), str); - } - } - return cp; -} - /* NB: _DESTROYS_ str[len] character! */ static unsigned long long getOctal(char *str, int len) { diff --git a/archival/libarchive/unsafe_prefix.c b/archival/libarchive/unsafe_prefix.c new file mode 100644 index 000000000..826c673bf --- /dev/null +++ b/archival/libarchive/unsafe_prefix.c @@ -0,0 +1,36 @@ +/* vi: set sw=4 ts=4: */ +/* + * Licensed under GPLv2 or later, see file LICENSE in this source tree. + */ + +#include "libbb.h" +#include "bb_archive.h" + +const char* FAST_FUNC strip_unsafe_prefix(const char *str) +{ + const char *cp = str; + while (1) { + char *cp2; + if (*cp == '/') { + cp++; + continue; + } + if (strncmp(cp, "/../"+1, 3) == 0) { + cp += 3; + continue; + } + cp2 = strstr(cp, "/../"); + if (!cp2) + break; + cp = cp2 + 4; + } + if (cp != str) { + static smallint warned = 0; + if (!warned) { + warned = 1; + bb_error_msg("removing leading '%.*s' from member names", + (int)(cp - str), str); + } + } + return cp; +} diff --git a/archival/unzip.c b/archival/unzip.c index 38a07e212..eed225677 100644 --- a/archival/unzip.c +++ b/archival/unzip.c @@ -596,14 +596,18 @@ int unzip_main(int argc, char **argv) /* Skip extra header bytes */ unzip_skip(zip_header.formatted.extra_len); + /* Guard against "/abspath", "/../" and similar attacks */ + overlapping_strcpy(dst_fn, strip_unsafe_prefix(dst_fn)); + /* Filter zip entries */ if (find_list_entry(zreject, dst_fn) || (zaccept && !find_list_entry(zaccept, dst_fn)) ) { /* Skip entry */ i = 'n'; - } else { /* Extract entry */ - if (listing) { /* List entry */ + } else { + if (listing) { + /* List entry */ unsigned dostime = zip_header.formatted.modtime | (zip_header.formatted.moddate << 16); if (!verbose) { // " Length Date Time Name\n" @@ -639,9 +643,11 @@ int unzip_main(int argc, char **argv) total_size += zip_header.formatted.cmpsize; } i = 'n'; - } else if (dst_fd == STDOUT_FILENO) { /* Extracting to STDOUT */ + } else if (dst_fd == STDOUT_FILENO) { + /* Extracting to STDOUT */ i = -1; - } else if (last_char_is(dst_fn, '/')) { /* Extract directory */ + } else if (last_char_is(dst_fn, '/')) { + /* Extract directory */ if (stat(dst_fn, &stat_buf) == -1) { if (errno != ENOENT) { bb_perror_msg_and_die("can't stat '%s'", dst_fn); @@ -655,22 +661,27 @@ int unzip_main(int argc, char **argv) } } else { if (!S_ISDIR(stat_buf.st_mode)) { - bb_error_msg_and_die("'%s' exists but is not directory", dst_fn); + bb_error_msg_and_die("'%s' exists but is not a %s", + dst_fn, "directory"); } } i = 'n'; - } else { /* Extract file */ + } else { + /* Extract file */ check_file: - if (stat(dst_fn, &stat_buf) == -1) { /* File does not exist */ + if (stat(dst_fn, &stat_buf) == -1) { + /* File does not exist */ if (errno != ENOENT) { bb_perror_msg_and_die("can't stat '%s'", dst_fn); } i = 'y'; - } else { /* File already exists */ + } else { + /* File already exists */ if (overwrite == O_NEVER) { i = 'n'; - } else if (S_ISREG(stat_buf.st_mode)) { /* File is regular file */ + } else if (S_ISREG(stat_buf.st_mode)) { + /* File is regular file */ if (overwrite == O_ALWAYS) { i = 'y'; } else { @@ -678,8 +689,10 @@ int unzip_main(int argc, char **argv) my_fgets80(key_buf); i = key_buf[0]; } - } else { /* File is not regular file */ - bb_error_msg_and_die("'%s' exists but is not regular file", dst_fn); + } else { + /* File is not regular file */ + bb_error_msg_and_die("'%s' exists but is not a %s", + dst_fn, "regular file"); } } } From 622a7aab2c4a918c0e71931505f5c38d66d81ad9 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 10 Feb 2015 03:16:25 +0100 Subject: [PATCH 063/256] i2cget, i2cset, i2cdetect, i2cdump: new applets Add a minimal implementation of i2cget, i2cset, i2cdump and i2cdetect tools. Supports most features of upstream i2c-tools. function old new delta i2cdump_main - 1444 +1444 i2cset_main - 1239 +1239 i2cdetect_main - 611 +611 list_i2c_busses_and_exit - 532 +532 packed_usage 29975 30438 +463 i2cget_main - 380 +380 check_read_funcs - 140 +140 i2c_funcs_tab - 128 +128 confirm_action - 100 +100 i2c_dev_open - 57 +57 i2c_smbus_access - 44 +44 confirm_or_abort - 43 +43 check_funcs_test_end - 39 +39 i2c_smbus_read_word_data - 38 +38 i2c_smbus_read_byte_data - 38 +38 i2c_smbus_read_byte - 37 +37 i2c_set_slave_addr - 32 +32 applet_names 2480 2512 +32 adap_descs - 32 +32 i2c_set_pec - 29 +29 get_funcs_matrix - 21 +21 i2c_parse_data_addr - 18 +18 i2c_parse_bus_addr - 18 +18 i2c_bus_lookup - 18 +18 i2c_smbus_write_byte - 17 +17 applet_main 1440 1456 +16 will_skip - 14 +14 no_support - 11 +11 applet_nameofs 720 728 +8 applet_install_loc 180 182 +2 ------------------------------------------------------------------------------ (add/remove: 26/0 grow/shrink: 5/0 up/down: 5601/0) Total: 5601 bytes Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- miscutils/i2c_tools.c | 1396 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1396 insertions(+) create mode 100644 miscutils/i2c_tools.c diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c new file mode 100644 index 000000000..90d1e1e14 --- /dev/null +++ b/miscutils/i2c_tools.c @@ -0,0 +1,1396 @@ +/* vi: set sw=4 ts=4: */ +/* + * Minimal i2c-tools implementation for busybox. + * Parts of code ported from i2c-tools: + * http://www.lm-sensors.org/wiki/I2CTools. + * + * Copyright (C) 2014 by Bartosz Golaszewski + * + * Licensed under GPLv2 or later, see file LICENSE in this source tree. + */ + +//config:config I2CGET +//config: bool "i2cget" +//config: default y +//config: select PLATFORM_LINUX +//config: help +//config: Read from I2C/SMBus chip registers. +//config: +//config:config I2CSET +//config: bool "i2cset" +//config: default y +//config: select PLATFORM_LINUX +//config: help +//config: Set I2C registers. +//config: +//config:config I2CDUMP +//config: bool "i2cdump" +//config: default y +//config: select PLATFORM_LINUX +//config: help +//config: Examine I2C registers. +//config: +//config:config I2CDETECT +//config: bool "i2cdetect" +//config: default y +//config: select PLATFORM_LINUX +//config: help +//config: Detect I2C chips. +//config: + +//applet:IF_I2CGET(APPLET(i2cget, BB_DIR_USR_SBIN, BB_SUID_DROP)) +//applet:IF_I2CSET(APPLET(i2cset, BB_DIR_USR_SBIN, BB_SUID_DROP)) +//applet:IF_I2CDUMP(APPLET(i2cdump, BB_DIR_USR_SBIN, BB_SUID_DROP)) +//applet:IF_I2CDETECT(APPLET(i2cdetect, BB_DIR_USR_SBIN, BB_SUID_DROP)) + +//kbuild:lib-$(CONFIG_I2CGET) += i2c_tools.o +//kbuild:lib-$(CONFIG_I2CSET) += i2c_tools.o +//kbuild:lib-$(CONFIG_I2CDUMP) += i2c_tools.o +//kbuild:lib-$(CONFIG_I2CDETECT) += i2c_tools.o + +/* + * Unsupported stuff: + * + * - upstream i2c-tools can also look-up i2c busses by name, we only accept + * numbers, + * - bank and bankreg parameters for i2cdump are not supported because of + * their limited usefulness (see i2cdump manual entry for more info), + * - i2cdetect doesn't look for bus info in /proc as it does in upstream, but + * it shouldn't be a problem in modern kernels. + */ + +#include "libbb.h" + +/* + * /dev/i2c-X ioctl commands. The ioctl's parameter is always an unsigned long, + * except for: + * - I2C_FUNCS, takes pointer to an unsigned long + * - I2C_RDWR, takes pointer to struct i2c_rdwr_ioctl_data + * - I2C_SMBUS, takes pointer to struct i2c_smbus_ioctl_data + */ + +/* + * NOTE: Slave address is 7 or 10 bits, but 10-bit addresses + * are not supported due to code brokenness. + */ + +/* Use this slave address. */ +#define I2C_SLAVE 0x0703 +/* Use this slave address, even if it is already in use by a driver. */ +#define I2C_SLAVE_FORCE 0x0706 +/* 0 for 7 bit addrs, != 0 for 10 bit. */ +#define I2C_TENBIT 0x0704 +/* Get the adapter functionality mask. */ +#define I2C_FUNCS 0x0705 +/* Combined R/W transfer (one STOP only). */ +#define I2C_RDWR 0x0707 +/* != 0 to use PEC with SMBus. */ +#define I2C_PEC 0x0708 +/* SMBus transfer. */ +#define I2C_SMBUS 0x0720 + +/* Structure used in the I2C_SMBUS ioctl call. */ +struct i2c_smbus_ioctl_data { + uint8_t read_write; + uint8_t command; + uint32_t size; + union i2c_smbus_data *data; +}; + +/* Structure used in the I2C_RDWR ioctl call. */ +struct i2c_rdwr_ioctl_data { + struct i2c_msg *msgs; /* Pointers to i2c_msgs. */ + uint32_t nmsgs; /* Number of i2c_msgs. */ +}; + +/* As specified in SMBus standard. */ +#define I2C_SMBUS_BLOCK_MAX 32 +/* Not specified but we use same structure. */ +#define I2C_SMBUS_I2C_BLOCK_MAX 32 + +/* Data for SMBus Messages. */ +union i2c_smbus_data { + uint8_t byte; + uint16_t word; + /* block[0] is used for length and one more for PEC */ + uint8_t block[I2C_SMBUS_BLOCK_MAX + 2]; +}; + +#define I2C_RDRW_IOCTL_MAX_MSGS 42 +#define I2C_MAX_REGS 256 + +/* Smbus_access read or write markers. */ +#define I2C_SMBUS_READ 1 +#define I2C_SMBUS_WRITE 0 + +/* SMBus transaction types (size parameter in the below functions). */ +#define I2C_SMBUS_QUICK 0 +#define I2C_SMBUS_BYTE 1 +#define I2C_SMBUS_BYTE_DATA 2 +#define I2C_SMBUS_WORD_DATA 3 +#define I2C_SMBUS_PROC_CALL 4 +#define I2C_SMBUS_BLOCK_DATA 5 +#define I2C_SMBUS_I2C_BLOCK_BROKEN 6 +#define I2C_SMBUS_BLOCK_PROC_CALL 7 +#define I2C_SMBUS_I2C_BLOCK_DATA 8 + +#define DETECT_MODE_AUTO 0 +#define DETECT_MODE_QUICK 1 +#define DETECT_MODE_READ 2 + +/* Defines to determine what functionality is present. */ +#define I2C_FUNC_I2C 0x00000001 +#define I2C_FUNC_10BIT_ADDR 0x00000002 +#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 +#define I2C_FUNC_SMBUS_PEC 0x00000008 +#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 +#define I2C_FUNC_SMBUS_QUICK 0x00010000 +#define I2C_FUNC_SMBUS_READ_BYTE 0x00020000 +#define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000 +#define I2C_FUNC_SMBUS_READ_BYTE_DATA 0x00080000 +#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA 0x00100000 +#define I2C_FUNC_SMBUS_READ_WORD_DATA 0x00200000 +#define I2C_FUNC_SMBUS_WRITE_WORD_DATA 0x00400000 +#define I2C_FUNC_SMBUS_PROC_CALL 0x00800000 +#define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000 +#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000 +#define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 +#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 + +#define I2C_FUNC_SMBUS_BYTE (I2C_FUNC_SMBUS_READ_BYTE | \ + I2C_FUNC_SMBUS_WRITE_BYTE) +#define I2C_FUNC_SMBUS_BYTE_DATA (I2C_FUNC_SMBUS_READ_BYTE_DATA | \ + I2C_FUNC_SMBUS_WRITE_BYTE_DATA) +#define I2C_FUNC_SMBUS_WORD_DATA (I2C_FUNC_SMBUS_READ_WORD_DATA | \ + I2C_FUNC_SMBUS_WRITE_WORD_DATA) +#define I2C_FUNC_SMBUS_BLOCK_DATA (I2C_FUNC_SMBUS_READ_BLOCK_DATA | \ + I2C_FUNC_SMBUS_WRITE_BLOCK_DATA) +#define I2C_FUNC_SMBUS_I2C_BLOCK (I2C_FUNC_SMBUS_READ_I2C_BLOCK | \ + I2C_FUNC_SMBUS_WRITE_I2C_BLOCK) + +/* + * This is needed for ioctl_or_perror_and_die() since it only accepts pointers. + */ +static ALWAYS_INLINE void *itoptr(int i) +{ + return (void*)(intptr_t)i; +} + +static int32_t i2c_smbus_access(int fd, char read_write, uint8_t cmd, + int size, union i2c_smbus_data *data) +{ + struct i2c_smbus_ioctl_data args; + + args.read_write = read_write; + args.command = cmd; + args.size = size; + args.data = data; + + return ioctl(fd, I2C_SMBUS, &args); +} + +static int32_t i2c_smbus_read_byte(int fd) +{ + union i2c_smbus_data data; + int err; + + err = i2c_smbus_access(fd, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &data); + if (err < 0) + return err; + + return data.byte; +} + +#if ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP +static int32_t i2c_smbus_write_byte(int fd, uint8_t val) +{ + return i2c_smbus_access(fd, I2C_SMBUS_WRITE, + val, I2C_SMBUS_BYTE, NULL); +} + +static int32_t i2c_smbus_read_byte_data(int fd, uint8_t cmd) +{ + union i2c_smbus_data data; + int err; + + err = i2c_smbus_access(fd, I2C_SMBUS_READ, cmd, + I2C_SMBUS_BYTE_DATA, &data); + if (err < 0) + return err; + + return data.byte; +} + +static int32_t i2c_smbus_read_word_data(int fd, uint8_t cmd) +{ + union i2c_smbus_data data; + int err; + + err = i2c_smbus_access(fd, I2C_SMBUS_READ, cmd, + I2C_SMBUS_WORD_DATA, &data); + if (err < 0) + return err; + + return data.word; +} +#endif /* ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP */ + +#if ENABLE_I2CSET +static int32_t i2c_smbus_write_byte_data(int file, + uint8_t cmd, uint8_t value) +{ + union i2c_smbus_data data; + + data.byte = value; + + return i2c_smbus_access(file, I2C_SMBUS_WRITE, cmd, + I2C_SMBUS_BYTE_DATA, &data); +} + +static int32_t i2c_smbus_write_word_data(int file, uint8_t cmd, uint16_t value) +{ + union i2c_smbus_data data; + + data.word = value; + + return i2c_smbus_access(file, I2C_SMBUS_WRITE, cmd, + I2C_SMBUS_WORD_DATA, &data); +} + +static int32_t i2c_smbus_write_block_data(int file, uint8_t cmd, + uint8_t length, const uint8_t *values) +{ + union i2c_smbus_data data; + + if (length > I2C_SMBUS_BLOCK_MAX) + length = I2C_SMBUS_BLOCK_MAX; + + memcpy(data.block+1, values, length); + data.block[0] = length; + + return i2c_smbus_access(file, I2C_SMBUS_WRITE, cmd, + I2C_SMBUS_BLOCK_DATA, &data); +} + +static int32_t i2c_smbus_write_i2c_block_data(int file, uint8_t cmd, + uint8_t length, const uint8_t *values) +{ + union i2c_smbus_data data; + + if (length > I2C_SMBUS_BLOCK_MAX) + length = I2C_SMBUS_BLOCK_MAX; + + memcpy(data.block+1, values, length); + data.block[0] = length; + + return i2c_smbus_access(file, I2C_SMBUS_WRITE, cmd, + I2C_SMBUS_I2C_BLOCK_BROKEN, &data); +} +#endif /* ENABLE_I2CSET */ + +#if ENABLE_I2CDUMP +/* + * Returns the number of bytes read, vals must hold at + * least I2C_SMBUS_BLOCK_MAX bytes. + */ +static int32_t i2c_smbus_read_block_data(int fd, uint8_t cmd, uint8_t *vals) +{ + union i2c_smbus_data data; + int i, err; + + err = i2c_smbus_access(fd, I2C_SMBUS_READ, cmd, + I2C_SMBUS_BLOCK_DATA, &data); + if (err < 0) + return err; + + for (i = 1; i <= data.block[0]; i++) + *vals++ = data.block[i]; + return data.block[0]; +} + +static int32_t i2c_smbus_read_i2c_block_data(int fd, uint8_t cmd, + uint8_t len, uint8_t *vals) +{ + union i2c_smbus_data data; + int i, err; + + if (len > I2C_SMBUS_BLOCK_MAX) + len = I2C_SMBUS_BLOCK_MAX; + data.block[0] = len; + + err = i2c_smbus_access(fd, I2C_SMBUS_READ, cmd, + len == 32 ? I2C_SMBUS_I2C_BLOCK_BROKEN : + I2C_SMBUS_I2C_BLOCK_DATA, &data); + if (err < 0) + return err; + + for (i = 1; i <= data.block[0]; i++) + *vals++ = data.block[i]; + return data.block[0]; +} +#endif /* ENABLE_I2CDUMP */ + +#if ENABLE_I2CDETECT +static int32_t i2c_smbus_write_quick(int fd, uint8_t val) +{ + return i2c_smbus_access(fd, val, 0, I2C_SMBUS_QUICK, NULL); +} +#endif /* ENABLE_I2CDETECT */ + +static int i2c_bus_lookup(const char *bus_str) +{ + return xstrtou_range(bus_str, 10, 0, 0xfffff); +} + +#if ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP +static int i2c_parse_bus_addr(const char *addr_str) +{ + /* Slave address must be in range 0x03 - 0x77. */ + return xstrtou_range(addr_str, 16, 0x03, 0x77); +} + +static void i2c_set_pec(int fd, int pec) +{ + ioctl_or_perror_and_die(fd, I2C_PEC, + itoptr(pec ? 1 : 0), + "can't set PEC"); +} +#endif /* ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP */ + +#if ENABLE_I2CGET || ENABLE_I2CSET +static int i2c_parse_data_addr(const char *data_addr) +{ + /* Data address must be an 8 bit integer. */ + return xstrtou_range(data_addr, 16, 0, 0xff); +} +#endif /* ENABLE_I2CGET || ENABLE_I2CSET */ + +/* + * Opens the device file associated with given i2c bus. + * + * Upstream i2c-tools also support opening devices by i2c bus name + * but we drop it here for size reduction. + */ +static int i2c_dev_open(int i2cbus) +{ + char filename[sizeof("/dev/i2c-%d") + sizeof(int)*3]; + int fd; + + sprintf(filename, "/dev/i2c-%d", i2cbus); + fd = open(filename, O_RDWR); + if (fd < 0) { + filename[8] = '/'; /* change to "/dev/i2c/%d" */ + fd = xopen(filename, O_RDWR); + } + + return fd; +} + +static void i2c_set_slave_addr(int fd, int addr, int force) +{ + ioctl_or_perror_and_die(fd, force ? I2C_SLAVE_FORCE : I2C_SLAVE, + itoptr(addr), + "can't set address to 0x%02x", addr); +} + +/* Size reducing helpers for xxx_check_funcs(). */ +static void get_funcs_matrix(int fd, unsigned long *funcs) +{ + ioctl_or_perror_and_die(fd, I2C_FUNCS, funcs, + "can't get adapter functionality matrix"); +} + +#if ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP +static void check_funcs_test_end(int funcs, int pec, const char *err) +{ + if (pec && !(funcs & (I2C_FUNC_SMBUS_PEC | I2C_FUNC_I2C))) + bb_error_msg("warning: adapter does not support PEC"); + + if (err) + bb_error_msg_and_die( + "adapter has no %s capability", err); +} +#endif /* ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP */ + +/* + * The below functions emit an error message and exit if the adapter doesn't + * support desired functionalities. + */ +#if ENABLE_I2CGET || ENABLE_I2CDUMP +static void check_read_funcs(int fd, int mode, int data_addr, int pec) +{ + unsigned long funcs; + const char *err = NULL; + + get_funcs_matrix(fd, &funcs); + switch (mode) { + case I2C_SMBUS_BYTE: + if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE)) { + err = "SMBus receive byte"; + break; + } + if (data_addr >= 0 && !(funcs & I2C_FUNC_SMBUS_WRITE_BYTE)) + err = "SMBus send byte"; + break; + case I2C_SMBUS_BYTE_DATA: + if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE_DATA)) + err = "SMBus read byte"; + break; + case I2C_SMBUS_WORD_DATA: + if (!(funcs & I2C_FUNC_SMBUS_READ_WORD_DATA)) + err = "SMBus read word"; + break; +#if ENABLE_I2CDUMP + case I2C_SMBUS_BLOCK_DATA: + if (!(funcs & I2C_FUNC_SMBUS_READ_BLOCK_DATA)) + err = "SMBus block read"; + break; + + case I2C_SMBUS_I2C_BLOCK_DATA: + if (!(funcs & I2C_FUNC_SMBUS_READ_I2C_BLOCK)) + err = "I2C block read"; + break; +#endif /* ENABLE_I2CDUMP */ + default: + bb_error_msg_and_die("Programmer goofed!"); + } + check_funcs_test_end(funcs, pec, err); +} +#endif /* ENABLE_I2CGET || ENABLE_I2CDUMP */ + +#if ENABLE_I2CSET +static void check_write_funcs(int fd, int mode, int pec) +{ + unsigned long funcs; + const char *err = NULL; + + get_funcs_matrix(fd, &funcs); + switch (mode) { + case I2C_SMBUS_BYTE: + if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE)) + err = "SMBus send byte"; + break; + + case I2C_SMBUS_BYTE_DATA: + if (!(funcs & I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) + err = "SMBus write byte"; + break; + + case I2C_SMBUS_WORD_DATA: + if (!(funcs & I2C_FUNC_SMBUS_WRITE_WORD_DATA)) + err = "SMBus write word"; + break; + + case I2C_SMBUS_BLOCK_DATA: + if (!(funcs & I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)) + err = "SMBus block write"; + break; + case I2C_SMBUS_I2C_BLOCK_DATA: + if (!(funcs & I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) + err = "I2C block write"; + break; + } + check_funcs_test_end(funcs, pec, err); +} +#endif /* ENABLE_I2CSET */ + +static void confirm_or_abort(void) +{ + fprintf(stderr, "Continue? [y/N] "); + fflush_all(); + if (!bb_ask_confirmation()) + bb_error_msg_and_die("aborting"); +} + +/* + * Return only if user confirms the action, abort otherwise. + * + * The messages displayed here are much less elaborate than their i2c-tools + * counterparts - this is done for size reduction. + */ +static void confirm_action(int bus_addr, int mode, int data_addr, int pec) +{ + bb_error_msg("WARNING! This program can confuse your I2C bus"); + + /* Don't let the user break his/her EEPROMs */ + if (bus_addr >= 0x50 && bus_addr <= 0x57 && pec) { + bb_error_msg_and_die("this is I2C not smbus - using PEC on I2C " + "devices may result in data loss, aborting"); + } + + if (mode == I2C_SMBUS_BYTE && data_addr >= 0 && pec) + bb_error_msg("WARNING! May interpret a write byte command " + "with PEC as a write byte data command"); + + if (pec) + bb_error_msg("PEC checking enabled"); + + confirm_or_abort(); +} + +#if ENABLE_I2CGET +//usage:#define i2cget_trivial_usage +//usage: "[-f] [-y] BUS CHIP-ADDRESS [DATA-ADDRESS [MODE]]" +//usage:#define i2cget_full_usage "\n\n" +//usage: "Read from I2C/SMBus chip registers\n" +//usage: "\n I2CBUS i2c bus number" +//usage: "\n ADDRESS 0x03 - 0x77" +//usage: "\nMODE is:" +//usage: "\n b read byte data (default)" +//usage: "\n w read word data" +//usage: "\n c write byte/read byte" +//usage: "\n Append p for SMBus PEC" +//usage: "\n" +//usage: "\n -f force access" +//usage: "\n -y disable interactive mode" +int i2cget_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int i2cget_main(int argc UNUSED_PARAM, char **argv) +{ + const unsigned opt_f = (1 << 0), opt_y = (1 << 1); + const char *const optstr = "fy"; + + int bus_num, bus_addr, data_addr = -1, status; + int mode = I2C_SMBUS_BYTE, pec = 0, fd; + unsigned opts; + + opt_complementary = "-2:?4"; /* from 2 to 4 args */ + opts = getopt32(argv, optstr); + argv += optind; + + bus_num = i2c_bus_lookup(argv[0]); + bus_addr = i2c_parse_bus_addr(argv[1]); + + if (argv[2]) { + data_addr = i2c_parse_data_addr(argv[2]); + mode = I2C_SMBUS_BYTE_DATA; + if (argv[3]) { + switch (argv[3][0]) { + case 'b': /* Already set */ break; + case 'w': mode = I2C_SMBUS_WORD_DATA; break; + case 'c': mode = I2C_SMBUS_BYTE; break; + default: + bb_error_msg("invalid mode"); + bb_show_usage(); + } + pec = argv[3][1] == 'p'; + } + } + + fd = i2c_dev_open(bus_num); + check_read_funcs(fd, mode, data_addr, pec); + i2c_set_slave_addr(fd, bus_addr, opts & opt_f); + + if (!(opts & opt_y)) + confirm_action(bus_addr, mode, data_addr, pec); + + if (pec) + i2c_set_pec(fd, 1); + + switch (mode) { + case I2C_SMBUS_BYTE: + if (data_addr >= 0) { + status = i2c_smbus_write_byte(fd, data_addr); + if (status < 0) + bb_error_msg("warning - write failed"); + } + status = i2c_smbus_read_byte(fd); + break; + case I2C_SMBUS_WORD_DATA: + status = i2c_smbus_read_word_data(fd, data_addr); + break; + default: /* I2C_SMBUS_BYTE_DATA */ + status = i2c_smbus_read_byte_data(fd, data_addr); + } + close(fd); + + if (status < 0) + bb_perror_msg_and_die("read failed"); + + printf("0x%0*x\n", mode == I2C_SMBUS_WORD_DATA ? 4 : 2, status); + + return 0; +} +#endif /* ENABLE_I2CGET */ + +#if ENABLE_I2CSET +//usage:#define i2cset_trivial_usage +//usage: "[-f] [-y] [-m MASK] BUS CHIP-ADDR DATA-ADDR [VALUE] ... [MODE]" +//usage:#define i2cset_full_usage "\n\n" +//usage: "Set I2C registers\n" +//usage: "\n I2CBUS i2c bus number" +//usage: "\n ADDRESS 0x03 - 0x77" +//usage: "\nMODE is:" +//usage: "\n c byte, no value" +//usage: "\n b byte data (default)" +//usage: "\n w word data" +//usage: "\n i I2C block data" +//usage: "\n s SMBus block data" +//usage: "\n Append p for SMBus PEC" +//usage: "\n" +//usage: "\n -f force access" +//usage: "\n -y disable interactive mode" +//usage: "\n -r read back and compare the result" +//usage: "\n -m MASK mask specifying which bits to write" +int i2cset_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int i2cset_main(int argc, char **argv) +{ + const unsigned opt_f = (1 << 0), opt_y = (1 << 1), + opt_m = (1 << 2), opt_r = (1 << 3); + const char *const optstr = "fym:r"; + + int bus_num, bus_addr, data_addr, mode = I2C_SMBUS_BYTE, pec = 0; + int val, blen = 0, mask = 0, fd, status; + unsigned char block[I2C_SMBUS_BLOCK_MAX]; + char *opt_m_arg = NULL; + unsigned opts; + + opt_complementary = "-3"; /* from 3 to ? args */ + opts = getopt32(argv, optstr, &opt_m_arg); + argv += optind; + argc -= optind; + + bus_num = i2c_bus_lookup(argv[0]); + bus_addr = i2c_parse_bus_addr(argv[1]); + data_addr = i2c_parse_data_addr(argv[2]); + + if (argv[3]) { + if (!argv[4] && argv[3][0] != 'c') { + mode = I2C_SMBUS_BYTE_DATA; /* Implicit b */ + } else { + switch (argv[argc-1][0]) { + case 'c': /* Already set */ break; + case 'b': mode = I2C_SMBUS_BYTE_DATA; break; + case 'w': mode = I2C_SMBUS_WORD_DATA; break; + case 's': mode = I2C_SMBUS_BLOCK_DATA; break; + case 'i': mode = I2C_SMBUS_I2C_BLOCK_DATA; break; + default: + bb_error_msg("invalid mode"); + bb_show_usage(); + } + + pec = argv[argc-1][1] == 'p'; + if (mode == I2C_SMBUS_BLOCK_DATA || + mode == I2C_SMBUS_I2C_BLOCK_DATA) { + if (pec && mode == I2C_SMBUS_I2C_BLOCK_DATA) + bb_error_msg_and_die( + "PEC not supported for I2C " + "block writes"); + if (opts & opt_m) + bb_error_msg_and_die( + "mask not supported for block " + "writes"); + } + } + } + + /* Prepare the value(s) to be written according to current mode. */ + switch (mode) { + case I2C_SMBUS_BYTE_DATA: + val = xstrtou_range(argv[3], 0, 0, 0xff); + break; + case I2C_SMBUS_WORD_DATA: + val = xstrtou_range(argv[3], 0, 0, 0xffff); + break; + case I2C_SMBUS_BLOCK_DATA: + case I2C_SMBUS_I2C_BLOCK_DATA: + for (blen = 3; blen < (argc - 1); blen++) + block[blen] = xstrtou_range(argv[blen], 0, 0, 0xff); + val = -1; + break; + default: + val = -1; + break; + } + + if (opts & opt_m) { + mask = xstrtou_range(opt_m_arg, 0, 0, + (mode == I2C_SMBUS_BYTE || + mode == I2C_SMBUS_BYTE_DATA) ? 0xff : 0xffff); + } + + fd = i2c_dev_open(bus_num); + check_write_funcs(fd, mode, pec); + i2c_set_slave_addr(fd, bus_addr, opts & opt_f); + + if (!(opts & opt_y)) + confirm_action(bus_addr, mode, data_addr, pec); + + /* + * If we're using mask - read the current value here and adjust the + * value to be written. + */ + if (opts & opt_m) { + int tmpval; + + switch (mode) { + case I2C_SMBUS_BYTE: + tmpval = i2c_smbus_read_byte(fd); + break; + case I2C_SMBUS_WORD_DATA: + tmpval = i2c_smbus_read_word_data(fd, data_addr); + break; + default: + tmpval = i2c_smbus_read_byte_data(fd, data_addr); + } + + if (tmpval < 0) + bb_perror_msg_and_die("can't read old value"); + + val = (val & mask) | (tmpval & ~mask); + + if (!(opts & opt_y)) { + bb_error_msg("old value 0x%0*x, write mask " + "0x%0*x, will write 0x%0*x to register " + "0x%02x", + mode == I2C_SMBUS_WORD_DATA ? 4 : 2, tmpval, + mode == I2C_SMBUS_WORD_DATA ? 4 : 2, mask, + mode == I2C_SMBUS_WORD_DATA ? 4 : 2, val, + data_addr); + confirm_or_abort(); + } + } + + if (pec) + i2c_set_pec(fd, 1); + + switch (mode) { + case I2C_SMBUS_BYTE: + status = i2c_smbus_write_byte(fd, data_addr); + break; + case I2C_SMBUS_WORD_DATA: + status = i2c_smbus_write_word_data(fd, data_addr, val); + break; + case I2C_SMBUS_BLOCK_DATA: + status = i2c_smbus_write_block_data(fd, data_addr, + blen, block); + break; + case I2C_SMBUS_I2C_BLOCK_DATA: + status = i2c_smbus_write_i2c_block_data(fd, data_addr, + blen, block); + break; + default: /* I2C_SMBUS_BYTE_DATA */ + status = i2c_smbus_write_byte_data(fd, data_addr, val); + break; + } + if (status < 0) + bb_perror_msg_and_die("write failed"); + + if (pec) + i2c_set_pec(fd, 0); /* Clear PEC. */ + + /* No readback required - we're done. */ + if (!(opts & opt_r)) + return 0; + + switch (mode) { + case I2C_SMBUS_BYTE: + status = i2c_smbus_read_byte(fd); + val = data_addr; + break; + case I2C_SMBUS_WORD_DATA: + status = i2c_smbus_read_word_data(fd, data_addr); + break; + default: /* I2C_SMBUS_BYTE_DATA */ + status = i2c_smbus_read_byte_data(fd, data_addr); + } + + if (status < 0) { + printf("Warning - readback failed\n"); + } else + if (status != val) { + printf("Warning - data mismatch - wrote " + "0x%0*x, read back 0x%0*x\n", + mode == I2C_SMBUS_WORD_DATA ? 4 : 2, val, + mode == I2C_SMBUS_WORD_DATA ? 4 : 2, status); + } else { + printf("Value 0x%0*x written, readback matched\n", + mode == I2C_SMBUS_WORD_DATA ? 4 : 2, val); + } + + return 0; +} +#endif /* ENABLE_I2CSET */ + +#if ENABLE_I2CDUMP +//usage:#define i2cdump_trivial_usage +//usage: "[-f] [-r FIRST-LAST] [-y] BUS ADDR [MODE]" +//usage:#define i2cdump_full_usage "\n\n" +//usage: "Examine I2C registers\n" +//usage: "\n I2CBUS i2c bus number" +//usage: "\n ADDRESS 0x03 - 0x77" +//usage: "\nMODE is:" +//usage: "\n b byte (default)" +//usage: "\n w word" +//usage: "\n W word on even register addresses" +//usage: "\n i I2C block" +//usage: "\n s SMBus block" +//usage: "\n c consecutive byte" +//usage: "\n Append p for SMBus PEC" +//usage: "\n" +//usage: "\n -f force access" +//usage: "\n -y disable interactive mode" +//usage: "\n -r limit the number of registers being accessed" +int i2cdump_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int i2cdump_main(int argc UNUSED_PARAM, char **argv) +{ + const unsigned opt_f = (1 << 0), opt_y = (1 << 1), + opt_r = (1 << 2); + const char *const optstr = "fyr:"; + + int bus_num, bus_addr, mode = I2C_SMBUS_BYTE_DATA, even = 0, pec = 0; + unsigned first = 0x00, last = 0xff; + int fd, i, j, res, blen = 0, tmp; + unsigned char cblock[I2C_SMBUS_BLOCK_MAX + I2C_MAX_REGS]; + unsigned char block[I2C_SMBUS_BLOCK_MAX]; + char *opt_r_str, *dash; + unsigned opts; + + opt_complementary = "-2:?3"; /* from 2 to 3 args */ + opts = getopt32(argv, optstr, &opt_r_str); + argv += optind; + + bus_num = i2c_bus_lookup(argv[0]); + bus_addr = i2c_parse_bus_addr(argv[1]); + + if (argv[2]) { + switch (argv[2][0]) { + case 'b': /* Already set */ break; + case 'c': mode = I2C_SMBUS_BYTE; break; + case 'w': mode = I2C_SMBUS_WORD_DATA; break; + case 'W': + mode = I2C_SMBUS_WORD_DATA; + even = 1; + break; + case 's': mode = I2C_SMBUS_BLOCK_DATA; break; + case 'i': mode = I2C_SMBUS_I2C_BLOCK_DATA; break; + default: + bb_error_msg_and_die("invalid mode"); + } + + if (argv[2][1] == 'p') { + if (argv[2][0] == 'W' || argv[2][0] == 'i') { + bb_error_msg_and_die( + "pec not supported for -W and -i"); + } else { + pec = 1; + } + } + } + + if (opts & opt_r) { + first = strtol(opt_r_str, &dash, 0); + if (dash == opt_r_str || *dash != '-' || first > 0xff) + bb_error_msg_and_die("invalid range"); + last = xstrtou_range(++dash, 0, first, 0xff); + + /* Range is not available for every mode */ + switch (mode) { + case I2C_SMBUS_BYTE: + case I2C_SMBUS_BYTE_DATA: + break; + case I2C_SMBUS_WORD_DATA: + if (!even || (!(first % 2) && last % 2)) + break; + /* Fall through */ + default: + bb_error_msg_and_die( + "range not compatible with selected mode"); + } + } + + fd = i2c_dev_open(bus_num); + check_read_funcs(fd, mode, -1 /* data_addr */, pec); + i2c_set_slave_addr(fd, bus_addr, opts & opt_f); + + if (pec) + i2c_set_pec(fd, 1); + + if (!(opts & opt_y)) + confirm_action(bus_addr, mode, -1 /* data_addr */, pec); + + /* All but word data */ + if (mode != I2C_SMBUS_WORD_DATA || even) { + /* + * FIXME This section has been ported from upstream i2cdump. + * It has been reworked a bit but is still pretty spaghetti + * and needs splitting into several functions. + */ + if (mode == I2C_SMBUS_BLOCK_DATA || + mode == I2C_SMBUS_I2C_BLOCK_DATA) { + res = i2c_smbus_read_block_data(fd, 0, cblock); + blen = res; + } else { + for (res = 0; res < I2C_MAX_REGS; res += tmp) { + tmp = i2c_smbus_read_i2c_block_data( + fd, res, I2C_SMBUS_BLOCK_MAX, + cblock + res); + if (tmp < 0) { + bb_error_msg_and_die( + "block read failed"); + } + } + if (res >= I2C_MAX_REGS) + res = I2C_MAX_REGS; + for (i = 0; i < res; i++) + block[i] = cblock[i]; + if (mode != I2C_SMBUS_BLOCK_DATA) + for (i = res; i < I2C_MAX_REGS; i++) + cblock[i] = -1; + } + + if (mode == I2C_SMBUS_BYTE) { + res = i2c_smbus_write_byte(fd, first); + if (res < 0) + bb_perror_msg_and_die( + "write start address failed"); + } + + printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f" + " 0123456789abcdef\n"); + + for (i = 0; i < I2C_MAX_REGS; i += 0x10) { + if (mode == I2C_SMBUS_BLOCK_DATA && i >= blen) + break; + if (i/16 < first/16) + continue; + if (i/16 > last/16) + break; + + printf("%02x: ", i); + for (j = 0; j < 16; j++) { + fflush_all(); + /* Skip unwanted registers */ + if (i+j < first || i+j > last) { + printf(" "); + if (mode == I2C_SMBUS_WORD_DATA) { + printf(" "); + j++; + } + continue; + } + + switch (mode) { + case I2C_SMBUS_BYTE_DATA: + res = i2c_smbus_read_byte_data(fd, i+j); + block[i+j] = res; + break; + case I2C_SMBUS_WORD_DATA: + res = i2c_smbus_read_word_data(fd, i+j); + if (res < 0) { + block[i+j] = res; + block[i+j+1] = res; + } else { + block[i+j] = res & 0xff; + block[i+j+1] = res >> 8; + } + break; + case I2C_SMBUS_BYTE: + res = i2c_smbus_read_byte(fd); + block[i+j] = res; + break; + default: + res = block[i+j]; + } + + if (mode == I2C_SMBUS_BLOCK_DATA && + i+j >= blen) { + printf(" "); + } else if (res < 0) { + printf("XX "); + if (mode == I2C_SMBUS_WORD_DATA) + printf("XX "); + } else { + printf("%02x ", block[i+j]); + if (mode == I2C_SMBUS_WORD_DATA) + printf("%02x ", block[i+j+1]); + } + + if (mode == I2C_SMBUS_WORD_DATA) + j++; + } + printf(" "); + + for (j = 0; j < 16; j++) { + if (mode == I2C_SMBUS_BLOCK_DATA && i+j >= blen) + break; + /* Skip unwanted registers */ + if (i+j < first || i+j > last) { + printf(" "); + continue; + } + + res = block[i+j]; + if (res < 0) { +//FIXME: impossible, block[] is uchar[] + printf("X"); + } else if (res == 0x00 || res == 0xff) { + printf("."); + } else if (res < 32 || res >= 127) { + printf("?"); + } else { + printf("%c", res); + } + } + printf("\n"); + } + } else { + /* Word data. */ + printf(" 0,8 1,9 2,a 3,b 4,c 5,d 6,e 7,f\n"); + for (i = 0; i < 256; i += 8) { + if (i/8 < first/8) + continue; + if (i/8 > last/8) + break; + + printf("%02x: ", i); + for (j = 0; j < 8; j++) { + /* Skip unwanted registers. */ + if (i+j < first || i+j > last) { + printf(" "); + continue; + } + + res = i2c_smbus_read_word_data(fd, i+j); + if (res < 0) + printf("XXXX "); + else + printf("%04x ", res & 0xffff); + } + printf("\n"); + } + } + + return 0; +} +#endif /* ENABLE_I2CDUMP */ + +#if ENABLE_I2CDETECT +enum adapter_type { + ADT_DUMMY = 0, + ADT_ISA, + ADT_I2C, + ADT_SMBUS, +}; + +struct adap_desc { + const char *funcs; + const char *algo; +}; + +static const struct adap_desc adap_descs[] = { + { .funcs = "dummy", + .algo = "Dummy bus", }, + { .funcs = "isa", + .algo = "ISA bus", }, + { .funcs = "i2c", + .algo = "I2C adapter", }, + { .funcs = "smbus", + .algo = "SMBus adapter", }, +}; + +struct i2c_func +{ + long value; + const char* name; +}; + +static const struct i2c_func i2c_funcs_tab[] = { + { .value = I2C_FUNC_I2C, + .name = "I2C" }, + { .value = I2C_FUNC_SMBUS_QUICK, + .name = "SMBus Quick Command" }, + { .value = I2C_FUNC_SMBUS_WRITE_BYTE, + .name = "SMBus Send Byte" }, + { .value = I2C_FUNC_SMBUS_READ_BYTE, + .name = "SMBus Receive Byte" }, + { .value = I2C_FUNC_SMBUS_WRITE_BYTE_DATA, + .name = "SMBus Write Byte" }, + { .value = I2C_FUNC_SMBUS_READ_BYTE_DATA, + .name = "SMBus Read Byte" }, + { .value = I2C_FUNC_SMBUS_WRITE_WORD_DATA, + .name = "SMBus Write Word" }, + { .value = I2C_FUNC_SMBUS_READ_WORD_DATA, + .name = "SMBus Read Word" }, + { .value = I2C_FUNC_SMBUS_PROC_CALL, + .name = "SMBus Process Call" }, + { .value = I2C_FUNC_SMBUS_WRITE_BLOCK_DATA, + .name = "SMBus Block Write" }, + { .value = I2C_FUNC_SMBUS_READ_BLOCK_DATA, + .name = "SMBus Block Read" }, + { .value = I2C_FUNC_SMBUS_BLOCK_PROC_CALL, + .name = "SMBus Block Process Call" }, + { .value = I2C_FUNC_SMBUS_PEC, + .name = "SMBus PEC" }, + { .value = I2C_FUNC_SMBUS_WRITE_I2C_BLOCK, + .name = "I2C Block Write" }, + { .value = I2C_FUNC_SMBUS_READ_I2C_BLOCK, + .name = "I2C Block Read" }, + { .value = 0, .name = NULL } +}; + +static enum adapter_type i2cdetect_get_funcs(int bus) +{ + enum adapter_type ret; + unsigned long funcs; + int fd; + + fd = i2c_dev_open(bus); + + get_funcs_matrix(fd, &funcs); + if (funcs & I2C_FUNC_I2C) + ret = ADT_I2C; + else if (funcs & (I2C_FUNC_SMBUS_BYTE | + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA)) + ret = ADT_SMBUS; + else + ret = ADT_DUMMY; + + close(fd); + + return ret; +} + +static void NORETURN list_i2c_busses_and_exit(void) +{ + const char *const i2cdev_path = "/sys/class/i2c-dev"; + + char path[NAME_MAX], name[128]; + struct dirent *de, *subde; + enum adapter_type adt; + DIR *dir, *subdir; + int rv, bus; + char *pos; + FILE *fp; + + /* + * XXX Upstream i2cdetect also looks for i2c bus info in /proc/bus/i2c, + * but we won't bother since it's only useful on older kernels (before + * 2.6.5). We expect sysfs to be present and mounted at /sys/. + */ + + dir = xopendir(i2cdev_path); + while ((de = readdir(dir))) { + if (de->d_name[0] == '.') + continue; + + /* Simple version for ISA chips. */ + snprintf(path, NAME_MAX, "%s/%s/name", + i2cdev_path, de->d_name); + fp = fopen(path, "r"); + if (fp == NULL) { + snprintf(path, NAME_MAX, + "%s/%s/device/name", + i2cdev_path, de->d_name); + fp = fopen(path, "r"); + } + + /* Non-ISA chips require the hard-way. */ + if (fp == NULL) { + snprintf(path, NAME_MAX, + "%s/%s/device/name", + i2cdev_path, de->d_name); + subdir = opendir(path); + if (subdir == NULL) + continue; + + while ((subde = readdir(subdir))) { + if (subde->d_name[0] == '.') + continue; + + if (strncmp(subde->d_name, "i2c-", 4) == 0) { + snprintf(path, NAME_MAX, + "%s/%s/device/%s/name", + i2cdev_path, de->d_name, + subde->d_name); + fp = fopen(path, "r"); + goto found; + } + } + } + +found: + if (fp != NULL) { + /* + * Get the rest of the info and display a line + * for a single bus. + */ + memset(name, 0, sizeof(name)); + pos = fgets(name, sizeof(name), fp); + fclose(fp); + if (pos == NULL) + continue; + + pos = strchr(name, '\n'); + if (pos != NULL) + *pos = '\0'; + + rv = sscanf(de->d_name, "i2c-%d", &bus); + if (rv != 1) + continue; + + if (strncmp(name, "ISA", 3) == 0) + adt = ADT_ISA; + else + adt = i2cdetect_get_funcs(bus); + + printf( + "i2c-%d\t%-10s\t%-32s\t%s\n", + bus, adap_descs[adt].funcs, + name, adap_descs[adt].algo); + } + } + + exit(EXIT_SUCCESS); +} + +static void NORETURN no_support(const char *cmd) +{ + bb_error_msg_and_die("bus doesn't support %s", cmd); +} + +static void will_skip(const char *cmd) +{ + bb_error_msg( + "warning: can't use %s command, " + "will skip some addresses", cmd); +} + +//usage:#define i2cdetect_trivial_usage +//usage: "[-F I2CBUS] [-l] [-y] [-a] [-q|-r] I2CBUS [FIRST LAST]" +//usage:#define i2cdetect_full_usage "\n\n" +//usage: "Detect I2C chips.\n" +//usage: "\n I2CBUS i2c bus number" +//usage: "\n FIRST and LAST limit the probing range" +//usage: "\n" +//usage: "\n -l output list of installed busses" +//usage: "\n -y disable interactive mode" +//usage: "\n -a force scanning of non-regular addresses" +//usage: "\n -q use smbus quick write commands for probing (default)" +//usage: "\n -r use smbus read byte commands for probing" +//usage: "\n -F display list of functionalities" +int i2cdetect_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int i2cdetect_main(int argc UNUSED_PARAM, char **argv) +{ + const unsigned opt_y = (1 << 0), opt_a = (1 << 1), + opt_q = (1 << 2), opt_r = (1 << 3), + opt_F = (1 << 4), opt_l = (1 << 5); + const char *const optstr = "yaqrFl"; + + int fd, bus_num, i, j, mode = DETECT_MODE_AUTO; + int status; + unsigned first = 0x00, last = 0x77; + unsigned long funcs; + unsigned opts; + + opt_complementary = "q--r:r--q:" /* mutually exclusive */ + "-1:?3"; /* from 1 to 3 args */ + opts = getopt32(argv, optstr); + argv += optind; + + if (opts & opt_l) + list_i2c_busses_and_exit(); + + bus_num = i2c_bus_lookup(argv[0]); + fd = i2c_dev_open(bus_num); + get_funcs_matrix(fd, &funcs); + + if (opts & opt_F) { + /* Only list the functionalities. */ + printf("Functionalities implemented by bus #%d\n", bus_num); + for (i = 0; i2c_funcs_tab[i].value; i++) { + printf("%-32s %s\n", i2c_funcs_tab[i].name, + funcs & i2c_funcs_tab[i].value ? "yes" : "no"); + } + + return EXIT_SUCCESS; + } + + if (opts & opt_r) + mode = DETECT_MODE_READ; + else if (opts & opt_q) + mode = DETECT_MODE_QUICK; + + if (opts & opt_a) + last = 0x7f; + + /* Read address range. */ + if (argv[1]) { + first = xstrtou_range(argv[1], 16, first, last); + if (argv[2]) + last = xstrtou_range(argv[2], 16, first, last); + } + + if (!(funcs & (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_READ_BYTE))) { + no_support("detection commands"); + } else + if (mode == DETECT_MODE_QUICK && !(funcs & I2C_FUNC_SMBUS_QUICK)) { + no_support("SMBus Quick Write command"); + } else + if (mode == DETECT_MODE_READ && !(funcs & I2C_FUNC_SMBUS_READ_BYTE)) { + no_support("SMBus Receive Byte command"); + } else { + if (!(funcs & I2C_FUNC_SMBUS_QUICK)) + will_skip("SMBus Quick Write"); + if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE)) + will_skip("SMBus Receive Byte"); + } + + if (!(opts & opt_y)) + confirm_action(-1, -1, -1, 0); + + printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\n"); + for (i = 0; i < 128; i += 16) { + printf("%02x: ", i); + for(j = 0; j < 16; j++) { + fflush_all(); + + if (mode == DETECT_MODE_AUTO) { + if ((i+j >= 0x30 && i+j <= 0x37) || + (i+j >= 0x50 && i+j <= 0x5F)) + mode = DETECT_MODE_READ; + else + mode = DETECT_MODE_QUICK; + } + + /* Skip unwanted addresses. */ + if (i+j < first + || i+j > last + || (mode == DETECT_MODE_READ && !(funcs & I2C_FUNC_SMBUS_READ_BYTE)) + || (mode == DETECT_MODE_QUICK && !(funcs & I2C_FUNC_SMBUS_QUICK))) + { + printf(" "); + continue; + } + + i2c_set_slave_addr(fd, i + j, 0); + + switch (mode) { + case DETECT_MODE_READ: + /* + * This is known to lock SMBus on various + * write-only chips (mainly clock chips). + */ + status = i2c_smbus_read_byte(fd); + break; + default: /* DETECT_MODE_QUICK: */ + /* + * This is known to corrupt the Atmel + * AT24RF08 EEPROM. + */ + status = i2c_smbus_write_quick(fd, + I2C_SMBUS_WRITE); + break; + } + + if (status < 0) + printf("-- "); + else + printf("%02x ", i+j); + } + printf("\n"); + } + + return 0; +} +#endif /* ENABLE_I2CDETECT */ From 1fd844267c3ad60e9122e141768e823e6ad74a28 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 12 Feb 2015 16:18:39 +0100 Subject: [PATCH 064/256] modprobe-small: if concurrent module load did not succeed, wait usecase: two sd cards are being mounted in parallel at same time on dual core. example modules which are getting loaded is nls_cp437. While one module is being loaded , it makes state in /proc/modules as 'coming' and then starts doing its module init function (in our case - registering nls). meanwhile on other core, if modprobe returns that is has already been loaded, then it will continue and search for the nls list which is not yet finished from first module init. This fails resulting in not mounting sd card. function old new delta process_module 667 746 +79 Signed-off-by: Denys Vlasenko --- modutils/modprobe-small.c | 50 ++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index 6b0a4400c..598965968 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c @@ -536,17 +536,49 @@ static module_info** find_alias(const char *alias) // TODO: open only once, invent config_rewind() static int already_loaded(const char *name) { - int ret = 0; - char *s; - parser_t *parser = config_open2("/proc/modules", xfopen_for_read); - while (config_read(parser, &s, 1, 1, "# \t", PARSE_NORMAL & ~PARSE_GREEDY)) { - if (strcmp(s, name) == 0) { - ret = 1; - break; + int ret, namelen; + char *line; + FILE *fp; + + ret = 5 * 2; + again: + fp = fopen_for_read("/proc/modules"); + if (!fp) + return 0; + namelen = strlen(name); + while ((line = xmalloc_fgetline(fp)) != NULL) { + char *live; + + // Examples from kernel 3.14.6: + //pcspkr 12718 0 - Live 0xffffffffa017e000 + //snd_timer 28690 2 snd_seq,snd_pcm, Live 0xffffffffa025e000 + //i915 801405 2 - Live 0xffffffffa0096000 + if (strncmp(line, name, namelen) != 0 || line[namelen] != ' ') { + free(line); + continue; } + live = strstr(line, " Live"); + free(line); + if (!live) { + /* State can be Unloading, Loading, or Live. + * modprobe must not return prematurely if we see "Loading": + * it can cause further programs to assume load completed, + * but it did not (yet)! + * Wait up to 5*20 ms for it to resolve. + */ + ret -= 2; + if (ret == 0) + break; /* huh? report as "not loaded" */ + fclose(fp); + usleep(20*1000); + goto again; + } + ret = 1; + break; } - config_close(parser); - return ret; + fclose(fp); + + return ret | 1; } #else #define already_loaded(name) 0 From 402afe1cc69ea505c9bf82ffe06e51ffecf694df Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 13 Feb 2015 11:53:33 +0100 Subject: [PATCH 065/256] modprobe-small: fix thinko in previous commit Signed-off-by: Denys Vlasenko --- modutils/modprobe-small.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index 598965968..ed177bb9b 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c @@ -578,7 +578,7 @@ static int already_loaded(const char *name) } fclose(fp); - return ret | 1; + return ret & 1; } #else #define already_loaded(name) 0 From 8e92df15b512d108901ce1762e917518553a8aaf Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 16 Feb 2015 15:36:25 +0100 Subject: [PATCH 066/256] ls: fix year 9999 bug :) Signed-off-by: Denys Vlasenko --- coreutils/ls.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/coreutils/ls.c b/coreutils/ls.c index 1b63be56d..a30422a8c 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -581,12 +581,15 @@ static NOINLINE unsigned display_single(const struct dnode *dn) } else { /* LIST_DATE_TIME */ /* G.current_time_t ~== time(NULL) */ time_t age = G.current_time_t - ttime; - printf("%.6s ", filetime + 4); /* "Jun 30" */ if (age < 3600L * 24 * 365 / 2 && age > -15 * 60) { - /* hh:mm if less than 6 months old */ - printf("%.5s ", filetime + 11); - } else { /* year. buggy if year > 9999 ;) */ - printf(" %.4s ", filetime + 20); + /* less than 6 months old */ + /* "mmm dd hh:mm " */ + printf("%.12s ", filetime + 4); + } else { + /* "mmm dd yyyy " */ + /* "mmm dd yyyyy " after year 9999 :) */ + strchr(filetime + 20, '\n')[0] = ' '; + printf("%.7s%6s", filetime + 4, filetime + 20); } column += 13; } From 70e30e8eec7f202cb584449e4c7a9176d57d980d Mon Sep 17 00:00:00 2001 From: Bernhard Reutner-Fischer Date: Mon, 16 Feb 2015 17:12:04 +0100 Subject: [PATCH 067/256] dc: tweak parsing https://bugs.debian.org/538685 dc requires whitespace between language elements. We were requiring 1 2 + p instead of the abbreviated 1 2+p (for example). function old new delta stack_machine 97 126 +29 dc_main 117 79 -38 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 29/-38) Total: -9 bytes Signed-off-by: Bernhard Reutner-Fischer Signed-off-by: Denys Vlasenko --- miscutils/dc.c | 57 ++++++++++++++++++++++------------------------ testsuite/dc.tests | 56 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 30 deletions(-) create mode 100755 testsuite/dc.tests diff --git a/miscutils/dc.c b/miscutils/dc.c index 6bcfbe249..a7bd360d2 100644 --- a/miscutils/dc.c +++ b/miscutils/dc.c @@ -196,14 +196,6 @@ struct op { }; static const struct op operators[] = { - {"+", add}, - {"add", add}, - {"-", sub}, - {"sub", sub}, - {"*", mul}, - {"mul", mul}, - {"/", divide}, - {"div", divide}, #if ENABLE_FEATURE_DC_LIBM {"**", power}, {"exp", power}, @@ -216,28 +208,47 @@ static const struct op operators[] = { {"not", not}, {"eor", eor}, {"xor", eor}, + {"+", add}, + {"add", add}, + {"-", sub}, + {"sub", sub}, + {"*", mul}, + {"mul", mul}, + {"/", divide}, + {"div", divide}, {"p", print_no_pop}, {"f", print_stack_no_pop}, {"o", set_output_base}, }; +/* Feed the stack machine */ static void stack_machine(const char *argument) { char *end; - double d; + double number; const struct op *o; - d = strtod(argument, &end); - if (end != argument && *end == '\0') { - push(d); - return; + next: + number = strtod(argument, &end); + if (end != argument) { + argument = end; + push(number); + goto next; } + /* We might have matched a digit, eventually advance the argument */ + argument = skip_whitespace(argument); + + if (*argument == '\0') + return; + o = operators; do { - if (strcmp(o->name, argument) == 0) { + const size_t name_len = strlen(o->name); + if (strncmp(o->name, argument, name_len) == 0) { + argument += name_len; o->function(); - return; + goto next; } o++; } while (o != operators + ARRAY_SIZE(operators)); @@ -254,25 +265,11 @@ int dc_main(int argc UNUSED_PARAM, char **argv) if (!argv[0]) { /* take stuff from stdin if no args are given */ char *line; - char *cursor; - char *token; while ((line = xmalloc_fgetline(stdin)) != NULL) { - cursor = line; - while (1) { - token = skip_whitespace(cursor); - if (*token == '\0') - break; - cursor = skip_non_whitespace(token); - if (*cursor != '\0') - *cursor++ = '\0'; - stack_machine(token); - } + stack_machine(line); free(line); } } else { - // why? it breaks "dc -2 2 + p" - //if (argv[0][0] == '-') - // bb_show_usage(); do { stack_machine(*argv); } while (*++argv); diff --git a/testsuite/dc.tests b/testsuite/dc.tests new file mode 100755 index 000000000..a5da5372d --- /dev/null +++ b/testsuite/dc.tests @@ -0,0 +1,56 @@ +#!/bin/sh +# Copyright 2015 by Bernhard Reutner-Fischer +# Licensed under GPLv2 or later, see file LICENSE in this source tree. + +. ./testing.sh + +# testing "test name" "command" "expected result" "file input" "stdin" + +testing "dc basic syntax (stdin, multiple args)" \ + "dc" \ + "30\n" \ + "" "10 20+p" + +testing "dc basic syntax (argv, single arg)" \ + "dc '10 20+p'" \ + "30\n" \ + "" "" + +testing "dc basic syntax (argv, multiple args)" \ + "dc 10 20+p" \ + "30\n" \ + "" "" + +testing "dc complex with spaces (single arg)" \ + "dc '8 8 * 2 2 + / p'" \ + "16\n" \ + "" "" + +testing "dc complex without spaces (single arg)" \ + "dc '8 8*2 2+/p'" \ + "16\n" \ + "" "" + +testing "dc complex with spaces (multiple args)" \ + "dc 8 8 \* 2 2 + / p" \ + "16\n" \ + "" "" + +testing "dc complex without spaces (multiple args)" \ + "dc 8 8\*2 2+/p" \ + "16\n" \ + "" "" + +exit $FAILCOUNT + +# we do not support arguments +testing "dc -e " \ + "dc -e '10 2+f'" \ + "12\n" \ + "" "" + +testing "dc -f " \ + "dc -f input" \ + "12\n" \ + "10 2+f" "" + From 0cb981c5e2f1a955e72dd9d3d2fad075dc9d0da6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 18 Feb 2015 11:29:07 +0100 Subject: [PATCH 068/256] ls: trivial code shrink function old new delta display_single 914 893 -21 Signed-off-by: Denys Vlasenko --- coreutils/ls.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/coreutils/ls.c b/coreutils/ls.c index a30422a8c..366758351 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -566,12 +566,12 @@ static NOINLINE unsigned display_single(const struct dnode *dn) #if ENABLE_FEATURE_LS_TIMESTAMPS if (G.all_fmt & (LIST_FULLTIME|LIST_DATE_TIME)) { char *filetime; - time_t ttime = dn->dn_mtime; + time_t *ttime = &dn->dn_mtime; if (G.all_fmt & TIME_ACCESS) - ttime = dn->dn_atime; + ttime = &dn->dn_atime; if (G.all_fmt & TIME_CHANGE) - ttime = dn->dn_ctime; - filetime = ctime(&ttime); + ttime = &dn->dn_ctime; + filetime = ctime(ttime); /* filetime's format: "Wed Jun 30 21:49:08 1993\n" */ if (G.all_fmt & LIST_FULLTIME) { /* -e */ /* Note: coreutils 8.4 ls --full-time prints: @@ -580,7 +580,7 @@ static NOINLINE unsigned display_single(const struct dnode *dn) column += printf("%.24s ", filetime); } else { /* LIST_DATE_TIME */ /* G.current_time_t ~== time(NULL) */ - time_t age = G.current_time_t - ttime; + time_t age = G.current_time_t - *ttime; if (age < 3600L * 24 * 365 / 2 && age > -15 * 60) { /* less than 6 months old */ /* "mmm dd hh:mm " */ From 54e9585e106348d6f0129376171fab305ddc0e27 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 18 Feb 2015 13:47:27 +0100 Subject: [PATCH 069/256] trivial code shrink function old new delta rdate_main 246 251 +5 show_entry 291 287 -4 daytime_stream 44 39 -5 packed_usage 30176 30168 -8 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/3 up/down: 5/-17) Total: -12 bytes text data bss dec hex filename 929453 932 17684 948069 e7765 busybox_old 929411 932 17684 948027 e773b busybox_unstripped Signed-off-by: Denys Vlasenko --- miscutils/last_fancy.c | 5 +++-- networking/inetd.c | 2 +- util-linux/rdate.c | 8 ++++---- util-linux/rtcwake.c | 12 ++++++------ 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/miscutils/last_fancy.c b/miscutils/last_fancy.c index f687d7e16..16ed9e920 100644 --- a/miscutils/last_fancy.c +++ b/miscutils/last_fancy.c @@ -42,7 +42,7 @@ enum { static void show_entry(struct utmp *ut, int state, time_t dur_secs) { unsigned days, hours, mins; - char duration[32]; + char duration[sizeof("(%u+02:02)") + sizeof(int)*3]; char login_time[17]; char logout_time[8]; const char *logout_str; @@ -53,7 +53,8 @@ static void show_entry(struct utmp *ut, int state, time_t dur_secs) * but some systems have it wrong */ tmp = ut->ut_tv.tv_sec; safe_strncpy(login_time, ctime(&tmp), 17); - snprintf(logout_time, 8, "- %s", ctime(&dur_secs) + 11); + tmp = dur_secs; + snprintf(logout_time, 8, "- %s", ctime(&tmp) + 11); dur_secs = MAX(dur_secs - (time_t)ut->ut_tv.tv_sec, (time_t)0); /* unsigned int is easier to divide than time_t (which may be signed long) */ diff --git a/networking/inetd.c b/networking/inetd.c index 584c5e5e4..b3f2e9fbc 100644 --- a/networking/inetd.c +++ b/networking/inetd.c @@ -1654,7 +1654,7 @@ static void FAST_FUNC daytime_stream(int s, servtab_t *sep UNUSED_PARAM) { time_t t; - t = time(NULL); + time(&t); fdprintf(s, "%.24s\r\n", ctime(&t)); } static void FAST_FUNC daytime_dg(int s, servtab_t *sep) diff --git a/util-linux/rdate.c b/util-linux/rdate.c index 6e35cd519..8075ef6af 100644 --- a/util-linux/rdate.c +++ b/util-linux/rdate.c @@ -11,9 +11,9 @@ //usage:#define rdate_trivial_usage //usage: "[-sp] HOST" //usage:#define rdate_full_usage "\n\n" -//usage: "Get and possibly set the system date/time from a remote HOST\n" -//usage: "\n -s Set the system date/time (default)" -//usage: "\n -p Print the date/time" +//usage: "Get and possibly set system time from a remote HOST\n" +//usage: "\n -s Set system time (default)" +//usage: "\n -p Print time" #include "libbb.h" @@ -36,7 +36,7 @@ static time_t askremotedate(const char *host) fd = create_and_connect_stream_or_die(host, bb_lookup_port("time", "tcp", 37)); if (safe_read(fd, &nett, 4) != 4) /* read time from server */ - bb_error_msg_and_die("%s did not send the complete time", host); + bb_error_msg_and_die("%s: %s", host, "short read"); if (ENABLE_FEATURE_CLEAN_UP) close(fd); diff --git a/util-linux/rtcwake.c b/util-linux/rtcwake.c index 33cdbfad4..53d9384db 100644 --- a/util-linux/rtcwake.c +++ b/util-linux/rtcwake.c @@ -32,18 +32,18 @@ //usage: "\n -l,--local Clock is set to local time" //usage: "\n -u,--utc Clock is set to UTC time" //usage: "\n -d,--device=DEV Specify the RTC device" -//usage: "\n -m,--mode=MODE Set the sleep state (default: standby)" -//usage: "\n -s,--seconds=SEC Set the timeout in SEC seconds from now" -//usage: "\n -t,--time=TIME Set the timeout to TIME seconds from epoch" +//usage: "\n -m,--mode=MODE Set sleep state (default: standby)" +//usage: "\n -s,--seconds=SEC Set timeout in SEC seconds from now" +//usage: "\n -t,--time=TIME Set timeout to TIME seconds from epoch" //usage: ) //usage: IF_NOT_LONG_OPTS( //usage: "\n -a Read clock mode from adjtime" //usage: "\n -l Clock is set to local time" //usage: "\n -u Clock is set to UTC time" //usage: "\n -d DEV Specify the RTC device" -//usage: "\n -m MODE Set the sleep state (default: standby)" -//usage: "\n -s SEC Set the timeout in SEC seconds from now" -//usage: "\n -t TIME Set the timeout to TIME seconds from epoch" +//usage: "\n -m MODE Set sleep state (default: standby)" +//usage: "\n -s SEC Set timeout in SEC seconds from now" +//usage: "\n -t TIME Set timeout to TIME seconds from epoch" //usage: ) #include "libbb.h" From d7bfee1edb551d3503c7b616702a73192ba069a9 Mon Sep 17 00:00:00 2001 From: Bernhard Reutner-Fischer Date: Wed, 18 Feb 2015 20:41:02 +0100 Subject: [PATCH 070/256] wget: fix --header to not append duplicate headers function old new delta wget_main 2551 2715 +164 wget_user_headers - 62 +62 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/0 up/down: 226/0) Total: 226 bytes Signed-off-by: Bernhard Reutner-Fischer Signed-off-by: Denys Vlasenko --- networking/wget.c | 98 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 78 insertions(+), 20 deletions(-) diff --git a/networking/wget.c b/networking/wget.c index 1013f66cb..6c8bd90a8 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -38,8 +38,14 @@ #if 0 # define log_io(...) bb_error_msg(__VA_ARGS__) +# define SENDFMT(fp, fmt, ...) \ + do { \ + log_io("> " fmt, ##__VA_ARGS__); \ + fprintf(fp, fmt, ##__VA_ARGS__); \ + } while (0); #else # define log_io(...) ((void)0) +# define SENDFMT(fp, fmt, ...) fprintf(fp, fmt, ##__VA_ARGS__) #endif @@ -55,6 +61,36 @@ static const char P_FTP[] = "ftp"; static const char P_HTTP[] = "http"; static const char P_HTTPS[] = "https"; +#if ENABLE_FEATURE_WGET_LONG_OPTIONS +/* User-specified headers prevent using our corresponding built-in headers. */ +enum { + HDR_HOST = (1<<0), + HDR_USER_AGENT = (1<<1), + HDR_RANGE = (1<<2), + HDR_AUTH = (1<<3) * ENABLE_FEATURE_WGET_AUTHENTICATION, + HDR_PROXY_AUTH = (1<<4) * ENABLE_FEATURE_WGET_AUTHENTICATION, +}; +static const char wget_user_headers[] ALIGN1 = + "Host:\0" + "User-Agent:\0" + "Range:\0" +# if ENABLE_FEATURE_WGET_AUTHENTICATION + "Authorization:\0" + "Proxy-Authorization:\0" +# endif + ; +# define USR_HEADER_HOST (G.user_headers & HDR_HOST) +# define USR_HEADER_USER_AGENT (G.user_headers & HDR_USER_AGENT) +# define USR_HEADER_RANGE (G.user_headers & HDR_RANGE) +# define USR_HEADER_AUTH (G.user_headers & HDR_AUTH) +# define USR_HEADER_PROXY_AUTH (G.user_headers & HDR_PROXY_AUTH) +#else /* No long options, no user-headers :( */ +# define USR_HEADER_HOST 0 +# define USR_HEADER_USER_AGENT 0 +# define USR_HEADER_RANGE 0 +# define USR_HEADER_AUTH 0 +# define USR_HEADER_PROXY_AUTH 0 +#endif /* Globals */ struct globals { @@ -69,6 +105,7 @@ struct globals { #if ENABLE_FEATURE_WGET_LONG_OPTIONS char *post_data; char *extra_headers; + unsigned char user_headers; /* Headers mentioned by the user */ #endif char *fname_out; /* where to direct output (-O) */ const char *proxy_flag; /* Use proxies if env vars are set */ @@ -830,43 +867,46 @@ static void download_one_url(const char *url) #endif /* Send HTTP request */ if (use_proxy) { - fprintf(sfp, "GET %s://%s/%s HTTP/1.1\r\n", + SENDFMT(sfp, "GET %s://%s/%s HTTP/1.1\r\n", target.protocol, target.host, target.path); } else { - fprintf(sfp, "%s /%s HTTP/1.1\r\n", + SENDFMT(sfp, "%s /%s HTTP/1.1\r\n", (option_mask32 & WGET_OPT_POST_DATA) ? "POST" : "GET", target.path); } - - fprintf(sfp, "Host: %s\r\nUser-Agent: %s\r\n", - target.host, G.user_agent); + if (!USR_HEADER_HOST) + SENDFMT(sfp, "Host: %s\r\n", target.host); + if (!USR_HEADER_USER_AGENT) + SENDFMT(sfp, "User-Agent: %s\r\n", G.user_agent); /* Ask server to close the connection as soon as we are done * (IOW: we do not intend to send more requests) */ - fprintf(sfp, "Connection: close\r\n"); + SENDFMT(sfp, "Connection: close\r\n"); #if ENABLE_FEATURE_WGET_AUTHENTICATION - if (target.user) { - fprintf(sfp, "Proxy-Authorization: Basic %s\r\n"+6, + if (target.user && !USR_HEADER_AUTH) { + SENDFMT(sfp, "Proxy-Authorization: Basic %s\r\n"+6, base64enc(target.user)); } - if (use_proxy && server.user) { - fprintf(sfp, "Proxy-Authorization: Basic %s\r\n", + if (use_proxy && server.user && !USR_HEADER_PROXY_AUTH) { + SENDFMT(sfp, "Proxy-Authorization: Basic %s\r\n", base64enc(server.user)); } #endif - if (G.beg_range != 0) - fprintf(sfp, "Range: bytes=%"OFF_FMT"u-\r\n", G.beg_range); + if (G.beg_range != 0 && !USR_HEADER_RANGE) + SENDFMT(sfp, "Range: bytes=%"OFF_FMT"u-\r\n", G.beg_range); #if ENABLE_FEATURE_WGET_LONG_OPTIONS - if (G.extra_headers) + if (G.extra_headers) { + log_io(G.extra_headers); fputs(G.extra_headers, sfp); + } if (option_mask32 & WGET_OPT_POST_DATA) { - fprintf(sfp, + SENDFMT(sfp, "Content-Type: application/x-www-form-urlencoded\r\n" "Content-Length: %u\r\n" "\r\n" @@ -876,7 +916,7 @@ static void download_one_url(const char *url) } else #endif { - fprintf(sfp, "\r\n"); + SENDFMT(sfp, "\r\n"); } fflush(sfp); @@ -1093,7 +1133,9 @@ int wget_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_FEATURE_WGET_LONG_OPTIONS applet_long_options = wget_longopts; #endif - opt_complementary = "-1" IF_FEATURE_WGET_TIMEOUT(":T+") IF_FEATURE_WGET_LONG_OPTIONS(":\xfe::"); + opt_complementary = "-1" + IF_FEATURE_WGET_TIMEOUT(":T+") + IF_FEATURE_WGET_LONG_OPTIONS(":\xfe::"); getopt32(argv, "csqO:P:Y:U:T:" /*ignored:*/ "t:", &G.fname_out, &G.dir_prefix, &G.proxy_flag, &G.user_agent, @@ -1106,16 +1148,32 @@ int wget_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_FEATURE_WGET_LONG_OPTIONS if (headers_llist) { - int size = 1; - char *cp; + int size = 0; + char *hdr; llist_t *ll = headers_llist; while (ll) { size += strlen(ll->data) + 2; ll = ll->link; } - G.extra_headers = cp = xmalloc(size); + G.extra_headers = hdr = xmalloc(size + 1); while (headers_llist) { - cp += sprintf(cp, "%s\r\n", (char*)llist_pop(&headers_llist)); + int bit; + const char *words; + + size = sprintf(hdr, "%s\r\n", + (char*)llist_pop(&headers_llist)); + /* a bit like index_in_substrings but don't match full key */ + bit = 1; + words = wget_user_headers; + while (*words) { + if (strstr(hdr, words) == hdr) { + G.user_headers |= bit; + break; + } + bit <<= 1; + words += strlen(words) + 1; + } + hdr += size; } } #endif From cb6a112f09c3b5dfe94b5c365ca50df4dcc05520 Mon Sep 17 00:00:00 2001 From: Tito Ragusa Date: Thu, 19 Feb 2015 22:02:59 +0100 Subject: [PATCH 071/256] libpwdgrp: fix thinko in getpwnam function old new delta parse_file - 64 +64 getXXnam_r 162 138 -24 getXXnam 90 50 -40 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/2 up/down: 64/-64) Total: 0 bytes Signed-off-by: Tito Ragusa Signed-off-by: Denys Vlasenko --- libpwdgrp/pwd_grp.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/libpwdgrp/pwd_grp.c b/libpwdgrp/pwd_grp.c index 7ec704ee4..3886facf0 100644 --- a/libpwdgrp/pwd_grp.c +++ b/libpwdgrp/pwd_grp.c @@ -450,15 +450,7 @@ static void* FAST_FUNC getXXnam(const char *name, unsigned db_and_field_pos) char *buf; struct passdb *db = &get_S()->db[db_and_field_pos >> 2]; - if (!db->fp) { - db->fp = fopen_for_read(db->filename); - if (!db->fp) { - return NULL; - } - close_on_exec_on(fileno(db->fp)); - } - - buf = parse_common(db->fp, db, name, db_and_field_pos & 3); + buf = parse_file(db, name, db_and_field_pos & 3); return massage_data_for_non_r_func(db, buf); } From a88db5c1a99ebc0ae23b5d108113d9b8af7afc3c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 21 Feb 2015 17:08:35 +0100 Subject: [PATCH 072/256] modinfo: fix fallout from basename removal Signed-off-by: Denys Vlasenko --- modutils/modinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modutils/modinfo.c b/modutils/modinfo.c index 0ab942890..ee379304c 100644 --- a/modutils/modinfo.c +++ b/modutils/modinfo.c @@ -154,7 +154,7 @@ int modinfo_main(int argc UNUSED_PARAM, char **argv) if (colon == NULL) continue; *colon = '\0'; - filename2modname(tokens[0], name); + filename2modname(bb_basename(tokens[0]), name); for (i = 0; argv[i]; i++) { if (fnmatch(argv[i], name, 0) == 0) { modinfo(tokens[0], uts.release, &env); From c5beaa08eb57c542768eebfdf6532e72c5c0c16b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 23 Feb 2015 15:25:58 +0100 Subject: [PATCH 073/256] ls: heed compiler warning Signed-off-by: Denys Vlasenko --- coreutils/ls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreutils/ls.c b/coreutils/ls.c index 366758351..14c8beaff 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -566,7 +566,7 @@ static NOINLINE unsigned display_single(const struct dnode *dn) #if ENABLE_FEATURE_LS_TIMESTAMPS if (G.all_fmt & (LIST_FULLTIME|LIST_DATE_TIME)) { char *filetime; - time_t *ttime = &dn->dn_mtime; + const time_t *ttime = &dn->dn_mtime; if (G.all_fmt & TIME_ACCESS) ttime = &dn->dn_atime; if (G.all_fmt & TIME_CHANGE) From 1eafd4494706c21a87dc66e4e0afa8799b576cb5 Mon Sep 17 00:00:00 2001 From: Serj Kalichev Date: Mon, 23 Feb 2015 15:26:47 +0100 Subject: [PATCH 074/256] acpid: fix logging Without this patch acpid can't log the events at all. Moreover it tries to truncate log file every time. Signed-off-by: Serj Kalichev Signed-off-by: Denys Vlasenko --- util-linux/acpid.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/util-linux/acpid.c b/util-linux/acpid.c index 38421c2d7..fc8151f6a 100644 --- a/util-linux/acpid.c +++ b/util-linux/acpid.c @@ -121,10 +121,8 @@ static void process_event(const char *event) char *handler = xasprintf("./%s", event); const char *args[] = { "run-parts", handler, NULL }; - // debug info - if (option_mask32 & OPT_d) { - bb_error_msg("%s", event); - } + // log the event + bb_error_msg("%s", event); // spawn handler // N.B. run-parts would require scripts to have #!/bin/sh @@ -256,7 +254,7 @@ int acpid_main(int argc UNUSED_PARAM, char **argv) /* No -d "Debug", we log to log file. * This includes any output from children. */ - xmove_fd(xopen(opt_logfile, O_WRONLY | O_CREAT | O_TRUNC), STDOUT_FILENO); + xmove_fd(xopen(opt_logfile, O_WRONLY | O_CREAT | O_APPEND), STDOUT_FILENO); xdup2(STDOUT_FILENO, STDERR_FILENO); /* Also, acpid's messages (but not children) will go to syslog too */ openlog(applet_name, LOG_PID, LOG_DAEMON); From fa535f3e485456a7fd85db060532ea6539670af0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 2 Mar 2015 17:37:31 +0100 Subject: [PATCH 075/256] runsvdir: (almost) close a signal race We could lose a signal while processing previous one function old new delta runsvdir_main 1088 1077 -11 Signed-off-by: Denys Vlasenko --- runit/runsvdir.c | 53 +++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/runit/runsvdir.c b/runit/runsvdir.c index af7e75ba7..809c48a51 100644 --- a/runit/runsvdir.c +++ b/runit/runsvdir.c @@ -59,7 +59,6 @@ struct globals { int svnum; #if ENABLE_FEATURE_RUNSVDIR_LOG char *rplog; - int rploglen; struct fd_pair logpipe; struct pollfd pfd[1]; unsigned stamplog; @@ -70,7 +69,6 @@ struct globals { #define svdir (G.svdir ) #define svnum (G.svnum ) #define rplog (G.rplog ) -#define rploglen (G.rploglen ) #define logpipe (G.logpipe ) #define pfd (G.pfd ) #define stamplog (G.stamplog ) @@ -219,15 +217,11 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) struct stat s; dev_t last_dev = last_dev; /* for gcc */ ino_t last_ino = last_ino; /* for gcc */ - time_t last_mtime = 0; - int wstat; + time_t last_mtime; int curdir; - pid_t pid; - unsigned deadline; - unsigned now; unsigned stampcheck; int i; - int need_rescan = 1; + int need_rescan; char *opt_s_argv[3]; INIT_G(); @@ -257,8 +251,7 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) /* setup log */ if (*argv) { rplog = *argv; - rploglen = strlen(rplog); - if (rploglen < 7) { + if (strlen(rplog) < 7) { warnx("log must have at least seven characters"); } else if (piped_pair(logpipe)) { warnx("can't create pipe for log"); @@ -287,11 +280,16 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) close_on_exec_on(curdir); stampcheck = monotonic_sec(); + need_rescan = 1; + last_mtime = 0; for (;;) { + unsigned now; + unsigned sig; + /* collect children */ for (;;) { - pid = wait_any_nohang(&wstat); + pid_t pid = wait_any_nohang(NULL); if (pid <= 0) break; for (i = 0; i < svnum; i++) { @@ -345,15 +343,17 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) } pfd[0].revents = 0; #endif - deadline = (need_rescan ? 1 : 5); - sig_block(SIGCHLD); + { + unsigned deadline = (need_rescan ? 1 : 5); + sig_block(SIGCHLD); #if ENABLE_FEATURE_RUNSVDIR_LOG - if (rplog) - poll(pfd, 1, deadline*1000); - else + if (rplog) + poll(pfd, 1, deadline*1000); + else #endif - sleep(deadline); - sig_unblock(SIGCHLD); + sleep(deadline); + sig_unblock(SIGCHLD); + } #if ENABLE_FEATURE_RUNSVDIR_LOG if (pfd[0].revents & POLLIN) { @@ -361,21 +361,25 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) while (read(logpipe.rd, &ch, 1) > 0) { if (ch < ' ') ch = ' '; - for (i = 6; i < rploglen; i++) + for (i = 6; rplog[i] != '\0'; i++) rplog[i-1] = rplog[i]; - rplog[rploglen-1] = ch; + rplog[i-1] = ch; } } #endif - if (!bb_got_signal) + sig = bb_got_signal; + if (!sig) continue; + bb_got_signal = 0; /* -s SCRIPT: useful if we are init. * In this case typically script never returns, * it halts/powers off/reboots the system. */ if (opt_s_argv[0]) { + pid_t pid; + /* Single parameter: signal# */ - opt_s_argv[1] = utoa(bb_got_signal); + opt_s_argv[1] = utoa(sig); pid = spawn(opt_s_argv); if (pid > 0) { /* Remembering to wait for _any_ children, @@ -385,7 +389,7 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) } } - if (bb_got_signal == SIGHUP) { + if (sig == SIGHUP) { for (i = 0; i < svnum; i++) if (sv[i].pid) kill(sv[i].pid, SIGTERM); @@ -393,9 +397,8 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) /* SIGHUP or SIGTERM (or SIGUSRn if we are init) */ /* Exit unless we are init */ if (getpid() != 1) - return (SIGHUP == bb_got_signal) ? 111 : EXIT_SUCCESS; + return (SIGHUP == sig) ? 111 : EXIT_SUCCESS; /* init continues to monitor services forever */ - bb_got_signal = 0; } /* for (;;) */ } From dac8d80f77af617effadc50f6be47768685d81b0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 2 Mar 2015 17:38:18 +0100 Subject: [PATCH 076/256] runsvdir: do not block SIGCHLD around poll/sleep There is no reason to do so. We do not even have SIGCHLD handler. function old new delta runsvdir_main 1077 1057 -20 Signed-off-by: Denys Vlasenko --- runit/runsvdir.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/runit/runsvdir.c b/runit/runsvdir.c index 809c48a51..a08af3bae 100644 --- a/runit/runsvdir.c +++ b/runit/runsvdir.c @@ -345,14 +345,12 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) #endif { unsigned deadline = (need_rescan ? 1 : 5); - sig_block(SIGCHLD); #if ENABLE_FEATURE_RUNSVDIR_LOG if (rplog) poll(pfd, 1, deadline*1000); else #endif sleep(deadline); - sig_unblock(SIGCHLD); } #if ENABLE_FEATURE_RUNSVDIR_LOG From 7db2a7c20e8d48ad9cce934c9a6d2ee563d32c84 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 2 Mar 2015 17:39:13 +0100 Subject: [PATCH 077/256] runsvdir: if pid==1, also intercept SIGINT for -s SCRIPT function old new delta runsvdir_main 1057 1064 +7 Signed-off-by: Denys Vlasenko --- runit/runsvdir.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/runit/runsvdir.c b/runit/runsvdir.c index a08af3bae..b4c0b2ef0 100644 --- a/runit/runsvdir.c +++ b/runit/runsvdir.c @@ -222,6 +222,7 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) unsigned stampcheck; int i; int need_rescan; + bool i_am_init; char *opt_s_argv[3]; INIT_G(); @@ -232,18 +233,21 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) getopt32(argv, "Ps:", &opt_s_argv[0]); argv += optind; + i_am_init = (getpid() == 1); bb_signals(0 | (1 << SIGTERM) | (1 << SIGHUP) /* For busybox's init, SIGTERM == reboot, - * SIGUSR1 == halt - * SIGUSR2 == poweroff - * so we need to intercept SIGUSRn too. + * SIGUSR1 == halt, + * SIGUSR2 == poweroff, + * Ctlr-ALt-Del sends SIGINT to init, + * so we need to intercept SIGUSRn and SIGINT too. * Note that we do not implement actual reboot * (killall(TERM) + umount, etc), we just pause * respawing and avoid exiting (-> making kernel oops). - * The user is responsible for the rest. */ - | (getpid() == 1 ? ((1 << SIGUSR1) | (1 << SIGUSR2)) : 0) + * The user is responsible for the rest. + */ + | (i_am_init ? ((1 << SIGUSR1) | (1 << SIGUSR2) | (1 << SIGINT)) : 0) , record_signo); svdir = *argv++; @@ -394,7 +398,7 @@ int runsvdir_main(int argc UNUSED_PARAM, char **argv) } /* SIGHUP or SIGTERM (or SIGUSRn if we are init) */ /* Exit unless we are init */ - if (getpid() != 1) + if (!i_am_init) return (SIGHUP == sig) ? 111 : EXIT_SUCCESS; /* init continues to monitor services forever */ From 3aef814c0b08d9703280b4772060ce5016c683c4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 2 Mar 2015 20:59:13 +0100 Subject: [PATCH 078/256] ntpd: chnage help text about -l to say that it doesn't disable client code Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index c016bfc50..0247abb6c 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -50,15 +50,15 @@ //usage: "\n -q Quit after clock is set" //usage: "\n -N Run at high priority" //usage: "\n -w Do not set time (only query peers), implies -n" -//usage: IF_FEATURE_NTPD_SERVER( -//usage: "\n -l Run as server on port 123" -//usage: "\n -I IFACE Bind server to IFACE, implies -l" -//usage: ) //usage: "\n -S PROG Run PROG after stepping time, stratum change, and every 11 mins" //usage: "\n -p PEER Obtain time from PEER (may be repeated)" //usage: IF_FEATURE_NTPD_CONF( //usage: "\n If -p is not given, read /etc/ntp.conf" //usage: ) +//usage: IF_FEATURE_NTPD_SERVER( +//usage: "\n -l Also run as server on port 123" +//usage: "\n -I IFACE Bind server to IFACE, implies -l" +//usage: ) // -l and -p options are not compatible with "standard" ntpd: // it has them as "-l logfile" and "-p pidfile". From 2ec4f44225f18bc00732cac21f3fde9d3dc2f29f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 3 Mar 2015 13:10:30 +0100 Subject: [PATCH 079/256] inetd: fix order of array index check and array access Signed-off-by: Denys Vlasenko --- networking/inetd.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/networking/inetd.c b/networking/inetd.c index b3f2e9fbc..8148925ce 100644 --- a/networking/inetd.c +++ b/networking/inetd.c @@ -645,7 +645,7 @@ static servtab_t *dup_servtab(servtab_t *sep) } /* gcc generates much more code if this is inlined */ -static servtab_t *parse_one_line(void) +static NOINLINE servtab_t *parse_one_line(void) { int argc; char *token[6+MAXARGV]; @@ -675,6 +675,8 @@ static servtab_t *parse_one_line(void) * default host for the following lines. */ free(default_local_hostname); default_local_hostname = sep->se_local_hostname; + /*sep->se_local_hostname = NULL; - redundant */ + /* (we'll overwrite this field anyway) */ goto more; } } else @@ -688,10 +690,10 @@ static servtab_t *parse_one_line(void) parse_err: bb_error_msg("parse error on line %u, line is ignored", parser->lineno); - free_servtab_strings(sep); /* Just "goto more" can make sep to carry over e.g. * "rpc"-ness (by having se_rpcver_lo != 0). * We will be more paranoid: */ + free_servtab_strings(sep); free(sep); goto new; } @@ -815,7 +817,7 @@ static servtab_t *parse_one_line(void) } #endif argc = 0; - while ((arg = token[6+argc]) != NULL && argc < MAXARGV) + while (argc < MAXARGV && (arg = token[6+argc]) != NULL) sep->se_argv[argc++] = xstrdup(arg); /* Some inetd.conf files have no argv's, not even argv[0]. * Fix them up. From 3c31b092ac21c09ce6c76111bceba00debe300c3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 5 Mar 2015 14:04:44 +0100 Subject: [PATCH 080/256] ntpd: tweak help text Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index 0247abb6c..0233ed82c 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -53,7 +53,8 @@ //usage: "\n -S PROG Run PROG after stepping time, stratum change, and every 11 mins" //usage: "\n -p PEER Obtain time from PEER (may be repeated)" //usage: IF_FEATURE_NTPD_CONF( -//usage: "\n If -p is not given, read /etc/ntp.conf" +//usage: "\n If -p is not given, 'server HOST' lines" +//usage: "\n from /etc/ntp.conf are used" //usage: ) //usage: IF_FEATURE_NTPD_SERVER( //usage: "\n -l Also run as server on port 123" From 7b434a67dcaa88047095cf0196941c5456bb1c87 Mon Sep 17 00:00:00 2001 From: Isaac Dunham Date: Wed, 11 Mar 2015 16:07:24 +0100 Subject: [PATCH 081/256] mount: -T OTHERTAB support function old new delta mount_main 1221 1241 +20 packed_usage 30616 30610 -6 Signed-off-by: Denys Vlasenko Signed-off-by: Isaac Dunham --- util-linux/Config.src | 88 -------------------------------- util-linux/mount.c | 114 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 108 insertions(+), 94 deletions(-) diff --git a/util-linux/Config.src b/util-linux/Config.src index c1cd6daa4..854b3682e 100644 --- a/util-linux/Config.src +++ b/util-linux/Config.src @@ -434,94 +434,6 @@ config MORE you will probably find this utility very helpful. If you don't have any need to reading text files, you can leave this disabled. -config MOUNT - bool "mount" - default y - select PLATFORM_LINUX - help - All files and filesystems in Unix are arranged into one big directory - tree. The 'mount' utility is used to graft a filesystem onto a - particular part of the tree. A filesystem can either live on a block - device, or it can be accessible over the network, as is the case with - NFS filesystems. Most people using BusyBox will also want to enable - the 'mount' utility. - -config FEATURE_MOUNT_FAKE - bool "Support option -f" - default y - depends on MOUNT - help - Enable support for faking a file system mount. - -config FEATURE_MOUNT_VERBOSE - bool "Support option -v" - default y - depends on MOUNT - help - Enable multi-level -v[vv...] verbose messages. Useful if you - debug mount problems and want to see what is exactly passed - to the kernel. - -config FEATURE_MOUNT_HELPERS - bool "Support mount helpers" - default n - depends on MOUNT - help - Enable mounting of virtual file systems via external helpers. - E.g. "mount obexfs#-b00.11.22.33.44.55 /mnt" will in effect call - "obexfs -b00.11.22.33.44.55 /mnt" - Also "mount -t sometype [-o opts] fs /mnt" will try - "sometype [-o opts] fs /mnt" if simple mount syscall fails. - The idea is to use such virtual filesystems in /etc/fstab. - -config FEATURE_MOUNT_LABEL - bool "Support specifying devices by label or UUID" - default y - depends on MOUNT - select VOLUMEID - help - This allows for specifying a device by label or uuid, rather than by - name. This feature utilizes the same functionality as blkid/findfs. - This also enables label or uuid support for swapon. - -config FEATURE_MOUNT_NFS - bool "Support mounting NFS file systems on Linux < 2.6.23" - default n - depends on MOUNT - select FEATURE_HAVE_RPC - select FEATURE_SYSLOG - help - Enable mounting of NFS file systems on Linux kernels prior - to version 2.6.23. Note that in this case mounting of NFS - over IPv6 will not be possible. - - Note that this option links in RPC support from libc, - which is rather large (~10 kbytes on uclibc). - -config FEATURE_MOUNT_CIFS - bool "Support mounting CIFS/SMB file systems" - default y - depends on MOUNT - help - Enable support for samba mounts. - -config FEATURE_MOUNT_FLAGS - depends on MOUNT - bool "Support lots of -o flags in mount" - default y - help - Without this, mount only supports ro/rw/remount. With this, it - supports nosuid, suid, dev, nodev, exec, noexec, sync, async, atime, - noatime, diratime, nodiratime, loud, bind, move, shared, slave, - private, unbindable, rshared, rslave, rprivate, and runbindable. - -config FEATURE_MOUNT_FSTAB - depends on MOUNT - bool "Support /etc/fstab and -a" - default y - help - Support mount all and looking for files in /etc/fstab. - config PIVOT_ROOT bool "pivot_root" default y diff --git a/util-linux/mount.c b/util-linux/mount.c index 62fd41fd7..fbc89c862 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c @@ -17,8 +17,103 @@ // mount_it_now() does the actual mount. // +//config:config MOUNT +//config: bool "mount" +//config: default y +//config: select PLATFORM_LINUX +//config: help +//config: All files and filesystems in Unix are arranged into one big directory +//config: tree. The 'mount' utility is used to graft a filesystem onto a +//config: particular part of the tree. A filesystem can either live on a block +//config: device, or it can be accessible over the network, as is the case with +//config: NFS filesystems. Most people using BusyBox will also want to enable +//config: the 'mount' utility. +//config: +//config:config FEATURE_MOUNT_FAKE +//config: bool "Support option -f" +//config: default y +//config: depends on MOUNT +//config: help +//config: Enable support for faking a file system mount. +//config: +//config:config FEATURE_MOUNT_VERBOSE +//config: bool "Support option -v" +//config: default y +//config: depends on MOUNT +//config: help +//config: Enable multi-level -v[vv...] verbose messages. Useful if you +//config: debug mount problems and want to see what is exactly passed +//config: to the kernel. +//config: +//config:config FEATURE_MOUNT_HELPERS +//config: bool "Support mount helpers" +//config: default n +//config: depends on MOUNT +//config: help +//config: Enable mounting of virtual file systems via external helpers. +//config: E.g. "mount obexfs#-b00.11.22.33.44.55 /mnt" will in effect call +//config: "obexfs -b00.11.22.33.44.55 /mnt" +//config: Also "mount -t sometype [-o opts] fs /mnt" will try +//config: "sometype [-o opts] fs /mnt" if simple mount syscall fails. +//config: The idea is to use such virtual filesystems in /etc/fstab. +//config: +//config:config FEATURE_MOUNT_LABEL +//config: bool "Support specifying devices by label or UUID" +//config: default y +//config: depends on MOUNT +//config: select VOLUMEID +//config: help +//config: This allows for specifying a device by label or uuid, rather than by +//config: name. This feature utilizes the same functionality as blkid/findfs. +//config: This also enables label or uuid support for swapon. +//config: +//config:config FEATURE_MOUNT_NFS +//config: bool "Support mounting NFS file systems on Linux < 2.6.23" +//config: default n +//config: depends on MOUNT +//config: select FEATURE_HAVE_RPC +//config: select FEATURE_SYSLOG +//config: help +//config: Enable mounting of NFS file systems on Linux kernels prior +//config: to version 2.6.23. Note that in this case mounting of NFS +//config: over IPv6 will not be possible. +//config: +//config: Note that this option links in RPC support from libc, +//config: which is rather large (~10 kbytes on uclibc). +//config: +//config:config FEATURE_MOUNT_CIFS +//config: bool "Support mounting CIFS/SMB file systems" +//config: default y +//config: depends on MOUNT +//config: help +//config: Enable support for samba mounts. +//config: +//config:config FEATURE_MOUNT_FLAGS +//config: depends on MOUNT +//config: bool "Support lots of -o flags in mount" +//config: default y +//config: help +//config: Without this, mount only supports ro/rw/remount. With this, it +//config: supports nosuid, suid, dev, nodev, exec, noexec, sync, async, atime, +//config: noatime, diratime, nodiratime, loud, bind, move, shared, slave, +//config: private, unbindable, rshared, rslave, rprivate, and runbindable. +//config: +//config:config FEATURE_MOUNT_FSTAB +//config: depends on MOUNT +//config: bool "Support /etc/fstab and -a" +//config: default y +//config: help +//config: Support mount all and looking for files in /etc/fstab. +//config: +//config:config FEATURE_MOUNT_OTHERTAB +//config: depends on FEATURE_MOUNT_FSTAB +//config: bool "Support -T " +//config: default y +//config: help +//config: Support mount -T (specifying an alternate fstab) + //usage:#define mount_trivial_usage -//usage: "[OPTIONS] [-o OPTS] DEVICE NODE" +//usage: "[OPTIONS] [-o OPT] DEVICE NODE" //usage:#define mount_full_usage "\n\n" //usage: "Mount a filesystem. Filesystem autodetection requires /proc.\n" //usage: "\n -a Mount all filesystems in fstab" @@ -41,8 +136,11 @@ //usage: ) ////usage: "\n -s Sloppy (ignored)" //usage: "\n -r Read-only mount" -//usage: "\n -w Read-write mount (default)" +////usage: "\n -w Read-write mount (default)" //usage: "\n -t FSTYPE[,...] Filesystem type(s)" +//usage: IF_FEATURE_MOUNT_OTHERTAB( +//usage: "\n -T FILE Read FILE instead of /etc/fstab" +//usage: ) //usage: "\n -O OPT Mount only filesystems with option OPT (-a only)" //usage: "\n-o OPT:" //usage: IF_FEATURE_MOUNT_LOOP( @@ -64,7 +162,7 @@ //usage: "\n move Relocate an existing mount point" //usage: ) //usage: "\n remount Remount a mounted filesystem, changing flags" -//usage: "\n ro/rw Same as -r/-w" +//usage: "\n ro Same as -r" //usage: "\n" //usage: "\nThere are filesystem-specific -o flags." //usage: @@ -167,7 +265,7 @@ enum { }; -#define OPTION_STR "o:t:rwanfvsiO:" +#define OPTION_STR "o:t:rwanfvsiO:" IF_FEATURE_MOUNT_OTHERTAB("T:") enum { OPT_o = (1 << 0), OPT_t = (1 << 1), @@ -180,6 +278,7 @@ enum { OPT_s = (1 << 8), OPT_i = (1 << 9), OPT_O = (1 << 10), + OPT_T = (1 << 11), }; #if ENABLE_FEATURE_MTAB_SUPPORT @@ -2034,7 +2133,7 @@ int mount_main(int argc UNUSED_PARAM, char **argv) char *O_optmatch = NULL; char *storage_path; llist_t *lst_o = NULL; - const char *fstabname; + const char *fstabname = "/etc/fstab"; FILE *fstab; int i, j; int rc = EXIT_SUCCESS; @@ -2061,6 +2160,7 @@ int mount_main(int argc UNUSED_PARAM, char **argv) // Max 2 params; -o is a list, -v is a counter opt_complementary = "?2o::" IF_FEATURE_MOUNT_VERBOSE("vv"); opt = getopt32(argv, OPTION_STR, &lst_o, &fstype, &O_optmatch + IF_FEATURE_MOUNT_OTHERTAB(, &fstabname) IF_FEATURE_MOUNT_VERBOSE(, &verbose)); while (lst_o) append_mount_options(&cmdopts, llist_pop(&lst_o)); // -o if (opt & OPT_r) append_mount_options(&cmdopts, "ro"); // -r @@ -2128,8 +2228,10 @@ int mount_main(int argc UNUSED_PARAM, char **argv) return rc; } + // A malicious user could overmount /usr without this. + if (ENABLE_FEATURE_MOUNT_OTHERTAB && nonroot) + fstabname = "/etc/fstab"; // Open either fstab or mtab - fstabname = "/etc/fstab"; if (cmdopt_flags & MS_REMOUNT) { // WARNING. I am not sure this matches util-linux's // behavior. It's possible util-linux does not From fe8b5802bafb7bce7af525237d1195a91a3e4af4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 11 Mar 2015 18:01:34 +0100 Subject: [PATCH 082/256] patch: segfault fix. Closes 7916 Fix segfault on this case (malformed --- line): -- dwarves.orig 2015-02-25 01:45:27.753000000 +0000 +++ dwarves 2015-02-25 01:46:08.199000000 +0000 @@ -1,7 +1,7 @@ Bashful Doc Dopey -Grouchy +Grumpy Happy Sleepy Sneezy function old new delta patch_main 1903 1957 +54 Signed-off-by: Denys Vlasenko --- editors/patch.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/editors/patch.c b/editors/patch.c index 13785ef46..f86067544 100644 --- a/editors/patch.c +++ b/editors/patch.c @@ -345,6 +345,8 @@ done: // state 1: Found +++ file indicator, look for @@ // state 2: In hunk: counting initial context lines // state 3: In hunk: getting body +// Like GNU patch, we don't require a --- line before the +++, and +// also allow the --- after the +++ line. int patch_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int patch_main(int argc UNUSED_PARAM, char **argv) @@ -462,6 +464,14 @@ int patch_main(int argc UNUSED_PARAM, char **argv) TT.context = 0; state = 2; + // If the --- line is missing or malformed, either oldname + // or (for -R) newname could be NULL -- but not both. Like + // GNU patch, proceed based on the +++ line, and avoid SEGVs. + if (!oldname) + oldname = xstrdup("MISSING_FILENAME"); + if (!newname) + newname = xstrdup("MISSING_FILENAME"); + // If this is the first hunk, open the file. if (TT.filein == -1) { int oldsum, newsum, empty = 0; From 748fb60f274b1ba40aa6ed4c4582185aae8f68f7 Mon Sep 17 00:00:00 2001 From: Alexander Korolkov Date: Thu, 12 Mar 2015 13:05:33 +0100 Subject: [PATCH 083/256] arping: fix iface name in error messages arping: interface eth0 not found: No such device ^^^^ This is because error template is formed before parsing command line arguments, so it always uses default interface name "eth0". Signed-off-by: Alexander Korolkov Signed-off-by: Denys Vlasenko --- networking/arping.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/networking/arping.c b/networking/arping.c index a4421edcb..dbfd75ef5 100644 --- a/networking/arping.c +++ b/networking/arping.c @@ -284,7 +284,6 @@ int arping_main(int argc UNUSED_PARAM, char **argv) // Need to remove SUID_NEVER from applets.h for this to work //xsetuid(getuid()); - err_str = xasprintf("interface %s %%s", device); { unsigned opt; char *str_timeout; @@ -302,7 +301,7 @@ int arping_main(int argc UNUSED_PARAM, char **argv) } target = argv[optind]; - + err_str = xasprintf("interface %s %%s", device); xfunc_error_retval = 2; { From 936c8809caea5705e26e5d7e06ea3895c28fffd8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 12 Mar 2015 15:30:46 +0100 Subject: [PATCH 084/256] deluser: also remove user from /etc/group function old new delta update_passwd 1270 1470 +200 deluser_main 310 332 +22 Signed-off-by: Denys Vlasenko --- libbb/update_passwd.c | 38 ++++++++++++++++++++++++++++++++++++-- loginutils/deluser.c | 18 ++++++++++++------ 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/libbb/update_passwd.c b/libbb/update_passwd.c index a30af6f72..dc26ebd1d 100644 --- a/libbb/update_passwd.c +++ b/libbb/update_passwd.c @@ -62,6 +62,8 @@ static void check_selinux_update_passwd(const char *username) only if CONFIG_PASSWD=y and applet_name[0] == 'p' like in passwd or if CONFIG_CHPASSWD=y and applet_name[0] == 'c' like in chpasswd + 8) delete a user from all groups: update_passwd(FILE, NULL, NULL, MEMBER) + This function does not validate the arguments fed to it so the calling program should take care of that. @@ -99,12 +101,13 @@ int FAST_FUNC update_passwd(const char *filename, if (filename == NULL) return ret; - check_selinux_update_passwd(name); + if (name) + check_selinux_update_passwd(name); /* New passwd file, "/etc/passwd+" for now */ fnamesfx = xasprintf("%s+", filename); sfx_char = &fnamesfx[strlen(fnamesfx)-1]; - name_colon = xasprintf("%s:", name); + name_colon = xasprintf("%s:", name ? name : ""); user_len = strlen(name_colon); if (shadow) @@ -167,6 +170,37 @@ int FAST_FUNC update_passwd(const char *filename, line = xmalloc_fgetline(old_fp); if (!line) /* EOF/error */ break; + + if (!name && member) { + /* Delete member from all groups */ + /* line is "GROUP:PASSWD:[member1[,member2]...]" */ + unsigned member_len = strlen(member); + char *list = strrchr(line, ':'); + while (list) { + list++; + next_list_element: + if (strncmp(list, member, member_len) == 0) { + char c; + changed_lines++; + c = list[member_len]; + if (c == '\0') { + if (list[-1] == ',') + list--; + *list = '\0'; + break; + } + if (c == ',') { + overlapping_strcpy(list, list + member_len + 1); + goto next_list_element; + } + changed_lines--; + } + list = strchr(list, ','); + } + fprintf(new_fp, "%s\n", line); + goto next; + } + if (strncmp(name_colon, line, user_len) != 0) { fprintf(new_fp, "%s\n", line); goto next; diff --git a/loginutils/deluser.c b/loginutils/deluser.c index 01a9386bc..110cd6310 100644 --- a/loginutils/deluser.c +++ b/loginutils/deluser.c @@ -114,16 +114,22 @@ int deluser_main(int argc, char **argv) } } while (ENABLE_FEATURE_SHADOWPASSWDS && pfile); - if (ENABLE_DELGROUP && do_deluser > 0) { - /* "deluser USER" also should try to delete - * same-named group. IOW: do "delgroup USER" - */ + if (do_deluser > 0) { + /* Delete user from all groups */ + if (update_passwd(bb_path_group_file, NULL, NULL, name) == -1) + return EXIT_FAILURE; + + if (ENABLE_DELGROUP) { + /* "deluser USER" also should try to delete + * same-named group. IOW: do "delgroup USER" + */ // On debian deluser is a perl script that calls userdel. // From man userdel: // If USERGROUPS_ENAB is defined to yes in /etc/login.defs, userdel will // delete the group with the same name as the user. - do_deluser = -1; - goto do_delgroup; + do_deluser = -1; + goto do_delgroup; + } } return EXIT_SUCCESS; } From 8dff01d06a7ebd7330e3a1dd1ba47b3c74ee7dfb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 12 Mar 2015 17:48:34 +0100 Subject: [PATCH 085/256] libbb: introduce and use is_prefixed_with() function old new delta is_prefixed_with - 18 +18 complete_username 78 77 -1 man_main 737 735 -2 fsck_device 429 427 -2 unpack_ar_archive 80 76 -4 strip_unsafe_prefix 105 101 -4 singlemount 1054 1050 -4 rtc_adjtime_is_utc 90 86 -4 resolve_mount_spec 88 84 -4 parse_one_line 1029 1025 -4 parse_conf 1460 1456 -4 may_wakeup 83 79 -4 loadkmap_main 219 215 -4 get_irqs_from_stat 103 99 -4 get_header_cpio 913 909 -4 findfs_main 79 75 -4 fbsplash_main 1230 1226 -4 load_crontab 776 771 -5 expand_vars_to_list 1151 1146 -5 date_main 881 876 -5 skip_dev_pfx 30 24 -6 make_device 2199 2193 -6 complete_cmd_dir_file 773 767 -6 run_applet_and_exit 715 708 -7 uudecode_main 321 313 -8 pwdx_main 197 189 -8 execute 568 560 -8 i2cdetect_main 1186 1176 -10 procps_scan 1242 1230 -12 procps_read_smaps 1017 1005 -12 process_module 746 734 -12 patch_main 1903 1891 -12 nfsmount 3572 3560 -12 stack_machine 126 112 -14 process_timer_stats 449 435 -14 match_fstype 111 97 -14 do_ipaddr 1344 1330 -14 open_list_and_close 359 343 -16 get_header_tar 1795 1779 -16 prepend_new_eth_table 340 323 -17 fsck_main 1811 1794 -17 find_iface_state 56 38 -18 dnsd_main 1321 1303 -18 base_device 179 158 -21 find_keyword 104 82 -22 handle_incoming_and_exit 2785 2762 -23 parse_and_put_prompt 774 746 -28 modinfo 347 317 -30 find_action 204 171 -33 update_passwd 1470 1436 -34 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/49 up/down: 18/-540) Total: -522 bytes Signed-off-by: Denys Vlasenko --- archival/libarchive/get_header_cpio.c | 2 +- archival/libarchive/get_header_tar.c | 6 ++-- archival/libarchive/unpack_ar_archive.c | 2 +- archival/libarchive/unsafe_prefix.c | 2 +- console-tools/loadkmap.c | 2 +- coreutils/date.c | 2 +- coreutils/uudecode.c | 4 +-- e2fsprogs/fsck.c | 40 ++++++++++++------------- editors/patch.c | 4 +-- include/libbb.h | 1 + libbb/appletlib.c | 8 ++--- libbb/compare_string_array.c | 23 ++++++++++++-- libbb/lineedit.c | 17 ++++++----- libbb/match_fstype.c | 7 ++--- libbb/procps.c | 12 ++++---- libbb/rtc.c | 2 +- libbb/skip_whitespace.c | 2 +- libbb/update_passwd.c | 9 +++--- libbb/xconnect.c | 2 +- miscutils/crond.c | 4 +-- miscutils/dc.c | 6 ++-- miscutils/devfsd.c | 10 +++---- miscutils/fbsplash.c | 2 +- miscutils/i2c_tools.c | 4 +-- miscutils/last.c | 6 ++-- miscutils/man.c | 4 +-- modutils/depmod.c | 8 ++--- modutils/modinfo.c | 12 ++++---- modutils/modprobe-small.c | 21 ++++++------- modutils/modprobe.c | 12 +++----- modutils/modutils-24.c | 2 +- networking/dnsd.c | 2 +- networking/httpd.c | 8 ++--- networking/ifupdown.c | 10 +++---- networking/inetd.c | 2 +- networking/libiproute/ipaddress.c | 2 +- networking/nameif.c | 8 ++--- networking/netstat.c | 4 +-- procps/mpstat.c | 2 +- procps/powertop.c | 4 +-- procps/pwdx.c | 2 +- shell/hush.c | 2 +- util-linux/acpid.c | 2 +- util-linux/fdisk.c | 6 ++-- util-linux/fdisk_osf.c | 2 +- util-linux/fdisk_sgi.c | 2 +- util-linux/findfs.c | 2 +- util-linux/mdev.c | 2 +- util-linux/mount.c | 10 +++---- util-linux/rtcwake.c | 2 +- util-linux/volume_id/get_devname.c | 4 +-- 51 files changed, 165 insertions(+), 151 deletions(-) diff --git a/archival/libarchive/get_header_cpio.c b/archival/libarchive/get_header_cpio.c index 1a0058b63..7861d1f6f 100644 --- a/archival/libarchive/get_header_cpio.c +++ b/archival/libarchive/get_header_cpio.c @@ -37,7 +37,7 @@ char FAST_FUNC get_header_cpio(archive_handle_t *archive_handle) } archive_handle->offset += 110; - if (strncmp(&cpio_header[0], "07070", 5) != 0 + if (!is_prefixed_with(&cpio_header[0], "07070") || (cpio_header[5] != '1' && cpio_header[5] != '2') ) { bb_error_msg_and_die("unsupported cpio format, use newc or crc"); diff --git a/archival/libarchive/get_header_tar.c b/archival/libarchive/get_header_tar.c index 0c663fbd7..2dbcdb50c 100644 --- a/archival/libarchive/get_header_tar.c +++ b/archival/libarchive/get_header_tar.c @@ -105,7 +105,7 @@ static void process_pax_hdr(archive_handle_t *archive_handle, unsigned sz, int g value = end + 1; #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS - if (!global && strncmp(value, "path=", sizeof("path=") - 1) == 0) { + if (!global && is_prefixed_with(value, "path=")) { value += sizeof("path=") - 1; free(archive_handle->tar__longname); archive_handle->tar__longname = xstrdup(value); @@ -118,7 +118,7 @@ static void process_pax_hdr(archive_handle_t *archive_handle, unsigned sz, int g * This is what Red Hat's patched version of tar uses. */ # define SELINUX_CONTEXT_KEYWORD "RHT.security.selinux" - if (strncmp(value, SELINUX_CONTEXT_KEYWORD"=", sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1) == 0) { + if (is_prefixed_with(value, SELINUX_CONTEXT_KEYWORD"=")) { value += sizeof(SELINUX_CONTEXT_KEYWORD"=") - 1; free(archive_handle->tar__sctx[global]); archive_handle->tar__sctx[global] = xstrdup(value); @@ -202,7 +202,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) /* Check header has valid magic, "ustar" is for the proper tar, * five NULs are for the old tar format */ - if (strncmp(tar.magic, "ustar", 5) != 0 + if (!is_prefixed_with(tar.magic, "ustar") && (!ENABLE_FEATURE_TAR_OLDGNU_COMPATIBILITY || memcmp(tar.magic, "\0\0\0\0", 5) != 0) ) { diff --git a/archival/libarchive/unpack_ar_archive.c b/archival/libarchive/unpack_ar_archive.c index 214d17e23..0bc030349 100644 --- a/archival/libarchive/unpack_ar_archive.c +++ b/archival/libarchive/unpack_ar_archive.c @@ -12,7 +12,7 @@ void FAST_FUNC unpack_ar_archive(archive_handle_t *ar_archive) char magic[7]; xread(ar_archive->src_fd, magic, AR_MAGIC_LEN); - if (strncmp(magic, AR_MAGIC, AR_MAGIC_LEN) != 0) { + if (!is_prefixed_with(magic, AR_MAGIC)) { bb_error_msg_and_die("invalid ar magic"); } ar_archive->offset += AR_MAGIC_LEN; diff --git a/archival/libarchive/unsafe_prefix.c b/archival/libarchive/unsafe_prefix.c index 826c673bf..9994f4d94 100644 --- a/archival/libarchive/unsafe_prefix.c +++ b/archival/libarchive/unsafe_prefix.c @@ -15,7 +15,7 @@ const char* FAST_FUNC strip_unsafe_prefix(const char *str) cp++; continue; } - if (strncmp(cp, "/../"+1, 3) == 0) { + if (is_prefixed_with(cp, "/../"+1)) { cp += 3; continue; } diff --git a/console-tools/loadkmap.c b/console-tools/loadkmap.c index 6dcf8133f..f525ee5d1 100644 --- a/console-tools/loadkmap.c +++ b/console-tools/loadkmap.c @@ -57,7 +57,7 @@ int loadkmap_main(int argc UNUSED_PARAM, char **argv) */ xread(STDIN_FILENO, flags, 7); - if (strncmp(flags, BINARY_KEYMAP_MAGIC, 7)) + if (!is_prefixed_with(flags, BINARY_KEYMAP_MAGIC)) bb_error_msg_and_die("not a valid binary keymap"); xread(STDIN_FILENO, flags, MAX_NR_KEYMAPS); diff --git a/coreutils/date.c b/coreutils/date.c index 767e0d4a2..7965775fe 100644 --- a/coreutils/date.c +++ b/coreutils/date.c @@ -373,7 +373,7 @@ int date_main(int argc UNUSED_PARAM, char **argv) date_buf[0] = '\0'; } else { /* Handle special conversions */ - if (strncmp(fmt_dt2str, "%f", 2) == 0) { + if (is_prefixed_with(fmt_dt2str, "%f")) { fmt_dt2str = (char*)"%Y.%m.%d-%H:%M:%S"; } /* Generate output string */ diff --git a/coreutils/uudecode.c b/coreutils/uudecode.c index b298fcb95..3f1227306 100644 --- a/coreutils/uudecode.c +++ b/coreutils/uudecode.c @@ -110,10 +110,10 @@ int uudecode_main(int argc UNUSED_PARAM, char **argv) FILE *dst_stream; int mode; - if (strncmp(line, "begin-base64 ", 13) == 0) { + if (is_prefixed_with(line, "begin-base64 ")) { line_ptr = line + 13; decode_fn_ptr = read_base64; - } else if (strncmp(line, "begin ", 6) == 0) { + } else if (is_prefixed_with(line, "begin ")) { line_ptr = line + 6; decode_fn_ptr = read_stduu; } else { diff --git a/e2fsprogs/fsck.c b/e2fsprogs/fsck.c index d32f396e9..d2d312e5c 100644 --- a/e2fsprogs/fsck.c +++ b/e2fsprogs/fsck.c @@ -199,7 +199,7 @@ static char *base_device(const char *device) } /* Handle DAC 960 devices */ - if (strncmp(cp, "rd/", 3) == 0) { + if (is_prefixed_with(cp, "rd/")) { cp += 3; if (cp[0] != 'c' || !isdigit(cp[1]) || cp[2] != 'd' || !isdigit(cp[3])) @@ -224,9 +224,9 @@ static char *base_device(const char *device) #if ENABLE_FEATURE_DEVFS /* Now let's handle devfs (ugh) names */ len = 0; - if (strncmp(cp, "ide/", 4) == 0) + if (is_prefixed_with(cp, "ide/")) len = 4; - if (strncmp(cp, "scsi/", 5) == 0) + if (is_prefixed_with(cp, "scsi/")) len = 5; if (len) { cp += len; @@ -237,38 +237,38 @@ static char *base_device(const char *device) * some number of digits at each level, abort. */ for (hier = devfs_hier; *hier; hier++) { - len = strlen(*hier); - if (strncmp(cp, *hier, len) != 0) + cp = is_prefixed_with(cp, *hier); + if (!cp) goto errout; - cp += len; - while (*cp != '/' && *cp != 0) { + while (*cp != '/' && *cp != '\0') { if (!isdigit(*cp)) goto errout; cp++; } +//FIXME: what if *cp = '\0' now? cp++ moves past it!!! cp++; } - cp[-1] = 0; + cp[-1] = '\0'; return str; } /* Now handle devfs /dev/disc or /dev/disk names */ - disk = 0; - if (strncmp(cp, "discs/", 6) == 0) + disk = NULL; + if (is_prefixed_with(cp, "discs/")) disk = "disc"; - else if (strncmp(cp, "disks/", 6) == 0) + else if (is_prefixed_with(cp, "disks/")) disk = "disk"; if (disk) { cp += 6; - if (strncmp(cp, disk, 4) != 0) + cp = is_prefixed_with(cp, disk); + if (!cp) goto errout; - cp += 4; - while (*cp != '/' && *cp != 0) { + while (*cp != '/' && *cp != '\0') { if (!isdigit(*cp)) goto errout; cp++; } - *cp = 0; + *cp = '\0'; return str; } #endif @@ -593,8 +593,8 @@ static void fsck_device(struct fs_info *fs /*, int interactive */) type, "from fstab"); } else if (fstype && (fstype[0] != 'n' || fstype[1] != 'o') /* != "no" */ - && strncmp(fstype, "opts=", 5) != 0 - && strncmp(fstype, "loop", 4) != 0 + && !is_prefixed_with(fstype, "opts=") + && !is_prefixed_with(fstype, "loop") && !strchr(fstype, ',') ) { type = fstype; @@ -627,8 +627,8 @@ static int device_already_active(char *device) #ifdef BASE_MD /* Don't check a soft raid disk with any other disk */ if (instance_list - && (!strncmp(instance_list->device, BASE_MD, sizeof(BASE_MD)-1) - || !strncmp(device, BASE_MD, sizeof(BASE_MD)-1)) + && (is_prefixed_with(instance_list->device, BASE_MD) + || is_prefixed_with(device, BASE_MD)) ) { return 1; } @@ -895,7 +895,7 @@ static void compile_fs_type(char *fs_type) if (strcmp(s, "loop") == 0) /* loop is really short-hand for opts=loop */ goto loop_special_case; - if (strncmp(s, "opts=", 5) == 0) { + if (is_prefixed_with(s, "opts=")) { s += 5; loop_special_case: fs_type_flag[num] = negate ? FS_TYPE_FLAG_NEGOPT : FS_TYPE_FLAG_OPT; diff --git a/editors/patch.c b/editors/patch.c index f86067544..cb25e4140 100644 --- a/editors/patch.c +++ b/editors/patch.c @@ -414,7 +414,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv) } // Open a new file? - if (!strncmp("--- ", patchline, 4) || !strncmp("+++ ", patchline, 4)) { + if (is_prefixed_with(patchline, "--- ") || is_prefixed_with(patchline, "+++ ")) { char *s, **name = reverse ? &newname : &oldname; int i; @@ -446,7 +446,7 @@ int patch_main(int argc UNUSED_PARAM, char **argv) // Start a new hunk? Usually @@ -oldline,oldlen +newline,newlen @@ // but a missing ,value means the value is 1. - } else if (state == 1 && !strncmp("@@ -", patchline, 4)) { + } else if (state == 1 && is_prefixed_with(patchline, "@@ -")) { int i; char *s = patchline+4; diff --git a/include/libbb.h b/include/libbb.h index be792d6b2..c97df6047 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -389,6 +389,7 @@ const char *bb_basename(const char *name) FAST_FUNC; /* NB: can violate const-ness (similarly to strchr) */ char *last_char_is(const char *s, int c) FAST_FUNC; const char* endofname(const char *name) FAST_FUNC; +char *is_prefixed_with(const char *string, const char *key) FAST_FUNC; int ndelay_on(int fd) FAST_FUNC; int ndelay_off(int fd) FAST_FUNC; diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 54300bd87..8fd8fd525 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -193,7 +193,7 @@ void lbb_prepare(const char *applet if (argv[1] && !argv[2] && strcmp(argv[1], "--help") == 0 - && strncmp(applet, "busybox", 7) != 0 + && !is_prefixed_with(applet, "busybox") ) { /* Special case. POSIX says "test --help" * should be no different from e.g. "test --foo". */ @@ -673,7 +673,7 @@ static int busybox_main(char **argv) return 0; } - if (strncmp(argv[1], "--list", 6) == 0) { + if (is_prefixed_with(argv[1], "--list")) { unsigned i = 0; const char *a = applet_names; dup2(1, 2); @@ -778,7 +778,7 @@ void FAST_FUNC run_applet_and_exit(const char *name, char **argv) int applet = find_applet_by_name(name); if (applet >= 0) run_applet_no_and_exit(applet, argv); - if (strncmp(name, "busybox", 7) == 0) + if (is_prefixed_with(name, "busybox")) exit(busybox_main(argv)); } @@ -817,7 +817,7 @@ int main(int argc UNUSED_PARAM, char **argv) #if defined(SINGLE_APPLET_MAIN) /* Only one applet is selected in .config */ - if (argv[1] && strncmp(argv[0], "busybox", 7) == 0) { + if (argv[1] && is_prefixed_with(argv[0], "busybox")) { /* "busybox " should still work as expected */ argv++; } diff --git a/libbb/compare_string_array.c b/libbb/compare_string_array.c index 4b10cc138..e24815a03 100644 --- a/libbb/compare_string_array.c +++ b/libbb/compare_string_array.c @@ -5,6 +5,24 @@ #include "libbb.h" +char* FAST_FUNC is_prefixed_with(const char *string, const char *key) +{ +#if 0 /* Two passes over key - probably slower */ + int len = strlen(key); + if (strncmp(string, key, len) == 0) + return string + len; + return NULL; +#else /* Open-coded */ + while (*key != '\0') { + if (*key != *string) + return NULL; + key++; + string++; + } + return (char*)string; +#endif +} + /* returns the array index of the string */ /* (index of first match is returned, or -1) */ int FAST_FUNC index_in_str_array(const char *const string_array[], const char *key) @@ -39,10 +57,9 @@ int FAST_FUNC index_in_strings(const char *strings, const char *key) int FAST_FUNC index_in_substr_array(const char *const string_array[], const char *key) { int i; - int len = strlen(key); - if (len) { + if (key[0]) { for (i = 0; string_array[i] != 0; i++) { - if (strncmp(string_array[i], key, len) == 0) { + if (is_prefixed_with(string_array[i], key)) { return i; } } diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 249b401b4..a83e07c0c 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -681,7 +681,7 @@ static NOINLINE unsigned complete_username(const char *ud) setpwent(); while ((pw = getpwent()) != NULL) { /* Null usernames should result in all users as possible completions. */ - if (/*!userlen || */ strncmp(ud, pw->pw_name, userlen) == 0) { + if (/* !ud[0] || */ is_prefixed_with(pw->pw_name, ud)) { add_match(xasprintf("~%s/", pw->pw_name)); } } @@ -792,7 +792,7 @@ static NOINLINE unsigned complete_cmd_dir_file(const char *command, int type) if (!pfind[0] && DOT_OR_DOTDOT(name_found)) continue; /* match? */ - if (strncmp(name_found, pfind, pf_len) != 0) + if (!is_prefixed_with(name_found, pfind)) continue; /* no */ found = concat_path_file(paths[i], name_found); @@ -1879,15 +1879,16 @@ static void parse_and_put_prompt(const char *prmt_ptr) cwd_buf = xrealloc_getcwd_or_warn(NULL); if (!cwd_buf) cwd_buf = (char *)bb_msg_unknown; - else { + else if (home_pwd_buf[0]) { + char *after_home_user; + /* /home/user[/something] -> ~[/something] */ - l = strlen(home_pwd_buf); - if (l != 0 - && strncmp(home_pwd_buf, cwd_buf, l) == 0 - && (cwd_buf[l] == '/' || cwd_buf[l] == '\0') + after_home_user = is_prefixed_with(cwd_buf, home_pwd_buf); + if (after_home_user + && (*after_home_user == '/' || *after_home_user == '\0') ) { cwd_buf[0] = '~'; - overlapping_strcpy(cwd_buf + 1, cwd_buf + l); + overlapping_strcpy(cwd_buf + 1, after_home_user); } } } diff --git a/libbb/match_fstype.c b/libbb/match_fstype.c index 32c3d7f18..b066b4211 100644 --- a/libbb/match_fstype.c +++ b/libbb/match_fstype.c @@ -17,7 +17,6 @@ int FAST_FUNC match_fstype(const struct mntent *mt, const char *t_fstype) { int match = 1; - int len; if (!t_fstype) return match; @@ -27,10 +26,10 @@ int FAST_FUNC match_fstype(const struct mntent *mt, const char *t_fstype) t_fstype += 2; } - len = strlen(mt->mnt_type); while (1) { - if (strncmp(mt->mnt_type, t_fstype, len) == 0 - && (t_fstype[len] == '\0' || t_fstype[len] == ',') + char *after_mnt_type = is_prefixed_with(t_fstype, mt->mnt_type); + if (after_mnt_type + && (*after_mnt_type == '\0' || *after_mnt_type == ',') ) { return match; } diff --git a/libbb/procps.c b/libbb/procps.c index 5b68d3431..948b91ee6 100644 --- a/libbb/procps.c +++ b/libbb/procps.c @@ -205,11 +205,11 @@ int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total, // Rss: nnn kB // ..... - char *tp = buf, *p; + char *tp, *p; #define SCAN(S, X) \ - if (strncmp(tp, S, sizeof(S)-1) == 0) { \ - tp = skip_whitespace(tp + sizeof(S)-1); \ + if ((tp = is_prefixed_with(buf, S)) != NULL) { \ + tp = skip_whitespace(tp); \ total->X += currec.X = fast_strtoul_10(&tp); \ continue; \ } @@ -247,7 +247,7 @@ int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total, // skipping "rw-s FILEOFS M:m INODE " tp = skip_whitespace(skip_fields(tp, 4)); // filter out /dev/something (something != zero) - if (strncmp(tp, "/dev/", 5) != 0 || strcmp(tp, "/dev/zero\n") == 0) { + if (!is_prefixed_with(tp, "/dev/") || strcmp(tp, "/dev/zero\n") == 0) { if (currec.smap_mode[1] == 'w') { currec.mapped_rw = currec.smap_size; total->mapped_rw += currec.smap_size; @@ -497,8 +497,8 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags) while (fgets(buf, sizeof(buf), file)) { char *tp; #define SCAN_TWO(str, name, statement) \ - if (strncmp(buf, str, sizeof(str)-1) == 0) { \ - tp = skip_whitespace(buf + sizeof(str)-1); \ + if ((tp = is_prefixed_with(buf, str)) != NULL) { \ + tp = skip_whitespace(tp); \ sscanf(tp, "%u", &sp->name); \ statement; \ } diff --git a/libbb/rtc.c b/libbb/rtc.c index 6d06d57f9..c4117ba34 100644 --- a/libbb/rtc.c +++ b/libbb/rtc.c @@ -22,7 +22,7 @@ int FAST_FUNC rtc_adjtime_is_utc(void) char buffer[128]; while (fgets(buffer, sizeof(buffer), f)) { - if (strncmp(buffer, "UTC", 3) == 0) { + if (is_prefixed_with(buffer, "UTC")) { utc = 1; break; } diff --git a/libbb/skip_whitespace.c b/libbb/skip_whitespace.c index 8c7b674c3..b6cfbba4d 100644 --- a/libbb/skip_whitespace.c +++ b/libbb/skip_whitespace.c @@ -33,7 +33,7 @@ char* FAST_FUNC skip_non_whitespace(const char *s) char* FAST_FUNC skip_dev_pfx(const char *tty_name) { - if (strncmp(tty_name, "/dev/", 5) == 0) + if (is_prefixed_with(tty_name, "/dev/")) tty_name += 5; return (char*)tty_name; } diff --git a/libbb/update_passwd.c b/libbb/update_passwd.c index dc26ebd1d..a2004f480 100644 --- a/libbb/update_passwd.c +++ b/libbb/update_passwd.c @@ -84,7 +84,6 @@ int FAST_FUNC update_passwd(const char *filename, char *fnamesfx; char *sfx_char; char *name_colon; - unsigned user_len; int old_fd; int new_fd; int i; @@ -108,7 +107,6 @@ int FAST_FUNC update_passwd(const char *filename, fnamesfx = xasprintf("%s+", filename); sfx_char = &fnamesfx[strlen(fnamesfx)-1]; name_colon = xasprintf("%s:", name ? name : ""); - user_len = strlen(name_colon); if (shadow) old_fp = fopen(filename, "r+"); @@ -179,7 +177,7 @@ int FAST_FUNC update_passwd(const char *filename, while (list) { list++; next_list_element: - if (strncmp(list, member, member_len) == 0) { + if (is_prefixed_with(list, member)) { char c; changed_lines++; c = list[member_len]; @@ -201,13 +199,14 @@ int FAST_FUNC update_passwd(const char *filename, goto next; } - if (strncmp(name_colon, line, user_len) != 0) { + cp = is_prefixed_with(line, name_colon); + if (!cp) { fprintf(new_fp, "%s\n", line); goto next; } /* We have a match with "name:"... */ - cp = line + user_len; /* move past name: */ + /* cp points past "name:" */ #if ENABLE_FEATURE_ADDUSER_TO_GROUP || ENABLE_FEATURE_DEL_USER_FROM_GROUP if (member) { diff --git a/libbb/xconnect.c b/libbb/xconnect.c index 1c8bb2b73..2a96e03dc 100644 --- a/libbb/xconnect.c +++ b/libbb/xconnect.c @@ -171,7 +171,7 @@ IF_NOT_FEATURE_IPV6(sa_family_t af = AF_INET;) const char *cp; struct addrinfo hint; - if (ENABLE_FEATURE_UNIX_LOCAL && strncmp(host, "local:", 6) == 0) { + if (ENABLE_FEATURE_UNIX_LOCAL && is_prefixed_with(host, "local:")) { struct sockaddr_un *sun; r = xzalloc(LSA_LEN_SIZE + sizeof(struct sockaddr_un)); diff --git a/miscutils/crond.c b/miscutils/crond.c index 3659b9a6f..eb327f855 100644 --- a/miscutils/crond.c +++ b/miscutils/crond.c @@ -438,14 +438,14 @@ static void load_crontab(const char *fileName) log5("user:%s entry:%s", fileName, parser->data); /* check if line is setting MAILTO= */ - if (0 == strncmp(tokens[0], "MAILTO=", 7)) { + if (is_prefixed_with(tokens[0], "MAILTO=")) { #if ENABLE_FEATURE_CROND_CALL_SENDMAIL free(mailTo); mailTo = (tokens[0][7]) ? xstrdup(&tokens[0][7]) : NULL; #endif /* otherwise just ignore such lines */ continue; } - if (0 == strncmp(tokens[0], "SHELL=", 6)) { + if (is_prefixed_with(tokens[0], "SHELL=")) { free(shell); shell = xstrdup(&tokens[0][6]); continue; diff --git a/miscutils/dc.c b/miscutils/dc.c index a7bd360d2..f94d6fa6b 100644 --- a/miscutils/dc.c +++ b/miscutils/dc.c @@ -244,9 +244,9 @@ static void stack_machine(const char *argument) o = operators; do { - const size_t name_len = strlen(o->name); - if (strncmp(o->name, argument, name_len) == 0) { - argument += name_len; + char *after_name = is_prefixed_with(argument, o->name); + if (after_name) { + argument = after_name; o->function(); goto next; } diff --git a/miscutils/devfsd.c b/miscutils/devfsd.c index 96ffe0738..5a6aec6bd 100644 --- a/miscutils/devfsd.c +++ b/miscutils/devfsd.c @@ -1405,7 +1405,6 @@ const char *get_old_name(const char *devname, unsigned int namelen, int indexx; const char *pty1; const char *pty2; - size_t len; /* 1 to 5 "scsi/" , 6 to 9 "ide/host", 10 sbp/, 11 vcc/, 12 pty/ */ static const char *const fmt[] = { NULL , @@ -1425,12 +1424,11 @@ const char *get_old_name(const char *devname, unsigned int namelen, }; for (trans = translate_table; trans->match != NULL; ++trans) { - len = strlen(trans->match); - - if (strncmp(devname, trans->match, len) == 0) { + char *after_match = is_prefixed_with(devname, trans->match); + if (after_match) { if (trans->format == NULL) - return devname + len; - sprintf(buffer, trans->format, devname + len); + return after_match; + sprintf(buffer, trans->format, after_match); return buffer; } } diff --git a/miscutils/fbsplash.c b/miscutils/fbsplash.c index 7b695b26f..77033c258 100644 --- a/miscutils/fbsplash.c +++ b/miscutils/fbsplash.c @@ -516,7 +516,7 @@ int fbsplash_main(int argc UNUSED_PARAM, char **argv) // handle a case when we have many buffered lines // already in the pipe while ((num_buf = xmalloc_fgetline(fp)) != NULL) { - if (strncmp(num_buf, "exit", 4) == 0) { + if (is_prefixed_with(num_buf, "exit")) { DEBUG_MESSAGE("exit"); break; } diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index 90d1e1e14..03bb03974 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c @@ -1198,7 +1198,7 @@ static void NORETURN list_i2c_busses_and_exit(void) if (subde->d_name[0] == '.') continue; - if (strncmp(subde->d_name, "i2c-", 4) == 0) { + if (is_prefixed_with(subde->d_name, "i2c-")) { snprintf(path, NAME_MAX, "%s/%s/device/%s/name", i2cdev_path, de->d_name, @@ -1229,7 +1229,7 @@ found: if (rv != 1) continue; - if (strncmp(name, "ISA", 3) == 0) + if (is_prefixed_with(name, "ISA")) adt = ADT_ISA; else adt = i2cdetect_get_funcs(bus); diff --git a/miscutils/last.c b/miscutils/last.c index 24f6e1c78..a144c7e47 100644 --- a/miscutils/last.c +++ b/miscutils/last.c @@ -87,11 +87,11 @@ int last_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) if (++n > 0) ut.ut_type = n != 3 ? n : SHUTDOWN_TIME; #else - if (strncmp(ut.ut_user, "shutdown", 8) == 0) + if (is_prefixed_with(ut.ut_user, "shutdown")) ut.ut_type = SHUTDOWN_TIME; - else if (strncmp(ut.ut_user, "reboot", 6) == 0) + else if (is_prefixed_with(ut.ut_user, "reboot")) ut.ut_type = BOOT_TIME; - else if (strncmp(ut.ut_user, "runlevel", 8) == 0) + else if (is_prefixed_with(ut.ut_user, "runlevel")) ut.ut_type = RUN_LVL; #endif } else { diff --git a/miscutils/man.c b/miscutils/man.c index c39870e67..58ed81955 100644 --- a/miscutils/man.c +++ b/miscutils/man.c @@ -66,7 +66,7 @@ static int run_pipe(const char *pager, char *man_filename, int man, int level) goto ordinary_manpage; line = xmalloc_open_zipped_read_close(man_filename, NULL); - if (!line || strncmp(line, ".so ", 4) != 0) { + if (!line || !is_prefixed_with(line, ".so ")) { free(line); goto ordinary_manpage; } @@ -228,7 +228,7 @@ int man_main(int argc UNUSED_PARAM, char **argv) if (!token[1]) continue; if (strcmp("DEFINE", token[0]) == 0) { - if (strncmp("pager", token[1], 5) == 0) { + if (is_prefixed_with("pager", token[1])) { pager = xstrdup(skip_whitespace(token[1]) + 5); } } else diff --git a/modutils/depmod.c b/modutils/depmod.c index 37a8482d9..9713aef92 100644 --- a/modutils/depmod.c +++ b/modutils/depmod.c @@ -55,7 +55,7 @@ static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARA NULL ); for (ptr = image; ptr < image + len - 10; ptr++) { - if (strncmp(ptr, "depends=", 8) == 0) { + if (is_prefixed_with(ptr, "depends=")) { char *u; ptr += 8; @@ -64,15 +64,15 @@ static int FAST_FUNC parse_module(const char *fname, struct stat *sb UNUSED_PARA *u = '_'; ptr += string_to_llist(ptr, &info->dependencies, ","); } else if (ENABLE_FEATURE_MODUTILS_ALIAS - && strncmp(ptr, "alias=", 6) == 0 + && is_prefixed_with(ptr, "alias=") ) { llist_add_to(&info->aliases, xstrdup(ptr + 6)); ptr += strlen(ptr); } else if (ENABLE_FEATURE_MODUTILS_SYMBOLS - && strncmp(ptr, "__ksymtab_", 10) == 0 + && is_prefixed_with(ptr, "__ksymtab_") ) { ptr += 10; - if (strncmp(ptr, "gpl", 3) == 0 + if (is_prefixed_with(ptr, "gpl") || strcmp(ptr, "strings") == 0 ) { continue; diff --git a/modutils/modinfo.c b/modutils/modinfo.c index ee379304c..8e74b6438 100644 --- a/modutils/modinfo.c +++ b/modutils/modinfo.c @@ -62,7 +62,7 @@ static void modinfo(const char *path, const char *version, "firmware", }; size_t len; - int j, length; + int j; char *ptr, *the_module; const char *field = env->field; int tags = env->tags; @@ -94,16 +94,18 @@ static void modinfo(const char *path, const char *version, pattern = field; if ((1< 0) { char *old = ptr; + char *after_word; + /* search for the first char in word */ - ptr = memchr(ptr, *word, len); + ptr = memchr(ptr, word[0], len); if (ptr == NULL) /* no occurance left, done */ break; - if (strncmp(ptr, word, wlen) == 0) - return ptr + wlen; /* found, return ptr past it */ + after_word = is_prefixed_with(ptr, word); + if (after_word) + return after_word; /* found, return ptr past it */ ++ptr; len -= (ptr - old); } @@ -536,7 +536,7 @@ static module_info** find_alias(const char *alias) // TODO: open only once, invent config_rewind() static int already_loaded(const char *name) { - int ret, namelen; + int ret; char *line; FILE *fp; @@ -545,15 +545,16 @@ static int already_loaded(const char *name) fp = fopen_for_read("/proc/modules"); if (!fp) return 0; - namelen = strlen(name); while ((line = xmalloc_fgetline(fp)) != NULL) { char *live; + char *after_name; // Examples from kernel 3.14.6: //pcspkr 12718 0 - Live 0xffffffffa017e000 //snd_timer 28690 2 snd_seq,snd_pcm, Live 0xffffffffa025e000 //i915 801405 2 - Live 0xffffffffa0096000 - if (strncmp(line, name, namelen) != 0 || line[namelen] != ' ') { + after_name = is_prefixed_with(line, name); + if (!after_name || *after_name != ' ') { free(line); continue; } diff --git a/modutils/modprobe.c b/modutils/modprobe.c index 0e8aa9e85..996de4074 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c @@ -260,7 +260,7 @@ static void add_probe(const char *name) llist_add_to_end(&G.probes, m); G.num_unresolved_deps++; if (ENABLE_FEATURE_MODUTILS_SYMBOLS - && strncmp(m->modname, "symbol:", 7) == 0 + && is_prefixed_with(m->modname, "symbol:") ) { G.need_symbols = 1; } @@ -353,22 +353,18 @@ static char *parse_and_add_kcmdline_module_options(char *options, const char *mo char *kcmdline_buf; char *kcmdline; char *kptr; - int len; kcmdline_buf = xmalloc_open_read_close("/proc/cmdline", NULL); if (!kcmdline_buf) return options; kcmdline = kcmdline_buf; - len = strlen(modulename); while ((kptr = strsep(&kcmdline, "\n\t ")) != NULL) { - if (strncmp(modulename, kptr, len) != 0) - continue; - kptr += len; - if (*kptr != '.') + char *after_modulename = is_prefixed_with(kptr, modulename); + if (!after_modulename || *after_modulename != '.') continue; /* It is "modulename.xxxx" */ - kptr++; + kptr = after_modulename + 1; if (strchr(kptr, '=') != NULL) { /* It is "modulename.opt=[val]" */ options = gather_options_str(options, kptr); diff --git a/modutils/modutils-24.c b/modutils/modutils-24.c index 12cb75c54..fe46fc3fd 100644 --- a/modutils/modutils-24.c +++ b/modutils/modutils-24.c @@ -2255,7 +2255,7 @@ static int add_symbols_from(struct obj_file *f, * symbols so they cannot fudge it by adding the prefix on * their references. */ - if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) { + if (is_prefixed_with((char *)s->name, "GPLONLY_")) { #if ENABLE_FEATURE_CHECK_TAINTED_MODULE if (gpl) s->name += 8; diff --git a/networking/dnsd.c b/networking/dnsd.c index fe98400f7..923ad6bc6 100644 --- a/networking/dnsd.c +++ b/networking/dnsd.c @@ -194,7 +194,7 @@ static char *table_lookup(struct dns_entry *d, if ((len != 1 || d->name[1] != '*') /* we assume (do not check) that query_string * ends in ".in-addr.arpa" */ - && strncmp(d->rip, query_string, strlen(d->rip)) == 0 + && is_prefixed_with(query_string, d->rip) ) { #if DEBUG fprintf(stderr, "Found name:%s\n", d->name); diff --git a/networking/httpd.c b/networking/httpd.c index 9cf080401..7a9065fcc 100644 --- a/networking/httpd.c +++ b/networking/httpd.c @@ -697,7 +697,7 @@ static void parse_conf(const char *path, int flag) goto config_error; } *host_port++ = '\0'; - if (strncmp(host_port, "http://", 7) == 0) + if (is_prefixed_with(host_port, "http://")) host_port += 7; if (*host_port == '\0') { goto config_error; @@ -1894,7 +1894,7 @@ static Htaccess_Proxy *find_proxy_entry(const char *url) { Htaccess_Proxy *p; for (p = proxy; p; p = p->next) { - if (strncmp(url, p->url_from, strlen(p->url_from)) == 0) + if (is_prefixed_with(url, p->url_from)) return p; } return NULL; @@ -2183,7 +2183,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) if (STRNCASECMP(iobuf, "Range:") == 0) { /* We know only bytes=NNN-[MMM] */ char *s = skip_whitespace(iobuf + sizeof("Range:")-1); - if (strncmp(s, "bytes=", 6) == 0) { + if (is_prefixed_with(s, "bytes=") == 0) { s += sizeof("bytes=")-1; range_start = BB_STRTOOFF(s, &s, 10); if (s[0] != '-' || range_start < 0) { @@ -2269,7 +2269,7 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) tptr = urlcopy + 1; /* skip first '/' */ #if ENABLE_FEATURE_HTTPD_CGI - if (strncmp(tptr, "cgi-bin/", 8) == 0) { + if (is_prefixed_with(tptr, "cgi-bin/")) { if (tptr[8] == '\0') { /* protect listing "cgi-bin/" */ send_headers_and_exit(HTTP_FORBIDDEN); diff --git a/networking/ifupdown.c b/networking/ifupdown.c index c35d97a1a..daabeec0c 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c @@ -289,7 +289,7 @@ static char *parse(const char *command, struct interface_defn_t *ifd) /* "hwaddress
": * unlike ifconfig, ip doesnt want * (usually "ether" keyword). Skip it. */ - if (strncmp(command, "hwaddress", 9) == 0) { + if (is_prefixed_with(command, "hwaddress")) { varvalue = skip_whitespace(skip_non_whitespace(varvalue)); } # endif @@ -298,7 +298,7 @@ static char *parse(const char *command, struct interface_defn_t *ifd) # if ENABLE_FEATURE_IFUPDOWN_IP /* Sigh... Add a special case for 'ip' to convert from * dotted quad to bit count style netmasks. */ - if (strncmp(command, "bnmask", 6) == 0) { + if (is_prefixed_with(command, "bnmask")) { unsigned res; varvalue = get_var("netmask", 7, ifd); if (varvalue) { @@ -1159,12 +1159,12 @@ static char *run_mapping(char *physical, struct mapping_defn_t *map) static llist_t *find_iface_state(llist_t *state_list, const char *iface) { - unsigned iface_len = strlen(iface); llist_t *search = state_list; while (search) { - if ((strncmp(search->data, iface, iface_len) == 0) - && (search->data[iface_len] == '=') + char *after_iface = is_prefixed_with(search->data, iface); + if (after_iface + && *after_iface == '=' ) { return search; } diff --git a/networking/inetd.c b/networking/inetd.c index 8148925ce..dce5a0885 100644 --- a/networking/inetd.c +++ b/networking/inetd.c @@ -727,7 +727,7 @@ static NOINLINE servtab_t *parse_one_line(void) goto parse_err; #endif } - if (strncmp(arg, "rpc/", 4) == 0) { + if (is_prefixed_with(arg, "rpc/")) { #if ENABLE_FEATURE_INETD_RPC unsigned n; arg += 4; diff --git a/networking/libiproute/ipaddress.c b/networking/libiproute/ipaddress.c index aa4779ad1..4072d0626 100644 --- a/networking/libiproute/ipaddress.c +++ b/networking/libiproute/ipaddress.c @@ -701,7 +701,7 @@ static int ipaddr_modify(int cmd, char **argv) /* There was no "dev IFACE", but we need that */ bb_error_msg_and_die("need \"dev IFACE\""); } - if (l && strncmp(d, l, strlen(d)) != 0) { + if (l && !is_prefixed_with(l, d)) { bb_error_msg_and_die("\"dev\" (%s) must match \"label\" (%s)", d, l); } diff --git a/networking/nameif.c b/networking/nameif.c index 9a8846dc0..9b18a6d16 100644 --- a/networking/nameif.c +++ b/networking/nameif.c @@ -161,19 +161,19 @@ static void nameif_parse_selector(ethtable_t *ch, char *selector) if (*next) *next++ = '\0'; /* Check for selectors, mac= is assumed */ - if (strncmp(selector, "bus=", 4) == 0) { + if (is_prefixed_with(selector, "bus=")) { ch->bus_info = xstrdup(selector + 4); found_selector++; - } else if (strncmp(selector, "driver=", 7) == 0) { + } else if (is_prefixed_with(selector, "driver=")) { ch->driver = xstrdup(selector + 7); found_selector++; - } else if (strncmp(selector, "phyaddr=", 8) == 0) { + } else if (is_prefixed_with(selector, "phyaddr=")) { ch->phy_address = xatoi_positive(selector + 8); found_selector++; } else { #endif lmac = xmalloc(ETH_ALEN); - ch->mac = ether_aton_r(selector + (strncmp(selector, "mac=", 4) != 0 ? 0 : 4), lmac); + ch->mac = ether_aton_r(selector + (is_prefixed_with(selector, "mac=") ? 4 : 0), lmac); if (ch->mac == NULL) bb_error_msg_and_die("can't parse %s", selector); #if ENABLE_FEATURE_NAMEIF_EXTENDED diff --git a/networking/netstat.c b/networking/netstat.c index f80b845bc..02f4cc7cc 100644 --- a/networking/netstat.c +++ b/networking/netstat.c @@ -228,12 +228,12 @@ static long extract_socket_inode(const char *lname) { long inode = -1; - if (strncmp(lname, "socket:[", sizeof("socket:[")-1) == 0) { + if (is_prefixed_with(lname, "socket:[")) { /* "socket:[12345]", extract the "12345" as inode */ inode = bb_strtoul(lname + sizeof("socket:[")-1, (char**)&lname, 0); if (*lname != ']') inode = -1; - } else if (strncmp(lname, "[0000]:", sizeof("[0000]:")-1) == 0) { + } else if (is_prefixed_with(lname, "[0000]:")) { /* "[0000]:12345", extract the "12345" as inode */ inode = bb_strtoul(lname + sizeof("[0000]:")-1, NULL, 0); if (errno) /* not NUL terminated? */ diff --git a/procps/mpstat.c b/procps/mpstat.c index af3263d67..6028903fa 100644 --- a/procps/mpstat.c +++ b/procps/mpstat.c @@ -526,7 +526,7 @@ static void get_irqs_from_stat(struct stats_irq *irq) while (fgets(buf, sizeof(buf), fp)) { //bb_error_msg("/proc/stat:'%s'", buf); - if (strncmp(buf, "intr ", 5) == 0) { + if (is_prefixed_with(buf, "intr ")) { /* Read total number of IRQs since system boot */ sscanf(buf + 5, "%"FMT_DATA"u", &irq->irq_nr); } diff --git a/procps/powertop.c b/procps/powertop.c index ddda5bd93..18affacdd 100644 --- a/procps/powertop.c +++ b/procps/powertop.c @@ -458,9 +458,9 @@ static NOINLINE int process_timer_stats(void) // func = "Load balancing tick"; //} - if (strncmp(func, "tick_nohz_", 10) == 0) + if (is_prefixed_with(func, "tick_nohz_")) continue; - if (strncmp(func, "tick_setup_sched_timer", 20) == 0) + if (is_prefixed_with(func, "tick_setup_sched_timer")) continue; //if (strcmp(process, "powertop") == 0) // continue; diff --git a/procps/pwdx.c b/procps/pwdx.c index 22b892275..4e34149ed 100644 --- a/procps/pwdx.c +++ b/procps/pwdx.c @@ -41,7 +41,7 @@ int pwdx_main(int argc UNUSED_PARAM, char **argv) // Allowed on the command line: // /proc/NUM // NUM - if (strncmp(arg, "/proc/", 6) == 0) + if (is_prefixed_with(arg, "/proc/")) arg += 6; pid = bb_strtou(arg, NULL, 10); diff --git a/shell/hush.c b/shell/hush.c index 92d790180..f2c0a70f2 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -5884,7 +5884,7 @@ static FILE *generate_stream_from_string(const char *s, pid_t *pid_p) * Our solution: ONLY bare $(trap) or `trap` is special. */ s = skip_whitespace(s); - if (strncmp(s, "trap", 4) == 0 + if (is_prefixed_with(s, "trap") && skip_whitespace(s + 4)[0] == '\0' ) { static const char *const argv[] = { NULL, NULL }; diff --git a/util-linux/acpid.c b/util-linux/acpid.c index fc8151f6a..0f2cb6bdc 100644 --- a/util-linux/acpid.c +++ b/util-linux/acpid.c @@ -151,7 +151,7 @@ static const char *find_action(struct input_event *ev, const char *buf) } if (buf) { - if (strncmp(buf, evt_tab[i].desc, strlen(buf)) == 0) { + if (is_prefixed_with(evt_tab[i].desc, buf)) { action = evt_tab[i].desc; break; } diff --git a/util-linux/fdisk.c b/util-linux/fdisk.c index 39eb27b47..7fe70fb72 100644 --- a/util-linux/fdisk.c +++ b/util-linux/fdisk.c @@ -2781,14 +2781,14 @@ is_ide_cdrom_or_tape(const char *device) the process hangs on the attempt to read a music CD. So try to be careful. This only works since 2.1.73. */ - if (strncmp("/dev/hd", device, 7)) + if (!is_prefixed_with(device, "/dev/hd")) return 0; snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5); procf = fopen_for_read(buf); if (procf != NULL && fgets(buf, sizeof(buf), procf)) - is_ide = (!strncmp(buf, "cdrom", 5) || - !strncmp(buf, "tape", 4)); + is_ide = (is_prefixed_with(buf, "cdrom") || + is_prefixed_with(buf, "tape")); else /* Now when this proc file does not exist, skip the device when it is read-only. */ diff --git a/util-linux/fdisk_osf.c b/util-linux/fdisk_osf.c index ff16389bd..af04cfcc8 100644 --- a/util-linux/fdisk_osf.c +++ b/util-linux/fdisk_osf.c @@ -854,7 +854,7 @@ xbsd_initlabel(struct partition *p) d->d_magic = BSD_DISKMAGIC; - if (strncmp(disk_device, "/dev/sd", 7) == 0) + if (is_prefixed_with(disk_device, "/dev/sd")) d->d_type = BSD_DTYPE_SCSI; else d->d_type = BSD_DTYPE_ST506; diff --git a/util-linux/fdisk_sgi.c b/util-linux/fdisk_sgi.c index 785fc661b..23ebc56ef 100644 --- a/util-linux/fdisk_sgi.c +++ b/util-linux/fdisk_sgi.c @@ -440,7 +440,7 @@ sgi_write_table(void) (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0); write_sector(0, sgilabel); - if (!strncmp((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8)) { + if (is_prefixed_with((char*)sgilabel->directory[0].vol_file_name, "sgilabel")) { /* * keep this habit of first writing the "sgilabel". * I never tested whether it works without (AN 981002). diff --git a/util-linux/findfs.c b/util-linux/findfs.c index 49e8979ac..07734f359 100644 --- a/util-linux/findfs.c +++ b/util-linux/findfs.c @@ -27,7 +27,7 @@ int findfs_main(int argc UNUSED_PARAM, char **argv) if (!dev) bb_show_usage(); - if (strncmp(dev, "/dev/", 5) == 0) { + if (is_prefixed_with(dev, "/dev/")) { /* Just pass any /dev/xxx name right through. * This might aid in some scripts being able * to call this unconditionally */ diff --git a/util-linux/mdev.c b/util-linux/mdev.c index b2d56575f..ccc00d365 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c @@ -610,7 +610,7 @@ static void make_device(char *device_name, char *path, int operation) * We use strstr("/block/") to forestall future surprises. */ type = S_IFCHR; - if (strstr(path, "/block/") || (G.subsystem && strncmp(G.subsystem, "block", 5) == 0)) + if (strstr(path, "/block/") || (G.subsystem && is_prefixed_with(G.subsystem, "block"))) type = S_IFBLK; #if ENABLE_FEATURE_MDEV_CONF diff --git a/util-linux/mount.c b/util-linux/mount.c index fbc89c862..cb40c802d 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c @@ -641,7 +641,7 @@ static llist_t *get_block_backed_filesystems(void) if (!f) continue; while ((buf = xmalloc_fgetline(f)) != NULL) { - if (strncmp(buf, "nodev", 5) == 0 && isspace(buf[5])) + if (is_prefixed_with(buf, "nodev") && isspace(buf[5])) goto next; fs = skip_whitespace(buf); if (*fs == '#' || *fs == '*' || !*fs) @@ -1364,9 +1364,9 @@ static NOINLINE int nfsmount(struct mntent *mp, unsigned long vfsflags, char *fi strcspn(opteq, " \t\n\r,")); continue; case 18: // "proto" - if (!strncmp(opteq, "tcp", 3)) + if (is_prefixed_with(opteq, "tcp")) tcp = 1; - else if (!strncmp(opteq, "udp", 3)) + else if (is_prefixed_with(opteq, "udp")) tcp = 0; else bb_error_msg("warning: unrecognized proto= option"); @@ -1459,7 +1459,7 @@ static NOINLINE int nfsmount(struct mntent *mp, unsigned long vfsflags, char *fi "rdirplus\0" "acl\0"; int val = 1; - if (!strncmp(opt, "no", 2)) { + if (is_prefixed_with(opt, "no")) { val = 0; opt += 2; } @@ -1979,7 +1979,7 @@ static int singlemount(struct mntent *mp, int ignore_busy) } // Might this be an NFS filesystem? - if ((!mp->mnt_type || strncmp(mp->mnt_type, "nfs", 3) == 0) + if ((!mp->mnt_type || is_prefixed_with(mp->mnt_type, "nfs")) && strchr(mp->mnt_fsname, ':') != NULL ) { if (!mp->mnt_type) diff --git a/util-linux/rtcwake.c b/util-linux/rtcwake.c index 53d9384db..8aee0cfcb 100644 --- a/util-linux/rtcwake.c +++ b/util-linux/rtcwake.c @@ -66,7 +66,7 @@ static NOINLINE bool may_wakeup(const char *rtcname) return false; /* wakeup events could be disabled or not supported */ - return strncmp(buf, "enabled\n", 8) == 0; + return is_prefixed_with(buf, "enabled\n") != NULL; } static NOINLINE void setup_alarm(int fd, time_t *wakeup, time_t rtc_time) diff --git a/util-linux/volume_id/get_devname.c b/util-linux/volume_id/get_devname.c index 0c6bdfddf..53bdbdf09 100644 --- a/util-linux/volume_id/get_devname.c +++ b/util-linux/volume_id/get_devname.c @@ -302,9 +302,9 @@ int resolve_mount_spec(char **fsname) { char *tmp = *fsname; - if (strncmp(*fsname, "UUID=", 5) == 0) + if (is_prefixed_with(*fsname, "UUID=")) tmp = get_devname_from_uuid(*fsname + 5); - else if (strncmp(*fsname, "LABEL=", 6) == 0) + else if (is_prefixed_with(*fsname, "LABEL=") == 0) tmp = get_devname_from_label(*fsname + 6); if (tmp == *fsname) From 53e9c51aded0af85c33d657143ed94c5151ba6f3 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Thu, 12 Mar 2015 20:10:40 +0100 Subject: [PATCH 086/256] od: fix printing of high-bit chars MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Example: echo £ | od -c Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- coreutils/od_bloaty.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/coreutils/od_bloaty.c b/coreutils/od_bloaty.c index 2c26dda16..ab7ea997d 100644 --- a/coreutils/od_bloaty.c +++ b/coreutils/od_bloaty.c @@ -387,11 +387,11 @@ print_named_ascii(size_t n_bytes, const char *block, " sp" }; // buf[N] pos: 01234 56789 - char buf[12] = " x\0 0xx\0"; - // actually " x\0 xxx\0", but want to share string with print_ascii. + char buf[12] = " x\0 xxx\0"; // [12] because we take three 32bit stack slots anyway, and // gcc is too dumb to initialize with constant stores, // it copies initializer from rodata. Oh well. + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65410 while (n_bytes--) { unsigned masked_c = *(unsigned char *) block++; @@ -419,7 +419,7 @@ print_ascii(size_t n_bytes, const char *block, const char *unused_fmt_string UNUSED_PARAM) { // buf[N] pos: 01234 56789 - char buf[12] = " x\0 0xx\0"; + char buf[12] = " x\0 xxx\0"; while (n_bytes--) { const char *s; @@ -455,11 +455,9 @@ print_ascii(size_t n_bytes, const char *block, case '\v': s = " \\v"; break; - case '\x7f': - s = " 177"; - break; - default: /* c is never larger than 040 */ - buf[7] = (c >> 3) + '0'; + default: + buf[6] = (c >> 6 & 3) + '0'; + buf[7] = (c >> 3 & 7) + '0'; buf[8] = (c & 7) + '0'; s = buf + 5; } From 8ec1ff350c28ae691ee80a001c7786f4ad8abe47 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Thu, 12 Mar 2015 20:18:51 +0100 Subject: [PATCH 087/256] Use chomp to remove newlines function old new delta unix_do_one 548 540 -8 process_timer_stats 508 500 -8 process_irq_counts 532 524 -8 lpd_main 839 831 -8 hwclock_main 502 494 -8 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/6 up/down: 0/-50) Total: -40 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- networking/netstat.c | 2 +- printutils/lpd.c | 2 +- procps/powertop.c | 4 ++-- util-linux/hwclock.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/networking/netstat.c b/networking/netstat.c index 02f4cc7cc..1303d3f3d 100644 --- a/networking/netstat.c +++ b/networking/netstat.c @@ -622,7 +622,7 @@ static int FAST_FUNC unix_do_one(char *line) /* TODO: currently we stop at first NUL byte. Is it a problem? */ line += path_ofs; - *strchrnul(line, '\n') = '\0'; + chomp(line); while (*line) fputc_printable(*line++, stdout); bb_putchar('\n'); diff --git a/printutils/lpd.c b/printutils/lpd.c index 642e8a89e..eaf42c08b 100644 --- a/printutils/lpd.c +++ b/printutils/lpd.c @@ -204,7 +204,7 @@ int lpd_main(int argc UNUSED_PARAM, char *argv[]) goto err_exit; } // get filename - *strchrnul(s, '\n') = '\0'; + chomp(s); fname = strchr(s, ' '); if (!fname) { // bad_fname: diff --git a/procps/powertop.c b/procps/powertop.c index 18affacdd..1de5d329e 100644 --- a/procps/powertop.c +++ b/procps/powertop.c @@ -360,7 +360,7 @@ static void process_irq_counts(void) } name = p; - strchrnul(name, '\n')[0] = '\0'; + chomp(p); /* Save description of the interrupt */ if (nr >= 20000) sprintf(irq_desc, " : %s", name); @@ -470,7 +470,7 @@ static NOINLINE int process_timer_stats(void) process = idx < 2 ? "[kernel module]" : ""; } - strchrnul(p, '\n')[0] = '\0'; + chomp(p); // 46D\01136\0kondemand/1\0do_dbs_timer (delayed_work_timer_fn) // ^ ^ ^ diff --git a/util-linux/hwclock.c b/util-linux/hwclock.c index 3f531555b..6c99977cf 100644 --- a/util-linux/hwclock.c +++ b/util-linux/hwclock.c @@ -69,7 +69,7 @@ static void show_clock(const char **pp_rtcname, int utc) strftime(cp, sizeof(cp), "%c", ptm); #else char *cp = ctime(&t); - strchrnul(cp, '\n')[0] = '\0'; + chomp(cp); #endif #if !SHOW_HWCLOCK_DIFF From 49acc1a7618a28d34381cbb7661d7c981fcb238f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 12 Mar 2015 21:15:34 +0100 Subject: [PATCH 088/256] vi: make BACKSPACE and DELETE join lines at start/end of line Signed-off-by: Denys Vlasenko --- editors/vi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/editors/vi.c b/editors/vi.c index 77535be92..495332a46 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -2017,8 +2017,7 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p' p--; } } else if (c == erase_char || c == 8 || c == 127) { // Is this a BS - // 123456789 - if ((p[-1] != '\n') && (dot>text)) { + if (p > text) { p--; p = text_hole_delete(p, p, ALLOW_UNDO_QUEUED); // shrink buffer 1 char } @@ -4026,8 +4025,9 @@ static void do_cmd(int c) undo_queue_commit(); break; case KEYCODE_DELETE: - c = 'x'; - // fall through + if (dot < end - 1) + dot = yank_delete(dot, dot, 1, YANKDEL, ALLOW_UNDO); + break; case 'X': // X- delete char before dot case 'x': // x- delete the current char case 's': // s- substitute the current char From 4a08e82d441dbde5412eca6a6db894b420f203f3 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 16 Mar 2015 17:46:17 -0400 Subject: [PATCH 089/256] trylink: use mktemp instead of hardcoding paths This way we respect standard tempdir env vars and are guaranteed to be unique. Signed-off-by: Mike Frysinger --- scripts/trylink | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/trylink b/scripts/trylink index 5da494fbb..5a67fcfa8 100755 --- a/scripts/trylink +++ b/scripts/trylink @@ -46,7 +46,7 @@ try() { } check_cc() { - local tempname="/tmp/temp.$$.$RANDOM" + local tempname="$(mktemp)" # Can use "-o /dev/null", but older gcc tend to *unlink it* on failure! :( # "-xc": C language. "/dev/null" is an empty source file. if $CC $1 -shared -xc /dev/null -o "$tempname".o >/dev/null 2>&1; then @@ -54,11 +54,11 @@ check_cc() { else echo "$2"; fi - rm "$tempname".o 2>/dev/null + rm -f "$tempname" "$tempname".o } check_libc_is_glibc() { - local tempname="/tmp/temp.$$.$RANDOM" + local tempname="$(mktemp)" echo "\ #include /* Apparently uclibc defines __GLIBC__ (compat trick?). Oh well. */ @@ -71,7 +71,7 @@ check_libc_is_glibc() { else echo "$1"; fi - rm "$tempname".c "$tempname".o 2>/dev/null + rm -f "$tempname" "$tempname".[co] } EXE="$1" From 6798564b9e2f1a81b8c2d0cb4add97cb736d982b Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Mon, 16 Mar 2015 17:47:01 -0400 Subject: [PATCH 090/256] trylink: respect compiler settings when probing features The CPPFLAGS/CFLAGS settings might have features that matter, so make sure we utilize them when testing the compiler. URL: https://bugs.gentoo.org/471118 Signed-off-by: Mike Frysinger --- scripts/trylink | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/trylink b/scripts/trylink index 5a67fcfa8..48c487bcd 100755 --- a/scripts/trylink +++ b/scripts/trylink @@ -49,7 +49,7 @@ check_cc() { local tempname="$(mktemp)" # Can use "-o /dev/null", but older gcc tend to *unlink it* on failure! :( # "-xc": C language. "/dev/null" is an empty source file. - if $CC $1 -shared -xc /dev/null -o "$tempname".o >/dev/null 2>&1; then + if $CC $CPPFLAGS $CFLAGS $1 -shared -xc /dev/null -o "$tempname".o >/dev/null 2>&1; then echo "$1"; else echo "$2"; @@ -66,7 +66,7 @@ check_libc_is_glibc() { syntax error here #endif " >"$tempname".c - if $CC "$tempname".c -c -o "$tempname".o >/dev/null 2>&1; then + if $CC $CPPFLAGS $CFLAGS "$tempname".c -c -o "$tempname".o >/dev/null 2>&1; then echo "$2"; else echo "$1"; From 75a76269ba2549cb5392d7d720a4c393de01b934 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Mon, 16 Mar 2015 14:14:11 +0000 Subject: [PATCH 091/256] ash: do not split the result of tilde expansion A tilde expansion generates a valid pathname. Splitting it using IFS either leaves it unchanged or changes it to something unintended. Example: IFS=m HOME=/tmp; printf "%s\n" ~ Based on this commit authored by Jilles Tjoelker: http://git.kernel.org/cgit/utils/dash/dash.git/commit/?id=834629283f6c629a4da05ef60bae9445c954a19a Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- shell/ash.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 0f9f73ec3..b568013b4 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -5791,7 +5791,6 @@ exptilde(char *startp, char *p, int flags) struct passwd *pw; const char *home; int quotes = flags & (EXP_FULL | EXP_CASE | EXP_REDIR); - int startloc; name = p + 1; @@ -5823,9 +5822,7 @@ exptilde(char *startp, char *p, int flags) if (!home || !*home) goto lose; *p = c; - startloc = expdest - (char *)stackblock(); strtodest(home, SQSYNTAX, quotes); - recordregion(startloc, expdest - (char *)stackblock(), 0); return p; lose: *p = c; From 6ca03f2dd82ee2a09f257fad7c2bf6898310c438 Mon Sep 17 00:00:00 2001 From: Frank Bergmann Date: Fri, 13 Mar 2015 10:05:08 +0100 Subject: [PATCH 092/256] ifupdown: correct ifstate update during 'ifup -a'. Closes 6212 When 'if -a' runs into an failure on an interface all further interfaces won't be correctly updated in ifstate. This patch inserts a new variable that only tracks the current interfaces failure so that the write to ifstate can rely on this and not the one for the functions return value. Fixes https://bugs.busybox.net/show_bug.cgi?id=6212 Signed-off-by: Frank Bergmann Signed-off-by: Denys Vlasenko --- networking/ifupdown.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/networking/ifupdown.c b/networking/ifupdown.c index daabeec0c..9f2500331 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c @@ -1239,6 +1239,7 @@ int ifupdown_main(int argc UNUSED_PARAM, char **argv) char *pch; bool okay = 0; int cmds_ret; + bool curr_failure = 0; iface = xstrdup(target_list->data); target_list = target_list->link; @@ -1306,9 +1307,9 @@ int ifupdown_main(int argc UNUSED_PARAM, char **argv) if (cmds_ret == -1) { bb_error_msg("don't seem to have all the variables for %s/%s", liface, currif->address_family->name); - any_failures = 1; + any_failures = curr_failure = 1; } else if (cmds_ret == 0) { - any_failures = 1; + any_failures = curr_failure = 1; } currif->iface = oldiface; @@ -1329,7 +1330,7 @@ int ifupdown_main(int argc UNUSED_PARAM, char **argv) llist_t *state_list = read_iface_state(); llist_t *iface_state = find_iface_state(state_list, iface); - if (cmds == iface_up && !any_failures) { + if (cmds == iface_up && !curr_failure) { char *newiface = xasprintf("%s=%s", iface, liface); if (!iface_state) { llist_add_to_end(&state_list, newiface); From 6d8ea1d50ec6088c51a61ab3e9f849b7845dce6b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 22 Mar 2015 17:08:51 +0100 Subject: [PATCH 093/256] ifupdown: shrink a message Signed-off-by: Denys Vlasenko --- networking/ifupdown.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/networking/ifupdown.c b/networking/ifupdown.c index 9f2500331..606fc049f 100644 --- a/networking/ifupdown.c +++ b/networking/ifupdown.c @@ -1305,7 +1305,7 @@ int ifupdown_main(int argc UNUSED_PARAM, char **argv) /* Call the cmds function pointer, does either iface_up() or iface_down() */ cmds_ret = cmds(currif); if (cmds_ret == -1) { - bb_error_msg("don't seem to have all the variables for %s/%s", + bb_error_msg("don't have all variables for %s/%s", liface, currif->address_family->name); any_failures = curr_failure = 1; } else if (cmds_ret == 0) { From 92edab1aa6eae45ac8fa0cec8c8df9a47f547300 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Sun, 22 Mar 2015 17:36:20 +0100 Subject: [PATCH 094/256] logread: implement dumpfollow mode of operation This is basically a combination of the default (dump mode) and -f (follow mode). Specifying -F makes logread first dump the log buffer and then immediately start following it. function old new delta packed_usage 30412 30443 +31 logread_main 491 497 +6 Signed-off-by: Phil Sutter Signed-off-by: Denys Vlasenko --- sysklogd/logread.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/sysklogd/logread.c b/sysklogd/logread.c index bea73d932..da4a4d4df 100644 --- a/sysklogd/logread.c +++ b/sysklogd/logread.c @@ -10,10 +10,11 @@ */ //usage:#define logread_trivial_usage -//usage: "[-f]" +//usage: "[-fF]" //usage:#define logread_full_usage "\n\n" //usage: "Show messages in syslogd's circular buffer\n" //usage: "\n -f Output data as log grows" +//usage: "\n -F Same as -f, but dump buffer first" #include "libbb.h" #include @@ -83,7 +84,7 @@ int logread_main(int argc UNUSED_PARAM, char **argv) unsigned cur; int log_semid; /* ipc semaphore id */ int log_shmid; /* ipc shared memory id */ - smallint follow = getopt32(argv, "f"); + int follow = getopt32(argv, "fF"); INIT_G(); @@ -106,7 +107,7 @@ int logread_main(int argc UNUSED_PARAM, char **argv) /* Max possible value for tail is shbuf->size - 1 */ cur = shbuf->tail; - /* Loop for logread -f, one pass if there was no -f */ + /* Loop for -f or -F, one pass otherwise */ do { unsigned shbuf_size; unsigned shbuf_tail; @@ -129,7 +130,12 @@ int logread_main(int argc UNUSED_PARAM, char **argv) printf("cur:%u tail:%u size:%u\n", cur, shbuf_tail, shbuf_size); - if (!follow) { + if (!(follow & 1)) { /* not -f */ + /* if -F, "convert" it to -f, so that we dont + * dump the entire buffer on each iteration + */ + follow >>= 1; + /* advance to oldest complete message */ /* find NUL */ cur += strlen(shbuf_data + cur); @@ -142,7 +148,7 @@ int logread_main(int argc UNUSED_PARAM, char **argv) cur++; if (cur >= shbuf_size) /* last byte in buffer? */ cur = 0; - } else { /* logread -f */ + } else { /* -f */ if (cur == shbuf_tail) { sem_up(log_semid); fflush_all(); From 8893023ba27ea87b12a333960271c9f86cdebf7b Mon Sep 17 00:00:00 2001 From: Ari Sundholm Date: Wed, 4 Mar 2015 18:46:48 +0200 Subject: [PATCH 095/256] dd: move suffix struct to xatonum.c This way it can be used by other applets without duplication. Signed-off-by: Ari Sundholm Signed-off-by: Denys Vlasenko --- coreutils/dd.c | 31 ++++++------------------------- include/libbb.h | 1 + libbb/xatonum.c | 19 +++++++++++++++++++ 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/coreutils/dd.c b/coreutils/dd.c index 302497074..53a843ca0 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c @@ -99,25 +99,6 @@ enum { ofd = STDOUT_FILENO, }; -static const struct suffix_mult dd_suffixes[] = { - { "c", 1 }, - { "w", 2 }, - { "b", 512 }, - { "kB", 1000 }, - { "kD", 1000 }, - { "k", 1024 }, - { "K", 1024 }, /* compat with coreutils dd (it also accepts KB and KD, TODO?) */ - { "MB", 1000000 }, - { "MD", 1000000 }, - { "M", 1024*1024 }, - { "GB", 1000000000 }, - { "GD", 1000000000 }, - { "G", 1024*1024*1024 }, - /* "D" suffix for decimal is not in coreutils manpage, looks like it's deprecated */ - /* coreutils also understands TPEZY suffixes for tera- and so on, with B suffix for decimal */ - { "", 0 } -}; - struct globals { off_t out_full, out_part, in_full, in_part; #if ENABLE_FEATURE_DD_THIRD_STATUS_LINE @@ -326,11 +307,11 @@ int dd_main(int argc UNUSED_PARAM, char **argv) #if ENABLE_FEATURE_DD_IBS_OBS if (what == OP_ibs) { /* Must fit into positive ssize_t */ - ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes); + ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, cwbkMG_suffixes); /*continue;*/ } if (what == OP_obs) { - obs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes); + obs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, cwbkMG_suffixes); /*continue;*/ } if (what == OP_conv) { @@ -356,22 +337,22 @@ int dd_main(int argc UNUSED_PARAM, char **argv) } #endif if (what == OP_bs) { - ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, dd_suffixes); + ibs = xatoul_range_sfx(val, 1, ((size_t)-1L)/2, cwbkMG_suffixes); obs = ibs; /*continue;*/ } /* These can be large: */ if (what == OP_count) { G.flags |= FLAG_COUNT; - count = XATOU_SFX(val, dd_suffixes); + count = XATOU_SFX(val, cwbkMG_suffixes); /*continue;*/ } if (what == OP_seek) { - seek = XATOU_SFX(val, dd_suffixes); + seek = XATOU_SFX(val, cwbkMG_suffixes); /*continue;*/ } if (what == OP_skip) { - skip = XATOU_SFX(val, dd_suffixes); + skip = XATOU_SFX(val, cwbkMG_suffixes); /*continue;*/ } if (what == OP_if) { diff --git a/include/libbb.h b/include/libbb.h index c97df6047..9550c0589 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -862,6 +862,7 @@ struct suffix_mult { }; extern const struct suffix_mult bkm_suffixes[]; #define km_suffixes (bkm_suffixes + 1) +extern const struct suffix_mult cwbkMG_suffixes[]; #include "xatonum.h" /* Specialized: */ diff --git a/libbb/xatonum.c b/libbb/xatonum.c index 6f4e023bb..19b54fb0c 100644 --- a/libbb/xatonum.c +++ b/libbb/xatonum.c @@ -75,3 +75,22 @@ const struct suffix_mult bkm_suffixes[] = { { "m", 1024*1024 }, { "", 0 } }; + +const struct suffix_mult cwbkMG_suffixes[] = { + { "c", 1 }, + { "w", 2 }, + { "b", 512 }, + { "kB", 1000 }, + { "kD", 1000 }, + { "k", 1024 }, + { "K", 1024 }, /* compat with coreutils dd (it also accepts KB and KD, TODO?) */ + { "MB", 1000000 }, + { "MD", 1000000 }, + { "M", 1024*1024 }, + { "GB", 1000000000 }, + { "GD", 1000000000 }, + { "G", 1024*1024*1024 }, + /* "D" suffix for decimal is not in coreutils manpage, looks like it's deprecated */ + /* coreutils also understands TPEZY suffixes for tera- and so on, with B suffix for decimal */ + { "", 0 } +}; From 911db16229d41f53b9c44272fcccdb3552a5a99e Mon Sep 17 00:00:00 2001 From: Ari Sundholm Date: Sun, 22 Mar 2015 17:55:38 +0100 Subject: [PATCH 096/256] truncate: new applet function old new delta truncate_main - 161 +161 cwbkMG_suffixes - 128 +128 packed_usage 30443 30459 +16 applet_names 2512 2521 +9 applet_main 1456 1460 +4 parse_command 1460 1463 +3 applet_nameofs 728 730 +2 applet_install_loc 182 183 +1 dd_suffixes 112 - -112 ------------------------------------------------------------------------------ (add/remove: 3/1 grow/shrink: 10/3 up/down: 337/-133) Total: 204 bytes Signed-off-by: Ari Sundholm Signed-off-by: Denys Vlasenko --- include/libbb.h | 1 + libbb/xatonum.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/libbb.h b/include/libbb.h index 9550c0589..26b686805 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -863,6 +863,7 @@ struct suffix_mult { extern const struct suffix_mult bkm_suffixes[]; #define km_suffixes (bkm_suffixes + 1) extern const struct suffix_mult cwbkMG_suffixes[]; +#define kMG_suffixes (cwbkMG_suffixes + 3) #include "xatonum.h" /* Specialized: */ diff --git a/libbb/xatonum.c b/libbb/xatonum.c index 19b54fb0c..9dd5c3e7e 100644 --- a/libbb/xatonum.c +++ b/libbb/xatonum.c @@ -83,7 +83,9 @@ const struct suffix_mult cwbkMG_suffixes[] = { { "kB", 1000 }, { "kD", 1000 }, { "k", 1024 }, - { "K", 1024 }, /* compat with coreutils dd (it also accepts KB and KD, TODO?) */ + { "KB", 1000 }, /* compat with coreutils dd */ + { "KD", 1000 }, /* compat with coreutils dd */ + { "K", 1024 }, /* compat with coreutils dd */ { "MB", 1000000 }, { "MD", 1000000 }, { "M", 1024*1024 }, From 4d15068d83054a9f82b3f8842706cd6deb401e25 Mon Sep 17 00:00:00 2001 From: Vladislav Grishenko Date: Thu, 19 Mar 2015 16:19:35 +0500 Subject: [PATCH 097/256] zcip: fix wrong comparison of source IP with our IP Commit "zcip: fix link-local IP conflict detection" has introduced wrong comparsion of source IP with our IP. This leads to a new IP being picked unnecessarily on every incoming ARP packet. Signed-off-by: Vladislav Grishenko Signed-off-by: Denys Vlasenko --- networking/zcip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/networking/zcip.c b/networking/zcip.c index a3307c5c9..962ba2e60 100644 --- a/networking/zcip.c +++ b/networking/zcip.c @@ -521,7 +521,7 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) target_ip_conflict = 0; if (memcmp(&p.arp.arp_sha, ð_addr, ETH_ALEN) != 0) { - if (memcmp(p.arp.arp_spa, &ip.s_addr, sizeof(struct in_addr))) { + if (memcmp(p.arp.arp_spa, &ip.s_addr, sizeof(struct in_addr)) == 0) { /* A probe or reply with source_ip == chosen ip */ source_ip_conflict = 1; } From 1850d5ec0e90fbfb598ed7ad8ff0a63b6e5692ce Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 22 Mar 2015 18:00:32 +0100 Subject: [PATCH 098/256] truncate: new applet Add the actual new source file :( Signed-off-by: Denys Vlasenko --- coreutils/truncate.c | 77 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 coreutils/truncate.c diff --git a/coreutils/truncate.c b/coreutils/truncate.c new file mode 100644 index 000000000..0e36daba3 --- /dev/null +++ b/coreutils/truncate.c @@ -0,0 +1,77 @@ +/* + * Mini truncate implementation for busybox + * + * Copyright (C) 2015 by Ari Sundholm + * + * Licensed under GPLv2 or later, see file LICENSE in this source tree. + */ + +//config:config TRUNCATE +//config: bool "truncate" +//config: default y +//config: help +//config: truncate truncates files to a given size. If a file does +//config: not exist, it is created unless told otherwise. + +//kbuild:lib-$(CONFIG_TRUNCATE) += truncate.o +//applet:IF_TRUNCATE(APPLET_NOFORK(truncate, truncate, BB_DIR_USR_BIN, BB_SUID_DROP, truncate)) + +//usage:#define truncate_trivial_usage +//usage: "[-c] -s SIZE FILE..." +//usage:#define truncate_full_usage "\n\n" +//usage: "Truncate FILEs to the given size\n" +//usage: "\n -c Do not create files" +//usage: "\n -s SIZE Truncate to SIZE" +//usage: +//usage:#define truncate_example_usage +//usage: "$ truncate -s 1G foo" + +#include "libbb.h" + +#if ENABLE_LFS +# define XATOU_SFX xatoull_sfx +#else +# define XATOU_SFX xatoul_sfx +#endif + +/* This is a NOFORK applet. Be very careful! */ + +int truncate_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int truncate_main(int argc UNUSED_PARAM, char **argv) +{ + unsigned opts; + int flags = O_RDWR; + int ret = EXIT_SUCCESS; + char *size_str; + off_t size; + + enum { + OPT_NOCREATE = (1 << 0), + OPT_SIZE = (1 << 1), + }; + + opt_complementary = "s:-1"; + opts = getopt32(argv, "cs:", &size_str); + + if (!(opts & OPT_NOCREATE)) + flags |= O_CREAT; + + // TODO: coreutils 8.17 also support "m" (lowercase) suffix + // with truncate, but not with dd! + // We share kMG_suffixes[], so we can't make both tools + // compatible at once... + size = XATOU_SFX(size_str, kMG_suffixes); + + argv += optind; + while (*argv) { + int fd = xopen(*argv, flags); + if (ftruncate(fd, size) == -1) { + bb_perror_msg("%s: ftruncate", *argv); + ret = EXIT_FAILURE; + } + xclose(fd); + ++argv; + } + + return ret; +} From 379e8e81afed0613271e39e33190c6dfec78b695 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 26 Mar 2015 10:49:02 +0100 Subject: [PATCH 099/256] typo fix Signed-off-by: Denys Vlasenko --- e2fsprogs/old_e2fsprogs/e2fsck.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2fsprogs/old_e2fsprogs/e2fsck.c b/e2fsprogs/old_e2fsprogs/e2fsck.c index 8400a92ce..0799b64ad 100644 --- a/e2fsprogs/old_e2fsprogs/e2fsck.c +++ b/e2fsprogs/old_e2fsprogs/e2fsck.c @@ -11462,7 +11462,7 @@ static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, count = 1; } if (retval) { - bb_error_msg(_("while calling ext2fs_adjust_ea_refocunt for inode %d"), + bb_error_msg(_("while calling ext2fs_adjust_ea_refcount for inode %d"), ino); return 1; } From 9472e8a86fa1837bccec9e25dd18fd3c88c5e209 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 31 Mar 2015 21:46:26 +0200 Subject: [PATCH 100/256] ftpd: change_identity() must be after chroot() Otherwise chroot() doesn't work for non-root Signed-off-by: Denys Vlasenko --- networking/ftpd.c | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/networking/ftpd.c b/networking/ftpd.c index 0c10e1f25..2351d6dd3 100644 --- a/networking/ftpd.c +++ b/networking/ftpd.c @@ -1116,6 +1116,9 @@ int ftpd_main(int argc, char **argv) int ftpd_main(int argc UNUSED_PARAM, char **argv) #endif { +#if ENABLE_FEATURE_FTP_AUTHENTICATION + struct passwd *pw = NULL; +#endif unsigned abs_timeout; unsigned verbose_S; smallint opts; @@ -1193,29 +1196,23 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv) signal(SIGALRM, timeout_handler); #if ENABLE_FEATURE_FTP_AUTHENTICATION - { - struct passwd *pw = NULL; - - while (1) { - uint32_t cmdval = cmdio_get_cmd_and_arg(); - + while (1) { + uint32_t cmdval = cmdio_get_cmd_and_arg(); if (cmdval == const_USER) { - pw = getpwnam(G.ftp_arg); - cmdio_write_raw(STR(FTP_GIVEPWORD)" Please specify password\r\n"); - } else if (cmdval == const_PASS) { - if (check_password(pw, G.ftp_arg) > 0) { - break; /* login success */ - } - cmdio_write_raw(STR(FTP_LOGINERR)" Login failed\r\n"); - pw = NULL; - } else if (cmdval == const_QUIT) { - WRITE_OK(FTP_GOODBYE); - return 0; - } else { - cmdio_write_raw(STR(FTP_LOGINERR)" Login with USER and PASS\r\n"); + pw = getpwnam(G.ftp_arg); + cmdio_write_raw(STR(FTP_GIVEPWORD)" Please specify password\r\n"); + } else if (cmdval == const_PASS) { + if (check_password(pw, G.ftp_arg) > 0) { + break; /* login success */ } + cmdio_write_raw(STR(FTP_LOGINERR)" Login failed\r\n"); + pw = NULL; + } else if (cmdval == const_QUIT) { + WRITE_OK(FTP_GOODBYE); + return 0; + } else { + cmdio_write_raw(STR(FTP_LOGINERR)" Login with USER and PASS\r\n"); } - change_identity(pw); } WRITE_OK(FTP_LOGINOK); #endif @@ -1233,6 +1230,10 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv) xchroot(argv[0]); } +#if ENABLE_FEATURE_FTP_AUTHENTICATION + change_identity(pw); +#endif + /* RFC-959 Section 5.1 * The following commands and options MUST be supported by every * server-FTP and user-FTP, except in cases where the underlying From 1186894f773e13ab9ca2b3e05a194e9b88796fbe Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 31 Mar 2015 22:00:55 +0200 Subject: [PATCH 101/256] update example ntp.script Handle an interesting corner case when NTP server is reachable... but on a different IP now. Signed-off-by: Denys Vlasenko --- examples/var_service/ntpd/ntp.script | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/examples/var_service/ntpd/ntp.script b/examples/var_service/ntpd/ntp.script index 76c34bf74..8542181eb 100755 --- a/examples/var_service/ntpd/ntp.script +++ b/examples/var_service/ntpd/ntp.script @@ -10,12 +10,30 @@ dt=`date '+%Y-%m-%d %H:%M:%S'` +echo "`tail -n 199 -- "$0.log" 2>/dev/null`" >"$0.log.$$" + +if test x"$1" = x"unsync" \ +; then + # No replies for our NTP requests were seen for some time. + # + # Among more mundate cases like network outages, this happens + # if we ran for a LONG time (days) and ntp server's IP has changed. + # ntpd has no code to re-resolve peers' addresses to IPs, + # we need to help it: + # + echo "$dt: $1"\ + "syncronization lost, restarting ntpd"\ + >>"$0.log.$$" + mv -- "$0.log.$$" "$0.log" + kill $PPID + exit +fi + if test x"$stratum" != x"" \ && test x"$poll_interval" != x"" \ && test 4 -ge "$stratum" \ && test 128 -le "$poll_interval" \ ; then - echo "`tail -n 199 -- "$0.log" 2>/dev/null`" >"$0.log.$$" echo "$dt: $1"\ "freq_drift_ppm=$freq_drift_ppm"\ "offset=$offset"\ @@ -27,7 +45,6 @@ if test x"$stratum" != x"" \ exec hwclock --systohc fi -echo "`tail -n 199 -- "$0.log" 2>/dev/null`" >"$0.log.$$" echo "$dt: $1"\ "freq_drift_ppm=$freq_drift_ppm"\ "offset=$offset"\ From 86a7f18f211af1abda5c855d2674b0fcb53de524 Mon Sep 17 00:00:00 2001 From: Bernhard Reutner-Fischer Date: Thu, 2 Apr 2015 23:03:46 +0200 Subject: [PATCH 102/256] *: Switch to POSIX utmpx API UTMP is SVID legacy, UTMPX is mandated by POSIX. Glibc and uClibc have identical layout of UTMP and UTMPX, both of these libc treat _PATH_UTMPX as _PATH_UTMP so from a user-perspective nothing changes except the names of the API entrypoints. Signed-off-by: Bernhard Reutner-Fischer --- coreutils/who.c | 8 ++++---- include/libbb.h | 2 +- init/halt.c | 4 ++-- libbb/utmp.c | 44 +++++++++++++++++++++--------------------- miscutils/last.c | 8 ++++---- miscutils/last_fancy.c | 16 +++++++++------ miscutils/runlevel.c | 12 ++++++------ miscutils/wall.c | 8 ++++---- procps/uptime.c | 6 +++--- 9 files changed, 56 insertions(+), 52 deletions(-) diff --git a/coreutils/who.c b/coreutils/who.c index f955ce6d3..8337212c9 100644 --- a/coreutils/who.c +++ b/coreutils/who.c @@ -73,7 +73,7 @@ static void idle_string(char *str6, time_t t) int who_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int who_main(int argc UNUSED_PARAM, char **argv) { - struct utmp *ut; + struct utmpx *ut; unsigned opt; int do_users = (ENABLE_USERS && (!ENABLE_WHO || applet_name[0] == 'u')); const char *fmt = "%s"; @@ -83,8 +83,8 @@ int who_main(int argc UNUSED_PARAM, char **argv) if (opt & 2) // -H printf("USER\t\tTTY\t\tIDLE\tTIME\t\t HOST\n"); - setutent(); - while ((ut = getutent()) != NULL) { + setutxent(); + while ((ut = getutxent()) != NULL) { if (ut->ut_user[0] && ((opt & 1) || ut->ut_type == USER_PROCESS) ) { @@ -126,6 +126,6 @@ int who_main(int argc UNUSED_PARAM, char **argv) if (do_users) bb_putchar('\n'); if (ENABLE_FEATURE_CLEAN_UP) - endutent(); + endutxent(); return EXIT_SUCCESS; } diff --git a/include/libbb.h b/include/libbb.h index 26b686805..0f8363b78 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -84,7 +84,7 @@ # include #endif #if ENABLE_FEATURE_UTMP -# include +# include #endif #if ENABLE_LOCALE_SUPPORT # include diff --git a/init/halt.c b/init/halt.c index 7974adb17..ad12d9148 100644 --- a/init/halt.c +++ b/init/halt.c @@ -74,7 +74,7 @@ static void write_wtmp(void) { - struct utmp utmp; + struct utmpx utmp; struct utsname uts; /* "man utmp" says wtmp file should *not* be created automagically */ /*if (access(bb_path_wtmp_file, R_OK|W_OK) == -1) { @@ -88,7 +88,7 @@ static void write_wtmp(void) utmp.ut_line[0] = '~'; utmp.ut_line[1] = '~'; /* = strcpy(utmp.ut_line, "~~"); */ uname(&uts); safe_strncpy(utmp.ut_host, uts.release, sizeof(utmp.ut_host)); - updwtmp(bb_path_wtmp_file, &utmp); + updwtmpx(bb_path_wtmp_file, &utmp); } #else #define write_wtmp() ((void)0) diff --git a/libbb/utmp.c b/libbb/utmp.c index 8ad9ba27e..bd07670db 100644 --- a/libbb/utmp.c +++ b/libbb/utmp.c @@ -16,7 +16,7 @@ static void touch(const char *filename) void FAST_FUNC write_new_utmp(pid_t pid, int new_type, const char *tty_name, const char *username, const char *hostname) { - struct utmp utent; + struct utmpx utent; char *id; unsigned width; @@ -45,17 +45,17 @@ void FAST_FUNC write_new_utmp(pid_t pid, int new_type, const char *tty_name, con tty_name += 3; strncpy(id, tty_name, width); - touch(_PATH_UTMP); - //utmpname(_PATH_UTMP); - setutent(); + touch(_PATH_UTMPX); + //utmpxname(_PATH_UTMPX); + setutxent(); /* Append new one (hopefully, unless we collide on ut_id) */ - pututline(&utent); - endutent(); + pututxline(&utent); + endutxent(); #if ENABLE_FEATURE_WTMP /* "man utmp" says wtmp file should *not* be created automagically */ /*touch(bb_path_wtmp_file);*/ - updwtmp(bb_path_wtmp_file, &utent); + updwtmpx(bb_path_wtmp_file, &utent); #endif } @@ -64,17 +64,17 @@ void FAST_FUNC write_new_utmp(pid_t pid, int new_type, const char *tty_name, con */ void FAST_FUNC update_utmp(pid_t pid, int new_type, const char *tty_name, const char *username, const char *hostname) { - struct utmp utent; - struct utmp *utp; + struct utmpx utent; + struct utmpx *utp; - touch(_PATH_UTMP); - //utmpname(_PATH_UTMP); - setutent(); + touch(_PATH_UTMPX); + //utmpxname(_PATH_UTMPX); + setutxent(); /* Did init/getty/telnetd/sshd/... create an entry for us? * It should be (new_type-1), but we'd also reuse * any other potentially stale xxx_PROCESS entry */ - while ((utp = getutent()) != NULL) { + while ((utp = getutxent()) != NULL) { if (utp->ut_pid == pid // && ut->ut_line[0] && utp->ut_id[0] /* must have nonzero id */ @@ -88,25 +88,25 @@ void FAST_FUNC update_utmp(pid_t pid, int new_type, const char *tty_name, const /* Stale record. Nuke hostname */ memset(utp->ut_host, 0, sizeof(utp->ut_host)); } - /* NB: pututline (see later) searches for matching utent - * using getutid(utent) - we must not change ut_id + /* NB: pututxline (see later) searches for matching utxent + * using getutxid(utent) - we must not change ut_id * if we want *exactly this* record to be overwritten! */ break; } } - //endutent(); - no need, pututline can deal with (and actually likes) + //endutxent(); - no need, pututxline can deal with (and actually likes) //the situation when utmp file is positioned on found record if (!utp) { if (new_type != DEAD_PROCESS) write_new_utmp(pid, new_type, tty_name, username, hostname); else - endutent(); + endutxent(); return; } - /* Make a copy. We can't use *utp, pututline's internal getutid + /* Make a copy. We can't use *utp, pututxline's internal getutxid * will overwrite it before it is used! */ utent = *utp; @@ -120,14 +120,14 @@ void FAST_FUNC update_utmp(pid_t pid, int new_type, const char *tty_name, const utent.ut_tv.tv_sec = time(NULL); /* Update, or append new one */ - //setutent(); - pututline(&utent); - endutent(); + //setutxent(); + pututxline(&utent); + endutxent(); #if ENABLE_FEATURE_WTMP /* "man utmp" says wtmp file should *not* be created automagically */ /*touch(bb_path_wtmp_file);*/ - updwtmp(bb_path_wtmp_file, &utent); + updwtmpx(bb_path_wtmp_file, &utent); #endif } diff --git a/miscutils/last.c b/miscutils/last.c index a144c7e47..6d8b58463 100644 --- a/miscutils/last.c +++ b/miscutils/last.c @@ -32,21 +32,21 @@ #if defined UT_LINESIZE \ && ((UT_LINESIZE != 32) || (UT_NAMESIZE != 32) || (UT_HOSTSIZE != 256)) -#error struct utmp member char[] size(s) have changed! +#error struct utmpx member char[] size(s) have changed! #elif defined __UT_LINESIZE \ && ((__UT_LINESIZE != 32) || (__UT_NAMESIZE != 64) || (__UT_HOSTSIZE != 256)) -#error struct utmp member char[] size(s) have changed! +#error struct utmpx member char[] size(s) have changed! #endif #if EMPTY != 0 || RUN_LVL != 1 || BOOT_TIME != 2 || NEW_TIME != 3 || \ OLD_TIME != 4 -#error Values for the ut_type field of struct utmp changed +#error Values for the ut_type field of struct utmpx changed #endif int last_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int last_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) { - struct utmp ut; + struct utmpx ut; int n, file = STDIN_FILENO; time_t t_tmp; off_t pos; diff --git a/miscutils/last_fancy.c b/miscutils/last_fancy.c index 16ed9e920..8194e31b5 100644 --- a/miscutils/last_fancy.c +++ b/miscutils/last_fancy.c @@ -22,6 +22,10 @@ #define HEADER_LINE_WIDE "USER", "TTY", \ INET6_ADDRSTRLEN, INET6_ADDRSTRLEN, "HOST", "LOGIN", " TIME", "" +#if !defined __UT_LINESIZE && defined UT_LINESIZE +# define __UT_LINESIZE UT_LINESIZE +#endif + enum { NORMAL, LOGGED, @@ -39,7 +43,7 @@ enum { #define show_wide (option_mask32 & LAST_OPT_W) -static void show_entry(struct utmp *ut, int state, time_t dur_secs) +static void show_entry(struct utmpx *ut, int state, time_t dur_secs) { unsigned days, hours, mins; char duration[sizeof("(%u+02:02)") + sizeof(int)*3]; @@ -104,7 +108,7 @@ static void show_entry(struct utmp *ut, int state, time_t dur_secs) duration_str); } -static int get_ut_type(struct utmp *ut) +static int get_ut_type(struct utmpx *ut) { if (ut->ut_line[0] == '~') { if (strcmp(ut->ut_user, "shutdown") == 0) { @@ -142,7 +146,7 @@ static int get_ut_type(struct utmp *ut) return ut->ut_type; } -static int is_runlevel_shutdown(struct utmp *ut) +static int is_runlevel_shutdown(struct utmpx *ut) { if (((ut->ut_pid & 255) == '0') || ((ut->ut_pid & 255) == '6')) { return 1; @@ -154,7 +158,7 @@ static int is_runlevel_shutdown(struct utmp *ut) int last_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int last_main(int argc UNUSED_PARAM, char **argv) { - struct utmp ut; + struct utmpx ut; const char *filename = _PATH_WTMP; llist_t *zlist; off_t pos; @@ -242,9 +246,9 @@ int last_main(int argc UNUSED_PARAM, char **argv) { llist_t *el, *next; for (el = zlist; el; el = next) { - struct utmp *up = (struct utmp *)el->data; + struct utmpx *up = (struct utmpx *)el->data; next = el->link; - if (strncmp(up->ut_line, ut.ut_line, UT_LINESIZE) == 0) { + if (strncmp(up->ut_line, ut.ut_line, __UT_LINESIZE) == 0) { if (show) { show_entry(&ut, NORMAL, up->ut_tv.tv_sec); show = 0; diff --git a/miscutils/runlevel.c b/miscutils/runlevel.c index 76231df22..8558db862 100644 --- a/miscutils/runlevel.c +++ b/miscutils/runlevel.c @@ -29,19 +29,19 @@ int runlevel_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int runlevel_main(int argc UNUSED_PARAM, char **argv) { - struct utmp *ut; + struct utmpx *ut; char prev; - if (argv[1]) utmpname(argv[1]); + if (argv[1]) utmpxname(argv[1]); - setutent(); - while ((ut = getutent()) != NULL) { + setutxent(); + while ((ut = getutxent()) != NULL) { if (ut->ut_type == RUN_LVL) { prev = ut->ut_pid / 256; if (prev == 0) prev = 'N'; printf("%c %c\n", prev, ut->ut_pid % 256); if (ENABLE_FEATURE_CLEAN_UP) - endutent(); + endutxent(); return 0; } } @@ -49,6 +49,6 @@ int runlevel_main(int argc UNUSED_PARAM, char **argv) puts("unknown"); if (ENABLE_FEATURE_CLEAN_UP) - endutent(); + endutxent(); return 1; } diff --git a/miscutils/wall.c b/miscutils/wall.c index bb709ee39..50658f457 100644 --- a/miscutils/wall.c +++ b/miscutils/wall.c @@ -32,7 +32,7 @@ int wall_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int wall_main(int argc UNUSED_PARAM, char **argv) { - struct utmp *ut; + struct utmpx *ut; char *msg; int fd; @@ -46,8 +46,8 @@ int wall_main(int argc UNUSED_PARAM, char **argv) msg = xmalloc_read(fd, NULL); if (ENABLE_FEATURE_CLEAN_UP && argv[1]) close(fd); - setutent(); - while ((ut = getutent()) != NULL) { + setutxent(); + while ((ut = getutxent()) != NULL) { char *line; if (ut->ut_type != USER_PROCESS) continue; @@ -56,7 +56,7 @@ int wall_main(int argc UNUSED_PARAM, char **argv) free(line); } if (ENABLE_FEATURE_CLEAN_UP) { - endutent(); + endutxent(); free(msg); } return EXIT_SUCCESS; diff --git a/procps/uptime.c b/procps/uptime.c index 778812a6f..149bae6e5 100644 --- a/procps/uptime.c +++ b/procps/uptime.c @@ -81,10 +81,10 @@ int uptime_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) #if ENABLE_FEATURE_UPTIME_UTMP_SUPPORT { - struct utmp *ut; + struct utmpx *ut; unsigned users = 0; - while ((ut = getutent()) != NULL) { - if ((ut->ut_type == USER_PROCESS) && (ut->ut_name[0] != '\0')) + while ((ut = getutxent()) != NULL) { + if ((ut->ut_type == USER_PROCESS) && (ut->ut_user[0] != '\0')) users++; } printf(", %u users", users); From 7b729edd33aea5361e0740df800a1a0a1ff70f7f Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Thu, 2 Apr 2015 00:55:17 +0300 Subject: [PATCH 103/256] update copyright years Copyright years seem to be out of date, e.g. coreutils/truncate.c has Copyright (C) 2015. Signed-off-by: Aaro Koskinen Signed-off-by: Bernhard Reutner-Fischer --- libbb/appletlib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 8fd8fd525..e0b843d30 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -631,7 +631,7 @@ static int busybox_main(char **argv) full_write2_str(bb_banner); /* reuse const string */ full_write2_str(" multi-call binary.\n"); /* reuse */ full_write2_str( - "BusyBox is copyrighted by many authors between 1998-2012.\n" + "BusyBox is copyrighted by many authors between 1998-2015.\n" "Licensed under GPLv2. See source distribution for detailed\n" "copyright notices.\n" "\n" From e0ddb65cb234db6482d80febee1a63778f818db6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 14 Apr 2015 14:15:15 +0200 Subject: [PATCH 104/256] build system: make CONFIG_EXTRA_LDFLAGS go to LDFLAGS, not EXTRA_LDFLAGS Signed-off-by: Denys Vlasenko --- Makefile.flags | 2 +- examples/android-build | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile.flags b/Makefile.flags index 307afa7f5..a1ed1480a 100644 --- a/Makefile.flags +++ b/Makefile.flags @@ -163,7 +163,7 @@ SKIP_STRIP = y endif ifneq ($(CONFIG_EXTRA_LDFLAGS),) -EXTRA_LDFLAGS += $(strip $(subst ",,$(CONFIG_EXTRA_LDFLAGS))) +LDFLAGS += $(strip $(subst ",,$(CONFIG_EXTRA_LDFLAGS))) #")) endif diff --git a/examples/android-build b/examples/android-build index 89f3b637a..123ba966e 100755 --- a/examples/android-build +++ b/examples/android-build @@ -29,4 +29,6 @@ else LDLIBS="dl m c gcc" fi +# It's possible with newer version +# you need to use CFLAGS_busybox instead of EXTRA_LDFLAGS below: make EXTRA_LDFLAGS="$LDFLAGS" LDLIBS="$LDLIBS" "$@" From a90490fb69f78148beacf371b603c16276137879 Mon Sep 17 00:00:00 2001 From: Alfonso Ranieri Date: Tue, 14 Apr 2015 14:32:39 +0200 Subject: [PATCH 105/256] volume_id: fix a buglet introduced by is_prefixed_with() conversion Signed-off-by: Alfonso Ranieri Signed-off-by: Denys Vlasenko --- util-linux/volume_id/get_devname.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util-linux/volume_id/get_devname.c b/util-linux/volume_id/get_devname.c index 53bdbdf09..6b97df113 100644 --- a/util-linux/volume_id/get_devname.c +++ b/util-linux/volume_id/get_devname.c @@ -304,7 +304,7 @@ int resolve_mount_spec(char **fsname) if (is_prefixed_with(*fsname, "UUID=")) tmp = get_devname_from_uuid(*fsname + 5); - else if (is_prefixed_with(*fsname, "LABEL=") == 0) + else if (is_prefixed_with(*fsname, "LABEL=")) tmp = get_devname_from_label(*fsname + 6); if (tmp == *fsname) From f7466e477691fd29f47ebe8ae27489e065c69e5e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 9 Apr 2015 10:20:16 +0200 Subject: [PATCH 106/256] find: fix regression in status processing for path arguments Regression added in commit 14158b4127dba30466c50147b868a6a89702960b "find: add optional support for '-exec ... {} +'" This commit causes find to exit on the first path argument that was not found, which breaks existing scripts and is incompatible to other implementations. Instead of exiting on the first failure, return EXIT_FAILURE at the end if any error occurred. Signed-off-by: Felix Fietkau Signed-off-by: Denys Vlasenko --- findutils/find.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/findutils/find.c b/findutils/find.c index 83aa63f92..ced8922e7 100644 --- a/findutils/find.c +++ b/findutils/find.c @@ -1460,12 +1460,10 @@ int find_main(int argc UNUSED_PARAM, char **argv) NULL, /* user data */ 0) /* depth */ ) { - status = EXIT_FAILURE; - goto out; + status |= EXIT_FAILURE; } } - IF_FEATURE_FIND_EXEC_PLUS(status = flush_exec_plus();) -out: + IF_FEATURE_FIND_EXEC_PLUS(status |= flush_exec_plus();) return status; } From 71a5b67ba0339265153217df646827a1213e03f5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 16 Apr 2015 12:44:02 +0200 Subject: [PATCH 107/256] uevent: new applet This applet listens on netlink socket with kernel's uevent messages. Run-tested. function old new delta uevent_main - 416 +416 packed_usage 30671 30713 +42 applet_names 2531 2538 +7 applet_main 1468 1472 +4 RCVBUF - 4 +4 applet_nameofs 734 736 +2 ------------------------------------------------------------------------------ (add/remove: 3/0 grow/shrink: 4/0 up/down: 475/0) Total: 475 bytes Signed-off-by: Denys Vlasenko --- util-linux/uevent.c | 127 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 util-linux/uevent.c diff --git a/util-linux/uevent.c b/util-linux/uevent.c new file mode 100644 index 000000000..fb98b4845 --- /dev/null +++ b/util-linux/uevent.c @@ -0,0 +1,127 @@ +/* + * Copyright 2015 Denys Vlasenko + * + * Licensed under GPLv2, see file LICENSE in this source tree. + */ + +//config:config UEVENT +//config: bool "uevent" +//config: default y +//config: select PLATFORM_LINUX +//config: help +//config: uevent is a netlink listener for kernel uevent notifications +//config: sent via netlink. It is usually used for dynamic device creation. + +//applet:IF_UEVENT(APPLET(uevent, BB_DIR_SBIN, BB_SUID_DROP)) + +//kbuild:lib-$(CONFIG_UEVENT) += uevent.o + +//usage:#define uevent_trivial_usage +//usage: "[PROG [ARGS]]" +//usage:#define uevent_full_usage "\n\n" +//usage: "uevent runs PROG for every netlink notification." +//usage: "\n""PROG's environment contains data passed from the kernel." +//usage: "\n""Typical usage (daemon for dynamic device node creation):" +//usage: "\n"" # uevent mdev & mdev -s" + +#include "libbb.h" +#include + +#define BUFFER_SIZE 16*1024 + +#define env ((char **)&bb_common_bufsiz1) +enum { + MAX_ENV = COMMON_BUFSIZE / sizeof(env[0]) - 1, +}; + +#ifndef SO_RCVBUFFORCE +#define SO_RCVBUFFORCE 33 +#endif +static const int RCVBUF = 2 * 1024 * 1024; + +int uevent_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int uevent_main(int argc UNUSED_PARAM, char **argv) +{ + struct sockaddr_nl sa; + int fd; + + argv++; + + // Subscribe for UEVENT kernel messages + sa.nl_family = AF_NETLINK; + sa.nl_pad = 0; + sa.nl_pid = getpid(); + sa.nl_groups = 1 << 0; + fd = xsocket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); + xbind(fd, (struct sockaddr *) &sa, sizeof(sa)); + close_on_exec_on(fd); + + // Without a sufficiently big RCVBUF, a ton of simultaneous events + // can trigger ENOBUFS on read, which is unrecoverable. + // Reproducer: + // uevent mdev & + // find /sys -name uevent -exec sh -c 'echo add >"{}"' ';' + // + // SO_RCVBUFFORCE (root only) can go above net.core.rmem_max sysctl + setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &RCVBUF, sizeof(RCVBUF)); + setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &RCVBUF, sizeof(RCVBUF)); + if (0) { + int z; + socklen_t zl = sizeof(z); + getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &z, &zl); + bb_error_msg("SO_RCVBUF:%d", z); + } + + for (;;) { + char *netbuf; + char *s, *end; + ssize_t len; + int idx; + + // In many cases, a system sits for *days* waiting + // for a new uevent notification to come in. + // We use a fresh mmap so that buffer is not allocated + // until kernel actually starts filling it. + netbuf = mmap(NULL, BUFFER_SIZE, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, + /* ignored: */ -1, 0); + if (netbuf == MAP_FAILED) + bb_perror_msg_and_die("mmap"); + + // Here we block, possibly for a very long time + len = safe_read(fd, netbuf, BUFFER_SIZE - 1); + if (len < 0) + bb_perror_msg_and_die("read"); + end = netbuf + len; + *end = '\0'; + + // Each netlink message starts with "ACTION@/path" + // (which we currently ignore), + // followed by environment variables. + if (!argv[0]) + putchar('\n'); + idx = 0; + s = netbuf; + while (s < end) { + if (!argv[0]) + puts(s); + if (strchr(s, '=') && idx < MAX_ENV) + env[idx++] = s; + s += strlen(s) + 1; + } + env[idx] = NULL; + + idx = 0; + while (env[idx]) + putenv(env[idx++]); + if (argv[0]) + spawn_and_wait(argv); + idx = 0; + while (env[idx]) + bb_unsetenv(env[idx++]); + munmap(netbuf, BUFFER_SIZE); + } + + return 0; // not reached +} From 63f4d32c9859c1ed341debefddad4b9c0ae944cc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 17 Apr 2015 14:24:55 +0200 Subject: [PATCH 108/256] sed: implement ",+N" range end function old new delta add_cmd 1115 1173 +58 process_files 2226 2253 +27 sed_main 696 702 +6 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/0 up/down: 91/0) Total: 91 bytes Signed-off-by: Denys Vlasenko --- editors/sed.c | 41 ++++++++++++++++++++++++++++++++++++----- testsuite/sed.tests | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 5 deletions(-) diff --git a/editors/sed.c b/editors/sed.c index 2c64ad500..7bbf820d8 100644 --- a/editors/sed.c +++ b/editors/sed.c @@ -53,6 +53,7 @@ * Reference * http://www.opengroup.org/onlinepubs/007904975/utilities/sed.html * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/sed.html + * http://sed.sourceforge.net/sedfaq3.html */ //config:config SED @@ -109,7 +110,8 @@ typedef struct sed_cmd_s { regex_t *sub_match; /* For 's/sub_match/string/' */ int beg_line; /* 'sed 1p' 0 == apply commands to all lines */ int beg_line_orig; /* copy of the above, needed for -i */ - int end_line; /* 'sed 1,3p' 0 == one line only. -1 = last line ($) */ + int end_line; /* 'sed 1,3p' 0 == one line only. -1 = last line ($). -2-N = +N */ + int end_line_orig; FILE *sw_file; /* File (sw) command writes to, -1 for none. */ char *string; /* Data string for (saicytb) commands. */ @@ -640,10 +642,29 @@ static void add_cmd(const char *cmdstr) int idx; cmdstr++; - idx = get_address(cmdstr, &sed_cmd->end_line, &sed_cmd->end_match); - if (!idx) + if (*cmdstr == '+' && isdigit(cmdstr[1])) { + /* http://sed.sourceforge.net/sedfaq3.html#s3.3 + * Under GNU sed 3.02+, ssed, and sed15+, + * may also be a notation of the form +num, + * indicating the next num lines after is + * matched. + * GNU sed 4.2.1 accepts even "+" (meaning "+0"). + * We don't (we check for isdigit, see above), think + * about the "+-3" case. + */ + char *end; + /* code is smaller compared to using &cmdstr here: */ + idx = strtol(cmdstr+1, &end, 10); + sed_cmd->end_line = -2 - idx; + cmdstr = end; + } else { + idx = get_address(cmdstr, &sed_cmd->end_line, &sed_cmd->end_match); + cmdstr += idx; + idx--; /* if 0, trigger error check below */ + } + if (idx < 0) bb_error_msg_and_die("no address after comma"); - cmdstr += idx; + sed_cmd->end_line_orig = sed_cmd->end_line; } /* skip whitespace before the command */ @@ -1089,10 +1110,19 @@ static void process_files(void) /* Is this line the end of the current match? */ if (matched) { + if (sed_cmd->end_line <= -2) { + /* address2 is +N, i.e. N lines from beg_line */ + sed_cmd->end_line = linenum + (-sed_cmd->end_line - 2); + } /* once matched, "n,xxx" range is dead, disabling it */ if (sed_cmd->beg_line > 0) { sed_cmd->beg_line = -2; } + dbg("end1:%d", sed_cmd->end_line ? sed_cmd->end_line == -1 + ? !next_line : (sed_cmd->end_line <= linenum) + : !sed_cmd->end_match); + dbg("end2:%d", sed_cmd->end_match && old_matched + && !regexec(sed_cmd->end_match,pattern_space, 0, NULL, 0)); sed_cmd->in_match = !( /* has the ending line come, or is this a single address command? */ (sed_cmd->end_line @@ -1551,9 +1581,10 @@ int sed_main(int argc UNUSED_PARAM, char **argv) free(G.outname); G.outname = NULL; - /* Re-enable disabled range matches */ + /* Fix disabled range matches and mangled ",+N" ranges */ for (sed_cmd = G.sed_cmd_head; sed_cmd; sed_cmd = sed_cmd->next) { sed_cmd->beg_line = sed_cmd->beg_line_orig; + sed_cmd->end_line = sed_cmd->end_line_orig; } } /* Here, to handle "sed 'cmds' nonexistent_file" case we did: diff --git a/testsuite/sed.tests b/testsuite/sed.tests index 19f2915ce..34479e55f 100755 --- a/testsuite/sed.tests +++ b/testsuite/sed.tests @@ -333,6 +333,38 @@ testing "sed s///NUM test" \ "sed -e 's/a/b/2; s/a/c/g'" \ "cb\n" "" "aa\n" +testing "sed /regex/,N{...} addresses work" \ + "sed /^2/,2{d}" \ + "1\n3\n4\n5\n" \ + "" \ + "1\n2\n3\n4\n5\n" + +testing "sed /regex/,+N{...} addresses work" \ + "sed /^2/,+2{d}" \ + "1\n5\n" \ + "" \ + "1\n2\n3\n4\n5\n" + +testing "sed /regex/,+N{...} -i works" \ + "cat - >input2; sed /^4/,+2{d} -i input input2; echo \$?; cat input input2; rm input2" \ + "0\n""1\n2\n3\n7\n8\n""1\n2\n7\n8\n" \ + "1\n2\n3\n4\n5\n6\n7\n8\n" \ + "1\n2\n4\n5\n6\n7\n8\n" \ + +# GNU sed 4.2.1 would also accept "/^4/,+{d}" with the same meaning, we don't +testing "sed /regex/,+0{...} -i works" \ + "cat - >input2; sed /^4/,+0{d} -i input input2; echo \$?; cat input input2; rm input2" \ + "0\n""1\n2\n3\n5\n6\n7\n8\n""1\n2\n5\n6\n7\n8\n" \ + "1\n2\n3\n4\n5\n6\n7\n8\n" \ + "1\n2\n4\n5\n6\n7\n8\n" \ + +# GNU sed 4.2.1 would also accept "/^4/,+d" with the same meaning, we don't +testing "sed /regex/,+0 -i works" \ + "cat - >input2; sed /^4/,+0d -i input input2; echo \$?; cat input input2; rm input2" \ + "0\n""1\n2\n3\n5\n6\n7\n8\n""1\n2\n5\n6\n7\n8\n" \ + "1\n2\n3\n4\n5\n6\n7\n8\n" \ + "1\n2\n4\n5\n6\n7\n8\n" \ + # testing "description" "commands" "result" "infile" "stdin" exit $FAILCOUNT From 0a0acb55db8d7c4dec445573f1b0528d126b9e1f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 18 Apr 2015 19:36:38 +0200 Subject: [PATCH 109/256] ash: fix handling of duplicate "local" Signed-off-by: Denys Vlasenko --- shell/ash.c | 51 ++++++++++++++++------- shell/ash_test/ash-heredoc/heredoc1.right | 2 +- shell/ash_test/ash-vars/var3.right | 5 +++ shell/ash_test/ash-vars/var3.tests | 1 + 4 files changed, 42 insertions(+), 17 deletions(-) create mode 100644 shell/ash_test/ash-vars/var3.right create mode 100755 shell/ash_test/ash-vars/var3.tests diff --git a/shell/ash.c b/shell/ash.c index b568013b4..697a64fea 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -2030,7 +2030,7 @@ varcmp(const char *p, const char *q) int c, d; while ((c = *p) == (d = *q)) { - if (!c || c == '=') + if (c == '\0' || c == '=') goto out; p++; q++; @@ -2247,7 +2247,7 @@ setvar(const char *name, const char *val, int flags) } static void FAST_FUNC -setvar2(const char *name, const char *val) +setvar0(const char *name, const char *val) { setvar(name, val, 0); } @@ -2310,7 +2310,7 @@ unsetvar(const char *s) free(vp); INT_ON; } else { - setvar2(s, 0); + setvar0(s, NULL); vp->flags &= ~VEXPORT; } ok: @@ -5505,7 +5505,7 @@ ash_arith(const char *s) arith_t result; math_state.lookupvar = lookupvar; - math_state.setvar = setvar2; + math_state.setvar = setvar0; //math_state.endofname = endofname; INT_OFF; @@ -6360,7 +6360,7 @@ subevalvar(char *p, char *varname, int strloc, int subtype, switch (subtype) { case VSASSIGN: - setvar2(varname, startp); + setvar0(varname, startp); amount = startp - expdest; STADJUST(amount, expdest); return startp; @@ -8591,7 +8591,7 @@ evalfor(union node *n, int flags) loopnest++; flags &= EV_TESTED; for (sp = arglist.list; sp; sp = sp->next) { - setvar2(n->nfor.var, sp->text); + setvar0(n->nfor.var, sp->text); evaltree(n->nfor.body, flags); if (evalskip) { if (evalskip == SKIPCONT && --skipcount <= 0) { @@ -8970,21 +8970,37 @@ mklocal(char *name) struct localvar *lvp; struct var **vpp; struct var *vp; + char *eq = strchr(name, '='); INT_OFF; - lvp = ckzalloc(sizeof(struct localvar)); + /* Cater for duplicate "local". Examples: + * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x + * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x + */ + lvp = localvars; + while (lvp) { + if (varcmp(lvp->vp->var_text, name) == 0) { + if (eq) + setvareq(name, 0); + /* else: + * it's a duplicate "local VAR" declaration, do nothing + */ + return; + } + lvp = lvp->next; + } + + lvp = ckzalloc(sizeof(*lvp)); if (LONE_DASH(name)) { char *p; p = ckmalloc(sizeof(optlist)); lvp->text = memcpy(p, optlist, sizeof(optlist)); vp = NULL; } else { - char *eq; - vpp = hashvar(name); vp = *findvar(vpp, name); - eq = strchr(name, '='); if (vp == NULL) { + /* variable did not exist yet */ if (eq) setvareq(name, VSTRFIXED); else @@ -8994,12 +9010,15 @@ mklocal(char *name) } else { lvp->text = vp->var_text; lvp->flags = vp->flags; + /* make sure neither "struct var" nor string gets freed + * during (un)setting: + */ vp->flags |= VSTRFIXED|VTEXTFIXED; if (eq) setvareq(name, 0); else /* "local VAR" unsets VAR: */ - setvar(name, NULL, 0); + setvar0(name, NULL); } } lvp->vp = vp; @@ -9491,7 +9510,7 @@ evalcommand(union node *cmd, int flags) * '_' in 'vi' command mode during line editing... * However I implemented that within libedit itself. */ - setvar2("_", lastarg); + setvar0("_", lastarg); } popstackmark(&smark); } @@ -12885,7 +12904,7 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) * to jump out of it. */ INT_OFF; - r = shell_builtin_read(setvar2, + r = shell_builtin_read(setvar0, argptr, bltinlookup("IFS"), /* can be NULL */ read_flags, @@ -13046,14 +13065,14 @@ init(void) } } - setvar2("PPID", utoa(getppid())); + setvar0("PPID", utoa(getppid())); #if ENABLE_ASH_BASH_COMPAT p = lookupvar("SHLVL"); setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT); if (!lookupvar("HOSTNAME")) { struct utsname uts; uname(&uts); - setvar2("HOSTNAME", uts.nodename); + setvar0("HOSTNAME", uts.nodename); } #endif p = lookupvar("PWD"); @@ -13309,7 +13328,7 @@ int ash_main(int argc UNUSED_PARAM, char **argv) hp = lookupvar("HOME"); if (hp) { hp = concat_path_file(hp, ".ash_history"); - setvar2("HISTFILE", hp); + setvar0("HISTFILE", hp); free((char*)hp); hp = lookupvar("HISTFILE"); } diff --git a/shell/ash_test/ash-heredoc/heredoc1.right b/shell/ash_test/ash-heredoc/heredoc1.right index 895f5ee80..40aa5a5fe 100644 --- a/shell/ash_test/ash-heredoc/heredoc1.right +++ b/shell/ash_test/ash-heredoc/heredoc1.right @@ -1 +1 @@ -heredoc1.tests: line 3: syntax error: unexpected "then" +./heredoc1.tests: line 3: syntax error: unexpected "then" diff --git a/shell/ash_test/ash-vars/var3.right b/shell/ash_test/ash-vars/var3.right new file mode 100644 index 000000000..8eb0e3337 --- /dev/null +++ b/shell/ash_test/ash-vars/var3.right @@ -0,0 +1,5 @@ +1 +1 + + +0 diff --git a/shell/ash_test/ash-vars/var3.tests b/shell/ash_test/ash-vars/var3.tests new file mode 100755 index 000000000..97b102cbe --- /dev/null +++ b/shell/ash_test/ash-vars/var3.tests @@ -0,0 +1 @@ +x=0; f() { local x=1; echo $x; local x; echo $x; unset x; echo $x; local x; echo $x; }; f; echo $x From 73327a048b112ba2b742b758bb5a3caf95c7bf1a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 18 Apr 2015 19:38:13 +0200 Subject: [PATCH 110/256] hush: document buggy handling of duplicate "local" Signed-off-by: Denys Vlasenko --- shell/hush_test/hush-bugs/var3.right | 5 +++++ shell/hush_test/hush-bugs/var3.tests | 1 + 2 files changed, 6 insertions(+) create mode 100644 shell/hush_test/hush-bugs/var3.right create mode 100755 shell/hush_test/hush-bugs/var3.tests diff --git a/shell/hush_test/hush-bugs/var3.right b/shell/hush_test/hush-bugs/var3.right new file mode 100644 index 000000000..8eb0e3337 --- /dev/null +++ b/shell/hush_test/hush-bugs/var3.right @@ -0,0 +1,5 @@ +1 +1 + + +0 diff --git a/shell/hush_test/hush-bugs/var3.tests b/shell/hush_test/hush-bugs/var3.tests new file mode 100755 index 000000000..97b102cbe --- /dev/null +++ b/shell/hush_test/hush-bugs/var3.tests @@ -0,0 +1 @@ +x=0; f() { local x=1; echo $x; local x; echo $x; unset x; echo $x; local x; echo $x; }; f; echo $x From bd77e9d6093dc8632788a3c3efffd53ac8ba3233 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 19 Apr 2015 18:54:49 +0200 Subject: [PATCH 111/256] mdev: improve logging Signed-off-by: Denys Vlasenko --- util-linux/mdev.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/util-linux/mdev.c b/util-linux/mdev.c index ccc00d365..884e5de33 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c @@ -283,7 +283,7 @@ struct globals { unsigned rule_idx; #endif struct rule cur_rule; - char timestr[sizeof("60.123456")]; + char timestr[sizeof("HH:MM:SS.123456")]; } FIX_ALIASING; #define G (*(struct globals*)&bb_common_bufsiz1) #define INIT_G() do { \ @@ -923,7 +923,11 @@ static char *curtime(void) { struct timeval tv; gettimeofday(&tv, NULL); - sprintf(G.timestr, "%u.%06u", (unsigned)tv.tv_sec % 60, (unsigned)tv.tv_usec); + sprintf( + strftime_HHMMSS(G.timestr, sizeof(G.timestr), &tv.tv_sec), + ".%06u", + (unsigned)tv.tv_usec + ); return G.timestr; } @@ -984,7 +988,7 @@ wait_for_seqfile(const char *seq) break; } if (do_once) { - dbg2("%s waiting for '%s'", curtime(), seqbuf); + dbg2("%s mdev.seq='%s', need '%s'", curtime(), seqbuf, seq); do_once = 0; } if (sigtimedwait(&set_CHLD, NULL, &ts) >= 0) { @@ -992,7 +996,7 @@ wait_for_seqfile(const char *seq) continue; /* don't decrement timeout! */ } if (--timeout == 0) { - dbg1("%s waiting for '%s'", "timed out", seqbuf); + dbg1("%s mdev.seq='%s'", "timed out", seqbuf); break; } } From ad795510d9fd6f4290be170c84c0d30eb1af7245 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 19 Apr 2015 18:55:12 +0200 Subject: [PATCH 112/256] mdev: if a "future" mdev.seq is seen, do not overwrite it with ours This was seen to happen if two mdevs are run in parallel, mdev.seq is empty, and the "newer" one manages to write it first. function old new delta mdev_main 1366 1388 +22 atoll - 20 +20 Signed-off-by: Denys Vlasenko --- util-linux/mdev.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/util-linux/mdev.c b/util-linux/mdev.c index 884e5de33..ca4b91510 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c @@ -947,7 +947,7 @@ static void open_mdev_log(const char *seq, unsigned my_pid) * Active mdev pokes us with SIGCHLD to check the new file. */ static int -wait_for_seqfile(const char *seq) +wait_for_seqfile(unsigned expected_seq) { /* We time out after 2 sec */ static const struct timespec ts = { 0, 32*1000*1000 }; @@ -962,12 +962,14 @@ wait_for_seqfile(const char *seq) for (;;) { int seqlen; - char seqbuf[sizeof(int)*3 + 2]; + char seqbuf[sizeof(long)*3 + 2]; + unsigned seqbufnum; if (seq_fd < 0) { seq_fd = open("mdev.seq", O_RDWR); if (seq_fd < 0) break; + close_on_exec_on(seq_fd); } seqlen = pread(seq_fd, seqbuf, sizeof(seqbuf) - 1, 0); if (seqlen < 0) { @@ -978,17 +980,25 @@ wait_for_seqfile(const char *seq) seqbuf[seqlen] = '\0'; if (seqbuf[0] == '\n' || seqbuf[0] == '\0') { /* seed file: write out seq ASAP */ - xwrite_str(seq_fd, seq); + xwrite_str(seq_fd, utoa(expected_seq)); xlseek(seq_fd, 0, SEEK_SET); dbg2("first seq written"); break; } - if (strcmp(seq, seqbuf) == 0) { + seqbufnum = atoll(seqbuf); + if (seqbufnum == expected_seq) { /* correct idx */ break; } + if (seqbufnum > expected_seq) { + /* a later mdev runs already (this was seen by users to happen) */ + /* do not overwrite seqfile on exit */ + close(seq_fd); + seq_fd = -1; + break; + } if (do_once) { - dbg2("%s mdev.seq='%s', need '%s'", curtime(), seqbuf, seq); + dbg2("%s mdev.seq='%s', need '%u'", curtime(), seqbuf, expected_seq); do_once = 0; } if (sigtimedwait(&set_CHLD, NULL, &ts) >= 0) { @@ -1079,6 +1089,7 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) char *env_devname; char *env_devpath; unsigned my_pid; + unsigned seqnum = seqnum; /* for compiler */ int seq_fd; smalluint op; @@ -1100,7 +1111,11 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) my_pid = getpid(); open_mdev_log(seq, my_pid); - seq_fd = seq ? wait_for_seqfile(seq) : -1; + seq_fd = -1; + if (seq) { + seqnum = atoll(seq); + seq_fd = wait_for_seqfile(seqnum); + } dbg1("%s " "ACTION:%s SUBSYSTEM:%s DEVNAME:%s DEVPATH:%s" @@ -1128,7 +1143,7 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) dbg1("%s exiting", curtime()); if (seq_fd >= 0) { - xwrite_str(seq_fd, utoa(xatou(seq) + 1)); + xwrite_str(seq_fd, utoa(seqnum + 1)); signal_mdevs(my_pid); } } From 61d6ae244af424b2a05468307723f21c8810ab9e Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Sun, 19 Apr 2015 10:50:25 +0100 Subject: [PATCH 113/256] libbb: remove unnecessary argument to nonblock_immune_read The loop_on_EINTR argument to nonblock_immune_read is always set to 1. function old new delta xmalloc_reads 200 195 -5 pgetc 488 483 -5 argstr 1313 1308 -5 nonblock_immune_read 123 86 -37 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/4 up/down: 0/-52) Total: -52 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- include/libbb.h | 2 +- libbb/read_printf.c | 8 ++++---- shell/ash.c | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index 0f8363b78..21da5f100 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -713,7 +713,7 @@ void* xrealloc_vector_helper(void *vector, unsigned sizeof_and_shift, int idx) F extern ssize_t safe_read(int fd, void *buf, size_t count) FAST_FUNC; -extern ssize_t nonblock_immune_read(int fd, void *buf, size_t count, int loop_on_EINTR) FAST_FUNC; +extern ssize_t nonblock_immune_read(int fd, void *buf, size_t count) FAST_FUNC; // NB: will return short read on error, not -1, // if some data was read before error occurred extern ssize_t full_read(int fd, void *buf, size_t count) FAST_FUNC; diff --git a/libbb/read_printf.c b/libbb/read_printf.c index 5ed6e3632..b6a17cc36 100644 --- a/libbb/read_printf.c +++ b/libbb/read_printf.c @@ -45,20 +45,20 @@ * which detects EAGAIN and uses poll() to wait on the fd. * Thankfully, poll() doesn't care about O_NONBLOCK flag. */ -ssize_t FAST_FUNC nonblock_immune_read(int fd, void *buf, size_t count, int loop_on_EINTR) +ssize_t FAST_FUNC nonblock_immune_read(int fd, void *buf, size_t count) { struct pollfd pfd[1]; ssize_t n; while (1) { - n = loop_on_EINTR ? safe_read(fd, buf, count) : read(fd, buf, count); + n = safe_read(fd, buf, count); if (n >= 0 || errno != EAGAIN) return n; /* fd is in O_NONBLOCK mode. Wait using poll and repeat */ pfd[0].fd = fd; pfd[0].events = POLLIN; /* note: safe_poll pulls in printf */ - loop_on_EINTR ? safe_poll(pfd, 1, -1) : poll(pfd, 1, -1); + safe_poll(pfd, 1, -1); } } @@ -81,7 +81,7 @@ char* FAST_FUNC xmalloc_reads(int fd, size_t *maxsz_p) p = buf + sz; sz += 128; } - if (nonblock_immune_read(fd, p, 1, /*loop_on_EINTR:*/ 1) != 1) { + if (nonblock_immune_read(fd, p, 1) != 1) { /* EOF/error */ if (p == buf) { /* we read nothing */ free(buf); diff --git a/shell/ash.c b/shell/ash.c index 697a64fea..c51fb804d 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -5923,7 +5923,7 @@ expbackq(union node *cmd, int quoted, int quotes) read: if (in.fd < 0) break; - i = nonblock_immune_read(in.fd, buf, sizeof(buf), /*loop_on_EINTR:*/ 1); + i = nonblock_immune_read(in.fd, buf, sizeof(buf)); TRACE(("expbackq: read returns %d\n", i)); if (i <= 0) break; @@ -9696,7 +9696,7 @@ preadfd(void) #if ENABLE_FEATURE_EDITING retry: if (!iflag || g_parsefile->pf_fd != STDIN_FILENO) - nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1, /*loop_on_EINTR:*/ 1); + nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1); else { int timeout = -1; # if ENABLE_ASH_IDLE_TIMEOUT @@ -9738,7 +9738,7 @@ preadfd(void) } } #else - nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1, /*loop_on_EINTR:*/ 1); + nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1); #endif #if 0 /* disabled: nonblock_immune_read() handles this problem */ From 7d86384b246434e72533332f7f409a7aa9efeacb Mon Sep 17 00:00:00 2001 From: Bernhard Reutner-Fischer Date: Sun, 19 Apr 2015 23:45:17 +0200 Subject: [PATCH 114/256] include: Fallback to UTMP unless there is UTMPX support Fixes compilation against uClibc-0.9.30 for instance Signed-off-by: Bernhard Reutner-Fischer --- include/libbb.h | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/include/libbb.h b/include/libbb.h index 21da5f100..f0ac1f50d 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -84,7 +84,30 @@ # include #endif #if ENABLE_FEATURE_UTMP -# include +# if defined __UCLIBC__ && ( \ + (UCLIBC_VERSION >= KERNEL_VERSION(0, 9, 32) \ + && UCLIBC_VERSION < KERNEL_VERSION(0, 9, 34) \ + && defined __UCLIBC_HAS_UTMPX__ \ + ) || ( \ + UCLIBC_VERSION >= KERNEL_VERSION(0, 9, 34) \ + ) \ + ) +# include +# elif defined __UCLIBC__ +# include +# define utmpx utmp +# define setutxent setutent +# define endutxent endutent +# define getutxent getutent +# define getutxid getutid +# define getutxline getutline +# define pututxline pututline +# define utmpxname utmpname +# define updwtmpx updwtmp +# define _PATH_UTMPX _PATH_UTMP +# else +# include +# endif #endif #if ENABLE_LOCALE_SUPPORT # include From de5edadee2dca2896492f97ab3a56e389305e74d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 21 Apr 2015 16:00:41 +0200 Subject: [PATCH 115/256] special-case {true,false,test} --help This also removes their help texts. function old new delta run_applet_no_and_exit 442 452 +10 packed_usage 30713 30625 -88 Signed-off-by: Denys Vlasenko --- coreutils/false.c | 8 +++----- coreutils/test.c | 11 +++-------- coreutils/true.c | 8 +++----- libbb/appletlib.c | 22 ++++++++++++---------- 4 files changed, 21 insertions(+), 28 deletions(-) diff --git a/coreutils/false.c b/coreutils/false.c index 59c2f321a..0591a6cdc 100644 --- a/coreutils/false.c +++ b/coreutils/false.c @@ -10,11 +10,9 @@ /* BB_AUDIT SUSv3 compliant */ /* http://www.opengroup.org/onlinepubs/000095399/utilities/false.html */ -//usage:#define false_trivial_usage -//usage: "" -//usage:#define false_full_usage "\n\n" -//usage: "Return an exit code of FALSE (1)" -//usage: +/* "false --help" is special-cased to ignore --help */ +//usage:#define false_trivial_usage NOUSAGE_STR +//usage:#define false_full_usage "" //usage:#define false_example_usage //usage: "$ false\n" //usage: "$ echo $?\n" diff --git a/coreutils/test.c b/coreutils/test.c index 88cc55050..7b8b10cd9 100644 --- a/coreutils/test.c +++ b/coreutils/test.c @@ -39,14 +39,9 @@ //config: help //config: Enable 64-bit support in test. -/* "test --help" does not print help (POSIX compat), only "[ --help" does. - * We display " EXPRESSION ]" here (not " EXPRESSION") - * Unfortunately, it screws up generated BusyBox.html. TODO. */ -//usage:#define test_trivial_usage -//usage: "EXPRESSION ]" -//usage:#define test_full_usage "\n\n" -//usage: "Check file types, compare values etc. Return a 0/1 exit code\n" -//usage: "depending on logical value of EXPRESSION" +/* "test --help" is special-cased to ignore --help */ +//usage:#define test_trivial_usage NOUSAGE_STR +//usage:#define test_full_usage "" //usage: //usage:#define test_example_usage //usage: "$ test 1 -eq 2\n" diff --git a/coreutils/true.c b/coreutils/true.c index 382e476a8..89f892961 100644 --- a/coreutils/true.c +++ b/coreutils/true.c @@ -10,11 +10,9 @@ /* BB_AUDIT SUSv3 compliant */ /* http://www.opengroup.org/onlinepubs/007904975/utilities/true.html */ -//usage:#define true_trivial_usage -//usage: "" -//usage:#define true_full_usage "\n\n" -//usage: "Return an exit code of TRUE (0)" -//usage: +/* "true --help" is special-cased to ignore --help */ +//usage:#define true_trivial_usage NOUSAGE_STR +//usage:#define true_full_usage "" //usage:#define true_example_usage //usage: "$ true\n" //usage: "$ echo $?\n" diff --git a/libbb/appletlib.c b/libbb/appletlib.c index e0b843d30..ba3d6e7a0 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -748,23 +748,25 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv) xfunc_error_retval = EXIT_FAILURE; applet_name = APPLET_NAME(applet_no); -#if defined APPLET_NO_test /* Special case. POSIX says "test --help" * should be no different from e.g. "test --foo". * Thus for "test", we skip --help check. + * "true" and "false" are also special. */ - if (applet_no != APPLET_NO_test) + if (1 +#if defined APPLET_NO_test + && applet_no != APPLET_NO_test +#endif +#if defined APPLET_NO_true + && applet_no != APPLET_NO_true #endif - { - if (argc == 2 && strcmp(argv[1], "--help") == 0) { #if defined APPLET_NO_false - /* Someone insisted that "false --help" must exit 1. Sigh */ - if (applet_no != APPLET_NO_false) + && applet_no != APPLET_NO_false #endif - { - /* Make "foo --help" exit with 0: */ - xfunc_error_retval = 0; - } + ) { + if (argc == 2 && strcmp(argv[1], "--help") == 0) { + /* Make "foo --help" exit with 0: */ + xfunc_error_retval = 0; bb_show_usage(); } } From cee59053dcf47b4a3ab87f7654c1ed20620def16 Mon Sep 17 00:00:00 2001 From: Matt Whitlock Date: Sat, 25 Apr 2015 21:32:48 +0200 Subject: [PATCH 116/256] Bionic lacks ttyname_r; provide a workaround Signed-off-by: Matt Whitlock Signed-off-by: Denys Vlasenko --- include/platform.h | 7 +++++++ libbb/platform.c | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/platform.h b/include/platform.h index df9594507..d5ab7bc29 100644 --- a/include/platform.h +++ b/include/platform.h @@ -368,6 +368,7 @@ typedef unsigned smalluint; #define HAVE_DPRINTF 1 #define HAVE_MEMRCHR 1 #define HAVE_MKDTEMP 1 +#define HAVE_TTYNAME_R 1 #define HAVE_PTSNAME_R 1 #define HAVE_SETBIT 1 #define HAVE_SIGHANDLER_T 1 @@ -480,6 +481,7 @@ typedef unsigned smalluint; #if defined(ANDROID) || defined(__ANDROID__) # undef HAVE_DPRINTF +# undef HAVE_TTYNAME_R # undef HAVE_GETLINE # undef HAVE_STPCPY # undef HAVE_STRCHRNUL @@ -505,6 +507,11 @@ extern void *memrchr(const void *s, int c, size_t n) FAST_FUNC; extern char *mkdtemp(char *template) FAST_FUNC; #endif +#ifndef HAVE_TTYNAME_R +#define ttyname_r bb_ttyname_r +extern int ttyname_r(int fd, char *buf, size_t buflen); +#endif + #ifndef HAVE_SETBIT # define setbit(a, b) ((a)[(b) >> 3] |= 1 << ((b) & 7)) # define clrbit(a, b) ((a)[(b) >> 3] &= ~(1 << ((b) & 7))) diff --git a/libbb/platform.c b/libbb/platform.c index 8d90ca4e9..03bbb798b 100644 --- a/libbb/platform.c +++ b/libbb/platform.c @@ -194,3 +194,22 @@ ssize_t FAST_FUNC getline(char **lineptr, size_t *n, FILE *stream) return len; } #endif + +#ifndef HAVE_TTYNAME_R +int ttyname_r(int fd, char *buf, size_t buflen) +{ + int r; + char path[sizeof("/proc/self/fd/%d") + sizeof(int)*3]; + + if (!isatty(fd)) + return errno == EINVAL ? ENOTTY : errno; + sprintf(path, "/proc/self/fd/%d", fd); + r = readlink(path, buf, buflen); + if (r < 0) + return errno; + if (r >= buflen) + return ERANGE; + buf[r] = '\0'; + return 0; +} +#endif From 93b98ff5726fd620e1f123d04072b956412c1b55 Mon Sep 17 00:00:00 2001 From: Matt Whitlock Date: Sun, 26 Apr 2015 13:14:50 +0200 Subject: [PATCH 117/256] Bionic lacks tcdrain; provide a workaround Signed-off-by: Matt Whitlock Signed-off-by: Denys Vlasenko --- libbb/missing_syscalls.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libbb/missing_syscalls.c b/libbb/missing_syscalls.c index dd430e3e2..e3c1e924b 100644 --- a/libbb/missing_syscalls.c +++ b/libbb/missing_syscalls.c @@ -39,4 +39,9 @@ int pivot_root(const char *new_root, const char *put_old) { return syscall(__NR_pivot_root, new_root, put_old); } + +int tcdrain(int fd) +{ + return ioctl(fd, TCSBRK, 1); +} #endif From bbd53216f80912944da0d4ca72bf3ed3188ca156 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Sun, 26 Apr 2015 14:22:05 +0200 Subject: [PATCH 118/256] gzip: add support for compression levels 4-9 function old new delta gzip_main 192 282 +90 static.gzip_level_config - 24 +24 packed_usage 30439 30459 +20 fill_window 216 220 +4 pack_gzip 1789 1729 -60 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 3/1 up/down: 138/-60) Total: 78 bytes Signed-off-by: Aaro Koskinen Signed-off-by: Denys Vlasenko --- archival/gzip.c | 72 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 10 deletions(-) diff --git a/archival/gzip.c b/archival/gzip.c index bc1f9c60b..42b2f0b2e 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -62,14 +62,27 @@ aa: 85.1% -- replaced with aa.gz //config: 1: larger buffers, larger hash-tables //config: 2: larger buffers, largest hash-tables //config: Larger models may give slightly better compression +//config: +//config:config FEATURE_GZIP_LEVELS +//config: bool "Enable compression levels" +//config: default n +//config: depends on GZIP +//config: help +//config: Enable support for compression levels 4-9. The default level +//config: is 6. If levels 1-3 are specified, 4 is used. +//config: If this option is not selected, -N options are ignored and -9 +//config: is used. //applet:IF_GZIP(APPLET(gzip, BB_DIR_BIN, BB_SUID_DROP)) //kbuild:lib-$(CONFIG_GZIP) += gzip.o //usage:#define gzip_trivial_usage -//usage: "[-cfd] [FILE]..." +//usage: "[-cfd" IF_FEATURE_GZIP_LEVELS("123456789") "] [FILE]..." //usage:#define gzip_full_usage "\n\n" //usage: "Compress FILEs (or stdin)\n" +//usage: IF_FEATURE_GZIP_LEVELS( +//usage: "\n -1..9 Compression level" +//usage: ) //usage: "\n -d Decompress" //usage: "\n -c Write to stdout" //usage: "\n -f Force" @@ -252,6 +265,8 @@ enum { * input file length plus MIN_LOOKAHEAD. */ +#ifndef ENABLE_FEATURE_GZIP_LEVELS + max_chain_length = 4096, /* To speed up deflation, hash chains are never searched beyond this length. * A higher limit improves compression ratio but degrades the speed. @@ -283,11 +298,23 @@ enum { * For deflate_fast() (levels <= 3) good is ignored and lazy has a different * meaning. */ +#endif /* ENABLE_FEATURE_GZIP_LEVELS */ }; struct globals { +#ifdef ENABLE_FEATURE_GZIP_LEVELS + unsigned max_chain_length; + unsigned max_lazy_match; + unsigned good_match; + unsigned nice_match; +#define max_chain_length (G1.max_chain_length) +#define max_lazy_match (G1.max_lazy_match) +#define good_match (G1.good_match) +#define nice_match (G1.nice_match) +#endif + lng block_start; /* window position at the beginning of the current output block. Gets @@ -2161,24 +2188,48 @@ int gzip_main(int argc UNUSED_PARAM, char **argv) #endif { unsigned opt; +#ifdef ENABLE_FEATURE_GZIP_LEVELS + static const struct { + uint8_t good; + uint8_t chain_shift; + uint8_t lazy2; + uint8_t nice2; + } gzip_level_config[6] = { + {4, 4, 4/2, 16/2}, /* Level 4 */ + {8, 5, 16/2, 32/2}, /* Level 5 */ + {8, 7, 16/2, 128/2}, /* Level 6 */ + {8, 8, 32/2, 128/2}, /* Level 7 */ + {32, 10, 128/2, 258/2}, /* Level 8 */ + {32, 12, 258/2, 258/2}, /* Level 9 */ + }; +#endif + + SET_PTR_TO_GLOBALS((char *)xzalloc(sizeof(struct globals)+sizeof(struct globals2)) + + sizeof(struct globals)); #if ENABLE_FEATURE_GZIP_LONG_OPTIONS applet_long_options = gzip_longopts; #endif /* Must match bbunzip's constants OPT_STDOUT, OPT_FORCE! */ - opt = getopt32(argv, "cfv" IF_GUNZIP("dt") "q123456789n"); + opt = getopt32(argv, "cfv" IF_GUNZIP("dt") "qn123456789"); #if ENABLE_GUNZIP /* gunzip_main may not be visible... */ if (opt & 0x18) // -d and/or -t return gunzip_main(argc, argv); #endif - option_mask32 &= 0x7; /* ignore -q, -0..9 */ - //if (opt & 0x1) // -c - //if (opt & 0x2) // -f - //if (opt & 0x4) // -v - argv += optind; - - SET_PTR_TO_GLOBALS((char *)xzalloc(sizeof(struct globals)+sizeof(struct globals2)) - + sizeof(struct globals)); +#ifdef ENABLE_FEATURE_GZIP_LEVELS + opt >>= ENABLE_GUNZIP ? 7 : 5; /* drop cfv[dt]qn bits */ + if (opt == 0) + opt = 1 << 6; /* default: 6 */ + /* Map 1..3 to 4 */ + if (opt & 0x7) + opt |= 1 << 4; + opt = ffs(opt >> 3); + max_chain_length = 1 << gzip_level_config[opt].chain_shift; + good_match = gzip_level_config[opt].good; + max_lazy_match = gzip_level_config[opt].lazy2 * 2; + nice_match = gzip_level_config[opt].nice2 * 2; +#endif + option_mask32 &= 0x7; /* retain only -cfv */ /* Allocate all global buffers (for DYN_ALLOC option) */ ALLOC(uch, G1.l_buf, INBUFSIZ); @@ -2190,5 +2241,6 @@ int gzip_main(int argc UNUSED_PARAM, char **argv) /* Initialize the CRC32 table */ global_crc32_table = crc32_filltable(NULL, 0); + argv += optind; return bbunpack(argv, pack_gzip, append_ext, "gz"); } From 4d8ddb810d52f5ad1bcef8bda07687200117e56b Mon Sep 17 00:00:00 2001 From: Andrew Fuller Date: Sun, 3 May 2015 18:18:25 +0200 Subject: [PATCH 119/256] vi: basic undo feature shouldn't depend on yankmark Currently basic undo functionality with the 'u' key depends on FEATURE_VI_YANKMARK. These two features are separate, so we can remove this dependency. Signed-off-by: Andrew Fuller Signed-off-by: Denys Vlasenko --- editors/vi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/editors/vi.c b/editors/vi.c index 495332a46..2e4f7fcb5 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -3676,11 +3676,6 @@ static void do_cmd(int c) string_insert(dot, p, ALLOW_UNDO); // insert the string end_cmd_q(); // stop adding to q break; -#if ENABLE_FEATURE_VI_UNDO - case 'u': // u- undo last operation - undo_pop(); - break; -#endif case 'U': // U- Undo; replace current line with original version if (reg[Ureg] != NULL) { p = begin_line(dot); @@ -3692,6 +3687,11 @@ static void do_cmd(int c) } break; #endif /* FEATURE_VI_YANKMARK */ +#if ENABLE_FEATURE_VI_UNDO + case 'u': // u- undo last operation + undo_pop(); + break; +#endif case '$': // $- goto end of line case KEYCODE_END: // Cursor Key End for (;;) { From c77a58fb2d84d4ee3883d385bc44bbfcfc7093c9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 3 May 2015 18:24:33 +0200 Subject: [PATCH 120/256] typo fix Signed-off-by: Denys Vlasenko --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index b940e357a..ada5935b9 100644 --- a/README +++ b/README @@ -185,7 +185,7 @@ Supported hardware: Under 2.4 Linux kernels, kernel module loading was implemented in a platform-specific manner. Busybox's insmod utility has been reported to work under ARM, CRIS, H8/300, x86, ia64, x86_64, m68k, MIPS, PowerPC, S390, - SH3/4/5, Sparc, v850e, and x86_64. Anything else probably won't work. + SH3/4/5, Sparc, and v850e. Anything else probably won't work. The module loading mechanism for the 2.6 kernel is much more generic, and we believe 2.6.x kernel module loading support should work on all From b4059f6309c5129a619bd1a95d27919231e07860 Mon Sep 17 00:00:00 2001 From: Thiago Jung Bauermann Date: Sun, 3 May 2015 18:40:12 +0200 Subject: [PATCH 121/256] libarchive: auto-detect .Z files as well Signed-off-by: Thiago Jung Bauermann Signed-off-by: Denys Vlasenko --- archival/libarchive/open_transformer.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c index ab6aa3afc..be536a3d7 100644 --- a/archival/libarchive/open_transformer.c +++ b/archival/libarchive/open_transformer.c @@ -185,6 +185,13 @@ static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_comp USE_FOR_NOMMU(xstate->xformer_prog = "gunzip";) goto found_magic; } + if (ENABLE_FEATURE_SEAMLESS_Z + && magic.b16[0] == COMPRESS_MAGIC + ) { + xstate->xformer = unpack_Z_stream; + USE_FOR_NOMMU(xstate->xformer_prog = "uncompress";) + goto found_magic; + } if (ENABLE_FEATURE_SEAMLESS_BZ2 && magic.b16[0] == BZIP2_MAGIC ) { From f23e3ec529c300712d529fa805d2e1f254bf1884 Mon Sep 17 00:00:00 2001 From: Matt Whitlock Date: Sun, 3 May 2015 18:57:44 +0200 Subject: [PATCH 122/256] Bionic lacks mempcpy; enable existing workaround Signed-off-by: Matt Whitlock Signed-off-by: Denys Vlasenko --- include/platform.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/platform.h b/include/platform.h index d5ab7bc29..8896a6b99 100644 --- a/include/platform.h +++ b/include/platform.h @@ -484,6 +484,7 @@ typedef unsigned smalluint; # undef HAVE_TTYNAME_R # undef HAVE_GETLINE # undef HAVE_STPCPY +# undef HAVE_MEMPCPY # undef HAVE_STRCHRNUL # undef HAVE_STRVERSCMP # undef HAVE_UNLOCKED_LINE_OPS From 778efe37eed03de6e194a746925f1160181ff587 Mon Sep 17 00:00:00 2001 From: Matt Whitlock Date: Sun, 3 May 2015 18:59:50 +0200 Subject: [PATCH 123/256] Conditionalize Bionic workarounds on __ANDROID_API__ Signed-off-by: Matt Whitlock Signed-off-by: Denys Vlasenko --- include/platform.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/include/platform.h b/include/platform.h index 8896a6b99..1706b1847 100644 --- a/include/platform.h +++ b/include/platform.h @@ -480,10 +480,16 @@ typedef unsigned smalluint; #endif #if defined(ANDROID) || defined(__ANDROID__) -# undef HAVE_DPRINTF -# undef HAVE_TTYNAME_R -# undef HAVE_GETLINE -# undef HAVE_STPCPY +# if __ANDROID_API__ < 8 +# undef HAVE_DPRINTF +# else +# define dprintf fdprintf +# endif +# if __ANDROID_API__ < 21 +# undef HAVE_TTYNAME_R +# undef HAVE_GETLINE +# undef HAVE_STPCPY +# endif # undef HAVE_MEMPCPY # undef HAVE_STRCHRNUL # undef HAVE_STRVERSCMP From bdb540e04f3eb52c4cd790c45c5d8efd6d749c70 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 11 May 2015 16:55:16 +0200 Subject: [PATCH 124/256] tar: do not try to decode GNU extended headers as pax headers function old new delta get_header_tar 1736 1692 -44 Signed-off-by: Denys Vlasenko --- archival/libarchive/get_header_tar.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/archival/libarchive/get_header_tar.c b/archival/libarchive/get_header_tar.c index 2dbcdb50c..fb68673b9 100644 --- a/archival/libarchive/get_header_tar.c +++ b/archival/libarchive/get_header_tar.c @@ -350,7 +350,14 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) case '6': file_header->mode |= S_IFIFO; goto size0; + case 'g': /* pax global header */ + case 'x': { /* pax extended header */ + if ((uoff_t)file_header->size > 0xfffff) /* paranoia */ + goto skip_ext_hdr; + process_pax_hdr(archive_handle, file_header->size, (tar.typeflag == 'g')); + goto again_after_align; #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS +/* See http://www.gnu.org/software/tar/manual/html_node/Extensions.html */ case 'L': /* free: paranoia: tar with several consecutive longnames */ free(p_longname); @@ -370,18 +377,17 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) archive_handle->offset += file_header->size; /* return get_header_tar(archive_handle); */ goto again; - case 'D': /* GNU dump dir */ - case 'M': /* Continuation of multi volume archive */ - case 'N': /* Old GNU for names > 100 characters */ - case 'S': /* Sparse file */ - case 'V': /* Volume header */ +/* + * case 'S': // Sparse file + * Was seen in the wild. Not supported (yet?). + * See https://www.gnu.org/software/tar/manual/html_section/tar_92.html + * for the format. (An "Old GNU Format" was seen, not PAX formats). + */ +// case 'D': /* GNU dump dir */ +// case 'M': /* Continuation of multi volume archive */ +// case 'N': /* Old GNU for names > 100 characters */ +// case 'V': /* Volume header */ #endif - case 'g': /* pax global header */ - case 'x': { /* pax extended header */ - if ((uoff_t)file_header->size > 0xfffff) /* paranoia */ - goto skip_ext_hdr; - process_pax_hdr(archive_handle, file_header->size, (tar.typeflag == 'g')); - goto again_after_align; } skip_ext_hdr: { From 17b16223f39c983a5d0eba8d3ab656a8d123b621 Mon Sep 17 00:00:00 2001 From: Thiago Jung Bauermann Date: Mon, 11 May 2015 17:18:59 +0200 Subject: [PATCH 125/256] bzcat.tests: Run both .gz and .bz2 tests, and add .Z tests Signed-off-by: Thiago Jung Bauermann Signed-off-by: Denys Vlasenko --- testsuite/bzcat.tests | 74 +++++++++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 24 deletions(-) diff --git a/testsuite/bzcat.tests b/testsuite/bzcat.tests index 1c1fd6563..9a1c28425 100755 --- a/testsuite/bzcat.tests +++ b/testsuite/bzcat.tests @@ -2,8 +2,6 @@ FAILCOUNT=0 -ext=bz2 - bb="busybox " unset LC_ALL @@ -11,6 +9,11 @@ unset LC_MESSAGES unset LANG unset LANGUAGE +hello_Z() { + # Compressed "HELLO\n" + $ECHO -ne "\x1f\x9d\x90\x48\x8a\x30\x61\xf2\x44\x01" +} + hello_gz() { # Gzipped "HELLO\n" #_________________________ vvv vvv vvv vvv - mtime @@ -25,32 +28,34 @@ hello_bz2() { $ECHO -ne "\x17\x72\x45\x38\x50\x90\x5b\xb8\xe8\xa3" } -prep() { - rm -f t* - hello_$ext >t1.$ext - hello_$ext >t2.$ext -} +for ext in gz bz2 Z +do + prep() { + rm -f t1.$ext t2.$ext t_actual + hello_$ext >t1.$ext + hello_$ext >t2.$ext + } -check() { - eval $2 >t_actual 2>&1 - if $ECHO -ne "$expected" | cmp - t_actual; then - echo "PASS: $1" - else - echo "FAIL: $1" - FAILCOUNT=$((FAILCOUNT + 1)) - fi -} + check() { + eval $2 >t_actual 2>&1 + if $ECHO -ne "$expected" | cmp - t_actual; then + echo "PASS: $1" + else + echo "FAIL: $1" + FAILCOUNT=$((FAILCOUNT + 1)) + fi + } -mkdir testdir 2>/dev/null -( -cd testdir || { echo "cannot cd testdir!"; exit 1; } + mkdir testdir 2>/dev/null + ( + cd testdir || { echo "cannot cd testdir!"; exit 1; } -expected="HELLO\nok\n" -prep; check "bzcat: dont delete src" "${bb}bzcat t2.bz2; test -f t2.bz2 && echo ok" - -) -rm -rf testdir + expected="HELLO\nok\n" + prep; check "zcat: dont delete $ext src" "${bb}zcat t2.$ext; test -f t2.$ext && echo ok" + ) + rm -rf testdir +done # Copyright 2011 by Denys Vlasenko @@ -60,6 +65,8 @@ rm -rf testdir # testing "test name" "command" "expected result" "file input" "stdin" +## bzip algorithm + # "input" file is bzipped file with "a\n" data testing "bzcat can print many files" \ "$ECHO -ne '$hexdump' | bzcat input input; echo \$?" \ @@ -79,6 +86,25 @@ testing "bzcat can handle compressed zero-length bzip2 files" \ "0\n" \ "\x42\x5a\x68\x39\x17\x72\x45\x38\x50\x90\x00\x00\x00\x00" "" +## compress algorithm + +# "input" file is compressed (.Z) file with "a\n" data +testing "zcat can print many files" \ +"$ECHO -ne '$hexdump' | zcat input input; echo \$?" \ +"\ +a +a +0 +" "\ +\x1f\x9d\x90\x61\x14\x00\ +" "" + +# "input" file is compressed (.Z) zero byte file +testing "zcat can handle compressed zero-length compressed (.Z) files" \ +"$ECHO -ne '$hexdump' | zcat input input; echo \$?" \ +"0\n" \ +"\x1f\x9d\x90\x00" "" + exit $((FAILCOUNT <= 255 ? FAILCOUNT : 255)) From b2cca32a37b969cce3b3bce693708759d44d3d15 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 11 May 2015 17:22:10 +0200 Subject: [PATCH 126/256] i2c-tools: fix 'i2cdetect -l' Calling 'i2cdetect -l' only displays usage and exits. Fix it by correctly parsing command-line arguments. Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- miscutils/i2c_tools.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index 03bb03974..2805cf3b0 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c @@ -1284,13 +1284,16 @@ int i2cdetect_main(int argc UNUSED_PARAM, char **argv) unsigned opts; opt_complementary = "q--r:r--q:" /* mutually exclusive */ - "-1:?3"; /* from 1 to 3 args */ + "?3"; /* up to 3 args */ opts = getopt32(argv, optstr); argv += optind; if (opts & opt_l) list_i2c_busses_and_exit(); + if (!argv[0]) + bb_show_usage(); + bus_num = i2c_bus_lookup(argv[0]); fd = i2c_dev_open(bus_num); get_funcs_matrix(fd, &funcs); From 7ca5c51cc8c54f35b6265d815d8a8be19e0821b0 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Mon, 11 May 2015 17:26:27 +0200 Subject: [PATCH 127/256] i2c-tools: only try /dev/i2c/* if opening /dev/i2c-* fails with ENOENT Trying to access /dev/i2c/* on every error after opening /dev/i2c-* can mislead users who e.g. don't have root access. Instead of bailing-out with "permission denied" we currently print "no such file or directory". Fix it by trying open("/dev/i2c/%d") only if we got ENOENT. Upstream i2cdetect tries to get any info it can from /sys and /proc even when invoked by an unprivileged user, but we don't want to add unnecessary bloat. Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- miscutils/i2c_tools.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index 2805cf3b0..7034dc9a8 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c @@ -379,8 +379,12 @@ static int i2c_dev_open(int i2cbus) sprintf(filename, "/dev/i2c-%d", i2cbus); fd = open(filename, O_RDWR); if (fd < 0) { - filename[8] = '/'; /* change to "/dev/i2c/%d" */ - fd = xopen(filename, O_RDWR); + if (errno == ENOENT) { + filename[8] = '/'; /* change to "/dev/i2c/%d" */ + fd = xopen(filename, O_RDWR); + } else { + bb_perror_msg_and_die("can't open '%s'", filename); + } } return fd; From a818777d4249e934ef7c9e6e7df8475d6692f315 Mon Sep 17 00:00:00 2001 From: Daniel Thompson Date: Tue, 12 May 2015 07:56:04 +0100 Subject: [PATCH 128/256] libbb: Enable support for !CONFIG_MULTIUSER Linux recently gained a new config option, CONFIG_MULTIUSER, that makes support for non-root users optional. This results in a number of syscalls being disabled: setuid, setregid, setgid, setreuid, setresuid, getresuid, setresgid, getresgid, setgroups, getgroups, setfsuid, setfsgid, capget, capset. Currently a number of busybox applets, including login, struggle to run when CONFIG_MULTIUSER is disabled. Even the root user is unable to login: login: can't set groups: Functi This patch adds code to make change_identity() a nop on single user systems. It works by recognising the signature errno value (ENOSYS, due to the system calls being disabled) and, to avoid security risks, only deploys when the current uid and target uid is the same. After the patch is applied any attempt to switch to a non-root user will fail. Thus a badly configured userspace (for example, one that tries to start a daemon as a non-root user when the kernel cannot support this) will report errors as one would expect. Signed-off-by: Daniel Thompson Signed-off-by: Denys Vlasenko --- libbb/change_identity.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/libbb/change_identity.c b/libbb/change_identity.c index 619db09a8..d48d86326 100644 --- a/libbb/change_identity.c +++ b/libbb/change_identity.c @@ -33,9 +33,28 @@ /* Become the user and group(s) specified by PW. */ void FAST_FUNC change_identity(const struct passwd *pw) { - if (initgroups(pw->pw_name, pw->pw_gid) == -1) - bb_perror_msg_and_die("can't set groups"); + int res; + + res = initgroups(pw->pw_name, pw->pw_gid); endgrent(); /* helps to close a fd used internally by libc */ + + if (res != 0) { + /* + * If initgroups() fails because a system call is unimplemented + * then we are running on a Linux kernel compiled without multiuser + * support (CONFIG_MULTIUSER is not defined). + * + * If we are running without multiuser support *and* the target uid + * already matches the current uid then we can skip the change of + * identity. + */ + if (errno == ENOSYS && pw->pw_uid == getuid()) { + return; + } + + bb_perror_msg_and_die("can't set groups"); + } + xsetgid(pw->pw_gid); xsetuid(pw->pw_uid); } From 1285aa62f914ba894b82880e57bd81cfbc41f180 Mon Sep 17 00:00:00 2001 From: Eugene Rudoy Date: Sun, 26 Apr 2015 23:32:00 +0200 Subject: [PATCH 129/256] ash: consider "local -" case while iterating over local variables in mklocal. fixes segfault introduced in 0a0acb55db8d7c4dec445573f1b0528d126b9e1f with functions using "local -". test-case: f() { local -; local x; }; f note: with this change applied multiple 'local -'s still cause multiple entries to be added to the localvars list. this problem will be addressed in a separate commit. Signed-off-by: Eugene Rudoy Signed-off-by: Denys Vlasenko --- shell/ash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/ash.c b/shell/ash.c index c51fb804d..3e9997b53 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -8979,7 +8979,7 @@ mklocal(char *name) */ lvp = localvars; while (lvp) { - if (varcmp(lvp->vp->var_text, name) == 0) { + if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) { if (eq) setvareq(name, 0); /* else: From e0a4e107aa9d1e03546c090b07874dff1865705e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 13 May 2015 02:20:14 +0200 Subject: [PATCH 130/256] ash: explain what "local -" does Signed-off-by: Denys Vlasenko --- shell/ash.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shell/ash.c b/shell/ash.c index 3e9997b53..7af8842bb 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -8962,7 +8962,8 @@ parse_command_args(char **argv, const char **path) * Make a variable a local variable. When a variable is made local, it's * value and flags are saved in a localvar structure. The saved values * will be restored when the shell function returns. We handle the name - * "-" as a special case. + * "-" as a special case: it makes changes to "set +-options" local + * (options will be restored on return from the function). */ static void mklocal(char *name) From d68d1fbd6cb31a61975112acb1c792735a063847 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Mon, 18 May 2015 09:49:28 +0200 Subject: [PATCH 131/256] ash: code shrink around varvalue Based on commit c989d72 from git://git.kernel.org/pub/scm/utils/dash/dash.git by Herbert Xu function old new delta strtodest - 40 +40 memtodest 123 147 +24 parse_command 1443 1440 -3 readtoken1 3205 3199 -6 argstr 1203 1180 -23 varvalue 788 660 -128 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/4 up/down: 64/-160) Total: -96 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- shell/ash.c | 84 ++++++++++++++++++++++++----------------------------- 1 file changed, 38 insertions(+), 46 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 7af8842bb..a81922add 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -5539,6 +5539,11 @@ ash_arith(const char *s) #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */ #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */ +/* Add CTLESC when necessary. */ +#define QUOTES_ESC (EXP_FULL | EXP_CASE | EXP_REDIR) +/* Do not skip NUL characters. */ +#define QUOTES_KEEPNUL EXP_TILDE + /* * Structure specifying which parts of the string should be searched * for IFS characters. @@ -5695,29 +5700,34 @@ preglob(const char *pattern, int quoted, int flag) static void memtodest(const char *p, size_t len, int syntax, int quotes) { - char *q = expdest; + char *q; - q = makestrspace(quotes ? len * 2 : len, q); + if (!len) + return; - while (len--) { + q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest); + + do { unsigned char c = *p++; - if (c == '\0') - continue; - if (quotes) { + if (c) { int n = SIT(c, syntax); - if (n == CCTL || n == CBACK) + if ((quotes & QUOTES_ESC) && + (n == CCTL || n == CBACK)) USTPUTC(CTLESC, q); - } + } else if (!(quotes & QUOTES_KEEPNUL)) + continue; USTPUTC(c, q); - } + } while (--len); expdest = q; } -static void +static size_t strtodest(const char *p, int syntax, int quotes) { - memtodest(p, strlen(p), syntax, quotes); + size_t len = strlen(p); + memtodest(p, len, syntax, quotes); + return len; } /* @@ -5790,7 +5800,7 @@ exptilde(char *startp, char *p, int flags) char *name; struct passwd *pw; const char *home; - int quotes = flags & (EXP_FULL | EXP_CASE | EXP_REDIR); + int quotes = flags & QUOTES_ESC; name = p + 1; @@ -6043,7 +6053,7 @@ argstr(char *p, int flags, struct strlist *var_str_list) '\0' }; const char *reject = spclchars; - int quotes = flags & (EXP_FULL | EXP_CASE | EXP_REDIR); /* do CTLESC */ + int quotes = flags & QUOTES_ESC; int breakall = flags & EXP_WORD; int inquotes; size_t length; @@ -6608,13 +6618,16 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list) const char *p; int num; int i; - int sepq = 0; ssize_t len = 0; - int subtype = varflags & VSTYPE; - int quotes = flags & (EXP_FULL | EXP_CASE | EXP_REDIR); + int sep; int quoted = varflags & VSQUOTE; + int subtype = varflags & VSTYPE; + int discard = subtype == VSPLUS || subtype == VSLENGTH; + int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL; int syntax = quoted ? DQSYNTAX : BASESYNTAX; + sep = quoted ? ((flags & EXP_FULL) << CHAR_BIT) : 0; + switch (*name) { case '$': num = rootpid; @@ -6649,7 +6662,7 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list) break; case '@': { char **ap; - int sep; + char sepc; if (quoted && (flags & EXP_FULL)) { /* note: this is not meant as PEOF value */ @@ -6659,39 +6672,20 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list) /* fall through */ case '*': sep = ifsset() ? (unsigned char)(ifsval()[0]) : ' '; - i = SIT(sep, syntax); - if (quotes && (i == CCTL || i == CBACK)) - sepq = 1; param: ap = shellparam.p; + sepc = sep; if (!ap) return -1; while ((p = *ap++) != NULL) { - size_t partlen; - - partlen = strlen(p); - len += partlen; - - if (!(subtype == VSPLUS || subtype == VSLENGTH)) - memtodest(p, partlen, syntax, quotes); + len += strtodest(p, syntax, quotes); if (*ap && sep) { - char *q; - len++; - if (subtype == VSPLUS || subtype == VSLENGTH) { - continue; - } - q = expdest; - if (sepq) - STPUTC(CTLESC, q); - /* note: may put NUL despite sep != 0 - * (see sep = 1 << CHAR_BIT above) */ - STPUTC(sep, q); - expdest = q; + memtodest(&sepc, 1, syntax, quotes); } } - return len; + break; } /* case '@' and '*' */ case '0': case '1': @@ -6740,9 +6734,7 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list) if (!p) return -1; - len = strlen(p); - if (!(subtype == VSPLUS || subtype == VSLENGTH)) - memtodest(p, len, syntax, quotes); + len = strtodest(p, syntax, quotes); #if ENABLE_UNICODE_SUPPORT if (subtype == VSLENGTH && len > 0) { reinit_unicode_for_ash(); @@ -6751,10 +6743,10 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list) } } #endif - return len; + break; } - if (subtype == VSPLUS || subtype == VSLENGTH) + if (discard) STADJUST(-len, expdest); return len; } @@ -6870,7 +6862,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list) patloc = expdest - (char *)stackblock(); if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype, startloc, varflags, - /* quotes: */ flags & (EXP_FULL | EXP_CASE | EXP_REDIR), + /* quotes: */ flags & QUOTES_ESC, var_str_list) ) { int amount = expdest - ( From eb6b48ba743d510ad9e6f9c3a8b3899d1eb9b5f3 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Mon, 18 May 2015 09:51:35 +0200 Subject: [PATCH 132/256] ash: perform tilde expansion in all parameter expansion words Previously tilde expansion was not carried out for =?#% expansion words. Test case: a=~root:~root echo ${a#~root} Old result: /root:/root New result: :/root Based on commit dd721f71 from git://git.kernel.org/pub/scm/utils/dash/dash.git by Herbert Xu function old new delta subevalvar 1152 1153 +1 Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- shell/ash.c | 4 ++-- .../ash-vars/var-expand-tilde-in-parameter-expansion.right | 1 + .../ash-vars/var-expand-tilde-in-parameter-expansion.tests | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 shell/ash_test/ash-vars/var-expand-tilde-in-parameter-expansion.right create mode 100755 shell/ash_test/ash-vars/var-expand-tilde-in-parameter-expansion.tests diff --git a/shell/ash.c b/shell/ash.c index a81922add..4c43f1f30 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -6361,8 +6361,8 @@ subevalvar(char *p, char *varname, int strloc, int subtype, // p, varname, strloc, subtype, startloc, varflags, quotes); herefd = -1; - argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0, - var_str_list); + argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ? + EXP_CASE : 0), var_str_list); STPUTC('\0', expdest); herefd = saveherefd; argbackq = saveargbackq; diff --git a/shell/ash_test/ash-vars/var-expand-tilde-in-parameter-expansion.right b/shell/ash_test/ash-vars/var-expand-tilde-in-parameter-expansion.right new file mode 100644 index 000000000..2357750c5 --- /dev/null +++ b/shell/ash_test/ash-vars/var-expand-tilde-in-parameter-expansion.right @@ -0,0 +1 @@ +:/root diff --git a/shell/ash_test/ash-vars/var-expand-tilde-in-parameter-expansion.tests b/shell/ash_test/ash-vars/var-expand-tilde-in-parameter-expansion.tests new file mode 100755 index 000000000..6605315d0 --- /dev/null +++ b/shell/ash_test/ash-vars/var-expand-tilde-in-parameter-expansion.tests @@ -0,0 +1,2 @@ +a=~root:~root +echo ${a#~root} From 3df47f9cbbb7f16608cbc642026625cdf7f06aa9 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Mon, 18 May 2015 09:53:26 +0200 Subject: [PATCH 133/256] ash: do not expand tilde in parameter expansion within quotes Test case: unset a echo "${a:-~root}" Old result: /root New result: ~root Based on commit 170f44d from git://git.kernel.org/pub/scm/utils/dash/dash.git by Herbert Xu function old new delta evalvar 598 604 +6 parse_command 1440 1443 +3 localcmd 325 327 +2 readtoken1 3199 3200 +1 argstr 1180 1164 -16 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/1 up/down: 12/-16) Total: -4 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- shell/ash.c | 8 +++----- ...ot-expand-tilde-in-parameter-expansion-in-quotes.right | 1 + ...ot-expand-tilde-in-parameter-expansion-in-quotes.tests | 2 ++ 3 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 shell/ash_test/ash-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.right create mode 100755 shell/ash_test/ash-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.tests diff --git a/shell/ash.c b/shell/ash.c index 4c43f1f30..d87166c4f 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -5529,7 +5529,7 @@ ash_arith(const char *s) #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */ #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */ #define EXP_WORD 0x80 /* expand word in parameter expansion */ -#define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */ +#define EXP_QUOTED 0x100 /* expand word in double quotes */ /* * rmescape() flags */ @@ -6054,7 +6054,7 @@ argstr(char *p, int flags, struct strlist *var_str_list) }; const char *reject = spclchars; int quotes = flags & QUOTES_ESC; - int breakall = flags & EXP_WORD; + int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD; int inquotes; size_t length; int startloc; @@ -6072,8 +6072,6 @@ argstr(char *p, int flags, struct strlist *var_str_list) flags &= ~EXP_TILDE; tilde: q = p; - if ((unsigned char)*q == CTLESC && (flags & EXP_QWORD)) - q++; if (*q == '~') p = exptilde(p, q, flags); } @@ -6790,7 +6788,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list) if (varlen < 0) { argstr( p, - flags | (quoted ? EXP_TILDE|EXP_QWORD : EXP_TILDE|EXP_WORD), + flags | EXP_TILDE | EXP_WORD | (quoted ? EXP_QUOTED : 0), var_str_list ); goto end; diff --git a/shell/ash_test/ash-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.right b/shell/ash_test/ash-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.right new file mode 100644 index 000000000..4b9b4f038 --- /dev/null +++ b/shell/ash_test/ash-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.right @@ -0,0 +1 @@ +~root diff --git a/shell/ash_test/ash-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.tests b/shell/ash_test/ash-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.tests new file mode 100755 index 000000000..d8eb8fc1b --- /dev/null +++ b/shell/ash_test/ash-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.tests @@ -0,0 +1,2 @@ +unset a +echo "${a:-~root}" From 7e4ed267b645090fb576e1c876a88a9c73faabe9 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Mon, 18 May 2015 09:54:43 +0200 Subject: [PATCH 134/256] ash: remove superfluous code in arithmetic mode Based on commits 1a74845, cfc3d6a and ff13779 from git://git.kernel.org/pub/scm/utils/dash/dash.git by Herbert Xu function old new delta evalcommand 1197 1204 +7 localcmd 327 325 -2 readtoken1 3200 3180 -20 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/2 up/down: 7/-22) Total: -15 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- shell/ash.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index d87166c4f..ee7642a64 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -11282,9 +11282,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) goto quotemark; case CENDQUOTE: IF_ASH_BASH_COMPAT(bash_dollar_squote = 0;) - if (eofmark != NULL && arinest == 0 - && varnest == 0 - ) { + if (eofmark != NULL && varnest == 0) { USTPUTC(c, out); } else { if (dqvarnest == 0) { @@ -11320,7 +11318,6 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) if (pgetc() == ')') { if (--arinest == 0) { syntax = prevsyntax; - dblquote = (syntax == DQSYNTAX); c = CTLENDARI; } } else { @@ -11645,7 +11642,7 @@ parsesub: { ((unsigned char *)stackblock())[typeloc] = subtype | flags; if (subtype != VSNORMAL) { varnest++; - if (dblquote || arinest) { + if (dblquote) { dqvarnest++; } } From ad88bdee0c382b9f1cbbb2d76cc739afb2790a60 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Mon, 18 May 2015 09:56:16 +0200 Subject: [PATCH 135/256] ash: remove arithmetic expansion collapsing at parse time Collapsing arithmetic expansion is incorrect when the inner arithmetic expansion is a part of a parameter expansion. Test case: unset a echo $((3 + ${a:=$((4 + 5))})) echo $a Old result: 12 (4 + 5) New result: 12 9 Based on commit bb777a6 from git://git.kernel.org/pub/scm/utils/dash/dash.git by Herbert Xu function old new delta readtoken1 3180 3163 -17 Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- shell/ash.c | 18 ++++++------------ ...se-arithmetic-expansion-at-parse-time.right | 2 ++ ...se-arithmetic-expansion-at-parse-time.tests | 3 +++ 3 files changed, 11 insertions(+), 12 deletions(-) create mode 100644 shell/ash_test/ash-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.right create mode 100755 shell/ash_test/ash-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.tests diff --git a/shell/ash.c b/shell/ash.c index ee7642a64..33a477d80 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -11316,9 +11316,9 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) parenlevel--; } else { if (pgetc() == ')') { + c = CTLENDARI; if (--arinest == 0) { syntax = prevsyntax; - c = CTLENDARI; } } else { /* @@ -11809,18 +11809,12 @@ parsearith: { if (++arinest == 1) { prevsyntax = syntax; syntax = ARISYNTAX; - USTPUTC(CTLARI, out); - if (dblquote) - USTPUTC('"', out); - else - USTPUTC(' ', out); - } else { - /* - * we collapse embedded arithmetic expansion to - * parenthesis, which should be equivalent - */ - USTPUTC('(', out); } + USTPUTC(CTLARI, out); + if (dblquote) + USTPUTC('"', out); + else + USTPUTC(' ', out); goto parsearith_return; } #endif diff --git a/shell/ash_test/ash-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.right b/shell/ash_test/ash-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.right new file mode 100644 index 000000000..81a15855c --- /dev/null +++ b/shell/ash_test/ash-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.right @@ -0,0 +1,2 @@ +12 +9 diff --git a/shell/ash_test/ash-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.tests b/shell/ash_test/ash-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.tests new file mode 100755 index 000000000..e97a08a57 --- /dev/null +++ b/shell/ash_test/ash-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.tests @@ -0,0 +1,3 @@ +unset a +echo $((3 + ${a:=$((4 + 5))})) +echo $a From 549deab5abd59c1ab752754170f69aa2248e72c9 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Mon, 18 May 2015 09:57:51 +0200 Subject: [PATCH 136/256] ash: move parse-time quote flag detection to run-time Because the parser does not recursively parse parameter expansion with respect to quotes, we can't accurately determine quote status at parse time. This patch works around this by moving the quote detection to run-time where we do interpret it recursively. Test case: foo=\\ echo "<${foo#[\\]}>" Old result: <\> New result: <> Do not quote back slashes in parameter expansions outside quotes. Test case: a=/b/c/* b=\\ echo ${a%$b*} Old result: /b/c/* New result: /b/c/ Based on commits 880d952, 7cfd8be, 0d7d660 and a7c21a6 from git://git.kernel.org/pub/scm/utils/dash/dash.git by Herbert Xu function old new delta argstr 1164 1193 +29 memtodest 147 174 +27 subevalvar 1153 1177 +24 redirect 1279 1282 +3 dolatstr 5 7 +2 static.spclchars 10 9 -1 expandarg 962 960 -2 evalcase 273 271 -2 evalcommand 1204 1197 -7 rmescapes 236 227 -9 preglob 27 8 -19 evalvar 604 582 -22 cmdputs 389 334 -55 readtoken1 3163 3061 -102 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 5/9 up/down: 85/-219) Total: -134 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- shell/ash.c | 166 +++++++----------- ...-parameter-expansions-outside-quotes.right | 1 + ...-parameter-expansions-outside-quotes.tests | 3 + .../var-runtime-quote-detection.right | 1 + .../var-runtime-quote-detection.tests | 1 + 5 files changed, 73 insertions(+), 99 deletions(-) create mode 100644 shell/ash_test/ash-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.right create mode 100755 shell/ash_test/ash-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.tests create mode 100644 shell/ash_test/ash-vars/var-runtime-quote-detection.right create mode 100755 shell/ash_test/ash-vars/var-runtime-quote-detection.tests diff --git a/shell/ash.c b/shell/ash.c index 33a477d80..e7e70817f 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -598,8 +598,6 @@ out2str(const char *p) #define CTLVAR ((unsigned char)'\202') /* variable defn */ #define CTLENDVAR ((unsigned char)'\203') #define CTLBACKQ ((unsigned char)'\204') -#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */ -/* CTLBACKQ | CTLQUOTE == '\205' */ #define CTLARI ((unsigned char)'\206') /* arithmetic expression */ #define CTLENDARI ((unsigned char)'\207') #define CTLQUOTEMARK ((unsigned char)'\210') @@ -608,7 +606,6 @@ out2str(const char *p) /* variable substitution byte (follows CTLVAR) */ #define VSTYPE 0x0f /* type of variable substitution */ #define VSNUL 0x10 /* colon--treat the empty string as unset */ -#define VSQUOTE 0x80 /* inside double quotes--suppress splitting */ /* values of VSTYPE field */ #define VSNORMAL 0x1 /* normal variable: $var or ${var} */ @@ -628,8 +625,9 @@ out2str(const char *p) #endif static const char dolatstr[] ALIGN1 = { - CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' + CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0' }; +#define DOLATSTRLEN 6 #define NCMD 0 #define NPIPE 1 @@ -865,9 +863,7 @@ trace_puts_quoted(char *s) case '\\': c = '\\'; goto backslash; case CTLESC: c = 'e'; goto backslash; case CTLVAR: c = 'v'; goto backslash; - case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; case CTLBACKQ: c = 'q'; goto backslash; - case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; backslash: putc('\\', tracefile); putc(c, tracefile); @@ -1030,7 +1026,6 @@ sharg(union node *arg, FILE *fp) putc('}', fp); break; case CTLBACKQ: - case CTLBACKQ|CTLQUOTE: putc('$', fp); putc('(', fp); shtree(bqlist->n, -1, NULL, fp); @@ -4413,11 +4408,7 @@ cmdputs(const char *s) str = "${#"; else str = "${"; - if (!(subtype & VSQUOTE) == !(quoted & 1)) - goto dostr; - quoted ^= 1; - c = '"'; - break; + goto dostr; case CTLENDVAR: str = "\"}" + !(quoted & 1); quoted >>= 1; @@ -4426,9 +4417,6 @@ cmdputs(const char *s) case CTLBACKQ: str = "$(...)"; goto dostr; - case CTLBACKQ+CTLQUOTE: - str = "\"$(...)\""; - goto dostr; #if ENABLE_SH_MATH_SUPPORT case CTLARI: str = "$(("; @@ -5526,7 +5514,7 @@ ash_arith(const char *s) #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */ #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */ #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */ -#define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */ +#define EXP_QPAT 0x20 /* pattern in quoted parameter expansion */ #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */ #define EXP_WORD 0x80 /* expand word in parameter expansion */ #define EXP_QUOTED 0x100 /* expand word in double quotes */ @@ -5535,12 +5523,11 @@ ash_arith(const char *s) */ #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */ #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */ -#define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */ #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */ #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */ /* Add CTLESC when necessary. */ -#define QUOTES_ESC (EXP_FULL | EXP_CASE | EXP_REDIR) +#define QUOTES_ESC (EXP_FULL | EXP_CASE | EXP_QPAT | EXP_REDIR) /* Do not skip NUL characters. */ #define QUOTES_KEEPNUL EXP_TILDE @@ -5641,13 +5628,11 @@ rmescapes(char *str, int flag) } } - inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED; + inquotes = 0; globbing = flag & RMESCAPE_GLOB; protect_against_glob = globbing; while (*p) { if ((unsigned char)*p == CTLQUOTEMARK) { -// TODO: if no RMESCAPE_QUOTED in flags, inquotes never becomes 0 -// (alternates between RMESCAPE_QUOTED and ~RMESCAPE_QUOTED). Is it ok? // Note: both inquotes and protect_against_glob only affect whether // CTLESC, gets converted to or to \ inquotes = ~inquotes; @@ -5655,17 +5640,16 @@ rmescapes(char *str, int flag) protect_against_glob = globbing; continue; } - if (*p == '\\') { + if ((unsigned char)*p == CTLESC) { + p++; + if (protect_against_glob) { + *q++ = '\\'; + } + } else if (*p == '\\' && !inquotes) { /* naked back slash */ protect_against_glob = 0; goto copy; } - if ((unsigned char)*p == CTLESC) { - p++; - if (protect_against_glob && inquotes && *p != '/') { - *q++ = '\\'; - } - } protect_against_glob = globbing; copy: *q++ = *p++; @@ -5685,13 +5669,9 @@ rmescapes(char *str, int flag) * Returns an stalloced string. */ static char * -preglob(const char *pattern, int quoted, int flag) +preglob(const char *pattern, int flag) { - flag |= RMESCAPE_GLOB; - if (quoted) { - flag |= RMESCAPE_QUOTED; - } - return rmescapes((char *)pattern, flag); + return rmescapes((char *)pattern, flag | RMESCAPE_GLOB); } /* @@ -5712,7 +5692,9 @@ memtodest(const char *p, size_t len, int syntax, int quotes) if (c) { int n = SIT(c, syntax); if ((quotes & QUOTES_ESC) && - (n == CCTL || n == CBACK)) + ((n == CCTL) || + (((quotes & EXP_FULL) || syntax != BASESYNTAX) && + n == CBACK))) USTPUTC(CTLESC, q); } else if (!(quotes & QUOTES_KEEPNUL)) continue; @@ -5905,7 +5887,7 @@ evalbackcmd(union node *n, struct backcmd *result) * Expand stuff in backwards quotes. */ static void -expbackq(union node *cmd, int quoted, int quotes) +expbackq(union node *cmd, int flag) { struct backcmd in; int i; @@ -5913,7 +5895,7 @@ expbackq(union node *cmd, int quoted, int quotes) char *p; char *dest; int startloc; - int syntax = quoted ? DQSYNTAX : BASESYNTAX; + int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX; struct stackmark smark; INT_OFF; @@ -5929,7 +5911,7 @@ expbackq(union node *cmd, int quoted, int quotes) if (i == 0) goto read; for (;;) { - memtodest(p, i, syntax, quotes); + memtodest(p, i, syntax, flag & QUOTES_ESC); read: if (in.fd < 0) break; @@ -5953,7 +5935,7 @@ expbackq(union node *cmd, int quoted, int quotes) STUNPUTC(dest); expdest = dest; - if (quoted == 0) + if (!(flag & EXP_QUOTED)) recordregion(startloc, dest - (char *)stackblock(), 0); TRACE(("evalbackq: size:%d:'%.*s'\n", (int)((dest - (char *)stackblock()) - startloc), @@ -5967,11 +5949,10 @@ expbackq(union node *cmd, int quoted, int quotes) * evaluate, place result in (backed up) result, adjust string position. */ static void -expari(int quotes) +expari(int flag) { char *p, *start; int begoff; - int flag; int len; /* ifsfree(); */ @@ -6009,16 +5990,14 @@ expari(int quotes) removerecordregions(begoff); - flag = p[1]; - expdest = p; - if (quotes) - rmescapes(p + 2, 0); + if (flag & QUOTES_ESC) + rmescapes(p + 1, 0); - len = cvtnum(ash_arith(p + 2)); + len = cvtnum(ash_arith(p + 1)); - if (flag != '"') + if (!(flag & EXP_QUOTED)) recordregion(begoff, begoff + len, 0); } #endif @@ -6046,14 +6025,12 @@ argstr(char *p, int flags, struct strlist *var_str_list) CTLESC, CTLVAR, CTLBACKQ, - CTLBACKQ | CTLQUOTE, #if ENABLE_SH_MATH_SUPPORT CTLENDARI, #endif '\0' }; const char *reject = spclchars; - int quotes = flags & QUOTES_ESC; int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD; int inquotes; size_t length; @@ -6128,19 +6105,14 @@ argstr(char *p, int flags, struct strlist *var_str_list) case CTLENDVAR: /* ??? */ goto breakloop; case CTLQUOTEMARK: + inquotes ^= EXP_QUOTED; /* "$@" syntax adherence hack */ - if (!inquotes - && memcmp(p, dolatstr, 4) == 0 - && ( p[4] == (char)CTLQUOTEMARK - || (p[4] == (char)CTLENDVAR && p[5] == (char)CTLQUOTEMARK) - ) - ) { - p = evalvar(p + 1, flags, /* var_str_list: */ NULL) + 1; + if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) { + p = evalvar(p + 1, flags | inquotes, /* var_str_list: */ NULL) + 1; goto start; } - inquotes = !inquotes; addquote: - if (quotes) { + if (flags & QUOTES_ESC) { p--; length++; startloc++; @@ -6149,22 +6121,30 @@ argstr(char *p, int flags, struct strlist *var_str_list) case CTLESC: startloc++; length++; + + /* + * Quoted parameter expansion pattern: remove quote + * unless inside inner quotes or we have a literal + * backslash. + */ + if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) == + EXP_QPAT && *p != '\\') + break; + goto addquote; case CTLVAR: TRACE(("argstr: evalvar('%s')\n", p)); - p = evalvar(p, flags, var_str_list); + p = evalvar(p, flags | inquotes, var_str_list); TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock())); goto start; case CTLBACKQ: - c = '\0'; - case CTLBACKQ|CTLQUOTE: - expbackq(argbackq->n, c, quotes); + expbackq(argbackq->n, flags | inquotes); argbackq = argbackq->next; goto start; #if ENABLE_SH_MATH_SUPPORT case CTLENDARI: p--; - expari(quotes); + expari(flags | inquotes); goto start; #endif } @@ -6296,13 +6276,13 @@ varunset(const char *end, const char *var, const char *umsg, int varflags) #if ENABLE_ASH_BASH_COMPAT static char * -parse_sub_pattern(char *arg, int varflags) +parse_sub_pattern(char *arg, int quoted) { char *idx, *repl = NULL; unsigned char c; //char *org_arg = arg; - //bb_error_msg("arg:'%s' varflags:%x", arg, varflags); + //bb_error_msg("arg:'%s' quoted:%x", arg, quoted); idx = arg; while (1) { c = *arg; @@ -6318,7 +6298,7 @@ parse_sub_pattern(char *arg, int varflags) *idx++ = c; arg++; /* - * Example: v='ab\c'; echo ${v/\\b/_\\_\z_} + * Example: v='a\bc'; echo ${v/\\b/_\\_\z_} * The result is a_\_z_c (not a\_\_z_c)! * * Enable debug prints in this function and you'll see: @@ -6328,7 +6308,7 @@ parse_sub_pattern(char *arg, int varflags) * IOW: search pattern and replace string treat backslashes * differently! That is the reason why we check repl below: */ - if (c == '\\' && *arg == '\\' && repl && !(varflags & VSQUOTE)) + if (c == '\\' && *arg == '\\' && repl && !quoted) arg++; /* skip both '\', not just first one */ } *idx = c; /* NUL */ @@ -6340,9 +6320,10 @@ parse_sub_pattern(char *arg, int varflags) static const char * subevalvar(char *p, char *varname, int strloc, int subtype, - int startloc, int varflags, int quotes, struct strlist *var_str_list) + int startloc, int varflags, int flag, struct strlist *var_str_list) { struct nodelist *saveargbackq = argbackq; + int quotes = flag & QUOTES_ESC; char *startp; char *loc; char *rmesc, *rmescend; @@ -6360,7 +6341,8 @@ subevalvar(char *p, char *varname, int strloc, int subtype, herefd = -1; argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ? - EXP_CASE : 0), var_str_list); + (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0), + var_str_list); STPUTC('\0', expdest); herefd = saveherefd; argbackq = saveargbackq; @@ -6471,7 +6453,7 @@ subevalvar(char *p, char *varname, int strloc, int subtype, } rmescend--; str = (char *)stackblock() + strloc; - preglob(str, varflags & VSQUOTE, 0); + preglob(str, 0); #if ENABLE_ASH_BASH_COMPAT workloc = expdest - (char *)stackblock(); @@ -6479,7 +6461,7 @@ subevalvar(char *p, char *varname, int strloc, int subtype, char *idx, *end; if (!repl) { - repl = parse_sub_pattern(str, varflags); + repl = parse_sub_pattern(str, flag & EXP_QUOTED); //bb_error_msg("repl:'%s'", repl); if (!repl) repl = nullstr; @@ -6618,7 +6600,7 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list) int i; ssize_t len = 0; int sep; - int quoted = varflags & VSQUOTE; + int quoted = flags & EXP_QUOTED; int subtype = varflags & VSTYPE; int discard = subtype == VSPLUS || subtype == VSLENGTH; int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL; @@ -6758,7 +6740,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list) { char varflags; char subtype; - char quoted; + int quoted; char easy; char *var; int patloc; @@ -6767,7 +6749,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list) varflags = (unsigned char) *p++; subtype = varflags & VSTYPE; - quoted = varflags & VSQUOTE; + quoted = flags & EXP_QUOTED; var = p; easy = (!quoted || (*var == '@' && shellparam.nparam)); startloc = expdest - (char *)stackblock(); @@ -6788,7 +6770,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list) if (varlen < 0) { argstr( p, - flags | EXP_TILDE | EXP_WORD | (quoted ? EXP_QUOTED : 0), + flags | EXP_TILDE | EXP_WORD, var_str_list ); goto end; @@ -6802,7 +6784,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list) if (varlen < 0) { if (subevalvar(p, var, /* strloc: */ 0, subtype, startloc, varflags, - /* quotes: */ 0, + /* quotes: */ flags & ~QUOTES_ESC, var_str_list) ) { varflags &= ~VSNUL; @@ -6859,10 +6841,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list) STPUTC('\0', expdest); patloc = expdest - (char *)stackblock(); if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype, - startloc, varflags, - /* quotes: */ flags & QUOTES_ESC, - var_str_list) - ) { + startloc, varflags, flags, var_str_list)) { int amount = expdest - ( (char *)stackblock() + patloc - 1 ); @@ -6881,7 +6860,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list) unsigned char c = *p++; if (c == CTLESC) p++; - else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) { + else if (c == CTLBACKQ) { if (varlen >= 0) argbackq = argbackq->next; } else if (c == CTLVAR) { @@ -7217,7 +7196,7 @@ expandmeta(struct strlist *str /*, int flag*/) savelastp = exparg.lastp; INT_OFF; - p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP); + p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP); { int i = strlen(str->text); expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */ @@ -7307,7 +7286,7 @@ static void expandhere(union node *arg, int fd) { herefd = fd; - expandarg(arg, (struct arglist *)NULL, 0); + expandarg(arg, (struct arglist *)NULL, EXP_QUOTED); full_write(fd, stackblock(), expdest - (char *)stackblock()); } @@ -7317,7 +7296,7 @@ expandhere(union node *arg, int fd) static int patmatch(char *pattern, const char *string) { - return pmatch(preglob(pattern, 0, 0), string); + return pmatch(preglob(pattern, 0), string); } /* @@ -8570,7 +8549,7 @@ evalfor(union node *n, int flags) arglist.list = NULL; arglist.lastp = &arglist.list; for (argp = n->nfor.args; argp; argp = argp->narg.next) { - expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD); + expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); /* XXX */ if (evalskip) goto out; @@ -11260,11 +11239,9 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) && c != '$' && (c != '"' || eofmark != NULL) ) { - USTPUTC(CTLESC, out); USTPUTC('\\', out); } - if (SIT(c, SQSYNTAX) == CCTL) - USTPUTC(CTLESC, out); + USTPUTC(CTLESC, out); USTPUTC(c, out); quotef = 1; } @@ -11637,8 +11614,6 @@ parsesub: { do_pungetc: pungetc(); } - if (dblquote || arinest) - flags |= VSQUOTE; ((unsigned char *)stackblock())[typeloc] = subtype | flags; if (subtype != VSNORMAL) { varnest++; @@ -11792,10 +11767,7 @@ parsebackq: { } parsebackquote = savepbq; exception_handler = savehandler; - if (arinest || dblquote) - USTPUTC(CTLBACKQ | CTLQUOTE, out); - else - USTPUTC(CTLBACKQ, out); + USTPUTC(CTLBACKQ, out); if (oldstyle) goto parsebackq_oldreturn; goto parsebackq_newreturn; @@ -11811,10 +11783,6 @@ parsearith: { syntax = ARISYNTAX; } USTPUTC(CTLARI, out); - if (dblquote) - USTPUTC('"', out); - else - USTPUTC(' ', out); goto parsearith_return; } #endif @@ -12129,7 +12097,7 @@ expandstr(const char *ps) n.narg.text = wordtext; n.narg.backquote = backquotelist; - expandarg(&n, NULL, 0); + expandarg(&n, NULL, EXP_QUOTED); return stackblock(); } #endif diff --git a/shell/ash_test/ash-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.right b/shell/ash_test/ash-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.right new file mode 100644 index 000000000..030ebdeb6 --- /dev/null +++ b/shell/ash_test/ash-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.right @@ -0,0 +1 @@ +/b/c/ diff --git a/shell/ash_test/ash-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.tests b/shell/ash_test/ash-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.tests new file mode 100755 index 000000000..fb9371467 --- /dev/null +++ b/shell/ash_test/ash-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.tests @@ -0,0 +1,3 @@ +a=/b/c/* +b=\\ +echo ${a%$b*} diff --git a/shell/ash_test/ash-vars/var-runtime-quote-detection.right b/shell/ash_test/ash-vars/var-runtime-quote-detection.right new file mode 100644 index 000000000..b554d9e46 --- /dev/null +++ b/shell/ash_test/ash-vars/var-runtime-quote-detection.right @@ -0,0 +1 @@ +<> diff --git a/shell/ash_test/ash-vars/var-runtime-quote-detection.tests b/shell/ash_test/ash-vars/var-runtime-quote-detection.tests new file mode 100755 index 000000000..e570631fd --- /dev/null +++ b/shell/ash_test/ash-vars/var-runtime-quote-detection.tests @@ -0,0 +1 @@ +foo=\\ echo "<${foo#[\\]}>" From 417622cc2e1ce0f3bc797b3997f5728433c8ccee Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Mon, 18 May 2015 09:59:14 +0200 Subject: [PATCH 137/256] ash: fix breakage of ${v/pat/str} The commit ash: move parse-time quote flag detection to run-time breaks pattern substitution in parameter expansion. Fix this and revise the code so that the different handling of the pattern and the replacement string takes place in rmescapes rather than the separate function parse_sub_pattern. function old new delta rmescapes 227 273 +46 static.qchars 3 4 +1 subevalvar 1177 1157 -20 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 47/-20) Total: 27 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- shell/ash.c | 79 +++++++++++++++++++---------------------------------- 1 file changed, 28 insertions(+), 51 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index e7e70817f..282f761fc 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -5525,6 +5525,7 @@ ash_arith(const char *s) #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */ #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */ #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */ +#define RMESCAPE_SLASH 0x20 /* Stop globbing after slash */ /* Add CTLESC when necessary. */ #define QUOTES_ESC (EXP_FULL | EXP_CASE | EXP_QPAT | EXP_REDIR) @@ -5594,14 +5595,16 @@ esclen(const char *start, const char *p) static char * rmescapes(char *str, int flag) { - static const char qchars[] ALIGN1 = { CTLESC, CTLQUOTEMARK, '\0' }; + static const char qchars[] ALIGN1 = { + IF_ASH_BASH_COMPAT('/',) CTLESC, CTLQUOTEMARK, '\0' }; char *p, *q, *r; unsigned inquotes; unsigned protect_against_glob; unsigned globbing; + IF_ASH_BASH_COMPAT(unsigned slash = flag & RMESCAPE_SLASH;) - p = strpbrk(str, qchars); + p = strpbrk(str, qchars IF_ASH_BASH_COMPAT(+ !slash)); if (!p) return str; @@ -5650,6 +5653,13 @@ rmescapes(char *str, int flag) protect_against_glob = 0; goto copy; } +#if ENABLE_ASH_BASH_COMPAT + else if (*p == '/' && slash) { + /* stop handling globbing and mark location of slash */ + globbing = slash = 0; + *p = CTLESC; + } +#endif protect_against_glob = globbing; copy: *q++ = *p++; @@ -6274,50 +6284,6 @@ varunset(const char *end, const char *var, const char *umsg, int varflags) ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail); } -#if ENABLE_ASH_BASH_COMPAT -static char * -parse_sub_pattern(char *arg, int quoted) -{ - char *idx, *repl = NULL; - unsigned char c; - - //char *org_arg = arg; - //bb_error_msg("arg:'%s' quoted:%x", arg, quoted); - idx = arg; - while (1) { - c = *arg; - if (!c) - break; - if (c == '/') { - /* Only the first '/' seen is our separator */ - if (!repl) { - repl = idx + 1; - c = '\0'; - } - } - *idx++ = c; - arg++; - /* - * Example: v='a\bc'; echo ${v/\\b/_\\_\z_} - * The result is a_\_z_c (not a\_\_z_c)! - * - * Enable debug prints in this function and you'll see: - * ash: arg:'\\b/_\\_z_' varflags:d - * ash: pattern:'\\b' repl:'_\_z_' - * That is, \\b is interpreted as \\b, but \\_ as \_! - * IOW: search pattern and replace string treat backslashes - * differently! That is the reason why we check repl below: - */ - if (c == '\\' && *arg == '\\' && repl && !quoted) - arg++; /* skip both '\', not just first one */ - } - *idx = c; /* NUL */ - //bb_error_msg("pattern:'%s' repl:'%s'", org_arg, repl); - - return repl; -} -#endif /* ENABLE_ASH_BASH_COMPAT */ - static const char * subevalvar(char *p, char *varname, int strloc, int subtype, int startloc, int varflags, int flag, struct strlist *var_str_list) @@ -6328,7 +6294,7 @@ subevalvar(char *p, char *varname, int strloc, int subtype, char *loc; char *rmesc, *rmescend; char *str; - IF_ASH_BASH_COMPAT(const char *repl = NULL;) + IF_ASH_BASH_COMPAT(char *repl = NULL;) IF_ASH_BASH_COMPAT(int pos, len, orig_len;) int saveherefd = herefd; int amount, resetloc; @@ -6453,7 +6419,17 @@ subevalvar(char *p, char *varname, int strloc, int subtype, } rmescend--; str = (char *)stackblock() + strloc; - preglob(str, 0); + /* + * Example: v='a\bc'; echo ${v/\\b/_\\_\z_} + * The result is a_\_z_c (not a\_\_z_c)! + * + * The search pattern and replace string treat backslashes differently! + * RMESCAPE_SLASH causes preglob to work differently on the pattern + * and string. It's only used on the first call. + */ + preglob(str, IF_ASH_BASH_COMPAT( + (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ? + RMESCAPE_SLASH :) 0); #if ENABLE_ASH_BASH_COMPAT workloc = expdest - (char *)stackblock(); @@ -6461,11 +6437,12 @@ subevalvar(char *p, char *varname, int strloc, int subtype, char *idx, *end; if (!repl) { - repl = parse_sub_pattern(str, flag & EXP_QUOTED); - //bb_error_msg("repl:'%s'", repl); - if (!repl) + if ((repl=strchr(str, CTLESC))) + *repl++ = '\0'; + else repl = nullstr; } + //bb_error_msg("str:'%s' repl:'%s'", str, repl); /* If there's no pattern to match, return the expansion unmolested */ if (str[0] == '\0') From 523006798c45307830eaae9d29ca9fdc1a1b50af Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Mon, 18 May 2015 10:13:21 +0200 Subject: [PATCH 138/256] testsuite: add some tests for ash Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- .../var-pattern-replacement-in-parameter-expansion-1.right | 1 + .../var-pattern-replacement-in-parameter-expansion-1.tests | 2 ++ .../var-pattern-replacement-in-parameter-expansion-2.right | 1 + .../var-pattern-replacement-in-parameter-expansion-2.tests | 2 ++ .../var-pattern-replacement-in-parameter-expansion-3.right | 1 + .../var-pattern-replacement-in-parameter-expansion-3.tests | 2 ++ .../var-pattern-replacement-in-parameter-expansion-4.right | 1 + .../var-pattern-replacement-in-parameter-expansion-4.tests | 2 ++ .../var-pattern-replacement-in-parameter-expansion-5.right | 1 + .../var-pattern-replacement-in-parameter-expansion-5.tests | 2 ++ 10 files changed, 15 insertions(+) create mode 100644 shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-1.right create mode 100755 shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-1.tests create mode 100644 shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-2.right create mode 100755 shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-2.tests create mode 100644 shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-3.right create mode 100755 shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-3.tests create mode 100644 shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-4.right create mode 100755 shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-4.tests create mode 100644 shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-5.right create mode 100755 shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-5.tests diff --git a/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-1.right b/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-1.right new file mode 100644 index 000000000..2da327222 --- /dev/null +++ b/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-1.right @@ -0,0 +1 @@ +a_\_z_c diff --git a/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-1.tests b/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-1.tests new file mode 100755 index 000000000..e4529c631 --- /dev/null +++ b/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-1.tests @@ -0,0 +1,2 @@ +v="a\bc" +echo ${v/\\b/_\\_\z_} diff --git a/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-2.right b/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-2.right new file mode 100644 index 000000000..7447c0a04 --- /dev/null +++ b/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-2.right @@ -0,0 +1 @@ +ax/yc diff --git a/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-2.tests b/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-2.tests new file mode 100755 index 000000000..2db1db897 --- /dev/null +++ b/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-2.tests @@ -0,0 +1,2 @@ +v="abc" +echo ${v/b/x/y} diff --git a/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-3.right b/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-3.right new file mode 100644 index 000000000..5ea5ff892 --- /dev/null +++ b/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-3.right @@ -0,0 +1 @@ +axcabc diff --git a/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-3.tests b/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-3.tests new file mode 100755 index 000000000..0935e4509 --- /dev/null +++ b/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-3.tests @@ -0,0 +1,2 @@ +v="abcabc" +echo ${v/b/x} diff --git a/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-4.right b/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-4.right new file mode 100644 index 000000000..46dd750c1 --- /dev/null +++ b/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-4.right @@ -0,0 +1 @@ +axcaxc diff --git a/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-4.tests b/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-4.tests new file mode 100755 index 000000000..d8de84347 --- /dev/null +++ b/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-4.tests @@ -0,0 +1,2 @@ +v="abcabc" +echo ${v//b/x} diff --git a/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-5.right b/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-5.right new file mode 100644 index 000000000..699b27b0c --- /dev/null +++ b/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-5.right @@ -0,0 +1 @@ +axc diff --git a/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-5.tests b/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-5.tests new file mode 100755 index 000000000..552388877 --- /dev/null +++ b/shell/ash_test/ash-vars/var-pattern-replacement-in-parameter-expansion-5.tests @@ -0,0 +1,2 @@ +v="ab/c" +echo ${v/b\//x} From 9a595bb36ded308e6d4336aef2c1cd3ac738a398 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 18 May 2015 10:23:16 +0200 Subject: [PATCH 139/256] hush: add recent ash tests to hush testsuite too (they all pass for hush) Signed-off-by: Denys Vlasenko --- ...ar-do-not-collapse-arithmetic-expansion-at-parse-time.right | 2 ++ ...ar-do-not-collapse-arithmetic-expansion-at-parse-time.tests | 3 +++ ...-do-not-expand-tilde-in-parameter-expansion-in-quotes.right | 1 + ...-do-not-expand-tilde-in-parameter-expansion-in-quotes.tests | 2 ++ ...te-backslashes-in-parameter-expansions-outside-quotes.right | 1 + ...te-backslashes-in-parameter-expansions-outside-quotes.tests | 3 +++ .../var-pattern-replacement-in-parameter-expansion-1.right | 1 + .../var-pattern-replacement-in-parameter-expansion-1.tests | 2 ++ .../var-pattern-replacement-in-parameter-expansion-2.right | 1 + .../var-pattern-replacement-in-parameter-expansion-2.tests | 2 ++ .../var-pattern-replacement-in-parameter-expansion-3.right | 1 + .../var-pattern-replacement-in-parameter-expansion-3.tests | 2 ++ .../var-pattern-replacement-in-parameter-expansion-4.right | 1 + .../var-pattern-replacement-in-parameter-expansion-4.tests | 2 ++ .../var-pattern-replacement-in-parameter-expansion-5.right | 1 + .../var-pattern-replacement-in-parameter-expansion-5.tests | 2 ++ shell/hush_test/hush-vars/var-runtime-quote-detection.right | 1 + shell/hush_test/hush-vars/var-runtime-quote-detection.tests | 1 + 18 files changed, 29 insertions(+) create mode 100644 shell/hush_test/hush-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.right create mode 100755 shell/hush_test/hush-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.tests create mode 100644 shell/hush_test/hush-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.right create mode 100755 shell/hush_test/hush-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.tests create mode 100644 shell/hush_test/hush-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.right create mode 100755 shell/hush_test/hush-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.tests create mode 100644 shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-1.right create mode 100755 shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-1.tests create mode 100644 shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-2.right create mode 100755 shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-2.tests create mode 100644 shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-3.right create mode 100755 shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-3.tests create mode 100644 shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-4.right create mode 100755 shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-4.tests create mode 100644 shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-5.right create mode 100755 shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-5.tests create mode 100644 shell/hush_test/hush-vars/var-runtime-quote-detection.right create mode 100755 shell/hush_test/hush-vars/var-runtime-quote-detection.tests diff --git a/shell/hush_test/hush-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.right b/shell/hush_test/hush-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.right new file mode 100644 index 000000000..81a15855c --- /dev/null +++ b/shell/hush_test/hush-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.right @@ -0,0 +1,2 @@ +12 +9 diff --git a/shell/hush_test/hush-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.tests b/shell/hush_test/hush-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.tests new file mode 100755 index 000000000..e97a08a57 --- /dev/null +++ b/shell/hush_test/hush-vars/var-do-not-collapse-arithmetic-expansion-at-parse-time.tests @@ -0,0 +1,3 @@ +unset a +echo $((3 + ${a:=$((4 + 5))})) +echo $a diff --git a/shell/hush_test/hush-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.right b/shell/hush_test/hush-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.right new file mode 100644 index 000000000..4b9b4f038 --- /dev/null +++ b/shell/hush_test/hush-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.right @@ -0,0 +1 @@ +~root diff --git a/shell/hush_test/hush-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.tests b/shell/hush_test/hush-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.tests new file mode 100755 index 000000000..d8eb8fc1b --- /dev/null +++ b/shell/hush_test/hush-vars/var-do-not-expand-tilde-in-parameter-expansion-in-quotes.tests @@ -0,0 +1,2 @@ +unset a +echo "${a:-~root}" diff --git a/shell/hush_test/hush-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.right b/shell/hush_test/hush-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.right new file mode 100644 index 000000000..030ebdeb6 --- /dev/null +++ b/shell/hush_test/hush-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.right @@ -0,0 +1 @@ +/b/c/ diff --git a/shell/hush_test/hush-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.tests b/shell/hush_test/hush-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.tests new file mode 100755 index 000000000..fb9371467 --- /dev/null +++ b/shell/hush_test/hush-vars/var-do-not-quote-backslashes-in-parameter-expansions-outside-quotes.tests @@ -0,0 +1,3 @@ +a=/b/c/* +b=\\ +echo ${a%$b*} diff --git a/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-1.right b/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-1.right new file mode 100644 index 000000000..2da327222 --- /dev/null +++ b/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-1.right @@ -0,0 +1 @@ +a_\_z_c diff --git a/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-1.tests b/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-1.tests new file mode 100755 index 000000000..e4529c631 --- /dev/null +++ b/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-1.tests @@ -0,0 +1,2 @@ +v="a\bc" +echo ${v/\\b/_\\_\z_} diff --git a/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-2.right b/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-2.right new file mode 100644 index 000000000..7447c0a04 --- /dev/null +++ b/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-2.right @@ -0,0 +1 @@ +ax/yc diff --git a/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-2.tests b/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-2.tests new file mode 100755 index 000000000..2db1db897 --- /dev/null +++ b/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-2.tests @@ -0,0 +1,2 @@ +v="abc" +echo ${v/b/x/y} diff --git a/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-3.right b/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-3.right new file mode 100644 index 000000000..5ea5ff892 --- /dev/null +++ b/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-3.right @@ -0,0 +1 @@ +axcabc diff --git a/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-3.tests b/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-3.tests new file mode 100755 index 000000000..0935e4509 --- /dev/null +++ b/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-3.tests @@ -0,0 +1,2 @@ +v="abcabc" +echo ${v/b/x} diff --git a/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-4.right b/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-4.right new file mode 100644 index 000000000..46dd750c1 --- /dev/null +++ b/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-4.right @@ -0,0 +1 @@ +axcaxc diff --git a/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-4.tests b/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-4.tests new file mode 100755 index 000000000..d8de84347 --- /dev/null +++ b/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-4.tests @@ -0,0 +1,2 @@ +v="abcabc" +echo ${v//b/x} diff --git a/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-5.right b/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-5.right new file mode 100644 index 000000000..699b27b0c --- /dev/null +++ b/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-5.right @@ -0,0 +1 @@ +axc diff --git a/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-5.tests b/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-5.tests new file mode 100755 index 000000000..552388877 --- /dev/null +++ b/shell/hush_test/hush-vars/var-pattern-replacement-in-parameter-expansion-5.tests @@ -0,0 +1,2 @@ +v="ab/c" +echo ${v/b\//x} diff --git a/shell/hush_test/hush-vars/var-runtime-quote-detection.right b/shell/hush_test/hush-vars/var-runtime-quote-detection.right new file mode 100644 index 000000000..b554d9e46 --- /dev/null +++ b/shell/hush_test/hush-vars/var-runtime-quote-detection.right @@ -0,0 +1 @@ +<> diff --git a/shell/hush_test/hush-vars/var-runtime-quote-detection.tests b/shell/hush_test/hush-vars/var-runtime-quote-detection.tests new file mode 100755 index 000000000..e570631fd --- /dev/null +++ b/shell/hush_test/hush-vars/var-runtime-quote-detection.tests @@ -0,0 +1 @@ +foo=\\ echo "<${foo#[\\]}>" From b878121e76730f7f7e458180363371dbe10fd253 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 24 May 2015 18:01:53 +0200 Subject: [PATCH 140/256] tc: fix print_rate Signed-off-by: Denys Vlasenko --- networking/tc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/networking/tc.c b/networking/tc.c index 533f7c042..76e2e8359 100644 --- a/networking/tc.c +++ b/networking/tc.c @@ -151,17 +151,17 @@ static void print_rate(char *buf, int len, uint32_t rate) double tmp = (double)rate*8; if (use_iec) { - if (tmp >= 1000.0*1024.0*1024.0) - snprintf(buf, len, "%.0fMibit", tmp/1024.0*1024.0); - else if (tmp >= 1000.0*1024) + if (tmp >= 1000*1024*1024) + snprintf(buf, len, "%.0fMibit", tmp/(1024*1024)); + else if (tmp >= 1000*1024) snprintf(buf, len, "%.0fKibit", tmp/1024); else snprintf(buf, len, "%.0fbit", tmp); } else { - if (tmp >= 1000.0*1000000.0) - snprintf(buf, len, "%.0fMbit", tmp/1000000.0); - else if (tmp >= 1000.0 * 1000.0) - snprintf(buf, len, "%.0fKbit", tmp/1000.0); + if (tmp >= 1000*1000000) + snprintf(buf, len, "%.0fMbit", tmp/1000000); + else if (tmp >= 1000*1000) + snprintf(buf, len, "%.0fKbit", tmp/1000); else snprintf(buf, len, "%.0fbit", tmp); } From c4603fb09aa2ec06bc8c0ad51b69fe7995a8ea17 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 25 May 2015 13:31:25 +0200 Subject: [PATCH 141/256] dc: fix "dc p" prinitng bogus data function old new delta check_under - 20 +20 print_no_pop 27 32 +5 pop 33 24 -9 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/1 up/down: 25/-9) Total: 16 bytes Signed-off-by: Denys Vlasenko --- miscutils/dc.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/miscutils/dc.c b/miscutils/dc.c index f94d6fa6b..9c74172ba 100644 --- a/miscutils/dc.c +++ b/miscutils/dc.c @@ -56,6 +56,12 @@ enum { STACK_SIZE = (COMMON_BUFSIZE - offsetof(struct globals, stack)) / sizeof( } while (0) +static void check_under(void) +{ + if (pointer == 0) + bb_error_msg_and_die("stack underflow"); +} + static void push(double a) { if (pointer >= STACK_SIZE) @@ -65,8 +71,7 @@ static void push(double a) static double pop(void) { - if (pointer == 0) - bb_error_msg_and_die("stack underflow"); + check_under(); return stack[--pointer]; } @@ -187,6 +192,7 @@ static void print_stack_no_pop(void) static void print_no_pop(void) { + check_under(); print_base(stack[pointer-1]); } From 97c6491b4edf4bc9db293533ae0c3a81c4ef07f7 Mon Sep 17 00:00:00 2001 From: Maninder Singh Date: Mon, 25 May 2015 13:46:36 +0200 Subject: [PATCH 142/256] typo fixes Signed-off-by: Maninder Singh Signed-off-by: Denys Vlasenko --- Makefile | 2 +- coreutils/Config.src | 2 +- coreutils/stat.c | 2 +- coreutils/uudecode.c | 2 +- docs/cgi/env.html | 2 +- e2fsprogs/old_e2fsprogs/blkid/dev.c | 2 +- e2fsprogs/old_e2fsprogs/blkid/tag.c | 2 +- e2fsprogs/old_e2fsprogs/e2fsck.c | 4 ++-- editors/diff.c | 2 +- editors/vi.c | 14 +++++++------- findutils/xargs.c | 2 +- miscutils/less.c | 2 +- networking/netstat.c | 2 +- scripts/basic/docproc.c | 2 +- selinux/Config.src | 2 +- shell/hush.c | 2 +- util-linux/mkfs_reiser.c | 2 +- 17 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Makefile b/Makefile index e0888578f..65b2642f0 100644 --- a/Makefile +++ b/Makefile @@ -552,7 +552,7 @@ export INSTALL_PATH ?= /boot # # INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory # relocations required by build roots. This is not defined in the -# makefile but the arguement can be passed to make if needed. +# makefile but the argument can be passed to make if needed. # MODLIB = $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE) diff --git a/coreutils/Config.src b/coreutils/Config.src index 1bbb91ee9..1ec3a0a99 100644 --- a/coreutils/Config.src +++ b/coreutils/Config.src @@ -11,7 +11,7 @@ config CAL bool "cal" default y help - cal is used to display a monthly calender. + cal is used to display a monthly calendar. config CATV bool "catv" diff --git a/coreutils/stat.c b/coreutils/stat.c index 769fac078..f7fd227bb 100644 --- a/coreutils/stat.c +++ b/coreutils/stat.c @@ -374,7 +374,7 @@ static void print_it(const char *masterformat, { /* Create a working copy of the format string */ char *format = xstrdup(masterformat); - /* Add 2 to accomodate our conversion of the stat '%s' format string + /* Add 2 to accommodate our conversion of the stat '%s' format string * to the printf '%llu' one. */ char *dest = xmalloc(strlen(format) + 2 + 1); char *b; diff --git a/coreutils/uudecode.c b/coreutils/uudecode.c index 3f1227306..7aa5c67f2 100644 --- a/coreutils/uudecode.c +++ b/coreutils/uudecode.c @@ -46,7 +46,7 @@ static void FAST_FUNC read_stduu(FILE *src_stream, FILE *dst_stream, int flags U encoded_len = line[0] * 4 / 3; /* Check that line is not too short. (we tolerate - * overly _long_ line to accomodate possible extra '`'). + * overly _long_ line to accommodate possible extra '`'). * Empty line case is also caught here. */ if (str_len <= encoded_len) { break; /* go to bb_error_msg_and_die("short file"); */ diff --git a/docs/cgi/env.html b/docs/cgi/env.html index b83c750bf..66a548b46 100644 --- a/docs/cgi/env.html +++ b/docs/cgi/env.html @@ -38,7 +38,7 @@ fulfilled by the gateway program:

  • SERVER_PROTOCOL

    - The name and revision of the information protcol this request came + The name and revision of the information protocol this request came in with. Format: protocol/revision

  • SERVER_PORT

    diff --git a/e2fsprogs/old_e2fsprogs/blkid/dev.c b/e2fsprogs/old_e2fsprogs/blkid/dev.c index 260e49c65..84b7b0a72 100644 --- a/e2fsprogs/old_e2fsprogs/blkid/dev.c +++ b/e2fsprogs/old_e2fsprogs/blkid/dev.c @@ -90,7 +90,7 @@ void blkid_debug_dump_dev(blkid_dev dev) * * These routines do not expose the list.h implementation, which are a * contamination of the namespace, and which force us to reveal far, far - * too much of our internal implemenation. I'm not convinced I want + * too much of our internal implementation. I'm not convinced I want * to keep list.h in the long term, anyway. It's fine for kernel * programming, but performance is not the #1 priority for this * library, and I really don't like the tradeoff of type-safety for diff --git a/e2fsprogs/old_e2fsprogs/blkid/tag.c b/e2fsprogs/old_e2fsprogs/blkid/tag.c index 7424edeb8..f10a701d2 100644 --- a/e2fsprogs/old_e2fsprogs/blkid/tag.c +++ b/e2fsprogs/old_e2fsprogs/blkid/tag.c @@ -230,7 +230,7 @@ errout: * * These routines do not expose the list.h implementation, which are a * contamination of the namespace, and which force us to reveal far, far - * too much of our internal implemenation. I'm not convinced I want + * too much of our internal implementation. I'm not convinced I want * to keep list.h in the long term, anyway. It's fine for kernel * programming, but performance is not the #1 priority for this * library, and I really don't like the tradeoff of type-safety for diff --git a/e2fsprogs/old_e2fsprogs/e2fsck.c b/e2fsprogs/old_e2fsprogs/e2fsck.c index 0799b64ad..b816c62b0 100644 --- a/e2fsprogs/old_e2fsprogs/e2fsck.c +++ b/e2fsprogs/old_e2fsprogs/e2fsck.c @@ -6381,7 +6381,7 @@ static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr, } /* - * This fuction deallocates an inode + * This function deallocates an inode */ static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf) { @@ -6447,7 +6447,7 @@ static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf) } /* - * This fuction clears the htree flag on an inode + * This function clears the htree flag on an inode */ static void clear_htree(e2fsck_t ctx, ext2_ino_t ino) { diff --git a/editors/diff.c b/editors/diff.c index c3ad31bf3..cf14b1d03 100644 --- a/editors/diff.c +++ b/editors/diff.c @@ -363,7 +363,7 @@ static void stone(const int *a, int n, const int *b, int *J, int pref) } struct line { - /* 'serial' is not used in the begining, so we reuse it + /* 'serial' is not used in the beginning, so we reuse it * to store line offsets, thus reducing memory pressure */ union { diff --git a/editors/vi.c b/editors/vi.c index 2e4f7fcb5..6ce513c0c 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -501,7 +501,7 @@ static char *prev_line(char *); // return pointer to prev line B-o-l static char *next_line(char *); // return pointer to next line B-o-l static char *end_screen(void); // get pointer to last char on screen static int count_lines(char *, char *); // count line from start to stop -static char *find_line(int); // find begining of line #li +static char *find_line(int); // find beginning of line #li static char *move_to_col(char *, int); // move "p" to column l static void dot_left(void); // move dot left- dont leave line static void dot_right(void); // move dot right- dont leave line @@ -1684,10 +1684,10 @@ static char *dollar_line(char *p) // return pointer to just before NL line static char *prev_line(char *p) // return pointer first char prev line { - p = begin_line(p); // goto begining of cur line + p = begin_line(p); // goto beginning of cur line if (p > text && p[-1] == '\n') p--; // step to prev line - p = begin_line(p); // goto begining of prev line + p = begin_line(p); // goto beginning of prev line return p; } @@ -1735,7 +1735,7 @@ static int count_lines(char *start, char *stop) return cnt; } -static char *find_line(int li) // find begining of line #li +static char *find_line(int li) // find beginning of line #li { char *q; @@ -3357,7 +3357,7 @@ static void refresh(int full_screen) tp = t + 1; } - // see if there are any changes between vitual screen and out_buf + // see if there are any changes between virtual screen and out_buf changed = FALSE; // assume no change cs = 0; ce = columns - 1; @@ -3394,7 +3394,7 @@ static void refresh(int full_screen) if (cs < 0) cs = 0; if (ce > columns - 1) ce = columns - 1; if (cs > ce) { cs = 0; ce = columns - 1; } - // is there a change between vitual screen and out_buf + // is there a change between virtual screen and out_buf if (changed) { // copy changed part of buffer to virtual screen memcpy(sp+cs, out_buf+cs, ce-cs+1); @@ -3844,7 +3844,7 @@ static void do_cmd(int c) } break; #endif /* FEATURE_VI_SEARCH */ - case '0': // 0- goto begining of line + case '0': // 0- goto beginning of line case '1': // 1- case '2': // 2- case '3': // 3- diff --git a/findutils/xargs.c b/findutils/xargs.c index 76c4747fe..25e47ec89 100644 --- a/findutils/xargs.c +++ b/findutils/xargs.c @@ -151,7 +151,7 @@ static void store_param(char *s) * is seen, store the address of a new parameter to args[]. * If reading discovers that last chars do not form the complete * parameter, the pointer to the first such "tail character" is returned. - * (buf has extra byte at the end to accomodate terminating NUL + * (buf has extra byte at the end to accommodate terminating NUL * of "tail characters" string). * Otherwise, the returned pointer points to NUL byte. * On entry, buf[] may contain some "seed chars" which are to become diff --git a/miscutils/less.c b/miscutils/less.c index 554e54687..d5a68d1e1 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -1848,7 +1848,7 @@ key and/or command line switch compatibility is a good idea: Most options may be changed either on the command line, or from within less by using the - or -- command. Options may be given in one of two forms: either a single - character preceded by a -, or a name preceeded by --. + character preceded by a -, or a name preceded by --. -? ........ --help Display help (from command line). -a ........ --search-skip-screen diff --git a/networking/netstat.c b/networking/netstat.c index 1303d3f3d..2196d42f7 100644 --- a/networking/netstat.c +++ b/networking/netstat.c @@ -119,7 +119,7 @@ typedef enum { #define ADDR_NORMAL_WIDTH 23 /* When there are IPv6 connections the IPv6 addresses will be * truncated to none-recognition. The '-W' option makes the - * address columns wide enough to accomodate for longest possible + * address columns wide enough to accommodate for longest possible * IPv6 addresses, i.e. addresses of the form * xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:ddd.ddd.ddd.ddd */ diff --git a/scripts/basic/docproc.c b/scripts/basic/docproc.c index 7f21443c1..720098a23 100644 --- a/scripts/basic/docproc.c +++ b/scripts/basic/docproc.c @@ -264,7 +264,7 @@ void singfunc(char * filename, char * line) vec[idx++] = KERNELDOC; vec[idx++] = DOCBOOK; - /* Split line up in individual parameters preceeded by FUNCTION */ + /* Split line up in individual parameters preceded by FUNCTION */ for (i=0; line[i]; i++) { if (isspace(line[i])) { line[i] = '\0'; diff --git a/selinux/Config.src b/selinux/Config.src index 47d15b6af..d4701f60b 100644 --- a/selinux/Config.src +++ b/selinux/Config.src @@ -64,7 +64,7 @@ config RUNCON default n depends on SELINUX help - Enable support to run command in speficied security context. + Enable support to run command in specified security context. config FEATURE_RUNCON_LONG_OPTIONS bool "Enable long options" diff --git a/shell/hush.c b/shell/hush.c index f2c0a70f2..96c739fb7 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -442,7 +442,7 @@ enum { MAYBE_ASSIGNMENT = 0, DEFINITELY_ASSIGNMENT = 1, NOT_ASSIGNMENT = 2, - /* Not an assigment, but next word may be: "if v=xyz cmd;" */ + /* Not an assignment, but next word may be: "if v=xyz cmd;" */ WORD_IS_KEYWORD = 3, }; /* Used for initialization: o_string foo = NULL_O_STRING; */ diff --git a/util-linux/mkfs_reiser.c b/util-linux/mkfs_reiser.c index 13abaa889..56c8f0ab5 100644 --- a/util-linux/mkfs_reiser.c +++ b/util-linux/mkfs_reiser.c @@ -66,7 +66,7 @@ struct reiserfs_super_block { char s_magic[10]; /* 52 "ReIsErFs" or "ReIsEr2Fs" or "ReIsEr3Fs" */ uint16_t sb_fs_state; /* 62 it is set to used by fsck to mark which phase of rebuilding is done (used for fsck debugging) */ - uint32_t sb_hash_function_code; /* 64 code of fuction which was/is/will be used to sort names in a directory. See codes in above */ + uint32_t sb_hash_function_code; /* 64 code of function which was/is/will be used to sort names in a directory. See codes in above */ uint16_t sb_tree_height; /* 68 height of filesytem tree. Tree consisting of only one root block has 2 here */ uint16_t sb_bmap_nr; /* 70 amount of bitmap blocks needed to address each block of file system */ uint16_t sb_version; /* 72 this field is only reliable on filesystem with non-standard journal */ From 7f4a49a96c4e6626f01a09a801d79c591ad0b1db Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 25 May 2015 14:30:52 +0200 Subject: [PATCH 143/256] Print one less newline at the end of bb_show_usage() Signed-off-by: Denys Vlasenko --- libbb/appletlib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libbb/appletlib.c b/libbb/appletlib.c index ba3d6e7a0..46849e4f0 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -130,7 +130,7 @@ void FAST_FUNC bb_show_usage(void) full_write2_str(applet_name); full_write2_str(" "); full_write2_str(p); - full_write2_str("\n\n"); + full_write2_str("\n"); } if (ENABLE_FEATURE_CLEAN_UP) dealloc_usage_messages((char*)usage_string); From fc3e40ee8102c8b17fc98fbc93417bed4d878723 Mon Sep 17 00:00:00 2001 From: Ari Sundholm Date: Mon, 25 May 2015 15:16:11 +0200 Subject: [PATCH 144/256] truncate: do not die when a file doesn't exist and no-create flag is on Additionally, open(2) failures do not make the program die immediately. This makes the behavior of the program match coreutils more closely. function old new delta truncate_main 161 221 +60 Signed-off-by: Ari Sundholm Signed-off-by: Denys Vlasenko --- coreutils/truncate.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/coreutils/truncate.c b/coreutils/truncate.c index 0e36daba3..e5fa656c8 100644 --- a/coreutils/truncate.c +++ b/coreutils/truncate.c @@ -64,12 +64,22 @@ int truncate_main(int argc UNUSED_PARAM, char **argv) argv += optind; while (*argv) { - int fd = xopen(*argv, flags); - if (ftruncate(fd, size) == -1) { - bb_perror_msg("%s: ftruncate", *argv); - ret = EXIT_FAILURE; + int fd = open(*argv, flags); + if (fd < 0) { + if (errno != ENOENT || !(opts & OPT_NOCREATE)) { + bb_perror_msg("%s: open", *argv); + ret = EXIT_FAILURE; + } + /* else: ENOENT && OPT_NOCREATE: + * do not report error, exitcode is also 0. + */ + } else { + if (ftruncate(fd, size) == -1) { + bb_perror_msg("%s: truncate", *argv); + ret = EXIT_FAILURE; + } + xclose(fd); } - xclose(fd); ++argv; } From d291c2fdd5cb8616605c67ecbfb04274fa094242 Mon Sep 17 00:00:00 2001 From: Junling Zheng Date: Sun, 7 Jun 2015 02:32:23 +0200 Subject: [PATCH 145/256] chown: fix help text Signed-off-by: Junling Zheng Signed-off-by: Denys Vlasenko --- coreutils/chown.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreutils/chown.c b/coreutils/chown.c index cb07bbcbb..679c0d832 100644 --- a/coreutils/chown.c +++ b/coreutils/chown.c @@ -11,7 +11,7 @@ /* http://www.opengroup.org/onlinepubs/007904975/utilities/chown.html */ //usage:#define chown_trivial_usage -//usage: "[-RhLHP"IF_DESKTOP("cvf")"]... OWNER[<.|:>[GROUP]] FILE..." +//usage: "[-Rh"IF_DESKTOP("LHPcvf")"]... OWNER[<.|:>[GROUP]] FILE..." //usage:#define chown_full_usage "\n\n" //usage: "Change the owner and/or group of each FILE to OWNER and/or GROUP\n" //usage: "\n -R Recurse" From 314742747deecd454ae58dfd68be453115ba226c Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 5 Jun 2015 10:27:28 +0200 Subject: [PATCH 146/256] i2cdetect: don't die on addresses already in use by drivers We can't use i2c_set_slave_addr() in i2cdetect, as we have to check for EBUSY after calling ioctl(I2C_SLAVE) and print 'UU' on busy addresses instead of bailing-out. While we're at it: reorder definitions of local vars in i2cdetect_main(). function old new delta i2cdetect_main 703 744 +41 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/0 up/down: 41/0) Total: 41 bytes text data bss dec hex filename 826097 4164 9584 839845 cd0a5 busybox_old 826145 4164 9584 839893 cd0d5 busybox_unstripped Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- miscutils/i2c_tools.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index 7034dc9a8..d5127ec27 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c @@ -355,6 +355,13 @@ static void i2c_set_pec(int fd, int pec) itoptr(pec ? 1 : 0), "can't set PEC"); } + +static void i2c_set_slave_addr(int fd, int addr, int force) +{ + ioctl_or_perror_and_die(fd, force ? I2C_SLAVE_FORCE : I2C_SLAVE, + itoptr(addr), + "can't set address to 0x%02x", addr); +} #endif /* ENABLE_I2CGET || ENABLE_I2CSET || ENABLE_I2CDUMP */ #if ENABLE_I2CGET || ENABLE_I2CSET @@ -390,13 +397,6 @@ static int i2c_dev_open(int i2cbus) return fd; } -static void i2c_set_slave_addr(int fd, int addr, int force) -{ - ioctl_or_perror_and_die(fd, force ? I2C_SLAVE_FORCE : I2C_SLAVE, - itoptr(addr), - "can't set address to 0x%02x", addr); -} - /* Size reducing helpers for xxx_check_funcs(). */ static void get_funcs_matrix(int fd, unsigned long *funcs) { @@ -1281,11 +1281,9 @@ int i2cdetect_main(int argc UNUSED_PARAM, char **argv) opt_F = (1 << 4), opt_l = (1 << 5); const char *const optstr = "yaqrFl"; - int fd, bus_num, i, j, mode = DETECT_MODE_AUTO; - int status; - unsigned first = 0x00, last = 0x77; + int fd, bus_num, i, j, mode = DETECT_MODE_AUTO, status; + unsigned first = 0x00, last = 0x77, opts; unsigned long funcs; - unsigned opts; opt_complementary = "q--r:r--q:" /* mutually exclusive */ "?3"; /* up to 3 args */ @@ -1370,7 +1368,16 @@ int i2cdetect_main(int argc UNUSED_PARAM, char **argv) continue; } - i2c_set_slave_addr(fd, i + j, 0); + status = ioctl(fd, I2C_SLAVE, itoptr(i + j)); + if (status < 0) { + if (errno == EBUSY) { + printf("UU "); + continue; + } + + bb_perror_msg_and_die( + "can't set address to 0x%02x", i + j); + } switch (mode) { case DETECT_MODE_READ: From e545bf6723ebfd486c6dce6b754b6de792c46de1 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 5 Jun 2015 10:27:29 +0200 Subject: [PATCH 147/256] i2cdetect: don't scan non-regular addresses without the '-a' option Addresses 0x00-0x02 shouldn't be scanned by default. This patch makes 'first' default to 0x03 and only enables lower addresses if '-a' option is passed Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- miscutils/i2c_tools.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index d5127ec27..6f9787280 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c @@ -1282,7 +1282,7 @@ int i2cdetect_main(int argc UNUSED_PARAM, char **argv) const char *const optstr = "yaqrFl"; int fd, bus_num, i, j, mode = DETECT_MODE_AUTO, status; - unsigned first = 0x00, last = 0x77, opts; + unsigned first = 0x03, last = 0x77, opts; unsigned long funcs; opt_complementary = "q--r:r--q:" /* mutually exclusive */ @@ -1316,8 +1316,10 @@ int i2cdetect_main(int argc UNUSED_PARAM, char **argv) else if (opts & opt_q) mode = DETECT_MODE_QUICK; - if (opts & opt_a) + if (opts & opt_a) { + first = 0x00; last = 0x7f; + } /* Read address range. */ if (argv[1]) { From 2204472497285dd6fd7b686bb49732fda7394492 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 5 Jun 2015 10:27:30 +0200 Subject: [PATCH 148/256] i2cdetect: add a check for (mode == DETECT_MODE_AUTO) We should only warn the user about addresses to be skipped if (mode == DETECT_MODE_AUTO). Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- miscutils/i2c_tools.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index 6f9787280..16784e948 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c @@ -1336,7 +1336,9 @@ int i2cdetect_main(int argc UNUSED_PARAM, char **argv) } else if (mode == DETECT_MODE_READ && !(funcs & I2C_FUNC_SMBUS_READ_BYTE)) { no_support("SMBus Receive Byte command"); - } else { + } + + if (mode == DETECT_MODE_AUTO) { if (!(funcs & I2C_FUNC_SMBUS_QUICK)) will_skip("SMBus Quick Write"); if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE)) From aeb11a949667f82173c733e55e9f762c56a1fcba Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 5 Jun 2015 10:27:31 +0200 Subject: [PATCH 149/256] i2cdump: code rework Split i2cdump_main() into shorter functions. Simplify the code a bit. Make block an array of ints so that we can store negative results of read functions (fixes a bug found by Denys Vlasenko). Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- miscutils/i2c_tools.c | 316 ++++++++++++++++++++++-------------------- 1 file changed, 167 insertions(+), 149 deletions(-) diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index 16784e948..2f501cd9c 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c @@ -816,6 +816,163 @@ int i2cset_main(int argc, char **argv) #endif /* ENABLE_I2CSET */ #if ENABLE_I2CDUMP +static int read_block_data(int buf_fd, int mode, int *block) +{ + uint8_t cblock[I2C_SMBUS_BLOCK_MAX + I2C_MAX_REGS]; + int res, blen = 0, tmp, i; + + if (mode == I2C_SMBUS_BLOCK_DATA || mode == I2C_SMBUS_I2C_BLOCK_DATA) { + res = i2c_smbus_read_block_data(buf_fd, 0, cblock); + blen = res; + } else { + for (res = 0; res < I2C_MAX_REGS; res += tmp) { + tmp = i2c_smbus_read_i2c_block_data( + buf_fd, res, I2C_SMBUS_BLOCK_MAX, + cblock + res); + if (tmp < 0) { + bb_error_msg_and_die("block read failed"); + } + } + + if (res >= I2C_MAX_REGS) + res = I2C_MAX_REGS; + + for (i = 0; i < res; i++) + block[i] = cblock[i]; + + if (mode != I2C_SMBUS_BLOCK_DATA) + for (i = res; i < I2C_MAX_REGS; i++) + block[i] = -1; + } + + return blen; +} + +/* Dump all but word data. */ +static void dump_data(int bus_fd, int mode, unsigned first, + unsigned last, int *block, int blen) +{ + int i, j, res; + + printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f" + " 0123456789abcdef\n"); + + for (i = 0; i < I2C_MAX_REGS; i += 0x10) { + if (mode == I2C_SMBUS_BLOCK_DATA && i >= blen) + break; + if (i/16 < first/16) + continue; + if (i/16 > last/16) + break; + + printf("%02x: ", i); + for (j = 0; j < 16; j++) { + fflush_all(); + /* Skip unwanted registers */ + if (i+j < first || i+j > last) { + printf(" "); + if (mode == I2C_SMBUS_WORD_DATA) { + printf(" "); + j++; + } + continue; + } + + switch (mode) { + case I2C_SMBUS_BYTE_DATA: + res = i2c_smbus_read_byte_data(bus_fd, i+j); + block[i+j] = res; + break; + case I2C_SMBUS_WORD_DATA: + res = i2c_smbus_read_word_data(bus_fd, i+j); + if (res < 0) { + block[i+j] = res; + block[i+j+1] = res; + } else { + block[i+j] = res & 0xff; + block[i+j+1] = res >> 8; + } + break; + case I2C_SMBUS_BYTE: + res = i2c_smbus_read_byte(bus_fd); + block[i+j] = res; + break; + default: + res = block[i+j]; + } + + if (mode == I2C_SMBUS_BLOCK_DATA && + i+j >= blen) { + printf(" "); + } else if (res < 0) { + printf("XX "); + if (mode == I2C_SMBUS_WORD_DATA) + printf("XX "); + } else { + printf("%02x ", block[i+j]); + if (mode == I2C_SMBUS_WORD_DATA) + printf("%02x ", block[i+j+1]); + } + + if (mode == I2C_SMBUS_WORD_DATA) + j++; + } + printf(" "); + + for (j = 0; j < 16; j++) { + if (mode == I2C_SMBUS_BLOCK_DATA && i+j >= blen) + break; + /* Skip unwanted registers */ + if (i+j < first || i+j > last) { + printf(" "); + continue; + } + + res = block[i+j]; + if (res < 0) { + printf("X"); + } else if (res == 0x00 || res == 0xff) { + printf("."); + } else if (res < 32 || res >= 127) { + printf("?"); + } else { + printf("%c", res); + } + } + printf("\n"); + } +} + +static void dump_word_data(int bus_fd, unsigned first, unsigned last) +{ + int i, j, rv; + + /* Word data. */ + printf(" 0,8 1,9 2,a 3,b 4,c 5,d 6,e 7,f\n"); + for (i = 0; i < 256; i += 8) { + if (i/8 < first/8) + continue; + if (i/8 > last/8) + break; + + printf("%02x: ", i); + for (j = 0; j < 8; j++) { + /* Skip unwanted registers. */ + if (i+j < first || i+j > last) { + printf(" "); + continue; + } + + rv = i2c_smbus_read_word_data(bus_fd, i+j); + if (rv < 0) + printf("XXXX "); + else + printf("%04x ", rv & 0xffff); + } + printf("\n"); + } +} + //usage:#define i2cdump_trivial_usage //usage: "[-f] [-r FIRST-LAST] [-y] BUS ADDR [MODE]" //usage:#define i2cdump_full_usage "\n\n" @@ -842,12 +999,10 @@ int i2cdump_main(int argc UNUSED_PARAM, char **argv) const char *const optstr = "fyr:"; int bus_num, bus_addr, mode = I2C_SMBUS_BYTE_DATA, even = 0, pec = 0; - unsigned first = 0x00, last = 0xff; - int fd, i, j, res, blen = 0, tmp; - unsigned char cblock[I2C_SMBUS_BLOCK_MAX + I2C_MAX_REGS]; - unsigned char block[I2C_SMBUS_BLOCK_MAX]; + unsigned first = 0x00, last = 0xff, opts; + int *block = (int *)bb_common_bufsiz1; char *opt_r_str, *dash; - unsigned opts; + int fd, res, blen; opt_complementary = "-2:?3"; /* from 2 to 3 args */ opts = getopt32(argv, optstr, &opt_r_str); @@ -858,7 +1013,7 @@ int i2cdump_main(int argc UNUSED_PARAM, char **argv) if (argv[2]) { switch (argv[2][0]) { - case 'b': /* Already set */ break; + case 'b': /* Already set. */ break; case 'c': mode = I2C_SMBUS_BYTE; break; case 'w': mode = I2C_SMBUS_WORD_DATA; break; case 'W': @@ -887,7 +1042,7 @@ int i2cdump_main(int argc UNUSED_PARAM, char **argv) bb_error_msg_and_die("invalid range"); last = xstrtou_range(++dash, 0, first, 0xff); - /* Range is not available for every mode */ + /* Range is not available for every mode. */ switch (mode) { case I2C_SMBUS_BYTE: case I2C_SMBUS_BYTE_DATA: @@ -912,156 +1067,19 @@ int i2cdump_main(int argc UNUSED_PARAM, char **argv) if (!(opts & opt_y)) confirm_action(bus_addr, mode, -1 /* data_addr */, pec); - /* All but word data */ + /* All but word data. */ if (mode != I2C_SMBUS_WORD_DATA || even) { - /* - * FIXME This section has been ported from upstream i2cdump. - * It has been reworked a bit but is still pretty spaghetti - * and needs splitting into several functions. - */ - if (mode == I2C_SMBUS_BLOCK_DATA || - mode == I2C_SMBUS_I2C_BLOCK_DATA) { - res = i2c_smbus_read_block_data(fd, 0, cblock); - blen = res; - } else { - for (res = 0; res < I2C_MAX_REGS; res += tmp) { - tmp = i2c_smbus_read_i2c_block_data( - fd, res, I2C_SMBUS_BLOCK_MAX, - cblock + res); - if (tmp < 0) { - bb_error_msg_and_die( - "block read failed"); - } - } - if (res >= I2C_MAX_REGS) - res = I2C_MAX_REGS; - for (i = 0; i < res; i++) - block[i] = cblock[i]; - if (mode != I2C_SMBUS_BLOCK_DATA) - for (i = res; i < I2C_MAX_REGS; i++) - cblock[i] = -1; - } + blen = read_block_data(fd, mode, block); if (mode == I2C_SMBUS_BYTE) { res = i2c_smbus_write_byte(fd, first); if (res < 0) - bb_perror_msg_and_die( - "write start address failed"); + bb_perror_msg_and_die("write start address"); } - printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f" - " 0123456789abcdef\n"); - - for (i = 0; i < I2C_MAX_REGS; i += 0x10) { - if (mode == I2C_SMBUS_BLOCK_DATA && i >= blen) - break; - if (i/16 < first/16) - continue; - if (i/16 > last/16) - break; - - printf("%02x: ", i); - for (j = 0; j < 16; j++) { - fflush_all(); - /* Skip unwanted registers */ - if (i+j < first || i+j > last) { - printf(" "); - if (mode == I2C_SMBUS_WORD_DATA) { - printf(" "); - j++; - } - continue; - } - - switch (mode) { - case I2C_SMBUS_BYTE_DATA: - res = i2c_smbus_read_byte_data(fd, i+j); - block[i+j] = res; - break; - case I2C_SMBUS_WORD_DATA: - res = i2c_smbus_read_word_data(fd, i+j); - if (res < 0) { - block[i+j] = res; - block[i+j+1] = res; - } else { - block[i+j] = res & 0xff; - block[i+j+1] = res >> 8; - } - break; - case I2C_SMBUS_BYTE: - res = i2c_smbus_read_byte(fd); - block[i+j] = res; - break; - default: - res = block[i+j]; - } - - if (mode == I2C_SMBUS_BLOCK_DATA && - i+j >= blen) { - printf(" "); - } else if (res < 0) { - printf("XX "); - if (mode == I2C_SMBUS_WORD_DATA) - printf("XX "); - } else { - printf("%02x ", block[i+j]); - if (mode == I2C_SMBUS_WORD_DATA) - printf("%02x ", block[i+j+1]); - } - - if (mode == I2C_SMBUS_WORD_DATA) - j++; - } - printf(" "); - - for (j = 0; j < 16; j++) { - if (mode == I2C_SMBUS_BLOCK_DATA && i+j >= blen) - break; - /* Skip unwanted registers */ - if (i+j < first || i+j > last) { - printf(" "); - continue; - } - - res = block[i+j]; - if (res < 0) { -//FIXME: impossible, block[] is uchar[] - printf("X"); - } else if (res == 0x00 || res == 0xff) { - printf("."); - } else if (res < 32 || res >= 127) { - printf("?"); - } else { - printf("%c", res); - } - } - printf("\n"); - } + dump_data(fd, mode, first, last, block, blen); } else { - /* Word data. */ - printf(" 0,8 1,9 2,a 3,b 4,c 5,d 6,e 7,f\n"); - for (i = 0; i < 256; i += 8) { - if (i/8 < first/8) - continue; - if (i/8 > last/8) - break; - - printf("%02x: ", i); - for (j = 0; j < 8; j++) { - /* Skip unwanted registers. */ - if (i+j < first || i+j > last) { - printf(" "); - continue; - } - - res = i2c_smbus_read_word_data(fd, i+j); - if (res < 0) - printf("XXXX "); - else - printf("%04x ", res & 0xffff); - } - printf("\n"); - } + dump_word_data(fd, first, last); } return 0; From d90899206dd96b4c18064c18afc3b856382e64d4 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Fri, 5 Jun 2015 10:27:32 +0200 Subject: [PATCH 150/256] i2cdetect: use break instead of goto in list_i2c_busses_and_exit() Since there are now more statements in the if block after the while loop in list_i2c_busses_and_exit(), there's no need for a label. Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- miscutils/i2c_tools.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/miscutils/i2c_tools.c b/miscutils/i2c_tools.c index 2f501cd9c..38d90ff10 100644 --- a/miscutils/i2c_tools.c +++ b/miscutils/i2c_tools.c @@ -1226,12 +1226,11 @@ static void NORETURN list_i2c_busses_and_exit(void) i2cdev_path, de->d_name, subde->d_name); fp = fopen(path, "r"); - goto found; + break; } } } -found: if (fp != NULL) { /* * Get the rest of the info and display a line From 0fabedf085591b50994e4f8c133bfa87f1777ee4 Mon Sep 17 00:00:00 2001 From: Maninder Singh Date: Mon, 1 Jun 2015 10:38:07 +0000 Subject: [PATCH 151/256] fix if(p)/free(p) construct No need of explicit NULL check before free. Signed-off-by: Maninder Singh Signed-off-by: Akhilesh Kumar Signed-off-by: Denys Vlasenko --- e2fsprogs/old_e2fsprogs/blkid/dev.c | 3 +-- e2fsprogs/old_e2fsprogs/fsck.c | 12 ++++-------- scripts/kconfig/confdata.c | 3 +-- scripts/kconfig/util.c | 3 +-- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/e2fsprogs/old_e2fsprogs/blkid/dev.c b/e2fsprogs/old_e2fsprogs/blkid/dev.c index 84b7b0a72..c2bbb06f3 100644 --- a/e2fsprogs/old_e2fsprogs/blkid/dev.c +++ b/e2fsprogs/old_e2fsprogs/blkid/dev.c @@ -44,8 +44,7 @@ void blkid_free_dev(blkid_dev dev) bit_tags); blkid_free_tag(tag); } - if (dev->bid_name) - free(dev->bid_name); + free(dev->bid_name); free(dev); } diff --git a/e2fsprogs/old_e2fsprogs/fsck.c b/e2fsprogs/old_e2fsprogs/fsck.c index 91cce970c..87874ce71 100644 --- a/e2fsprogs/old_e2fsprogs/fsck.c +++ b/e2fsprogs/old_e2fsprogs/fsck.c @@ -354,12 +354,9 @@ static void parse_escape(char *word) static void free_instance(struct fsck_instance *i) { - if (i->prog) - free(i->prog); - if (i->device) - free(i->device); - if (i->base_device) - free(i->base_device); + free(i->prog); + free(i->device); + free(i->base_device); free(i); } @@ -432,8 +429,7 @@ static int parse_fstab_line(char *line, struct fs_info **ret_fs) fs = create_fs_device(device, mntpnt, type ? type : "auto", opts, freq ? atoi(freq) : -1, passno ? atoi(passno) : -1); - if (dev) - free(dev); + free(dev); if (!fs) return -1; diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index 303df0be7..8f4ecbd33 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -124,8 +124,7 @@ int conf_read_simple(const char *name) case S_INT: case S_HEX: case S_STRING: - if (sym->user.val) - free(sym->user.val); + free(sym->user.val); default: sym->user.val = NULL; sym->user.tri = no; diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c index 263091945..13369e6a1 100644 --- a/scripts/kconfig/util.c +++ b/scripts/kconfig/util.c @@ -79,8 +79,7 @@ struct gstr str_assign(const char *s) /* Free storage for growable string */ void str_free(struct gstr *gs) { - if (gs->s) - free(gs->s); + free(gs->s); gs->s = NULL; gs->len = 0; } From 7db312ad265608264c1d42106ceadf158ff7f77e Mon Sep 17 00:00:00 2001 From: Maninder Singh Date: Mon, 1 Jun 2015 10:40:09 +0000 Subject: [PATCH 152/256] fix whitespaces reported by script :- scripts/fix_ws.sh Signed-off-by: Maninder Singh Signed-off-by: Denys Vlasenko --- coreutils/shuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreutils/shuf.c b/coreutils/shuf.c index 6d0a68fc1..9f61f2f7d 100644 --- a/coreutils/shuf.c +++ b/coreutils/shuf.c @@ -94,7 +94,7 @@ int shuf_main(int argc, char **argv) *dash = '\0'; lo = xatou(opt_i_str); hi = xatou(dash + 1); - *dash = '-'; + *dash = '-'; if (hi < lo) { bb_error_msg_and_die("bad range '%s'", opt_i_str); } From 6a7cd3d4aba493c0b0d00155b1e09a867db437cf Mon Sep 17 00:00:00 2001 From: Michael Tokarev Date: Wed, 20 May 2015 16:27:44 +0300 Subject: [PATCH 153/256] ip addr: support change and replace commands Signed-off-by: Michael Tokarev Signed-off-by: Denys Vlasenko --- networking/ip.c | 2 +- networking/libiproute/ipaddress.c | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/networking/ip.c b/networking/ip.c index 98fe621b1..d35345c36 100644 --- a/networking/ip.c +++ b/networking/ip.c @@ -33,7 +33,7 @@ //usage: "{ {add|del} IFADDR dev STRING | {show|flush}\n" //usage: " [dev STRING] [to PREFIX] }" //usage:#define ipaddr_full_usage "\n\n" -//usage: "ipaddr {add|delete} IFADDR dev STRING\n" +//usage: "ipaddr {add|change|replace|delete} IFADDR dev STRING\n" //usage: "ipaddr {show|flush} [dev STRING] [scope SCOPE-ID]\n" //usage: " [to PREFIX] [label PATTERN]\n" //usage: " IFADDR := PREFIX | ADDR peer PREFIX\n" diff --git a/networking/libiproute/ipaddress.c b/networking/libiproute/ipaddress.c index 4072d0626..85f33560f 100644 --- a/networking/libiproute/ipaddress.c +++ b/networking/libiproute/ipaddress.c @@ -598,7 +598,7 @@ static int default_scope(inet_prefix *lcl) } /* Return value becomes exitcode. It's okay to not return at all */ -static int ipaddr_modify(int cmd, char **argv) +static int ipaddr_modify(int cmd, int flags, char **argv) { static const char option[] ALIGN1 = "peer\0""remote\0""broadcast\0""brd\0" @@ -622,7 +622,7 @@ static int ipaddr_modify(int cmd, char **argv) memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); - req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_flags = NLM_F_REQUEST | flags; req.n.nlmsg_type = cmd; req.ifa.ifa_family = preferred_family; @@ -749,16 +749,20 @@ static int ipaddr_modify(int cmd, char **argv) int FAST_FUNC do_ipaddr(char **argv) { static const char commands[] ALIGN1 = - "add\0""delete\0""list\0""show\0""lst\0""flush\0"; + /* 0 1 2 3 4 5 6 7 8 */ + "add\0""change\0""chg\0""replace\0""delete\0""list\0""show\0""lst\0""flush\0"; int cmd = 2; if (*argv) { cmd = index_in_substrings(commands, *argv); if (cmd < 0) invarg(*argv, applet_name); argv++; - if (cmd <= 1) - return ipaddr_modify((cmd == 0) ? RTM_NEWADDR : RTM_DELADDR, argv); + if (cmd <= 4) + return ipaddr_modify(cmd == 4 ? RTM_DELADDR : RTM_NEWADDR, + cmd == 0 ? NLM_F_CREATE|NLM_F_EXCL : + cmd == 1 || cmd == 2 ? NLM_F_REPLACE : + cmd == 3 ? NLM_F_CREATE|NLM_F_REPLACE : + 0, argv); } - /* 2 == list, 3 == show, 4 == lst */ - return ipaddr_list_or_flush(argv, cmd == 5); + return ipaddr_list_or_flush(argv, cmd == 8); } From db31c637fa72cfdc546dd85e10d231a0fdce2b1e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 1 Jul 2015 18:36:06 +0200 Subject: [PATCH 154/256] ipaddress: better formatting, no code changes Signed-off-by: Denys Vlasenko --- networking/libiproute/ipaddress.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/networking/libiproute/ipaddress.c b/networking/libiproute/ipaddress.c index 85f33560f..a6d5129e7 100644 --- a/networking/libiproute/ipaddress.c +++ b/networking/libiproute/ipaddress.c @@ -757,12 +757,16 @@ int FAST_FUNC do_ipaddr(char **argv) if (cmd < 0) invarg(*argv, applet_name); argv++; - if (cmd <= 4) - return ipaddr_modify(cmd == 4 ? RTM_DELADDR : RTM_NEWADDR, - cmd == 0 ? NLM_F_CREATE|NLM_F_EXCL : - cmd == 1 || cmd == 2 ? NLM_F_REPLACE : - cmd == 3 ? NLM_F_CREATE|NLM_F_REPLACE : - 0, argv); + if (cmd <= 4) { + return ipaddr_modify( + /*cmd:*/ cmd == 4 ? RTM_DELADDR : RTM_NEWADDR, + /*flags:*/ + cmd == 0 ? NLM_F_CREATE|NLM_F_EXCL : /* add */ + cmd == 1 || cmd == 2 ? NLM_F_REPLACE : /* change */ + cmd == 3 ? NLM_F_CREATE|NLM_F_REPLACE : /* replace */ + 0 /* delete */ + , argv); + } } return ipaddr_list_or_flush(argv, cmd == 8); } From c9091d8947b6f0e28485eadab11d737e4c910430 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 1 Jul 2015 19:07:24 +0200 Subject: [PATCH 155/256] ps: fix SEGV on narrow screens. closes 8176 Signed-off-by: Denys Vlasenko --- procps/ps.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/procps/ps.c b/procps/ps.c index c65fa012a..bde5f9485 100644 --- a/procps/ps.c +++ b/procps/ps.c @@ -654,8 +654,8 @@ int ps_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) OPT_l = (1 << ENABLE_SELINUX) * (1 << ENABLE_FEATURE_SHOW_THREADS) * ENABLE_FEATURE_PS_LONG, }; #if ENABLE_FEATURE_PS_LONG - time_t now = now; - unsigned long uptime; + time_t now = now; /* for compiler */ + unsigned long uptime = uptime; #endif /* If we support any options, parse argv */ #if ENABLE_SELINUX || ENABLE_FEATURE_SHOW_THREADS || ENABLE_FEATURE_PS_WIDE || ENABLE_FEATURE_PS_LONG @@ -786,9 +786,11 @@ int ps_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) { int sz = terminal_width - len; - char buf[sz + 1]; - read_cmdline(buf, sz, p->pid, p->comm); - puts(buf); + if (sz >= 0) { + char buf[sz + 1]; + read_cmdline(buf, sz, p->pid, p->comm); + puts(buf); + } } } if (ENABLE_FEATURE_CLEAN_UP) From b7ee7e1e13fa4a680e8b228bd158e7aa53fe342a Mon Sep 17 00:00:00 2001 From: Clayton Shotwell Date: Thu, 21 May 2015 14:48:35 -0500 Subject: [PATCH 156/256] applets: Add installation of individual binaries Adding support to install individual binaries if the option is enabled. This also installs the shared libbusybox.so.* library. Signed-off-by: Clayton Shotwell Signed-off-by: Denys Vlasenko --- Makefile.custom | 4 ++++ applets/install.sh | 26 ++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/Makefile.custom b/Makefile.custom index f8a12831d..891c9ced7 100644 --- a/Makefile.custom +++ b/Makefile.custom @@ -28,6 +28,10 @@ ifeq ($(CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER),y) INSTALL_OPTS:= --scriptwrapper endif endif +ifeq ($(CONFIG_FEATURE_INDIVIDUAL),y) +INSTALL_OPTS:= --binaries +LIBBUSYBOX_SONAME:= 0_lib/libbusybox.so.$(BB_VER) +endif install: $(srctree)/applets/install.sh busybox busybox.links $(Q)DO_INSTALL_LIBS="$(strip $(LIBBUSYBOX_SONAME) $(DO_INSTALL_LIBS))" \ $(SHELL) $< $(CONFIG_PREFIX) $(INSTALL_OPTS) diff --git a/applets/install.sh b/applets/install.sh index 95b4719d4..f6c097e57 100755 --- a/applets/install.sh +++ b/applets/install.sh @@ -5,19 +5,26 @@ export LC_CTYPE=POSIX prefix=$1 if [ -z "$prefix" ]; then - echo "usage: applets/install.sh DESTINATION [--symlinks/--hardlinks/--scriptwrapper]" + echo "usage: applets/install.sh DESTINATION [--symlinks/--hardlinks/--binaries/--scriptwrapper]" exit 1 fi +# Source the configuration +. ./.config + h=`sort busybox.links | uniq` +sharedlib_dir="0_lib" + linkopts="" scriptwrapper="n" +binaries="n" cleanup="0" noclobber="0" case "$2" in --hardlinks) linkopts="-f";; --symlinks) linkopts="-fs";; + --binaries) binaries="y";; --scriptwrapper) scriptwrapper="y";swrapall="y";; --sw-sh-hard) scriptwrapper="y";linkopts="-f";; --sw-sh-sym) scriptwrapper="y";linkopts="-fs";; @@ -40,8 +47,9 @@ if [ -n "$DO_INSTALL_LIBS" ] && [ "$DO_INSTALL_LIBS" != "n" ]; then for i in $DO_INSTALL_LIBS; do rm -f "$prefix/$libdir/$i" || exit 1 if [ -f "$i" ]; then + echo " Installing $i to the target at $prefix/$libdir/" cp -pPR "$i" "$prefix/$libdir/" || exit 1 - chmod 0644 "$prefix/$libdir/$i" || exit 1 + chmod 0644 "$prefix/$libdir/`basename $i`" || exit 1 fi done fi @@ -68,6 +76,7 @@ install -m 755 busybox "$prefix/bin/busybox" || exit 1 for i in $h; do appdir=`dirname "$i"` + app=`basename "$i"` mkdir -p "$prefix/$appdir" || exit 1 if [ "$scriptwrapper" = "y" ]; then if [ "$swrapall" != "y" ] && [ "$i" = "/bin/sh" ]; then @@ -78,6 +87,19 @@ for i in $h; do chmod +x "$prefix/$i" fi echo " $prefix/$i" + elif [ "$binaries" = "y" ]; then + # Copy the binary over rather + if [ -e $sharedlib_dir/$app ]; then + if [ "$noclobber" = "0" ] || [ ! -e "$prefix/$i" ]; then + echo " Copying $sharedlib_dir/$app to $prefix/$i" + cp -pPR $sharedlib_dir/$app $prefix/$i || exit 1 + else + echo " $prefix/$i already exists" + fi + else + echo "Error: Could not find $sharedlib_dir/$app" + exit 1 + fi else if [ "$2" = "--hardlinks" ]; then bb_path="$prefix/bin/busybox" From 97f2f7ca7fe10783a592087df989a7f394492fa1 Mon Sep 17 00:00:00 2001 From: Maninder Singh Date: Wed, 10 Jun 2015 03:47:27 +0000 Subject: [PATCH 157/256] Removes stray empty line from code This patch removes stray empty line from busybox code reported by script find_stray_empty_lines Signed-off-by: Maninder Singh Signed-off-by: Akhilesh Kumar Signed-off-by: Denys Vlasenko --- archival/cpio.c | 1 - archival/gzip.c | 3 --- archival/libarchive/bz/compress.c | 1 - archival/libarchive/decompress_uncompress.c | 1 - archival/libarchive/lzo1x_9x.c | 1 - archival/libarchive/unxz/xz_dec_lzma2.c | 3 --- archival/libarchive/unxz/xz_dec_stream.c | 2 -- archival/unzip.c | 2 -- console-tools/showkey.c | 1 - coreutils/ln.c | 1 - editors/awk.c | 12 ------------ editors/ed.c | 1 - editors/vi.c | 1 - libbb/appletlib.c | 1 - libbb/in_ether.c | 1 - libbb/procps.c | 1 - libbb/xfuncs.c | 1 - mailutils/reformime.c | 1 - miscutils/crontab.c | 1 - networking/arp.c | 1 - networking/ntpd.c | 1 - networking/tftp.c | 1 - networking/wget.c | 1 - selinux/setfiles.c | 1 - shell/ash.c | 2 -- shell/hush.c | 1 - shell/shell_common.c | 1 - sysklogd/syslogd.c | 1 - 28 files changed, 46 deletions(-) diff --git a/archival/cpio.c b/archival/cpio.c index 454648d68..cdc16c14e 100644 --- a/archival/cpio.c +++ b/archival/cpio.c @@ -257,7 +257,6 @@ static NOINLINE int cpio_o(void) free(line); continue; } - } else { /* line == NULL: EOF */ next_link: if (links) { diff --git a/archival/gzip.c b/archival/gzip.c index 42b2f0b2e..c9171304a 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -1372,7 +1372,6 @@ static void build_tree(tree_desc * desc) /* and insert the new node in the heap */ G2.heap[SMALLEST] = node++; pqdownheap(tree, SMALLEST); - } while (G2.heap_len >= 2); G2.heap[--G2.heap_max] = G2.heap[SMALLEST]; @@ -1720,7 +1719,6 @@ static ulg flush_block(char *buf, ulg stored_len, int eof) copy_block(buf, (unsigned) stored_len, 0); /* without header */ G2.compressed_len = stored_len << 3; - } else if (stored_len + 4 <= opt_lenb && buf != NULL) { /* 4: two words for the lengths */ /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. @@ -1734,7 +1732,6 @@ static ulg flush_block(char *buf, ulg stored_len, int eof) G2.compressed_len += (stored_len + 4) << 3; copy_block(buf, (unsigned) stored_len, 1); /* with header */ - } else if (static_lenb == opt_lenb) { send_bits((STATIC_TREES << 1) + eof, 3); compress_block((ct_data *) G2.static_ltree, (ct_data *) G2.static_dtree); diff --git a/archival/libarchive/bz/compress.c b/archival/libarchive/bz/compress.c index 23de9d3f5..2d994685c 100644 --- a/archival/libarchive/bz/compress.c +++ b/archival/libarchive/bz/compress.c @@ -385,7 +385,6 @@ void sendMTFValues(EState* s) cost[0] = cost01 & 0xffff; cost[1] = cost01 >> 16; cost[2] = cost23 & 0xffff; cost[3] = cost23 >> 16; cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16; - } else #endif { diff --git a/archival/libarchive/decompress_uncompress.c b/archival/libarchive/decompress_uncompress.c index 496d864a7..034ed502d 100644 --- a/archival/libarchive/decompress_uncompress.c +++ b/archival/libarchive/decompress_uncompress.c @@ -297,7 +297,6 @@ unpack_Z_stream(transformer_state_t *xstate) /* Remember previous code. */ oldcode = incode; } - } while (rsize > 0); if (outpos > 0) { diff --git a/archival/libarchive/lzo1x_9x.c b/archival/libarchive/lzo1x_9x.c index 2b490ae83..09ee4ba5c 100644 --- a/archival/libarchive/lzo1x_9x.c +++ b/archival/libarchive/lzo1x_9x.c @@ -71,7 +71,6 @@ typedef struct { uint8_t *out; unsigned r1_lit; - } lzo1x_999_t; #define getbyte(c) ((c).ip < (c).in_end ? *((c).ip)++ : (-1)) diff --git a/archival/libarchive/unxz/xz_dec_lzma2.c b/archival/libarchive/unxz/xz_dec_lzma2.c index 3c2dc88b7..351251f7c 100644 --- a/archival/libarchive/unxz/xz_dec_lzma2.c +++ b/archival/libarchive/unxz/xz_dec_lzma2.c @@ -995,10 +995,8 @@ XZ_EXTERN NOINLINE enum xz_ret XZ_FUNC xz_dec_lzma2_run( s->lzma2.need_props = false; s->lzma2.next_sequence = SEQ_PROPERTIES; - } else if (s->lzma2.need_props) { return XZ_DATA_ERROR; - } else { s->lzma2.next_sequence = SEQ_LZMA_PREPARE; @@ -1080,7 +1078,6 @@ XZ_EXTERN NOINLINE enum xz_ret XZ_FUNC xz_dec_lzma2_run( rc_reset(&s->rc); s->lzma2.sequence = SEQ_CONTROL; - } else if (b->out_pos == b->out_size || (b->in_pos == b->in_size && s->temp.size diff --git a/archival/libarchive/unxz/xz_dec_stream.c b/archival/libarchive/unxz/xz_dec_stream.c index bdcbf1ba3..bf791055b 100644 --- a/archival/libarchive/unxz/xz_dec_stream.c +++ b/archival/libarchive/unxz/xz_dec_stream.c @@ -353,7 +353,6 @@ static enum xz_ret XZ_FUNC crc32_validate(struct xz_dec *s, struct xz_buf *b) return XZ_DATA_ERROR; s->pos += 8; - } while (s->pos < 32); s->crc32 = 0; @@ -753,7 +752,6 @@ XZ_EXTERN enum xz_ret XZ_FUNC xz_dec_run(struct xz_dec *s, struct xz_buf *b) b->in_pos = in_start; b->out_pos = out_start; } - } else if (ret == XZ_OK && in_start == b->in_pos && out_start == b->out_pos) { if (s->allow_buf_error) diff --git a/archival/unzip.c b/archival/unzip.c index eed225677..f41ab6f44 100644 --- a/archival/unzip.c +++ b/archival/unzip.c @@ -604,7 +604,6 @@ int unzip_main(int argc, char **argv) || (zaccept && !find_list_entry(zaccept, dst_fn)) ) { /* Skip entry */ i = 'n'; - } else { if (listing) { /* List entry */ @@ -666,7 +665,6 @@ int unzip_main(int argc, char **argv) } } i = 'n'; - } else { /* Extract file */ check_file: diff --git a/console-tools/showkey.c b/console-tools/showkey.c index 69b785ec6..b7b4c32a8 100644 --- a/console-tools/showkey.c +++ b/console-tools/showkey.c @@ -83,7 +83,6 @@ int showkey_main(int argc UNUSED_PARAM, char **argv) if (04 /*CTRL-D*/ == c) break; } - } else { // we assume a PC keyboard xioctl(STDIN_FILENO, KDGKBMODE, &kbmode); diff --git a/coreutils/ln.c b/coreutils/ln.c index 3b822e8c7..168814801 100644 --- a/coreutils/ln.c +++ b/coreutils/ln.c @@ -134,7 +134,6 @@ int ln_main(int argc, char **argv) } free(src_name); - } while ((++argv)[1]); return status; diff --git a/editors/awk.c b/editors/awk.c index f487163af..9c6819ad2 100644 --- a/editors/awk.c +++ b/editors/awk.c @@ -1060,12 +1060,10 @@ static uint32_t next_token(uint32_t expected) if (t_rollback) { t_rollback = FALSE; - } else if (concat_inserted) { concat_inserted = FALSE; t_tclass = save_tclass; t_info = save_info; - } else { p = g_pos; readnext: @@ -1081,7 +1079,6 @@ static uint32_t next_token(uint32_t expected) if (*p == '\0') { tc = TC_EOF; debug_printf_parse("%s: token found: TC_EOF\n", __func__); - } else if (*p == '\"') { /* it's a string */ t_string = s = ++p; @@ -1097,7 +1094,6 @@ static uint32_t next_token(uint32_t expected) *s = '\0'; tc = TC_STRING; debug_printf_parse("%s: token found:'%s' TC_STRING\n", __func__, t_string); - } else if ((expected & TC_REGEXP) && *p == '/') { /* it's regexp */ t_string = s = ++p; @@ -1130,7 +1126,6 @@ static uint32_t next_token(uint32_t expected) syntax_error(EMSG_UNEXP_TOKEN); tc = TC_NUMBER; debug_printf_parse("%s: token found:%f TC_NUMBER\n", __func__, t_double); - } else { /* search for something known */ tl = tokenlist; @@ -1580,12 +1575,10 @@ static void parse_program(char *p) debug_printf_parse("%s: TC_BEGIN\n", __func__); seq = &beginseq; chain_group(); - } else if (tclass & TC_END) { debug_printf_parse("%s: TC_END\n", __func__); seq = &endseq; chain_group(); - } else if (tclass & TC_FUNCDECL) { debug_printf_parse("%s: TC_FUNCDECL\n", __func__); next_token(TC_FUNCTION); @@ -1603,7 +1596,6 @@ static void parse_program(char *p) seq = &f->body; chain_group(); clear_array(ahash); - } else if (tclass & TC_OPSEQ) { debug_printf_parse("%s: TC_OPSEQ\n", __func__); rollback_token(); @@ -1618,7 +1610,6 @@ static void parse_program(char *p) chain_node(OC_PRINT); } cn->r.n = mainseq.last; - } else /* if (tclass & TC_GRPSTART) */ { debug_printf_parse("%s: TC_GRPSTART(?)\n", __func__); rollback_token(); @@ -1879,13 +1870,10 @@ static void handle_special(var *v) split_f0(); mk_splitter(getvar_s(v), &fsplitter); - } else if (v == intvar[RS]) { mk_splitter(getvar_s(v), &rsplitter); - } else if (v == intvar[IGNORECASE]) { icase = istrue(v); - } else { /* $n */ n = getvar_i(intvar[NF]); setvar_i(intvar[NF], n > v-Fields ? n : v-Fields+1); diff --git a/editors/ed.c b/editors/ed.c index 3087fb0b9..f0e5e4d5d 100644 --- a/editors/ed.c +++ b/editors/ed.c @@ -732,7 +732,6 @@ static int readLines(const char *file, int num) cc = safe_read(fd, bufPtr, bufSize - bufUsed); bufUsed += cc; bufPtr = bufBase; - } while (cc > 0); if (cc < 0) { diff --git a/editors/vi.c b/editors/vi.c index 6ce513c0c..3db597ae1 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -411,7 +411,6 @@ struct globals { char undo_text[1]; // text that was deleted (if deletion) } *undo_stack_tail; #endif /* ENABLE_FEATURE_VI_UNDO */ - }; #define G (*ptr_to_globals) #define text (G.text ) diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 46849e4f0..24253cf27 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -457,7 +457,6 @@ static void parse_config_file(void) errmsg = "keyword outside section"; goto pe_label; } - } /* while (1) */ pe_label: diff --git a/libbb/in_ether.c b/libbb/in_ether.c index 1de383bde..161c8ea3c 100644 --- a/libbb/in_ether.c +++ b/libbb/in_ether.c @@ -51,7 +51,6 @@ int FAST_FUNC in_ether(const char *bufp, struct sockaddr *sap) } while (j); *ptr++ = val; - } while (--i); /* Error if we aren't at end of string */ diff --git a/libbb/procps.c b/libbb/procps.c index 948b91ee6..3d335b37b 100644 --- a/libbb/procps.c +++ b/libbb/procps.c @@ -614,7 +614,6 @@ void FAST_FUNC read_cmdline(char *buf, int col, unsigned pid, const char *comm) buf[comm_len - 1] = ' '; buf[col - 1] = '\0'; } - } else { snprintf(buf, col, "[%s]", comm); } diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index f25ce9446..0c9969640 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c @@ -207,7 +207,6 @@ off_t FAST_FUNC fdlength(int fd) else bottom = pos; // If we can't, it's smaller. - } else { if (bottom == top) { if (!top) return 0; diff --git a/mailutils/reformime.c b/mailutils/reformime.c index 8e7d455f6..86b2cfed3 100644 --- a/mailutils/reformime.c +++ b/mailutils/reformime.c @@ -134,7 +134,6 @@ static int parse(const char *boundary, char **argv) if (strcasecmp(type + 10, "mixed") != 0) bb_error_msg_and_die("no support of content type '%s'", type); parse(xfind_token(tokens, "boundary"), argv); - } else { /* No, process one non-multipart section */ char *end; diff --git a/miscutils/crontab.c b/miscutils/crontab.c index aad242fd8..85c6623b2 100644 --- a/miscutils/crontab.c +++ b/miscutils/crontab.c @@ -170,7 +170,6 @@ int crontab_main(int argc UNUSED_PARAM, char **argv) unlink(tmp_fname); /*free(tmp_fname);*/ /*free(new_fname);*/ - } /* switch */ /* Bump notification file. Handle window where crond picks file up diff --git a/networking/arp.c b/networking/arp.c index e79b1b6a1..0099aa534 100644 --- a/networking/arp.c +++ b/networking/arp.c @@ -68,7 +68,6 @@ struct globals { const struct hwtype *hw; /* current hardware type */ const char *device; /* current device */ smallint hw_set; /* flag if hw-type was set (-H) */ - } FIX_ALIASING; #define G (*(struct globals*)&bb_common_bufsiz1) #define ap (G.ap ) diff --git a/networking/ntpd.c b/networking/ntpd.c index 0233ed82c..b5120a70d 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -1497,7 +1497,6 @@ update_local_clock(peer_t *p) #endif abs_offset = offset = 0; set_new_values(STATE_SYNC, offset, recv_time); - } else { /* abs_offset <= STEP_THRESHOLD */ /* The ratio is calculated before jitter is updated to make diff --git a/networking/tftp.c b/networking/tftp.c index 7c0ee58d7..8ecd7bb6f 100644 --- a/networking/tftp.c +++ b/networking/tftp.c @@ -348,7 +348,6 @@ static int tftp_protocol( * as if it is "block 0" */ block_nr = 0; } - } else { /* tftp */ /* Open file (must be after changing user) */ local_fd = CMD_GET(option_mask32) ? STDOUT_FILENO : STDIN_FILENO; diff --git a/networking/wget.c b/networking/wget.c index 6c8bd90a8..f744ea2de 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -1050,7 +1050,6 @@ However, in real world it was observed that some web servers /* For HTTP, data is pumped over the same connection */ dfp = sfp; - } else { /* * FTP session diff --git a/selinux/setfiles.c b/selinux/setfiles.c index 0173db99e..c974c4a9d 100644 --- a/selinux/setfiles.c +++ b/selinux/setfiles.c @@ -251,7 +251,6 @@ static int match(const char *name, struct stat *sb, char **con) name = path; if (excludeCtr > 0 && exclude(name)) goto err; - } else { char *p; p = realpath(name, path); diff --git a/shell/ash.c b/shell/ash.c index 282f761fc..4c01e67d4 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -9447,7 +9447,6 @@ evalcommand(union node *cmd, int flags) if (evalfun(cmdentry.u.func, argc, argv, flags)) goto raise; break; - } /* switch */ out: @@ -11763,7 +11762,6 @@ parsearith: { goto parsearith_return; } #endif - } /* end of readtoken */ /* diff --git a/shell/hush.c b/shell/hush.c index 96c739fb7..3ca04494c 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -5390,7 +5390,6 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)); } break; - } /* switch (char after ) */ if (val && val[0]) { diff --git a/shell/shell_common.c b/shell/shell_common.c index 57297155e..2b6f7dc92 100644 --- a/shell/shell_common.c +++ b/shell/shell_common.c @@ -493,7 +493,6 @@ shell_builtin_ulimit(char **argv) /* bad option. getopt already complained. */ break; } - } /* while (there are options) */ return 0; diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index 266657f3b..156f487e5 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c @@ -237,7 +237,6 @@ enum { OPT_dup = IF_FEATURE_SYSLOGD_DUP( (1 << OPTBIT_dup )) + 0, OPT_cfg = IF_FEATURE_SYSLOGD_CFG( (1 << OPTBIT_cfg )) + 0, OPT_kmsg = IF_FEATURE_KMSG_SYSLOG( (1 << OPTBIT_kmsg )) + 0, - }; #define OPTION_STR "m:nO:l:S" \ IF_FEATURE_ROTATE_LOGFILE("s:" ) \ From 0e056f7e9efcebbbb85444221e141b37d3ab79e6 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Wed, 1 Jul 2015 16:45:40 +0100 Subject: [PATCH 158/256] ash: remove parsebackquote flag Commit 503a0b8 from git://git.kernel.org/pub/scm/utils/dash/dash.git by Herbert Xu says: >The parsebackquote flag is only used in a test where it always has the >value zero. So we can remove it altogether. The first statement is incorrect: parsebackquote is non-zero when backquotes (as opposed to $(...)) are used for command substitution. It is possible for the test to be executed with parsebackquote != 0 in that case. The test is question checks whether quotes have been closed, raising the error "unterminated quoted string" if they haven't. There seems to be no good reason to allow unclosed quotes within backquotes. Bash, hush and dash (after commit 503a0b8) all treat the following as an error: XX=`"pwd` whereas BusyBox ash doesn't. It just ignores the unclosed quote and executes pwd. So, parsebackquote should be removed but not for the reason stated. function old new delta parsebackquote 1 - -1 readtoken1 3222 3182 -40 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 0/1 up/down: 0/-41) Total: -41 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- shell/ash.c | 8 +------- shell/ash_test/ash-misc/tickquote1.right | 1 + shell/ash_test/ash-misc/tickquote1.tests | 1 + 3 files changed, 3 insertions(+), 7 deletions(-) create mode 100644 shell/ash_test/ash-misc/tickquote1.right create mode 100755 shell/ash_test/ash-misc/tickquote1.tests diff --git a/shell/ash.c b/shell/ash.c index 4c01e67d4..6627cec9b 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -10473,7 +10473,6 @@ struct heredoc { }; static smallint tokpushback; /* last token pushed back */ -static smallint parsebackquote; /* nonzero if we are inside backquotes */ static smallint quoteflag; /* set if (part of) last token was quoted */ static token_id_t lasttoken; /* last token read (integer id Txxx) */ static struct heredoc *heredoclist; /* list of here documents to read */ @@ -11313,7 +11312,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) if (syntax == ARISYNTAX) raise_error_syntax("missing '))'"); #endif - if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL) + if (syntax != BASESYNTAX && eofmark == NULL) raise_error_syntax("unterminated quoted string"); if (varnest != 0) { startlinno = g_parsefile->linno; @@ -11609,7 +11608,6 @@ parsesub: { */ parsebackq: { struct nodelist **nlpp; - smallint savepbq; union node *n; char *volatile str; struct jmploc jmploc; @@ -11620,10 +11618,8 @@ parsebackq: { #ifdef __GNUC__ (void) &saveprompt; #endif - savepbq = parsebackquote; if (setjmp(jmploc.loc)) { free(str); - parsebackquote = 0; exception_handler = savehandler; longjmp(exception_handler->loc, 1); } @@ -11707,7 +11703,6 @@ parsebackq: { nlpp = &(*nlpp)->next; *nlpp = stzalloc(sizeof(**nlpp)); /* (*nlpp)->next = NULL; - stzalloc did it */ - parsebackquote = oldstyle; if (oldstyle) { saveprompt = doprompt; @@ -11741,7 +11736,6 @@ parsebackq: { str = NULL; INT_ON; } - parsebackquote = savepbq; exception_handler = savehandler; USTPUTC(CTLBACKQ, out); if (oldstyle) diff --git a/shell/ash_test/ash-misc/tickquote1.right b/shell/ash_test/ash-misc/tickquote1.right new file mode 100644 index 000000000..2e661bfe3 --- /dev/null +++ b/shell/ash_test/ash-misc/tickquote1.right @@ -0,0 +1 @@ +./tickquote1.tests: line 1: syntax error: unterminated quoted string diff --git a/shell/ash_test/ash-misc/tickquote1.tests b/shell/ash_test/ash-misc/tickquote1.tests new file mode 100755 index 000000000..90d5bbc9b --- /dev/null +++ b/shell/ash_test/ash-misc/tickquote1.tests @@ -0,0 +1 @@ +echo `"pwd` From f54a487bb4d36a4318c5ec539f8265fdff2cac90 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 13 Jul 2015 03:52:32 +0200 Subject: [PATCH 159/256] fix file mode Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-misc/echo_write_error.tests | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 shell/ash_test/ash-misc/echo_write_error.tests diff --git a/shell/ash_test/ash-misc/echo_write_error.tests b/shell/ash_test/ash-misc/echo_write_error.tests old mode 100644 new mode 100755 From 072fc60f29ee3a4ff38f095a9ef149b2e820c8c0 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Wed, 1 Jul 2015 16:46:18 +0100 Subject: [PATCH 160/256] ash: use alloca to get rid of setjmp Now that the only thing protected by setjmp/longjmp is the saved string, we can allocate it on the stack to get rid of the jump. Based on commit bd35d8e from git://git.kernel.org/pub/scm/utils/dash/dash.git by Herbert Xu. function old new delta readtoken1 3182 3116 -66 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-66) Total: -66 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- shell/ash.c | 36 ++---------------------------------- 1 file changed, 2 insertions(+), 34 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 6627cec9b..f4779ee2b 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -11132,19 +11132,6 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) IF_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;) -#if __GNUC__ - /* Avoid longjmp clobbering */ - (void) &out; - (void) "ef; - (void) &dblquote; - (void) &varnest; - (void) &arinest; - (void) &parenlevel; - (void) &dqvarnest; - (void) &oldstyle; - (void) &prevsyntax; - (void) &syntax; -#endif startlinno = g_parsefile->linno; bqlist = NULL; quotef = 0; @@ -11609,30 +11596,16 @@ parsesub: { parsebackq: { struct nodelist **nlpp; union node *n; - char *volatile str; - struct jmploc jmploc; - struct jmploc *volatile savehandler; + char *str; size_t savelen; smallint saveprompt = 0; -#ifdef __GNUC__ - (void) &saveprompt; -#endif - if (setjmp(jmploc.loc)) { - free(str); - exception_handler = savehandler; - longjmp(exception_handler->loc, 1); - } - INT_OFF; str = NULL; savelen = out - (char *)stackblock(); if (savelen > 0) { - str = ckmalloc(savelen); + str = alloca(savelen); memcpy(str, stackblock(), savelen); } - savehandler = exception_handler; - exception_handler = &jmploc; - INT_ON; if (oldstyle) { /* We must read until the closing backquote, giving special * treatment to some slashes, and then push the string and @@ -11731,12 +11704,7 @@ parsebackq: { if (str) { memcpy(out, str, savelen); STADJUST(savelen, out); - INT_OFF; - free(str); - str = NULL; - INT_ON; } - exception_handler = savehandler; USTPUTC(CTLBACKQ, out); if (oldstyle) goto parsebackq_oldreturn; From 51aa861843002e92b605be840460e7141d4d86a2 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Sun, 19 Jul 2015 11:12:29 +0100 Subject: [PATCH 161/256] less: document -S flag and make it independently configurable The -S flag, to cause long lines to be truncated, was enabled by FEATURE_LESS_DASHCMD. This is non-obvious and -S is useful even if the '-' command isn't enabled. function old new delta .rodata 156045 156077 +32 packed_usage 30223 30244 +21 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 53/0) Total: 53 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- miscutils/less.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/miscutils/less.c b/miscutils/less.c index d5a68d1e1..c1755655a 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -48,6 +48,14 @@ //config: help //config: The -M/-m flag enables a more sophisticated status line. //config: +//config:config FEATURE_LESS_TRUNCATE +//config: bool "Enable -S" +//config: default y +//config: depends on LESS +//config: help +//config: The -S flag causes long lines to be truncated rather than +//config: wrapped. +//config: //config:config FEATURE_LESS_MARKS //config: bool "Enable marks" //config: default y @@ -98,7 +106,8 @@ //config: Enables "-N" command. //usage:#define less_trivial_usage -//usage: "[-E" IF_FEATURE_LESS_REGEXP("I")IF_FEATURE_LESS_FLAGS("Mm") "Nh~] [FILE]..." +//usage: "[-E" IF_FEATURE_LESS_REGEXP("I")IF_FEATURE_LESS_FLAGS("Mm") +//usage: "N" IF_FEATURE_LESS_TRUNCATE("S") "h~] [FILE]..." //usage:#define less_full_usage "\n\n" //usage: "View FILE (or stdin) one screenful at a time\n" //usage: "\n -E Quit once the end of a file is reached" @@ -110,6 +119,9 @@ //usage: "\n and percentage through the file" //usage: ) //usage: "\n -N Prefix line number to each line" +//usage: IF_FEATURE_LESS_TRUNCATE( +//usage: "\n -S Truncate long lines" +//usage: ) //usage: "\n -~ Suppress ~s displayed past EOF" #include /* sched_yield() */ @@ -144,7 +156,7 @@ enum { FLAG_N = 1 << 3, FLAG_TILDE = 1 << 4, FLAG_I = 1 << 5, - FLAG_S = (1 << 6) * ENABLE_FEATURE_LESS_DASHCMD, + FLAG_S = (1 << 6) * ENABLE_FEATURE_LESS_TRUNCATE, /* hijack command line options variable for internal state vars */ LESS_STATE_MATCH_BACKWARDS = 1 << 15, }; @@ -820,7 +832,7 @@ static void buffer_print(void) static void buffer_fill_and_print(void) { unsigned i; -#if ENABLE_FEATURE_LESS_DASHCMD +#if ENABLE_FEATURE_LESS_TRUNCATE int fpos = cur_fline; if (option_mask32 & FLAG_S) { @@ -1330,10 +1342,12 @@ static void flag_change(void) case '~': option_mask32 ^= FLAG_TILDE; break; +#if ENABLE_FEATURE_LESS_TRUNCATE case 'S': option_mask32 ^= FLAG_S; buffer_fill_and_print(); break; +#endif #if ENABLE_FEATURE_LESS_LINENUMS case 'N': option_mask32 ^= FLAG_N; @@ -1638,7 +1652,7 @@ int less_main(int argc, char **argv) * -s: condense many empty lines to one * (used by some setups for manpage display) */ - getopt32(argv, "EMmN~I" IF_FEATURE_LESS_DASHCMD("S") /*ignored:*/"s"); + getopt32(argv, "EMmN~I" IF_FEATURE_LESS_TRUNCATE("S") /*ignored:*/"s"); argc -= optind; argv += optind; num_files = argc; From f06386ad4f5e1e5b5a3aea71ac757d5be8574067 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Sat, 18 Jul 2015 16:20:03 +0100 Subject: [PATCH 162/256] less: fix display of line numbers Line numbers are displayed incorrectly on lines that have a search pattern highlighted. The problem can be fixed by moving the call to lineno_str in print_found above the while loop that alters the value of the line pointer. However, a more substantial rewrite results in savings. function old new delta buffer_print 688 697 +9 .rodata 156077 156045 -32 lineno_str 85 - -85 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 1/1 up/down: 9/-117) Total: -108 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- miscutils/less.c | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/miscutils/less.c b/miscutils/less.c index c1755655a..7c46ba5cc 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -677,27 +677,21 @@ static const char ctrlconv[] ALIGN1 = "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x40\x4b\x4c\x4d\x4e\x4f" "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"; -static void lineno_str(char *nbuf9, const char *line) +static void print_lineno(const char *line) { - nbuf9[0] = '\0'; - if (option_mask32 & FLAG_N) { - const char *fmt; - unsigned n; + const char *fmt = " "; + unsigned n = n; /* for compiler */ - if (line == empty_line_marker) { - memset(nbuf9, ' ', 8); - nbuf9[8] = '\0'; - return; - } + if (line != empty_line_marker) { /* Width of 7 preserves tab spacing in the text */ fmt = "%7u "; n = LINENO(line) + 1; - if (n > 9999999) { + if (n > 9999999 && MAXLINES > 9999999) { n %= 10000000; fmt = "%07u "; } - sprintf(nbuf9, fmt, n); } + printf(fmt, n); } @@ -710,7 +704,6 @@ static void print_found(const char *line) regmatch_t match_structs; char buf[width]; - char nbuf9[9]; const char *str = line; char *p = buf; size_t n; @@ -760,12 +753,7 @@ static void print_found(const char *line) match_status = 1; } - lineno_str(nbuf9, line); - if (!growline) { - printf(CLEAR_2_EOL"%s%s\n", nbuf9, str); - return; - } - printf(CLEAR_2_EOL"%s%s%s\n", nbuf9, growline, str); + printf("%s%s\n", growline ? growline : "", str); free(growline); } #else @@ -775,13 +763,9 @@ void print_found(const char *line); static void print_ascii(const char *str) { char buf[width]; - char nbuf9[9]; char *p; size_t n; - lineno_str(nbuf9, str); - printf(CLEAR_2_EOL"%s", nbuf9); - while (*str) { n = strcspn(str, controls); if (n) { @@ -815,6 +799,9 @@ static void buffer_print(void) move_cursor(0, 0); for (i = 0; i <= max_displayed_line; i++) { + printf(CLEAR_2_EOL); + if (option_mask32 & FLAG_N) + print_lineno(buffer[i]); if (pattern_valid) print_found(buffer[i]); else From 78cfa00154dca18a1326d2064121bf65cd081781 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Sun, 19 Jul 2015 21:41:09 +0100 Subject: [PATCH 163/256] less: correctly account for tabs when rewrapping lines Lines are rewrapped when the terminal width changes or line numbers are enabled/disabled. The current calculation always adds eight to the line length for a tab whereas it should only add enough to move to the next tab stop. This doesn't affect the display of lines, which is handled elsewhere and gets tab stops right, but it does cause lines to be wrapped at the wrong position. Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- miscutils/less.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/miscutils/less.c b/miscutils/less.c index 7c46ba5cc..90c103888 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -331,8 +331,10 @@ static void re_wrap(void) *d = *s; if (*d != '\0') { new_line_pos++; - if (*d == '\t') /* tab */ + if (*d == '\t') { /* tab */ new_line_pos += 7; + new_line_pos &= (~7); + } s++; d++; if (new_line_pos >= w) { From d840c5d139cfa50fbe4f6f67c178b0edf0c690c8 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Sun, 19 Jul 2015 23:05:20 +0200 Subject: [PATCH 164/256] libbb: add a function to make a copy of a region of memory Introduce a library routine to package the idiom: p = xmalloc(b, n); memcpy(p, b, n); and use it where possible. The example in traceroute used xzalloc but it didn't need to. function old new delta xmemdup - 32 +32 last_main 834 826 -8 make_device 2321 2311 -10 common_traceroute_main 3698 3685 -13 readtoken1 3182 3168 -14 procps_scan 1222 1206 -16 forkchild 655 638 -17 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/6 up/down: 32/-78) Total: -46 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- include/libbb.h | 1 + libbb/procps.c | 3 +-- libbb/xfuncs_printf.c | 5 +++++ miscutils/last_fancy.c | 4 ++-- networking/traceroute.c | 11 +---------- networking/udhcp/d6_dhcpc.c | 2 +- shell/ash.c | 2 +- util-linux/mdev.c | 2 +- 8 files changed, 13 insertions(+), 17 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index f0ac1f50d..54d01b75a 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -673,6 +673,7 @@ uint16_t inet_cksum(uint16_t *addr, int len) FAST_FUNC; char *xstrdup(const char *s) FAST_FUNC RETURNS_MALLOC; char *xstrndup(const char *s, int n) FAST_FUNC RETURNS_MALLOC; +void *xmemdup(const void *s, int n) FAST_FUNC RETURNS_MALLOC; void overlapping_strcpy(char *dst, const char *src) FAST_FUNC; char *safe_strncpy(char *dst, const char *src, size_t size) FAST_FUNC; char *strncpy_IFNAMSIZ(char *dst, const char *src) FAST_FUNC; diff --git a/libbb/procps.c b/libbb/procps.c index 3d335b37b..71ad071e6 100644 --- a/libbb/procps.c +++ b/libbb/procps.c @@ -554,8 +554,7 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags) break; if (flags & PSSCAN_ARGVN) { sp->argv_len = n; - sp->argv0 = xmalloc(n + 1); - memcpy(sp->argv0, buf, n + 1); + sp->argv0 = xmemdup(buf, n + 1); /* sp->argv0[n] = '\0'; - buf has it */ } else { sp->argv_len = 0; 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) return memcpy(t, s, n); } +void* FAST_FUNC xmemdup(const void *s, int n) +{ + return memcpy(xmalloc(n), s, n); +} + // Die if we can't open a file and return a FILE* to it. // Notice we haven't got xfread(), This is for use with fscanf() and friends. FILE* FAST_FUNC xfopen(const char *path, const char *mode) 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) break; } /* add_entry */ - llist_add_to(&zlist, memcpy(xmalloc(sizeof(ut)), &ut, sizeof(ut))); + llist_add_to(&zlist, xmemdup(&ut, sizeof(ut))); break; case USER_PROCESS: { int show; @@ -275,7 +275,7 @@ int last_main(int argc UNUSED_PARAM, char **argv) show_entry(&ut, state, boot_time); } /* add_entry */ - llist_add_to(&zlist, memcpy(xmalloc(sizeof(ut)), &ut, sizeof(ut))); + llist_add_to(&zlist, xmemdup(&ut, sizeof(ut))); break; } } diff --git a/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 { #define outudp ((struct udphdr *)(outip + 1)) -/* libbb candidate? tftp uses this idiom too */ -static len_and_sockaddr* dup_sockaddr(const len_and_sockaddr *lsa) -{ - len_and_sockaddr *new_lsa = xzalloc(LSA_LEN_SIZE + lsa->len); - memcpy(new_lsa, lsa, LSA_LEN_SIZE + lsa->len); - return new_lsa; -} - - static int wait_for_reply(len_and_sockaddr *from_lsa, struct sockaddr *to, unsigned *timestamp_us, int *left_ms) { @@ -1074,7 +1065,7 @@ common_traceroute_main(int op, char **argv) printf(" from %s", source); printf(", %d hops max, %d byte packets\n", max_ttl, packlen); - from_lsa = dup_sockaddr(dest_lsa); + from_lsa = xmemdup(dest_lsa, LSA_LEN_SIZE + dest_lsa->len); lastaddr = xzalloc(dest_lsa->len); to = xzalloc(dest_lsa->len); seq = 0; 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) uint8_t *opt = d6_find_option(option, option_end, code); if (!opt) return opt; - return memcpy(xmalloc(opt[3] + 4), opt, opt[3] + 4); + return xmemdup(opt, opt[3] + 4); } static void *d6_store_blob(void *dst, const void *src, unsigned len) diff --git a/shell/ash.c b/shell/ash.c index f4779ee2b..f6190c3e2 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -4751,7 +4751,7 @@ forkchild(struct job *jp, union node *n, int mode) * Our solution: ONLY bare $(trap) or `trap` is special. */ /* Save trap handler strings for trap builtin to print */ - trap_ptr = memcpy(xmalloc(sizeof(trap)), trap, sizeof(trap)); + trap_ptr = xmemdup(trap, sizeof(trap)); /* Fall through into clearing traps */ } clear_traps(); 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) if (G.parser) { parse_next_rule(); if (G.rule_vec) { /* mdev -s */ - rule = memcpy(xmalloc(sizeof(G.cur_rule)), &G.cur_rule, sizeof(G.cur_rule)); + rule = xmemdup(&G.cur_rule, sizeof(G.cur_rule)); G.rule_vec = xrealloc_vector(G.rule_vec, 4, G.rule_idx); G.rule_vec[G.rule_idx++] = rule; dbg3("> G.rule_vec[G.rule_idx:%d]=%p", G.rule_idx, G.rule_vec[G.rule_idx]); From ce193f809b32368796a3aacf2ac8ba277f4c102a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 19 Jul 2015 23:12:51 +0200 Subject: [PATCH 165/256] Remove old_e2fsprogs/* Signed-off-by: Denys Vlasenko --- e2fsprogs/old_e2fsprogs/Config.src | 69 - e2fsprogs/old_e2fsprogs/Kbuild.src | 18 - e2fsprogs/old_e2fsprogs/README | 3 - e2fsprogs/old_e2fsprogs/blkid/Kbuild.src | 26 - e2fsprogs/old_e2fsprogs/blkid/blkid.h | 104 - e2fsprogs/old_e2fsprogs/blkid/blkidP.h | 182 - e2fsprogs/old_e2fsprogs/blkid/blkid_getsize.c | 179 - e2fsprogs/old_e2fsprogs/blkid/cache.c | 125 - e2fsprogs/old_e2fsprogs/blkid/dev.c | 212 - e2fsprogs/old_e2fsprogs/blkid/devname.c | 367 - e2fsprogs/old_e2fsprogs/blkid/devno.c | 222 - e2fsprogs/old_e2fsprogs/blkid/list.c | 110 - e2fsprogs/old_e2fsprogs/blkid/list.h | 73 - e2fsprogs/old_e2fsprogs/blkid/probe.c | 726 - e2fsprogs/old_e2fsprogs/blkid/probe.h | 374 - e2fsprogs/old_e2fsprogs/blkid/read.c | 459 - e2fsprogs/old_e2fsprogs/blkid/resolve.c | 139 - e2fsprogs/old_e2fsprogs/blkid/save.c | 189 - e2fsprogs/old_e2fsprogs/blkid/tag.c | 431 - e2fsprogs/old_e2fsprogs/chattr.c | 220 - e2fsprogs/old_e2fsprogs/e2fsbb.h | 43 - e2fsprogs/old_e2fsprogs/e2fsck.c | 13516 ---------------- e2fsprogs/old_e2fsprogs/e2fsck.h | 638 - e2fsprogs/old_e2fsprogs/e2p/Kbuild.src | 18 - e2fsprogs/old_e2fsprogs/e2p/e2p.h | 64 - e2fsprogs/old_e2fsprogs/e2p/feature.c | 187 - e2fsprogs/old_e2fsprogs/e2p/fgetsetflags.c | 70 - e2fsprogs/old_e2fsprogs/e2p/fgetsetversion.c | 70 - e2fsprogs/old_e2fsprogs/e2p/hashstr.c | 70 - e2fsprogs/old_e2fsprogs/e2p/iod.c | 52 - e2fsprogs/old_e2fsprogs/e2p/ls.c | 273 - e2fsprogs/old_e2fsprogs/e2p/mntopts.c | 134 - e2fsprogs/old_e2fsprogs/e2p/ostype.c | 72 - e2fsprogs/old_e2fsprogs/e2p/parse_num.c | 65 - e2fsprogs/old_e2fsprogs/e2p/pe.c | 32 - e2fsprogs/old_e2fsprogs/e2p/pf.c | 74 - e2fsprogs/old_e2fsprogs/e2p/ps.c | 27 - e2fsprogs/old_e2fsprogs/e2p/uuid.c | 78 - e2fsprogs/old_e2fsprogs/ext2fs/Kbuild.src | 26 - e2fsprogs/old_e2fsprogs/ext2fs/alloc.c | 173 - e2fsprogs/old_e2fsprogs/ext2fs/alloc_sb.c | 58 - e2fsprogs/old_e2fsprogs/ext2fs/alloc_stats.c | 53 - e2fsprogs/old_e2fsprogs/ext2fs/alloc_tables.c | 114 - e2fsprogs/old_e2fsprogs/ext2fs/badblocks.c | 328 - e2fsprogs/old_e2fsprogs/ext2fs/bb_compat.c | 64 - e2fsprogs/old_e2fsprogs/ext2fs/bb_inode.c | 262 - e2fsprogs/old_e2fsprogs/ext2fs/bitmaps.c | 211 - e2fsprogs/old_e2fsprogs/ext2fs/bitops.c | 90 - e2fsprogs/old_e2fsprogs/ext2fs/bitops.h | 105 - e2fsprogs/old_e2fsprogs/ext2fs/block.c | 437 - e2fsprogs/old_e2fsprogs/ext2fs/bmap.c | 261 - e2fsprogs/old_e2fsprogs/ext2fs/bmove.c | 155 - e2fsprogs/old_e2fsprogs/ext2fs/brel.h | 86 - e2fsprogs/old_e2fsprogs/ext2fs/brel_ma.c | 196 - e2fsprogs/old_e2fsprogs/ext2fs/check_desc.c | 69 - e2fsprogs/old_e2fsprogs/ext2fs/closefs.c | 380 - e2fsprogs/old_e2fsprogs/ext2fs/cmp_bitmaps.c | 72 - e2fsprogs/old_e2fsprogs/ext2fs/dblist.c | 260 - e2fsprogs/old_e2fsprogs/ext2fs/dblist_dir.c | 76 - e2fsprogs/old_e2fsprogs/ext2fs/dir_iterate.c | 219 - e2fsprogs/old_e2fsprogs/ext2fs/dirblock.c | 132 - e2fsprogs/old_e2fsprogs/ext2fs/dirhash.c | 234 - e2fsprogs/old_e2fsprogs/ext2fs/dupfs.c | 95 - e2fsprogs/old_e2fsprogs/ext2fs/e2image.h | 39 - e2fsprogs/old_e2fsprogs/ext2fs/expanddir.c | 127 - e2fsprogs/old_e2fsprogs/ext2fs/ext2_err.h | 116 - .../old_e2fsprogs/ext2fs/ext2_ext_attr.h | 52 - e2fsprogs/old_e2fsprogs/ext2fs/ext2_fs.h | 569 - e2fsprogs/old_e2fsprogs/ext2fs/ext2_io.h | 112 - e2fsprogs/old_e2fsprogs/ext2fs/ext2_types.h | 2 - e2fsprogs/old_e2fsprogs/ext2fs/ext2fs.h | 922 -- e2fsprogs/old_e2fsprogs/ext2fs/ext2fsP.h | 87 - .../old_e2fsprogs/ext2fs/ext2fs_inline.c | 365 - e2fsprogs/old_e2fsprogs/ext2fs/ext_attr.c | 101 - e2fsprogs/old_e2fsprogs/ext2fs/fileio.c | 377 - e2fsprogs/old_e2fsprogs/ext2fs/finddev.c | 199 - e2fsprogs/old_e2fsprogs/ext2fs/flushb.c | 83 - e2fsprogs/old_e2fsprogs/ext2fs/freefs.c | 127 - e2fsprogs/old_e2fsprogs/ext2fs/gen_bitmap.c | 49 - e2fsprogs/old_e2fsprogs/ext2fs/get_pathname.c | 156 - e2fsprogs/old_e2fsprogs/ext2fs/getsectsize.c | 58 - e2fsprogs/old_e2fsprogs/ext2fs/getsize.c | 291 - e2fsprogs/old_e2fsprogs/ext2fs/icount.c | 467 - e2fsprogs/old_e2fsprogs/ext2fs/imager.c | 377 - e2fsprogs/old_e2fsprogs/ext2fs/ind_block.c | 69 - e2fsprogs/old_e2fsprogs/ext2fs/initialize.c | 388 - e2fsprogs/old_e2fsprogs/ext2fs/inline.c | 32 - e2fsprogs/old_e2fsprogs/ext2fs/inode.c | 766 - e2fsprogs/old_e2fsprogs/ext2fs/inode_io.c | 270 - e2fsprogs/old_e2fsprogs/ext2fs/io_manager.c | 70 - e2fsprogs/old_e2fsprogs/ext2fs/irel.h | 115 - e2fsprogs/old_e2fsprogs/ext2fs/irel_ma.c | 367 - e2fsprogs/old_e2fsprogs/ext2fs/ismounted.c | 357 - e2fsprogs/old_e2fsprogs/ext2fs/jfs_dat.h | 63 - e2fsprogs/old_e2fsprogs/ext2fs/kernel-jbd.h | 235 - e2fsprogs/old_e2fsprogs/ext2fs/kernel-list.h | 113 - e2fsprogs/old_e2fsprogs/ext2fs/link.c | 135 - e2fsprogs/old_e2fsprogs/ext2fs/lookup.c | 68 - e2fsprogs/old_e2fsprogs/ext2fs/mkdir.c | 139 - e2fsprogs/old_e2fsprogs/ext2fs/mkjournal.c | 426 - e2fsprogs/old_e2fsprogs/ext2fs/namei.c | 204 - e2fsprogs/old_e2fsprogs/ext2fs/newdir.c | 72 - e2fsprogs/old_e2fsprogs/ext2fs/openfs.c | 330 - e2fsprogs/old_e2fsprogs/ext2fs/read_bb.c | 96 - e2fsprogs/old_e2fsprogs/ext2fs/read_bb_file.c | 96 - e2fsprogs/old_e2fsprogs/ext2fs/res_gdt.c | 220 - e2fsprogs/old_e2fsprogs/ext2fs/rs_bitmap.c | 106 - e2fsprogs/old_e2fsprogs/ext2fs/rw_bitmaps.c | 294 - e2fsprogs/old_e2fsprogs/ext2fs/sparse.c | 79 - e2fsprogs/old_e2fsprogs/ext2fs/swapfs.c | 234 - e2fsprogs/old_e2fsprogs/ext2fs/test_io.c | 380 - e2fsprogs/old_e2fsprogs/ext2fs/unix_io.c | 703 - e2fsprogs/old_e2fsprogs/ext2fs/unlink.c | 99 - e2fsprogs/old_e2fsprogs/ext2fs/valid_blk.c | 57 - e2fsprogs/old_e2fsprogs/ext2fs/version.c | 51 - .../old_e2fsprogs/ext2fs/write_bb_file.c | 35 - e2fsprogs/old_e2fsprogs/fsck.c | 1371 -- e2fsprogs/old_e2fsprogs/fsck.h | 16 - e2fsprogs/old_e2fsprogs/lsattr.c | 129 - e2fsprogs/old_e2fsprogs/mke2fs.c | 1333 -- e2fsprogs/old_e2fsprogs/tune2fs.c | 710 - e2fsprogs/old_e2fsprogs/util.c | 263 - e2fsprogs/old_e2fsprogs/util.h | 22 - e2fsprogs/old_e2fsprogs/uuid/Kbuild.src | 16 - e2fsprogs/old_e2fsprogs/uuid/compare.c | 55 - e2fsprogs/old_e2fsprogs/uuid/gen_uuid.c | 304 - e2fsprogs/old_e2fsprogs/uuid/pack.c | 69 - e2fsprogs/old_e2fsprogs/uuid/parse.c | 80 - e2fsprogs/old_e2fsprogs/uuid/unpack.c | 63 - e2fsprogs/old_e2fsprogs/uuid/unparse.c | 77 - e2fsprogs/old_e2fsprogs/uuid/uuid.h | 103 - e2fsprogs/old_e2fsprogs/uuid/uuidP.h | 60 - e2fsprogs/old_e2fsprogs/uuid/uuid_time.c | 161 - 133 files changed, 40044 deletions(-) delete mode 100644 e2fsprogs/old_e2fsprogs/Config.src delete mode 100644 e2fsprogs/old_e2fsprogs/Kbuild.src delete mode 100644 e2fsprogs/old_e2fsprogs/README delete mode 100644 e2fsprogs/old_e2fsprogs/blkid/Kbuild.src delete mode 100644 e2fsprogs/old_e2fsprogs/blkid/blkid.h delete mode 100644 e2fsprogs/old_e2fsprogs/blkid/blkidP.h delete mode 100644 e2fsprogs/old_e2fsprogs/blkid/blkid_getsize.c delete mode 100644 e2fsprogs/old_e2fsprogs/blkid/cache.c delete mode 100644 e2fsprogs/old_e2fsprogs/blkid/dev.c delete mode 100644 e2fsprogs/old_e2fsprogs/blkid/devname.c delete mode 100644 e2fsprogs/old_e2fsprogs/blkid/devno.c delete mode 100644 e2fsprogs/old_e2fsprogs/blkid/list.c delete mode 100644 e2fsprogs/old_e2fsprogs/blkid/list.h delete mode 100644 e2fsprogs/old_e2fsprogs/blkid/probe.c delete mode 100644 e2fsprogs/old_e2fsprogs/blkid/probe.h delete mode 100644 e2fsprogs/old_e2fsprogs/blkid/read.c delete mode 100644 e2fsprogs/old_e2fsprogs/blkid/resolve.c delete mode 100644 e2fsprogs/old_e2fsprogs/blkid/save.c delete mode 100644 e2fsprogs/old_e2fsprogs/blkid/tag.c delete mode 100644 e2fsprogs/old_e2fsprogs/chattr.c delete mode 100644 e2fsprogs/old_e2fsprogs/e2fsbb.h delete mode 100644 e2fsprogs/old_e2fsprogs/e2fsck.c delete mode 100644 e2fsprogs/old_e2fsprogs/e2fsck.h delete mode 100644 e2fsprogs/old_e2fsprogs/e2p/Kbuild.src delete mode 100644 e2fsprogs/old_e2fsprogs/e2p/e2p.h delete mode 100644 e2fsprogs/old_e2fsprogs/e2p/feature.c delete mode 100644 e2fsprogs/old_e2fsprogs/e2p/fgetsetflags.c delete mode 100644 e2fsprogs/old_e2fsprogs/e2p/fgetsetversion.c delete mode 100644 e2fsprogs/old_e2fsprogs/e2p/hashstr.c delete mode 100644 e2fsprogs/old_e2fsprogs/e2p/iod.c delete mode 100644 e2fsprogs/old_e2fsprogs/e2p/ls.c delete mode 100644 e2fsprogs/old_e2fsprogs/e2p/mntopts.c delete mode 100644 e2fsprogs/old_e2fsprogs/e2p/ostype.c delete mode 100644 e2fsprogs/old_e2fsprogs/e2p/parse_num.c delete mode 100644 e2fsprogs/old_e2fsprogs/e2p/pe.c delete mode 100644 e2fsprogs/old_e2fsprogs/e2p/pf.c delete mode 100644 e2fsprogs/old_e2fsprogs/e2p/ps.c delete mode 100644 e2fsprogs/old_e2fsprogs/e2p/uuid.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/Kbuild.src delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/alloc.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/alloc_sb.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/alloc_stats.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/alloc_tables.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/badblocks.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/bb_compat.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/bb_inode.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/bitmaps.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/bitops.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/bitops.h delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/block.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/bmap.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/bmove.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/brel.h delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/brel_ma.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/check_desc.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/closefs.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/cmp_bitmaps.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/dblist.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/dblist_dir.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/dir_iterate.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/dirblock.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/dirhash.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/dupfs.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/e2image.h delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/expanddir.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/ext2_err.h delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/ext2_ext_attr.h delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/ext2_fs.h delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/ext2_io.h delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/ext2_types.h delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/ext2fs.h delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/ext2fsP.h delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/ext2fs_inline.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/ext_attr.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/fileio.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/finddev.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/flushb.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/freefs.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/gen_bitmap.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/get_pathname.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/getsectsize.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/getsize.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/icount.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/imager.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/ind_block.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/initialize.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/inline.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/inode.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/inode_io.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/io_manager.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/irel.h delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/irel_ma.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/ismounted.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/jfs_dat.h delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/kernel-jbd.h delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/kernel-list.h delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/link.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/lookup.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/mkdir.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/mkjournal.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/namei.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/newdir.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/openfs.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/read_bb.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/read_bb_file.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/res_gdt.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/rs_bitmap.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/rw_bitmaps.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/sparse.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/swapfs.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/test_io.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/unix_io.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/unlink.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/valid_blk.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/version.c delete mode 100644 e2fsprogs/old_e2fsprogs/ext2fs/write_bb_file.c delete mode 100644 e2fsprogs/old_e2fsprogs/fsck.c delete mode 100644 e2fsprogs/old_e2fsprogs/fsck.h delete mode 100644 e2fsprogs/old_e2fsprogs/lsattr.c delete mode 100644 e2fsprogs/old_e2fsprogs/mke2fs.c delete mode 100644 e2fsprogs/old_e2fsprogs/tune2fs.c delete mode 100644 e2fsprogs/old_e2fsprogs/util.c delete mode 100644 e2fsprogs/old_e2fsprogs/util.h delete mode 100644 e2fsprogs/old_e2fsprogs/uuid/Kbuild.src delete mode 100644 e2fsprogs/old_e2fsprogs/uuid/compare.c delete mode 100644 e2fsprogs/old_e2fsprogs/uuid/gen_uuid.c delete mode 100644 e2fsprogs/old_e2fsprogs/uuid/pack.c delete mode 100644 e2fsprogs/old_e2fsprogs/uuid/parse.c delete mode 100644 e2fsprogs/old_e2fsprogs/uuid/unpack.c delete mode 100644 e2fsprogs/old_e2fsprogs/uuid/unparse.c delete mode 100644 e2fsprogs/old_e2fsprogs/uuid/uuid.h delete mode 100644 e2fsprogs/old_e2fsprogs/uuid/uuidP.h delete mode 100644 e2fsprogs/old_e2fsprogs/uuid/uuid_time.c 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 @@ -# -# For a description of the syntax of this configuration file, -# see scripts/kbuild/config-language.txt. -# - -menu "Linux Ext2 FS Progs" - -INSERT - -config CHATTR - bool "chattr" - default n - help - chattr changes the file attributes on a second extended file system. - -config E2FSCK - bool "e2fsck" - default n - help - e2fsck is used to check Linux second extended file systems (ext2fs). - e2fsck also supports ext2 filesystems countaining a journal (ext3). - The normal compat symlinks 'fsck.ext2' and 'fsck.ext3' are also - provided. - -config FSCK - bool "fsck" - default n - help - fsck is used to check and optionally repair one or more filesystems. - In actuality, fsck is simply a front-end for the various file system - checkers (fsck.fstype) available under Linux. - -config LSATTR - bool "lsattr" - default n - help - lsattr lists the file attributes on a second extended file system. - -config MKE2FS - bool "mke2fs" - default n - help - mke2fs is used to create an ext2/ext3 filesystem. The normal compat - symlinks 'mkfs.ext2' and 'mkfs.ext3' are also provided. - -config TUNE2FS - bool "tune2fs" - default n - help - tune2fs allows the system administrator to adjust various tunable - filesystem parameters on Linux ext2/ext3 filesystems. - -config E2LABEL - bool "e2label" - default n - depends on TUNE2FS - help - e2label will display or change the filesystem label on the ext2 - filesystem located on device. - -config FINDFS - bool "findfs" - default n - depends on TUNE2FS - help - findfs will search the disks in the system looking for a filesystem - which has a label matching label or a UUID equal to uuid. - -endmenu diff --git a/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 @@ -# Makefile for busybox -# -# Copyright (C) 1999-2005 by Erik Andersen -# -# Licensed under GPLv2, see file LICENSE in this source tree. - -lib-y:= - -INSERT - -lib-$(CONFIG_CHATTR) += chattr.o -lib-$(CONFIG_E2FSCK) += e2fsck.o util.o -lib-$(CONFIG_FSCK) += fsck.o util.o -lib-$(CONFIG_LSATTR) += lsattr.o -lib-$(CONFIG_MKE2FS) += mke2fs.o util.o -lib-$(CONFIG_TUNE2FS) += tune2fs.o util.o - -CFLAGS += -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 @@ -This is a pretty straight rip from the e2fsprogs pkg. - -See 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 @@ -# Makefile for busybox -# -# Copyright (C) 1999-2005 by Erik Andersen -# -# Licensed under GPLv2, see file LICENSE in this source tree. - -NEEDED-$(CONFIG_E2FSCK) = y -NEEDED-$(CONFIG_FSCK) = y -NEEDED-$(CONFIG_MKE2FS) = y -NEEDED-$(CONFIG_TUNE2FS) = y - -lib-y:= - -INSERT - -lib-$(NEEDED-y) += cache.o dev.o devname.o devno.o blkid_getsize.o \ - probe.o read.o resolve.o save.o tag.o list.o - -CFLAGS_dev.o := -include $(srctree)/include/busybox.h -CFLAGS_devname.o := -include $(srctree)/include/busybox.h -CFLAGS_devno.o := -include $(srctree)/include/busybox.h -CFLAGS_blkid_getsize.o := -include $(srctree)/include/busybox.h -CFLAGS_probe.o := -include $(srctree)/include/busybox.h -CFLAGS_save.o := -include $(srctree)/include/busybox.h -CFLAGS_tag.o := -include $(srctree)/include/busybox.h -CFLAGS_list.o := -include $(srctree)/include/busybox.h diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * blkid.h - Interface for libblkid, a library to identify block devices - * - * Copyright (C) 2001 Andreas Dilger - * Copyright (C) 2003 Theodore Ts'o - * - * %Begin-Header% - * This file may be redistributed under the terms of the - * GNU Lesser General Public License. - * %End-Header% - */ -#ifndef BLKID_BLKID_H -#define BLKID_BLKID_H 1 - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define BLKID_VERSION "1.0.0" -#define BLKID_DATE "12-Feb-2003" - -typedef struct blkid_struct_dev *blkid_dev; -typedef struct blkid_struct_cache *blkid_cache; -typedef __s64 blkid_loff_t; - -typedef struct blkid_struct_tag_iterate *blkid_tag_iterate; -typedef struct blkid_struct_dev_iterate *blkid_dev_iterate; - -/* - * Flags for blkid_get_dev - * - * BLKID_DEV_CREATE Create an empty device structure if not found - * in the cache. - * BLKID_DEV_VERIFY Make sure the device structure corresponds - * with reality. - * BLKID_DEV_FIND Just look up a device entry, and return NULL - * if it is not found. - * BLKID_DEV_NORMAL Get a valid device structure, either from the - * cache or by probing the device. - */ -#define BLKID_DEV_FIND 0x0000 -#define BLKID_DEV_CREATE 0x0001 -#define BLKID_DEV_VERIFY 0x0002 -#define BLKID_DEV_NORMAL (BLKID_DEV_CREATE | BLKID_DEV_VERIFY) - -/* cache.c */ -extern void blkid_put_cache(blkid_cache cache); -extern int blkid_get_cache(blkid_cache *cache, const char *filename); - -/* dev.c */ -extern const char *blkid_dev_devname(blkid_dev dev); - -extern blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache); -extern int blkid_dev_set_search(blkid_dev_iterate iter, - char *search_type, char *search_value); -extern int blkid_dev_next(blkid_dev_iterate iterate, blkid_dev *dev); -extern void blkid_dev_iterate_end(blkid_dev_iterate iterate); - -/* devno.c */ -extern char *blkid_devno_to_devname(dev_t devno); - -/* devname.c */ -extern int blkid_probe_all(blkid_cache cache); -extern int blkid_probe_all_new(blkid_cache cache); -extern blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, - int flags); - -/* getsize.c */ -extern blkid_loff_t blkid_get_dev_size(int fd); - -/* probe.c */ -int blkid_known_fstype(const char *fstype); -extern blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev); - -/* read.c */ - -/* resolve.c */ -extern char *blkid_get_tag_value(blkid_cache cache, const char *tagname, - const char *devname); -extern char *blkid_get_devname(blkid_cache cache, const char *token, - const char *value); - -/* tag.c */ -extern blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev); -extern int blkid_tag_next(blkid_tag_iterate iterate, - const char **type, const char **value); -extern void blkid_tag_iterate_end(blkid_tag_iterate iterate); -extern int blkid_dev_has_tag(blkid_dev dev, const char *type, - const char *value); -extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache, - const char *type, - const char *value); -extern int blkid_parse_tag_string(const char *token, char **ret_type, - char **ret_val); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * blkidP.h - Internal interfaces for libblkid - * - * Copyright (C) 2001 Andreas Dilger - * Copyright (C) 2003 Theodore Ts'o - * - * %Begin-Header% - * This file may be redistributed under the terms of the - * GNU Lesser General Public License. - * %End-Header% - */ -#ifndef BLKID_BLKIDP_H -#define BLKID_BLKIDP_H 1 - -#include -#include - -#include "blkid.h" -#include "list.h" - -#ifdef __GNUC__ -#define __BLKID_ATTR(x) __attribute__(x) -#else -#define __BLKID_ATTR(x) -#endif - - -/* - * This describes the attributes of a specific device. - * We can traverse all of the tags by bid_tags (linking to the tag bit_names). - * The bid_label and bid_uuid fields are shortcuts to the LABEL and UUID tag - * values, if they exist. - */ -struct blkid_struct_dev -{ - struct list_head bid_devs; /* All devices in the cache */ - struct list_head bid_tags; /* All tags for this device */ - blkid_cache bid_cache; /* Dev belongs to this cache */ - char *bid_name; /* Device inode pathname */ - char *bid_type; /* Preferred device TYPE */ - int bid_pri; /* Device priority */ - dev_t bid_devno; /* Device major/minor number */ - time_t bid_time; /* Last update time of device */ - unsigned int bid_flags; /* Device status bitflags */ - char *bid_label; /* Shortcut to device LABEL */ - char *bid_uuid; /* Shortcut to binary UUID */ -}; - -#define BLKID_BID_FL_VERIFIED 0x0001 /* Device data validated from disk */ -#define BLKID_BID_FL_INVALID 0x0004 /* Device is invalid */ - -/* - * Each tag defines a NAME=value pair for a particular device. The tags - * are linked via bit_names for a single device, so that traversing the - * names list will get you a list of all tags associated with a device. - * They are also linked via bit_values for all devices, so one can easily - * search all tags with a given NAME for a specific value. - */ -struct blkid_struct_tag -{ - struct list_head bit_tags; /* All tags for this device */ - struct list_head bit_names; /* All tags with given NAME */ - char *bit_name; /* NAME of tag (shared) */ - char *bit_val; /* value of tag */ - blkid_dev bit_dev; /* pointer to device */ -}; -typedef struct blkid_struct_tag *blkid_tag; - -/* - * Minimum number of seconds between device probes, even when reading - * from the cache. This is to avoid re-probing all devices which were - * just probed by another program that does not share the cache. - */ -#define BLKID_PROBE_MIN 2 - -/* - * Time in seconds an entry remains verified in the in-memory cache - * before being reverified (in case of long-running processes that - * keep a cache in memory and continue to use it for a long time). - */ -#define BLKID_PROBE_INTERVAL 200 - -/* This describes an entire blkid cache file and probed devices. - * We can traverse all of the found devices via bic_list. - * We can traverse all of the tag types by bic_tags, which hold empty tags - * for each tag type. Those tags can be used as list_heads for iterating - * through all devices with a specific tag type (e.g. LABEL). - */ -struct blkid_struct_cache -{ - struct list_head bic_devs; /* List head of all devices */ - struct list_head bic_tags; /* List head of all tag types */ - time_t bic_time; /* Last probe time */ - time_t bic_ftime; /* Mod time of the cachefile */ - unsigned int bic_flags; /* Status flags of the cache */ - char *bic_filename; /* filename of cache */ -}; - -#define BLKID_BIC_FL_PROBED 0x0002 /* We probed /proc/partition devices */ -#define BLKID_BIC_FL_CHANGED 0x0004 /* Cache has changed from disk */ - -extern char *blkid_strdup(const char *s); -extern char *blkid_strndup(const char *s, const int length); - -#define BLKID_CACHE_FILE "/etc/blkid.tab" -extern const char *blkid_devdirs[]; - -#define BLKID_ERR_IO 5 -#define BLKID_ERR_PROC 9 -#define BLKID_ERR_MEM 12 -#define BLKID_ERR_CACHE 14 -#define BLKID_ERR_DEV 19 -#define BLKID_ERR_PARAM 22 -#define BLKID_ERR_BIG 27 - -/* - * Priority settings for different types of devices - */ -#define BLKID_PRI_EVMS 30 -#define BLKID_PRI_LVM 20 -#define BLKID_PRI_MD 10 - -#if defined(TEST_PROGRAM) && !defined(CONFIG_BLKID_DEBUG) -#define CONFIG_BLKID_DEBUG -#endif - -#define DEBUG_CACHE 0x0001 -#define DEBUG_DUMP 0x0002 -#define DEBUG_DEV 0x0004 -#define DEBUG_DEVNAME 0x0008 -#define DEBUG_DEVNO 0x0010 -#define DEBUG_PROBE 0x0020 -#define DEBUG_READ 0x0040 -#define DEBUG_RESOLVE 0x0080 -#define DEBUG_SAVE 0x0100 -#define DEBUG_TAG 0x0200 -#define DEBUG_INIT 0x8000 -#define DEBUG_ALL 0xFFFF - -#ifdef CONFIG_BLKID_DEBUG -#include -extern int blkid_debug_mask; -#define DBG(m,x) if ((m) & blkid_debug_mask) x; -#else -#define DBG(m,x) -#endif - -#ifdef CONFIG_BLKID_DEBUG -extern void blkid_debug_dump_dev(blkid_dev dev); -extern void blkid_debug_dump_tag(blkid_tag tag); -#endif - -/* lseek.c */ -/* extern blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence); */ -#ifdef CONFIG_LFS -# define blkid_llseek lseek64 -#else -# define blkid_llseek lseek -#endif - -/* read.c */ -extern void blkid_read_cache(blkid_cache cache); - -/* save.c */ -extern int blkid_flush_cache(blkid_cache cache); - -/* - * Functions to create and find a specific tag type: tag.c - */ -extern void blkid_free_tag(blkid_tag tag); -extern blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type); -extern int blkid_set_tag(blkid_dev dev, const char *name, - const char *value, const int vlength); - -/* - * Functions to create and find a specific tag type: dev.c - */ -extern blkid_dev blkid_new_dev(void); -extern void blkid_free_dev(blkid_dev dev); - -#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 @@ -/* vi: set sw=4 ts=4: */ -/* - * getsize.c --- get the size of a partition. - * - * Copyright (C) 1995, 1995 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the - * GNU Lesser General Public License. - * %End-Header% - */ - -/* include this before sys/queues.h! */ -#include "blkidP.h" - -#include -#include -#ifdef HAVE_ERRNO_H -#include -#endif -#include -#ifdef HAVE_SYS_IOCTL_H -#include -#endif -#ifdef HAVE_LINUX_FD_H -#include -#endif -#ifdef HAVE_SYS_DISKLABEL_H -#include -#include -#endif -#ifdef HAVE_SYS_DISK_H -#ifdef HAVE_SYS_QUEUE_H -#include /* for LIST_HEAD */ -#endif -#include -#endif -#ifdef __linux__ -#include -#endif - -#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE) -#define BLKGETSIZE _IO(0x12,96) /* return device size */ -#endif - -#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64) -#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */ -#endif - -#ifdef APPLE_DARWIN -#define BLKGETSIZE DKIOCGETBLOCKCOUNT32 -#endif /* APPLE_DARWIN */ - -static int valid_offset(int fd, blkid_loff_t offset) -{ - char ch; - - if (blkid_llseek(fd, offset, 0) < 0) - return 0; - if (read(fd, &ch, 1) < 1) - return 0; - return 1; -} - -/* - * Returns the number of blocks in a partition - */ -blkid_loff_t blkid_get_dev_size(int fd) -{ - int valid_blkgetsize64 = 1; -#ifdef __linux__ - struct utsname ut; -#endif - unsigned long long size64; - unsigned long size; - blkid_loff_t high, low; -#ifdef FDGETPRM - struct floppy_struct this_floppy; -#endif -#ifdef HAVE_SYS_DISKLABEL_H - int part = -1; - struct disklabel lab; - struct partition *pp; - char ch; - struct stat st; -#endif /* HAVE_SYS_DISKLABEL_H */ - -#ifdef DKIOCGETBLOCKCOUNT /* For Apple Darwin */ - if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) { - if ((sizeof(blkid_loff_t) < sizeof(unsigned long long)) - && (size64 << 9 > 0xFFFFFFFF)) - return 0; /* EFBIG */ - return (blkid_loff_t) size64 << 9; - } -#endif - -#ifdef BLKGETSIZE64 -#ifdef __linux__ - uname(&ut); - if ((ut.release[0] == '2') && (ut.release[1] == '.') && - (ut.release[2] < '6') && (ut.release[3] == '.')) - valid_blkgetsize64 = 0; -#endif - if (valid_blkgetsize64 && - ioctl(fd, BLKGETSIZE64, &size64) >= 0) { - if ((sizeof(blkid_loff_t) < sizeof(unsigned long long)) - && ((size64) > 0xFFFFFFFF)) - return 0; /* EFBIG */ - return size64; - } -#endif - -#ifdef BLKGETSIZE - if (ioctl(fd, BLKGETSIZE, &size) >= 0) - return (blkid_loff_t)size << 9; -#endif - -#ifdef FDGETPRM - if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) - return (blkid_loff_t)this_floppy.size << 9; -#endif -#ifdef HAVE_SYS_DISKLABEL_H -#if 0 - /* - * This should work in theory but I haven't tested it. Anyone - * on a BSD system want to test this for me? In the meantime, - * binary search mechanism should work just fine. - */ - if ((fstat(fd, &st) >= 0) && S_ISBLK(st.st_mode)) - part = st.st_rdev & 7; - if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) { - pp = &lab.d_partitions[part]; - if (pp->p_size) - return pp->p_size << 9; - } -#endif -#endif /* HAVE_SYS_DISKLABEL_H */ - - /* - * OK, we couldn't figure it out by using a specialized ioctl, - * which is generally the best way. So do binary search to - * find the size of the partition. - */ - low = 0; - for (high = 1024; valid_offset(fd, high); high *= 2) - low = high; - while (low < high - 1) - { - const blkid_loff_t mid = (low + high) / 2; - - if (valid_offset(fd, mid)) - low = mid; - else - high = mid; - } - return low + 1; -} - -#ifdef TEST_PROGRAM -int main(int argc, char **argv) -{ - blkid_loff_t bytes; - int fd; - - if (argc < 2) { - fprintf(stderr, "Usage: %s device\n" - "Determine the size of a device\n", argv[0]); - return 1; - } - - if ((fd = open(argv[1], O_RDONLY)) < 0) - perror(argv[0]); - - bytes = blkid_get_dev_size(fd); - printf("Device %s has %lld 1k blocks.\n", argv[1], bytes >> 10); - - return 0; -} -#endif diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * cache.c - allocation/initialization/free routines for cache - * - * Copyright (C) 2001 Andreas Dilger - * Copyright (C) 2003 Theodore Ts'o - * - * %Begin-Header% - * This file may be redistributed under the terms of the - * GNU Lesser General Public License. - * %End-Header% - */ - -#include -#include -#include -#include "blkidP.h" - -int blkid_debug_mask = 0; - -int blkid_get_cache(blkid_cache *ret_cache, const char *filename) -{ - blkid_cache cache; - -#ifdef CONFIG_BLKID_DEBUG - if (!(blkid_debug_mask & DEBUG_INIT)) { - char *dstr = getenv("BLKID_DEBUG"); - - if (dstr) - blkid_debug_mask = strtoul(dstr, 0, 0); - blkid_debug_mask |= DEBUG_INIT; - } -#endif - - DBG(DEBUG_CACHE, printf("creating blkid cache (using %s)\n", - filename ? filename : "default cache")); - - cache = xzalloc(sizeof(struct blkid_struct_cache)); - - INIT_LIST_HEAD(&cache->bic_devs); - INIT_LIST_HEAD(&cache->bic_tags); - - if (filename && !strlen(filename)) - filename = 0; - if (!filename && (getuid() == geteuid())) - filename = getenv("BLKID_FILE"); - if (!filename) - filename = BLKID_CACHE_FILE; - cache->bic_filename = blkid_strdup(filename); - - blkid_read_cache(cache); - - *ret_cache = cache; - return 0; -} - -void blkid_put_cache(blkid_cache cache) -{ - if (!cache) - return; - - (void) blkid_flush_cache(cache); - - DBG(DEBUG_CACHE, printf("freeing cache struct\n")); - - /* DBG(DEBUG_CACHE, blkid_debug_dump_cache(cache)); */ - - while (!list_empty(&cache->bic_devs)) { - blkid_dev dev = list_entry(cache->bic_devs.next, - struct blkid_struct_dev, - bid_devs); - blkid_free_dev(dev); - } - - while (!list_empty(&cache->bic_tags)) { - blkid_tag tag = list_entry(cache->bic_tags.next, - struct blkid_struct_tag, - bit_tags); - - while (!list_empty(&tag->bit_names)) { - blkid_tag bad = list_entry(tag->bit_names.next, - struct blkid_struct_tag, - bit_names); - - DBG(DEBUG_CACHE, printf("warning: unfreed tag %s=%s\n", - bad->bit_name, bad->bit_val)); - blkid_free_tag(bad); - } - blkid_free_tag(tag); - } - free(cache->bic_filename); - - free(cache); -} - -#ifdef TEST_PROGRAM -int main(int argc, char** argv) -{ - blkid_cache cache = NULL; - int ret; - - blkid_debug_mask = DEBUG_ALL; - if ((argc > 2)) { - fprintf(stderr, "Usage: %s [filename]\n", argv[0]); - exit(1); - } - - if ((ret = blkid_get_cache(&cache, argv[1])) < 0) { - fprintf(stderr, "error %d parsing cache file %s\n", ret, - argv[1] ? argv[1] : BLKID_CACHE_FILE); - exit(1); - } - if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) { - fprintf(stderr, "%s: error creating cache (%d)\n", - argv[0], ret); - exit(1); - } - if ((ret = blkid_probe_all(cache)) < 0) - fprintf(stderr, "error probing devices\n"); - - blkid_put_cache(cache); - - return ret; -} -#endif diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * dev.c - allocation/initialization/free routines for dev - * - * Copyright (C) 2001 Andreas Dilger - * Copyright (C) 2003 Theodore Ts'o - * - * %Begin-Header% - * This file may be redistributed under the terms of the - * GNU Lesser General Public License. - * %End-Header% - */ - -#include -#include - -#include "blkidP.h" - -blkid_dev blkid_new_dev(void) -{ - blkid_dev dev; - - dev = xzalloc(sizeof(struct blkid_struct_dev)); - - INIT_LIST_HEAD(&dev->bid_devs); - INIT_LIST_HEAD(&dev->bid_tags); - - return dev; -} - -void blkid_free_dev(blkid_dev dev) -{ - if (!dev) - return; - - DBG(DEBUG_DEV, - printf(" freeing dev %s (%s)\n", dev->bid_name, dev->bid_type)); - DBG(DEBUG_DEV, blkid_debug_dump_dev(dev)); - - list_del(&dev->bid_devs); - while (!list_empty(&dev->bid_tags)) { - blkid_tag tag = list_entry(dev->bid_tags.next, - struct blkid_struct_tag, - bit_tags); - blkid_free_tag(tag); - } - free(dev->bid_name); - free(dev); -} - -/* - * Given a blkid device, return its name - */ -const char *blkid_dev_devname(blkid_dev dev) -{ - return dev->bid_name; -} - -#ifdef CONFIG_BLKID_DEBUG -void blkid_debug_dump_dev(blkid_dev dev) -{ - struct list_head *p; - - if (!dev) { - printf(" dev: NULL\n"); - return; - } - - printf(" dev: name = %s\n", dev->bid_name); - printf(" dev: DEVNO=\"0x%0llx\"\n", dev->bid_devno); - printf(" dev: TIME=\"%lu\"\n", dev->bid_time); - printf(" dev: PRI=\"%d\"\n", dev->bid_pri); - printf(" dev: flags = 0x%08X\n", dev->bid_flags); - - list_for_each(p, &dev->bid_tags) { - blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags); - if (tag) - printf(" tag: %s=\"%s\"\n", tag->bit_name, - tag->bit_val); - else - printf(" tag: NULL\n"); - } - bb_putchar('\n'); -} -#endif - -/* - * dev iteration routines for the public libblkid interface. - * - * These routines do not expose the list.h implementation, which are a - * contamination of the namespace, and which force us to reveal far, far - * too much of our internal implementation. I'm not convinced I want - * to keep list.h in the long term, anyway. It's fine for kernel - * programming, but performance is not the #1 priority for this - * library, and I really don't like the tradeoff of type-safety for - * performance for this application. [tytso:20030125.2007EST] - */ - -/* - * This series of functions iterate over all devices in a blkid cache - */ -#define DEV_ITERATE_MAGIC 0x01a5284c - -struct blkid_struct_dev_iterate { - int magic; - blkid_cache cache; - struct list_head *p; -}; - -blkid_dev_iterate blkid_dev_iterate_begin(blkid_cache cache) -{ - blkid_dev_iterate iter; - - iter = xmalloc(sizeof(struct blkid_struct_dev_iterate)); - iter->magic = DEV_ITERATE_MAGIC; - iter->cache = cache; - iter->p = cache->bic_devs.next; - return iter; -} - -/* - * Return 0 on success, -1 on error - */ -extern int blkid_dev_next(blkid_dev_iterate iter, - blkid_dev *dev) -{ - *dev = 0; - if (!iter || iter->magic != DEV_ITERATE_MAGIC || - iter->p == &iter->cache->bic_devs) - return -1; - *dev = list_entry(iter->p, struct blkid_struct_dev, bid_devs); - iter->p = iter->p->next; - return 0; -} - -void blkid_dev_iterate_end(blkid_dev_iterate iter) -{ - if (!iter || iter->magic != DEV_ITERATE_MAGIC) - return; - iter->magic = 0; - free(iter); -} - -#ifdef TEST_PROGRAM -#ifdef HAVE_GETOPT_H -#include -#else -extern char *optarg; -extern int optind; -#endif - -void usage(char *prog) -{ - fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask]\n", prog); - fprintf(stderr, "\tList all devices and exit\n"); - exit(1); -} - -int main(int argc, char **argv) -{ - blkid_dev_iterate iter; - blkid_cache cache = NULL; - blkid_dev dev; - int c, ret; - char *tmp; - char *file = NULL; - char *search_type = NULL; - char *search_value = NULL; - - while ((c = getopt (argc, argv, "m:f:")) != EOF) - switch (c) { - case 'f': - file = optarg; - break; - case 'm': - blkid_debug_mask = strtoul (optarg, &tmp, 0); - if (*tmp) { - fprintf(stderr, "Invalid debug mask: %s\n", - optarg); - exit(1); - } - break; - case '?': - usage(argv[0]); - } - if (argc >= optind+2) { - search_type = argv[optind]; - search_value = argv[optind+1]; - optind += 2; - } - if (argc != optind) - usage(argv[0]); - - if ((ret = blkid_get_cache(&cache, file)) != 0) { - fprintf(stderr, "%s: error creating cache (%d)\n", - argv[0], ret); - exit(1); - } - - iter = blkid_dev_iterate_begin(cache); - if (search_type) - blkid_dev_set_search(iter, search_type, search_value); - while (blkid_dev_next(iter, &dev) == 0) { - printf("Device: %s\n", blkid_dev_devname(dev)); - } - blkid_dev_iterate_end(iter); - - - blkid_put_cache(cache); - return 0; -} -#endif diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * devname.c - get a dev by its device inode name - * - * Copyright (C) Andries Brouwer - * Copyright (C) 1999, 2000, 2001, 2002, 2003 Theodore Ts'o - * Copyright (C) 2001 Andreas Dilger - * - * %Begin-Header% - * This file may be redistributed under the terms of the - * GNU Lesser General Public License. - * %End-Header% - */ - -#include -#include -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#include -#include -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#include -#ifdef HAVE_ERRNO_H -#include -#endif -#ifdef HAVE_SYS_MKDEV_H -#include -#endif -#include - -#include "blkidP.h" - -/* - * Find a dev struct in the cache by device name, if available. - * - * If there is no entry with the specified device name, and the create - * flag is set, then create an empty device entry. - */ -blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags) -{ - blkid_dev dev = NULL, tmp; - struct list_head *p; - - if (!cache || !devname) - return NULL; - - list_for_each(p, &cache->bic_devs) { - tmp = list_entry(p, struct blkid_struct_dev, bid_devs); - if (strcmp(tmp->bid_name, devname)) - continue; - - DBG(DEBUG_DEVNAME, - printf("found devname %s in cache\n", tmp->bid_name)); - dev = tmp; - break; - } - - if (!dev && (flags & BLKID_DEV_CREATE)) { - dev = blkid_new_dev(); - if (!dev) - return NULL; - dev->bid_name = blkid_strdup(devname); - dev->bid_cache = cache; - list_add_tail(&dev->bid_devs, &cache->bic_devs); - cache->bic_flags |= BLKID_BIC_FL_CHANGED; - } - - if (flags & BLKID_DEV_VERIFY) - dev = blkid_verify(cache, dev); - return dev; -} - -/* - * Probe a single block device to add to the device cache. - */ -static void probe_one(blkid_cache cache, const char *ptname, - dev_t devno, int pri) -{ - blkid_dev dev = NULL; - struct list_head *p; - const char **dir; - char *devname = NULL; - - /* See if we already have this device number in the cache. */ - list_for_each(p, &cache->bic_devs) { - blkid_dev tmp = list_entry(p, struct blkid_struct_dev, - bid_devs); - if (tmp->bid_devno == devno) { - dev = blkid_verify(cache, tmp); - break; - } - } - if (dev && dev->bid_devno == devno) - goto set_pri; - - /* - * Take a quick look at /dev/ptname for the device number. We check - * all of the likely device directories. If we don't find it, or if - * the stat information doesn't check out, use blkid_devno_to_devname() - * to find it via an exhaustive search for the device major/minor. - */ - for (dir = blkid_devdirs; *dir; dir++) { - struct stat st; - char device[256]; - - sprintf(device, "%s/%s", *dir, ptname); - if ((dev = blkid_get_dev(cache, device, BLKID_DEV_FIND)) && - dev->bid_devno == devno) - goto set_pri; - - if (stat(device, &st) == 0 && S_ISBLK(st.st_mode) && - st.st_rdev == devno) { - devname = blkid_strdup(device); - break; - } - } - if (!devname) { - devname = blkid_devno_to_devname(devno); - if (!devname) - return; - } - dev = blkid_get_dev(cache, devname, BLKID_DEV_NORMAL); - free(devname); - -set_pri: - if (!pri && !strncmp(ptname, "md", 2)) - pri = BLKID_PRI_MD; - if (dev) - dev->bid_pri = pri; -} - -#define PROC_PARTITIONS "/proc/partitions" -#define VG_DIR "/proc/lvm/VGs" - -/* - * This function initializes the UUID cache with devices from the LVM - * proc hierarchy. We currently depend on the names of the LVM - * hierarchy giving us the device structure in /dev. (XXX is this a - * safe thing to do?) - */ -#ifdef VG_DIR -#include -static dev_t lvm_get_devno(const char *lvm_device) -{ - FILE *lvf; - char buf[1024]; - int ma, mi; - dev_t ret = 0; - - DBG(DEBUG_DEVNAME, printf("opening %s\n", lvm_device)); - if ((lvf = fopen_for_read(lvm_device)) == NULL) { - DBG(DEBUG_DEVNAME, printf("%s: (%d) %s\n", lvm_device, errno, - strerror(errno))); - return 0; - } - - while (fgets(buf, sizeof(buf), lvf)) { - if (sscanf(buf, "device: %d:%d", &ma, &mi) == 2) { - ret = makedev(ma, mi); - break; - } - } - fclose(lvf); - - return ret; -} - -static void lvm_probe_all(blkid_cache cache) -{ - DIR *vg_list; - struct dirent *vg_iter; - int vg_len = strlen(VG_DIR); - dev_t dev; - - if ((vg_list = opendir(VG_DIR)) == NULL) - return; - - DBG(DEBUG_DEVNAME, printf("probing LVM devices under %s\n", VG_DIR)); - - while ((vg_iter = readdir(vg_list)) != NULL) { - DIR *lv_list; - char *vdirname; - char *vg_name; - struct dirent *lv_iter; - - vg_name = vg_iter->d_name; - if (LONE_CHAR(vg_name, '.') || !strcmp(vg_name, "..")) - continue; - vdirname = xmalloc(vg_len + strlen(vg_name) + 8); - sprintf(vdirname, "%s/%s/LVs", VG_DIR, vg_name); - - lv_list = opendir(vdirname); - free(vdirname); - if (lv_list == NULL) - continue; - - while ((lv_iter = readdir(lv_list)) != NULL) { - char *lv_name, *lvm_device; - - lv_name = lv_iter->d_name; - if (LONE_CHAR(lv_name, '.') || !strcmp(lv_name, "..")) - continue; - - lvm_device = xmalloc(vg_len + strlen(vg_name) + - strlen(lv_name) + 8); - sprintf(lvm_device, "%s/%s/LVs/%s", VG_DIR, vg_name, - lv_name); - dev = lvm_get_devno(lvm_device); - sprintf(lvm_device, "%s/%s", vg_name, lv_name); - DBG(DEBUG_DEVNAME, printf("LVM dev %s: devno 0x%04X\n", - lvm_device, - (unsigned int) dev)); - probe_one(cache, lvm_device, dev, BLKID_PRI_LVM); - free(lvm_device); - } - closedir(lv_list); - } - closedir(vg_list); -} -#endif - -#define PROC_EVMS_VOLUMES "/proc/evms/volumes" - -static int -evms_probe_all(blkid_cache cache) -{ - char line[100]; - int ma, mi, sz, num = 0; - FILE *procpt; - char device[110]; - - procpt = fopen_for_read(PROC_EVMS_VOLUMES); - if (!procpt) - return 0; - while (fgets(line, sizeof(line), procpt)) { - if (sscanf(line, " %d %d %d %*s %*s %[^\n ]", - &ma, &mi, &sz, device) != 4) - continue; - - DBG(DEBUG_DEVNAME, printf("Checking partition %s (%d, %d)\n", - device, ma, mi)); - - probe_one(cache, device, makedev(ma, mi), BLKID_PRI_EVMS); - num++; - } - fclose(procpt); - return num; -} - -/* - * Read the device data for all available block devices in the system. - */ -int blkid_probe_all(blkid_cache cache) -{ - FILE *proc; - char line[1024]; - char ptname0[128], ptname1[128], *ptname = NULL; - char *ptnames[2]; - dev_t devs[2]; - int ma, mi; - unsigned long long sz; - int lens[2] = { 0, 0 }; - int which = 0, last = 0; - - ptnames[0] = ptname0; - ptnames[1] = ptname1; - - if (!cache) - return -BLKID_ERR_PARAM; - - if (cache->bic_flags & BLKID_BIC_FL_PROBED && - time(NULL) - cache->bic_time < BLKID_PROBE_INTERVAL) - return 0; - - blkid_read_cache(cache); - evms_probe_all(cache); -#ifdef VG_DIR - lvm_probe_all(cache); -#endif - - proc = fopen_for_read(PROC_PARTITIONS); - if (!proc) - return -BLKID_ERR_PROC; - - while (fgets(line, sizeof(line), proc)) { - last = which; - which ^= 1; - ptname = ptnames[which]; - - if (sscanf(line, " %d %d %llu %128[^\n ]", - &ma, &mi, &sz, ptname) != 4) - continue; - devs[which] = makedev(ma, mi); - - DBG(DEBUG_DEVNAME, printf("read partition name %s\n", ptname)); - - /* Skip whole disk devs unless they have no partitions - * If we don't have a partition on this dev, also - * check previous dev to see if it didn't have a partn. - * heuristic: partition name ends in a digit. - * - * Skip extended partitions. - * heuristic: size is 1 - * - * FIXME: skip /dev/{ida,cciss,rd} whole-disk devs - */ - - lens[which] = strlen(ptname); - if (isdigit(ptname[lens[which] - 1])) { - DBG(DEBUG_DEVNAME, - printf("partition dev %s, devno 0x%04X\n", - ptname, (unsigned int) devs[which])); - - if (sz > 1) - probe_one(cache, ptname, devs[which], 0); - lens[which] = 0; - lens[last] = 0; - } else if (lens[last] && strncmp(ptnames[last], ptname, - lens[last])) { - DBG(DEBUG_DEVNAME, - printf("whole dev %s, devno 0x%04X\n", - ptnames[last], (unsigned int) devs[last])); - probe_one(cache, ptnames[last], devs[last], 0); - lens[last] = 0; - } - } - - /* Handle the last device if it wasn't partitioned */ - if (lens[which]) - probe_one(cache, ptname, devs[which], 0); - - fclose(proc); - - cache->bic_time = time(NULL); - cache->bic_flags |= BLKID_BIC_FL_PROBED; - blkid_flush_cache(cache); - return 0; -} - -#ifdef TEST_PROGRAM -int main(int argc, char **argv) -{ - blkid_cache cache = NULL; - int ret; - - blkid_debug_mask = DEBUG_ALL; - if (argc != 1) { - fprintf(stderr, "Usage: %s\n" - "Probe all devices and exit\n", argv[0]); - exit(1); - } - if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) { - fprintf(stderr, "%s: error creating cache (%d)\n", - argv[0], ret); - exit(1); - } - if (blkid_probe_all(cache) < 0) - printf("%s: error probing devices\n", argv[0]); - - blkid_put_cache(cache); - return 0; -} -#endif diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * devno.c - find a particular device by its device number (major/minor) - * - * Copyright (C) 2000, 2001, 2003 Theodore Ts'o - * Copyright (C) 2001 Andreas Dilger - * - * %Begin-Header% - * This file may be redistributed under the terms of the - * GNU Lesser General Public License. - * %End-Header% - */ - -#include -#include -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#include -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#include -#include -#ifdef HAVE_ERRNO_H -#include -#endif -#ifdef HAVE_SYS_MKDEV_H -#include -#endif - -#include "blkidP.h" - -struct dir_list { - char *name; - struct dir_list *next; -}; - -char *blkid_strndup(const char *s, int length) -{ - char *ret; - - if (!s) - return NULL; - - if (!length) - length = strlen(s); - - ret = xmalloc(length + 1); - strncpy(ret, s, length); - ret[length] = '\0'; - return ret; -} - -char *blkid_strdup(const char *s) -{ - return blkid_strndup(s, 0); -} - -/* - * This function adds an entry to the directory list - */ -static void add_to_dirlist(const char *name, struct dir_list **list) -{ - struct dir_list *dp; - - dp = xmalloc(sizeof(struct dir_list)); - dp->name = blkid_strdup(name); - dp->next = *list; - *list = dp; -} - -/* - * This function frees a directory list - */ -static void free_dirlist(struct dir_list **list) -{ - struct dir_list *dp, *next; - - for (dp = *list; dp; dp = next) { - next = dp->next; - free(dp->name); - free(dp); - } - *list = NULL; -} - -static void scan_dir(char *dir_name, dev_t devno, struct dir_list **list, - char **devname) -{ - DIR *dir; - struct dirent *dp; - char path[1024]; - int dirlen; - struct stat st; - - if ((dir = opendir(dir_name)) == NULL) - return; - dirlen = strlen(dir_name) + 2; - while ((dp = readdir(dir)) != 0) { - if (dirlen + strlen(dp->d_name) >= sizeof(path)) - continue; - - if (dp->d_name[0] == '.' && - ((dp->d_name[1] == 0) || - ((dp->d_name[1] == '.') && (dp->d_name[2] == 0)))) - continue; - - sprintf(path, "%s/%s", dir_name, dp->d_name); - if (stat(path, &st) < 0) - continue; - - if (S_ISDIR(st.st_mode)) - add_to_dirlist(path, list); - else if (S_ISBLK(st.st_mode) && st.st_rdev == devno) { - *devname = blkid_strdup(path); - DBG(DEBUG_DEVNO, - printf("found 0x%llx at %s (%p)\n", devno, - path, *devname)); - break; - } - } - closedir(dir); -} - -/* Directories where we will try to search for device numbers */ -const char *blkid_devdirs[] = { "/devices", "/devfs", "/dev", NULL }; - -/* - * This function finds the pathname to a block device with a given - * device number. It returns a pointer to allocated memory to the - * pathname on success, and NULL on failure. - */ -char *blkid_devno_to_devname(dev_t devno) -{ - struct dir_list *list = NULL, *new_list = NULL; - char *devname = NULL; - const char **dir; - - /* - * Add the starting directories to search in reverse order of - * importance, since we are using a stack... - */ - for (dir = blkid_devdirs; *dir; dir++) - add_to_dirlist(*dir, &list); - - while (list) { - struct dir_list *current = list; - - list = list->next; - DBG(DEBUG_DEVNO, printf("directory %s\n", current->name)); - scan_dir(current->name, devno, &new_list, &devname); - free(current->name); - free(current); - if (devname) - break; - /* - * If we're done checking at this level, descend to - * the next level of subdirectories. (breadth-first) - */ - if (list == NULL) { - list = new_list; - new_list = NULL; - } - } - free_dirlist(&list); - free_dirlist(&new_list); - - if (!devname) { - DBG(DEBUG_DEVNO, - printf("blkid: cannot find devno 0x%04lx\n", - (unsigned long) devno)); - } else { - DBG(DEBUG_DEVNO, - printf("found devno 0x%04llx as %s\n", devno, devname)); - } - - - return devname; -} - -#ifdef TEST_PROGRAM -int main(int argc, char** argv) -{ - char *devname, *tmp; - int major, minor; - dev_t devno; - const char *errmsg = "Cannot parse %s: %s\n"; - - blkid_debug_mask = DEBUG_ALL; - if ((argc != 2) && (argc != 3)) { - fprintf(stderr, "Usage:\t%s device_number\n\t%s major minor\n" - "Resolve a device number to a device name\n", - argv[0], argv[0]); - exit(1); - } - if (argc == 2) { - devno = strtoul(argv[1], &tmp, 0); - if (*tmp) { - fprintf(stderr, errmsg, "device number", argv[1]); - exit(1); - } - } else { - major = strtoul(argv[1], &tmp, 0); - if (*tmp) { - fprintf(stderr, errmsg, "major number", argv[1]); - exit(1); - } - minor = strtoul(argv[2], &tmp, 0); - if (*tmp) { - fprintf(stderr, errmsg, "minor number", argv[2]); - exit(1); - } - devno = makedev(major, minor); - } - printf("Looking for device 0x%04Lx\n", devno); - devname = blkid_devno_to_devname(devno); - free(devname); - return 0; -} -#endif diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ - -#include "list.h" - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -void __list_add(struct list_head * add, - struct list_head * prev, - struct list_head * next) -{ - next->prev = add; - add->next = next; - add->prev = prev; - prev->next = add; -} - -/* - * list_add - add a new entry - * @add: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -void list_add(struct list_head *add, struct list_head *head) -{ - __list_add(add, head, head->next); -} - -/* - * list_add_tail - add a new entry - * @add: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -void list_add_tail(struct list_head *add, struct list_head *head) -{ - __list_add(add, head->prev, head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -void __list_del(struct list_head * prev, struct list_head * next) -{ - next->prev = prev; - prev->next = next; -} - -/* - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * - * list_empty() on @entry does not return true after this, @entry is - * in an undefined state. - */ -void list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); -} - -/* - * list_del_init - deletes entry from list and reinitialize it. - * @entry: the element to delete from the list. - */ -void list_del_init(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - INIT_LIST_HEAD(entry); -} - -/* - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -int list_empty(struct list_head *head) -{ - return head->next == head; -} - -/* - * list_splice - join two lists - * @list: the new list to add. - * @head: the place to add it in the first list. - */ -void list_splice(struct list_head *list, struct list_head *head) -{ - struct list_head *first = list->next; - - if (first != list) { - struct list_head *last = list->prev; - struct list_head *at = head->next; - - first->prev = head; - head->next = first; - - last->next = at; - at->prev = last; - } -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -#if !defined(_BLKID_LIST_H) && !defined(LIST_HEAD) -#define BLKID_LIST_H 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ - -struct list_head { - struct list_head *next, *prev; -}; - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -#define INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -} while (0) - -void __list_add(struct list_head * add, struct list_head * prev, struct list_head * next); -void list_add(struct list_head *add, struct list_head *head); -void list_add_tail(struct list_head *add, struct list_head *head); -void __list_del(struct list_head * prev, struct list_head * next); -void list_del(struct list_head *entry); -void list_del_init(struct list_head *entry); -int list_empty(struct list_head *head); -void list_splice(struct list_head *list, struct list_head *head); - -/** - * list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#define list_entry(ptr, type, member) \ - ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) - -/** - * list_for_each - iterate over elements in a list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) - -/** - * list_for_each_safe - iterate over elements in a list, but don't dereference - * pos after the body is done (in case it is freed) - * @pos: the &struct list_head to use as a loop counter. - * @pnext: the &struct list_head to use as a pointer to the next item. - * @head: the head for your list (not included in iteration). - */ -#define list_for_each_safe(pos, pnext, head) \ - for (pos = (head)->next, pnext = pos->next; pos != (head); \ - pos = pnext, pnext = pos->next) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * probe.c - identify a block device by its contents, and return a dev - * struct with the details - * - * Copyright (C) 1999 by Andries Brouwer - * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o - * Copyright (C) 2001 by Andreas Dilger - * - * %Begin-Header% - * This file may be redistributed under the terms of the - * GNU Lesser General Public License. - * %End-Header% - */ - -#include -#include -#include -#include -#include -#include -#ifdef HAVE_SYS_STAT_H -#include -#endif -#ifdef HAVE_SYS_MKDEV_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif -#include "blkidP.h" -#include "../uuid/uuid.h" -#include "probe.h" - -/* - * This is a special case code to check for an MDRAID device. We do - * this special since it requires checking for a superblock at the end - * of the device. - */ -static int check_mdraid(int fd, unsigned char *ret_uuid) -{ - struct mdp_superblock_s *md; - blkid_loff_t offset; - char buf[4096]; - - if (fd < 0) - return -BLKID_ERR_PARAM; - - offset = (blkid_get_dev_size(fd) & ~((blkid_loff_t)65535)) - 65536; - - if (blkid_llseek(fd, offset, 0) < 0 || - read(fd, buf, 4096) != 4096) - return -BLKID_ERR_IO; - - /* Check for magic number */ - if (memcmp("\251+N\374", buf, 4)) - return -BLKID_ERR_PARAM; - - if (!ret_uuid) - return 0; - *ret_uuid = 0; - - /* The MD UUID is not contiguous in the superblock, make it so */ - md = (struct mdp_superblock_s *)buf; - if (md->set_uuid0 || md->set_uuid1 || md->set_uuid2 || md->set_uuid3) { - memcpy(ret_uuid, &md->set_uuid0, 4); - memcpy(ret_uuid, &md->set_uuid1, 12); - } - return 0; -} - -static void set_uuid(blkid_dev dev, uuid_t uuid) -{ - char str[37]; - - if (!uuid_is_null(uuid)) { - uuid_unparse(uuid, str); - blkid_set_tag(dev, "UUID", str, sizeof(str)); - } -} - -static void get_ext2_info(blkid_dev dev, unsigned char *buf) -{ - struct ext2_super_block *es = (struct ext2_super_block *) buf; - const char *label = NULL; - - DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n", - blkid_le32(es->s_feature_compat), - blkid_le32(es->s_feature_incompat), - blkid_le32(es->s_feature_ro_compat))); - - if (strlen(es->s_volume_name)) - label = es->s_volume_name; - blkid_set_tag(dev, "LABEL", label, sizeof(es->s_volume_name)); - - set_uuid(dev, es->s_uuid); -} - -static int probe_ext3(int fd __BLKID_ATTR((unused)), - blkid_cache cache __BLKID_ATTR((unused)), - blkid_dev dev, - const struct blkid_magic *id __BLKID_ATTR((unused)), - unsigned char *buf) -{ - struct ext2_super_block *es; - - es = (struct ext2_super_block *)buf; - - /* Distinguish between jbd and ext2/3 fs */ - if (blkid_le32(es->s_feature_incompat) & - EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) - return -BLKID_ERR_PARAM; - - /* Distinguish between ext3 and ext2 */ - if (!(blkid_le32(es->s_feature_compat) & - EXT3_FEATURE_COMPAT_HAS_JOURNAL)) - return -BLKID_ERR_PARAM; - - get_ext2_info(dev, buf); - - blkid_set_tag(dev, "SEC_TYPE", "ext2", sizeof("ext2")); - - return 0; -} - -static int probe_ext2(int fd __BLKID_ATTR((unused)), - blkid_cache cache __BLKID_ATTR((unused)), - blkid_dev dev, - const struct blkid_magic *id __BLKID_ATTR((unused)), - unsigned char *buf) -{ - struct ext2_super_block *es; - - es = (struct ext2_super_block *)buf; - - /* Distinguish between jbd and ext2/3 fs */ - if (blkid_le32(es->s_feature_incompat) & - EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) - return -BLKID_ERR_PARAM; - - get_ext2_info(dev, buf); - - return 0; -} - -static int probe_jbd(int fd __BLKID_ATTR((unused)), - blkid_cache cache __BLKID_ATTR((unused)), - blkid_dev dev, - const struct blkid_magic *id __BLKID_ATTR((unused)), - unsigned char *buf) -{ - struct ext2_super_block *es = (struct ext2_super_block *) buf; - - if (!(blkid_le32(es->s_feature_incompat) & - EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) - return -BLKID_ERR_PARAM; - - get_ext2_info(dev, buf); - - return 0; -} - -static int probe_vfat(int fd __BLKID_ATTR((unused)), - blkid_cache cache __BLKID_ATTR((unused)), - blkid_dev dev, - const struct blkid_magic *id __BLKID_ATTR((unused)), - unsigned char *buf) -{ - struct vfat_super_block *vs; - char serno[10]; - const char *label = NULL; - int label_len = 0; - - vs = (struct vfat_super_block *)buf; - - if (strncmp(vs->vs_label, "NO NAME", 7)) { - char *end = vs->vs_label + sizeof(vs->vs_label) - 1; - - while (*end == ' ' && end >= vs->vs_label) - --end; - if (end >= vs->vs_label) { - label = vs->vs_label; - label_len = end - vs->vs_label + 1; - } - } - - /* We can't just print them as %04X, because they are unaligned */ - sprintf(serno, "%02X%02X-%02X%02X", vs->vs_serno[3], vs->vs_serno[2], - vs->vs_serno[1], vs->vs_serno[0]); - blkid_set_tag(dev, "LABEL", label, label_len); - blkid_set_tag(dev, "UUID", serno, sizeof(serno)); - - return 0; -} - -static int probe_msdos(int fd __BLKID_ATTR((unused)), - blkid_cache cache __BLKID_ATTR((unused)), - blkid_dev dev, - const struct blkid_magic *id __BLKID_ATTR((unused)), - unsigned char *buf) -{ - struct msdos_super_block *ms = (struct msdos_super_block *) buf; - char serno[10]; - const char *label = NULL; - int label_len = 0; - - if (strncmp(ms->ms_label, "NO NAME", 7)) { - char *end = ms->ms_label + sizeof(ms->ms_label) - 1; - - while (*end == ' ' && end >= ms->ms_label) - --end; - if (end >= ms->ms_label) { - label = ms->ms_label; - label_len = end - ms->ms_label + 1; - } - } - - /* We can't just print them as %04X, because they are unaligned */ - sprintf(serno, "%02X%02X-%02X%02X", ms->ms_serno[3], ms->ms_serno[2], - ms->ms_serno[1], ms->ms_serno[0]); - blkid_set_tag(dev, "UUID", serno, 0); - blkid_set_tag(dev, "LABEL", label, label_len); - blkid_set_tag(dev, "SEC_TYPE", "msdos", sizeof("msdos")); - - return 0; -} - -static int probe_xfs(int fd __BLKID_ATTR((unused)), - blkid_cache cache __BLKID_ATTR((unused)), - blkid_dev dev, - const struct blkid_magic *id __BLKID_ATTR((unused)), - unsigned char *buf) -{ - struct xfs_super_block *xs; - const char *label = NULL; - - xs = (struct xfs_super_block *)buf; - - if (strlen(xs->xs_fname)) - label = xs->xs_fname; - blkid_set_tag(dev, "LABEL", label, sizeof(xs->xs_fname)); - set_uuid(dev, xs->xs_uuid); - return 0; -} - -static int probe_reiserfs(int fd __BLKID_ATTR((unused)), - blkid_cache cache __BLKID_ATTR((unused)), - blkid_dev dev, - const struct blkid_magic *id, unsigned char *buf) -{ - struct reiserfs_super_block *rs = (struct reiserfs_super_block *) buf; - unsigned int blocksize; - const char *label = NULL; - - blocksize = blkid_le16(rs->rs_blocksize); - - /* If the superblock is inside the journal, we have the wrong one */ - if (id->bim_kboff/(blocksize>>10) > blkid_le32(rs->rs_journal_block)) - return -BLKID_ERR_BIG; - - /* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */ - if (!strcmp(id->bim_magic, "ReIsEr2Fs") || - !strcmp(id->bim_magic, "ReIsEr3Fs")) { - if (strlen(rs->rs_label)) - label = rs->rs_label; - set_uuid(dev, rs->rs_uuid); - } - blkid_set_tag(dev, "LABEL", label, sizeof(rs->rs_label)); - - return 0; -} - -static int probe_jfs(int fd __BLKID_ATTR((unused)), - blkid_cache cache __BLKID_ATTR((unused)), - blkid_dev dev, - const struct blkid_magic *id __BLKID_ATTR((unused)), - unsigned char *buf) -{ - struct jfs_super_block *js; - const char *label = NULL; - - js = (struct jfs_super_block *)buf; - - if (strlen((char *) js->js_label)) - label = (char *) js->js_label; - blkid_set_tag(dev, "LABEL", label, sizeof(js->js_label)); - set_uuid(dev, js->js_uuid); - return 0; -} - -static int probe_romfs(int fd __BLKID_ATTR((unused)), - blkid_cache cache __BLKID_ATTR((unused)), - blkid_dev dev, - const struct blkid_magic *id __BLKID_ATTR((unused)), - unsigned char *buf) -{ - struct romfs_super_block *ros; - const char *label = NULL; - - ros = (struct romfs_super_block *)buf; - - if (strlen((char *) ros->ros_volume)) - label = (char *) ros->ros_volume; - blkid_set_tag(dev, "LABEL", label, 0); - return 0; -} - -static int probe_cramfs(int fd __BLKID_ATTR((unused)), - blkid_cache cache __BLKID_ATTR((unused)), - blkid_dev dev, - const struct blkid_magic *id __BLKID_ATTR((unused)), - unsigned char *buf) -{ - struct cramfs_super_block *csb; - const char *label = NULL; - - csb = (struct cramfs_super_block *)buf; - - if (strlen((char *) csb->name)) - label = (char *) csb->name; - blkid_set_tag(dev, "LABEL", label, 0); - return 0; -} - -static int probe_swap0(int fd __BLKID_ATTR((unused)), - blkid_cache cache __BLKID_ATTR((unused)), - blkid_dev dev, - const struct blkid_magic *id __BLKID_ATTR((unused)), - unsigned char *buf __BLKID_ATTR((unused))) -{ - blkid_set_tag(dev, "UUID", 0, 0); - blkid_set_tag(dev, "LABEL", 0, 0); - return 0; -} - -static int probe_swap1(int fd, - blkid_cache cache __BLKID_ATTR((unused)), - blkid_dev dev, - const struct blkid_magic *id __BLKID_ATTR((unused)), - unsigned char *buf __BLKID_ATTR((unused))) -{ - struct swap_id_block *sws; - - probe_swap0(fd, cache, dev, id, buf); - /* - * Version 1 swap headers are always located at offset of 1024 - * bytes, although the swap signature itself is located at the - * end of the page (which may vary depending on hardware - * pagesize). - */ - if (lseek(fd, 1024, SEEK_SET) < 0) return 1; - sws = xmalloc(1024); - if (read(fd, sws, 1024) != 1024) { - free(sws); - return 1; - } - - /* arbitrary sanity check.. is there any garbage down there? */ - if (sws->sws_pad[32] == 0 && sws->sws_pad[33] == 0) { - if (sws->sws_volume[0]) - blkid_set_tag(dev, "LABEL", (const char*)sws->sws_volume, - sizeof(sws->sws_volume)); - if (sws->sws_uuid[0]) - set_uuid(dev, sws->sws_uuid); - } - free(sws); - - return 0; -} - -static const char -* const udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02", - "NSR03", "TEA01", 0 }; - -static int probe_udf(int fd, blkid_cache cache __BLKID_ATTR((unused)), - blkid_dev dev __BLKID_ATTR((unused)), - const struct blkid_magic *id __BLKID_ATTR((unused)), - unsigned char *buf __BLKID_ATTR((unused))) -{ - int j, bs; - struct iso_volume_descriptor isosb; - const char *const *m; - - /* determine the block size by scanning in 2K increments - (block sizes larger than 2K will be null padded) */ - for (bs = 1; bs < 16; bs++) { - lseek(fd, bs*2048+32768, SEEK_SET); - if (read(fd, (char *)&isosb, sizeof(isosb)) != sizeof(isosb)) - return 1; - if (isosb.id[0]) - break; - } - - /* Scan up to another 64 blocks looking for additional VSD's */ - for (j = 1; j < 64; j++) { - if (j > 1) { - lseek(fd, j*bs*2048+32768, SEEK_SET); - if (read(fd, (char *)&isosb, sizeof(isosb)) - != sizeof(isosb)) - return 1; - } - /* If we find NSR0x then call it udf: - NSR01 for UDF 1.00 - NSR02 for UDF 1.50 - NSR03 for UDF 2.00 */ - if (!strncmp(isosb.id, "NSR0", 4)) - return 0; - for (m = udf_magic; *m; m++) - if (!strncmp(*m, isosb.id, 5)) - break; - if (*m == 0) - return 1; - } - return 1; -} - -static int probe_ocfs(int fd __BLKID_ATTR((unused)), - blkid_cache cache __BLKID_ATTR((unused)), - blkid_dev dev, - const struct blkid_magic *id __BLKID_ATTR((unused)), - unsigned char *buf) -{ - struct ocfs_volume_header ovh; - struct ocfs_volume_label ovl; - __u32 major; - - memcpy(&ovh, buf, sizeof(ovh)); - memcpy(&ovl, buf+512, sizeof(ovl)); - - major = ocfsmajor(ovh); - if (major == 1) - blkid_set_tag(dev, "SEC_TYPE", "ocfs1", sizeof("ocfs1")); - else if (major >= 9) - blkid_set_tag(dev, "SEC_TYPE", "ntocfs", sizeof("ntocfs")); - - blkid_set_tag(dev, "LABEL", (const char*)ovl.label, ocfslabellen(ovl)); - blkid_set_tag(dev, "MOUNT", (const char*)ovh.mount, ocfsmountlen(ovh)); - set_uuid(dev, ovl.vol_id); - return 0; -} - -static int probe_ocfs2(int fd __BLKID_ATTR((unused)), - blkid_cache cache __BLKID_ATTR((unused)), - blkid_dev dev, - const struct blkid_magic *id __BLKID_ATTR((unused)), - unsigned char *buf) -{ - struct ocfs2_super_block *osb; - - osb = (struct ocfs2_super_block *)buf; - - blkid_set_tag(dev, "LABEL", (const char*)osb->s_label, sizeof(osb->s_label)); - set_uuid(dev, osb->s_uuid); - return 0; -} - -static int probe_oracleasm(int fd __BLKID_ATTR((unused)), - blkid_cache cache __BLKID_ATTR((unused)), - blkid_dev dev, - const struct blkid_magic *id __BLKID_ATTR((unused)), - unsigned char *buf) -{ - struct oracle_asm_disk_label *dl; - - dl = (struct oracle_asm_disk_label *)buf; - - blkid_set_tag(dev, "LABEL", dl->dl_id, sizeof(dl->dl_id)); - return 0; -} - -/* - * BLKID_BLK_OFFS is at least as large as the highest bim_kboff defined - * in the type_array table below + bim_kbalign. - * - * When probing for a lot of magics, we handle everything in 1kB buffers so - * that we don't have to worry about reading each combination of block sizes. - */ -#define BLKID_BLK_OFFS 64 /* currently reiserfs */ - -/* - * Various filesystem magics that we can check for. Note that kboff and - * sboff are in kilobytes and bytes respectively. All magics are in - * byte strings so we don't worry about endian issues. - */ -static const struct blkid_magic type_array[] = { -/* type kboff sboff len magic probe */ - { "oracleasm", 0, 32, 8, "ORCLDISK", probe_oracleasm }, - { "ntfs", 0, 3, 8, "NTFS ", 0 }, - { "jbd", 1, 0x38, 2, "\123\357", probe_jbd }, - { "ext3", 1, 0x38, 2, "\123\357", probe_ext3 }, - { "ext2", 1, 0x38, 2, "\123\357", probe_ext2 }, - { "reiserfs", 8, 0x34, 8, "ReIsErFs", probe_reiserfs }, - { "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", probe_reiserfs }, - { "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", probe_reiserfs }, - { "reiserfs", 64, 0x34, 8, "ReIsErFs", probe_reiserfs }, - { "reiserfs", 8, 20, 8, "ReIsErFs", probe_reiserfs }, - { "vfat", 0, 0x52, 5, "MSWIN", probe_vfat }, - { "vfat", 0, 0x52, 8, "FAT32 ", probe_vfat }, - { "vfat", 0, 0x36, 5, "MSDOS", probe_msdos }, - { "vfat", 0, 0x36, 8, "FAT16 ", probe_msdos }, - { "vfat", 0, 0x36, 8, "FAT12 ", probe_msdos }, - { "minix", 1, 0x10, 2, "\177\023", 0 }, - { "minix", 1, 0x10, 2, "\217\023", 0 }, - { "minix", 1, 0x10, 2, "\150\044", 0 }, - { "minix", 1, 0x10, 2, "\170\044", 0 }, - { "vxfs", 1, 0, 4, "\365\374\001\245", 0 }, - { "xfs", 0, 0, 4, "XFSB", probe_xfs }, - { "romfs", 0, 0, 8, "-rom1fs-", probe_romfs }, - { "bfs", 0, 0, 4, "\316\372\173\033", 0 }, - { "cramfs", 0, 0, 4, "E=\315\050", probe_cramfs }, - { "qnx4", 0, 4, 6, "QNX4FS", 0 }, - { "udf", 32, 1, 5, "BEA01", probe_udf }, - { "udf", 32, 1, 5, "BOOT2", probe_udf }, - { "udf", 32, 1, 5, "CD001", probe_udf }, - { "udf", 32, 1, 5, "CDW02", probe_udf }, - { "udf", 32, 1, 5, "NSR02", probe_udf }, - { "udf", 32, 1, 5, "NSR03", probe_udf }, - { "udf", 32, 1, 5, "TEA01", probe_udf }, - { "iso9660", 32, 1, 5, "CD001", 0 }, - { "iso9660", 32, 9, 5, "CDROM", 0 }, - { "jfs", 32, 0, 4, "JFS1", probe_jfs }, - { "hfs", 1, 0, 2, "BD", 0 }, - { "ufs", 8, 0x55c, 4, "T\031\001\000", 0 }, - { "hpfs", 8, 0, 4, "I\350\225\371", 0 }, - { "sysv", 0, 0x3f8, 4, "\020~\030\375", 0 }, - { "swap", 0, 0xff6, 10, "SWAP-SPACE", probe_swap0 }, - { "swap", 0, 0xff6, 10, "SWAPSPACE2", probe_swap1 }, - { "swap", 0, 0x1ff6, 10, "SWAP-SPACE", probe_swap0 }, - { "swap", 0, 0x1ff6, 10, "SWAPSPACE2", probe_swap1 }, - { "swap", 0, 0x3ff6, 10, "SWAP-SPACE", probe_swap0 }, - { "swap", 0, 0x3ff6, 10, "SWAPSPACE2", probe_swap1 }, - { "swap", 0, 0x7ff6, 10, "SWAP-SPACE", probe_swap0 }, - { "swap", 0, 0x7ff6, 10, "SWAPSPACE2", probe_swap1 }, - { "swap", 0, 0xfff6, 10, "SWAP-SPACE", probe_swap0 }, - { "swap", 0, 0xfff6, 10, "SWAPSPACE2", probe_swap1 }, - { "ocfs", 0, 8, 9, "OracleCFS", probe_ocfs }, - { "ocfs2", 1, 0, 6, "OCFSV2", probe_ocfs2 }, - { "ocfs2", 2, 0, 6, "OCFSV2", probe_ocfs2 }, - { "ocfs2", 4, 0, 6, "OCFSV2", probe_ocfs2 }, - { "ocfs2", 8, 0, 6, "OCFSV2", probe_ocfs2 }, - { NULL, 0, 0, 0, NULL, NULL } -}; - -/* - * Verify that the data in dev is consistent with what is on the actual - * block device (using the devname field only). Normally this will be - * called when finding items in the cache, but for long running processes - * is also desirable to revalidate an item before use. - * - * If we are unable to revalidate the data, we return the old data and - * do not set the BLKID_BID_FL_VERIFIED flag on it. - */ -blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev) -{ - const struct blkid_magic *id; - unsigned char *bufs[BLKID_BLK_OFFS + 1], *buf; - const char *type; - struct stat st; - time_t diff, now; - int fd, idx; - - if (!dev) - return NULL; - - now = time(NULL); - diff = now - dev->bid_time; - - if ((now < dev->bid_time) || - (diff < BLKID_PROBE_MIN) || - (dev->bid_flags & BLKID_BID_FL_VERIFIED && - diff < BLKID_PROBE_INTERVAL)) - return dev; - - DBG(DEBUG_PROBE, - printf("need to revalidate %s (time since last check %lu)\n", - dev->bid_name, diff)); - - fd = open(dev->bid_name, O_RDONLY); - if (fd < 0 - || fstat(fd, &st) < 0 - ) { - if (fd >= 0) - close(fd); - if (errno == ENXIO || errno == ENODEV || errno == ENOENT) { - blkid_free_dev(dev); - return NULL; - } - /* We don't have read permission, just return cache data. */ - DBG(DEBUG_PROBE, - printf("returning unverified data for %s\n", - dev->bid_name)); - return dev; - } - - memset(bufs, 0, sizeof(bufs)); - - /* - * Iterate over the type array. If we already know the type, - * then try that first. If it doesn't work, then blow away - * the type information, and try again. - * - */ -try_again: - type = 0; - if (!dev->bid_type || !strcmp(dev->bid_type, "mdraid")) { - uuid_t uuid; - - if (check_mdraid(fd, uuid) == 0) { - set_uuid(dev, uuid); - type = "mdraid"; - goto found_type; - } - } - for (id = type_array; id->bim_type; id++) { - if (dev->bid_type && - strcmp(id->bim_type, dev->bid_type)) - continue; - - idx = id->bim_kboff + (id->bim_sboff >> 10); - if (idx > BLKID_BLK_OFFS || idx < 0) - continue; - buf = bufs[idx]; - if (!buf) { - if (lseek(fd, idx << 10, SEEK_SET) < 0) - continue; - - buf = xmalloc(1024); - - if (read(fd, buf, 1024) != 1024) { - free(buf); - continue; - } - bufs[idx] = buf; - } - - if (memcmp(id->bim_magic, buf + (id->bim_sboff&0x3ff), - id->bim_len)) - continue; - - if ((id->bim_probe == NULL) || - (id->bim_probe(fd, cache, dev, id, buf) == 0)) { - type = id->bim_type; - goto found_type; - } - } - - if (!id->bim_type && dev->bid_type) { - /* - * Zap the device filesystem type and try again - */ - blkid_set_tag(dev, "TYPE", 0, 0); - blkid_set_tag(dev, "SEC_TYPE", 0, 0); - blkid_set_tag(dev, "LABEL", 0, 0); - blkid_set_tag(dev, "UUID", 0, 0); - goto try_again; - } - - if (!dev->bid_type) { - blkid_free_dev(dev); - close(fd); - return NULL; - } - -found_type: - if (dev && type) { - dev->bid_devno = st.st_rdev; - dev->bid_time = time(NULL); - dev->bid_flags |= BLKID_BID_FL_VERIFIED; - cache->bic_flags |= BLKID_BIC_FL_CHANGED; - - blkid_set_tag(dev, "TYPE", type, 0); - - DBG(DEBUG_PROBE, printf("%s: devno 0x%04llx, type %s\n", - dev->bid_name, st.st_rdev, type)); - } - - close(fd); - - return dev; -} - -int blkid_known_fstype(const char *fstype) -{ - const struct blkid_magic *id; - - for (id = type_array; id->bim_type; id++) { - if (strcmp(fstype, id->bim_type) == 0) - return 1; - } - return 0; -} - -#ifdef TEST_PROGRAM -int main(int argc, char **argv) -{ - blkid_dev dev; - blkid_cache cache; - int ret; - - blkid_debug_mask = DEBUG_ALL; - if (argc != 2) { - fprintf(stderr, "Usage: %s device\n" - "Probe a single device to determine type\n", argv[0]); - exit(1); - } - if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) { - fprintf(stderr, "%s: error creating cache (%d)\n", - argv[0], ret); - exit(1); - } - dev = blkid_get_dev(cache, argv[1], BLKID_DEV_NORMAL); - if (!dev) { - printf("%s: %s has an unsupported type\n", argv[0], argv[1]); - return 1; - } - printf("%s is type %s\n", argv[1], dev->bid_type ? - dev->bid_type : "(null)"); - if (dev->bid_label) - printf("\tlabel is '%s'\n", dev->bid_label); - if (dev->bid_uuid) - printf("\tuuid is %s\n", dev->bid_uuid); - - blkid_free_dev(dev); - return 0; -} -#endif diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * probe.h - constants and on-disk structures for extracting device data - * - * Copyright (C) 1999 by Andries Brouwer - * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o - * Copyright (C) 2001 by Andreas Dilger - * - * %Begin-Header% - * This file may be redistributed under the terms of the - * GNU Lesser General Public License. - * %End-Header% - */ -#ifndef BLKID_PROBE_H -#define BLKID_PROBE_H 1 - -#include - -struct blkid_magic; - -typedef int (*blkid_probe_t)(int fd, blkid_cache cache, blkid_dev dev, - const struct blkid_magic *id, unsigned char *buf); - -struct blkid_magic { - const char *bim_type; /* type name for this magic */ - long bim_kboff; /* kilobyte offset of superblock */ - unsigned bim_sboff; /* byte offset within superblock */ - unsigned bim_len; /* length of magic */ - const char *bim_magic; /* magic string */ - blkid_probe_t bim_probe; /* probe function */ -}; - -/* - * Structures for each of the content types we want to extract information - * from. We do not necessarily need the magic field here, because we have - * already identified the content type before we get this far. It may still - * be useful if there are probe functions which handle multiple content types. - */ -struct ext2_super_block { - __u32 s_inodes_count; - __u32 s_blocks_count; - __u32 s_r_blocks_count; - __u32 s_free_blocks_count; - __u32 s_free_inodes_count; - __u32 s_first_data_block; - __u32 s_log_block_size; - __u32 s_dummy3[7]; - unsigned char s_magic[2]; - __u16 s_state; - __u32 s_dummy5[8]; - __u32 s_feature_compat; - __u32 s_feature_incompat; - __u32 s_feature_ro_compat; - unsigned char s_uuid[16]; - char s_volume_name[16]; -}; -#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x00000004 -#define EXT3_FEATURE_INCOMPAT_RECOVER 0x00000004 -#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x00000008 - -struct xfs_super_block { - unsigned char xs_magic[4]; - __u32 xs_blocksize; - __u64 xs_dblocks; - __u64 xs_rblocks; - __u32 xs_dummy1[2]; - unsigned char xs_uuid[16]; - __u32 xs_dummy2[15]; - char xs_fname[12]; - __u32 xs_dummy3[2]; - __u64 xs_icount; - __u64 xs_ifree; - __u64 xs_fdblocks; -}; - -struct reiserfs_super_block { - __u32 rs_blocks_count; - __u32 rs_free_blocks; - __u32 rs_root_block; - __u32 rs_journal_block; - __u32 rs_journal_dev; - __u32 rs_orig_journal_size; - __u32 rs_dummy2[5]; - __u16 rs_blocksize; - __u16 rs_dummy3[3]; - unsigned char rs_magic[12]; - __u32 rs_dummy4[5]; - unsigned char rs_uuid[16]; - char rs_label[16]; -}; - -struct jfs_super_block { - unsigned char js_magic[4]; - __u32 js_version; - __u64 js_size; - __u32 js_bsize; - __u32 js_dummy1; - __u32 js_pbsize; - __u32 js_dummy2[27]; - unsigned char js_uuid[16]; - unsigned char js_label[16]; - unsigned char js_loguuid[16]; -}; - -struct romfs_super_block { - unsigned char ros_magic[8]; - __u32 ros_dummy1[2]; - unsigned char ros_volume[16]; -}; - -struct cramfs_super_block { - __u8 magic[4]; - __u32 size; - __u32 flags; - __u32 future; - __u8 signature[16]; - struct cramfs_info { - __u32 crc; - __u32 edition; - __u32 blocks; - __u32 files; - } info; - __u8 name[16]; -}; - -struct swap_id_block { -/* unsigned char sws_boot[1024]; */ - __u32 sws_version; - __u32 sws_lastpage; - __u32 sws_nrbad; - unsigned char sws_uuid[16]; - char sws_volume[16]; - unsigned char sws_pad[117]; - __u32 sws_badpg; -}; - -/* Yucky misaligned values */ -struct vfat_super_block { -/* 00*/ unsigned char vs_ignored[3]; -/* 03*/ unsigned char vs_sysid[8]; -/* 0b*/ unsigned char vs_sector_size[2]; -/* 0d*/ __u8 vs_cluster_size; -/* 0e*/ __u16 vs_reserved; -/* 10*/ __u8 vs_fats; -/* 11*/ unsigned char vs_dir_entries[2]; -/* 13*/ unsigned char vs_sectors[2]; -/* 15*/ unsigned char vs_media; -/* 16*/ __u16 vs_fat_length; -/* 18*/ __u16 vs_secs_track; -/* 1a*/ __u16 vs_heads; -/* 1c*/ __u32 vs_hidden; -/* 20*/ __u32 vs_total_sect; -/* 24*/ __u32 vs_fat32_length; -/* 28*/ __u16 vs_flags; -/* 2a*/ __u8 vs_version[2]; -/* 2c*/ __u32 vs_root_cluster; -/* 30*/ __u16 vs_insfo_sector; -/* 32*/ __u16 vs_backup_boot; -/* 34*/ __u16 vs_reserved2[6]; -/* 40*/ unsigned char vs_unknown[3]; -/* 43*/ unsigned char vs_serno[4]; -/* 47*/ char vs_label[11]; -/* 52*/ unsigned char vs_magic[8]; -/* 5a*/ unsigned char vs_dummy2[164]; -/*1fe*/ unsigned char vs_pmagic[2]; -}; - -/* Yucky misaligned values */ -struct msdos_super_block { -/* 00*/ unsigned char ms_ignored[3]; -/* 03*/ unsigned char ms_sysid[8]; -/* 0b*/ unsigned char ms_sector_size[2]; -/* 0d*/ __u8 ms_cluster_size; -/* 0e*/ __u16 ms_reserved; -/* 10*/ __u8 ms_fats; -/* 11*/ unsigned char ms_dir_entries[2]; -/* 13*/ unsigned char ms_sectors[2]; -/* 15*/ unsigned char ms_media; -/* 16*/ __u16 ms_fat_length; -/* 18*/ __u16 ms_secs_track; -/* 1a*/ __u16 ms_heads; -/* 1c*/ __u32 ms_hidden; -/* 20*/ __u32 ms_total_sect; -/* 24*/ unsigned char ms_unknown[3]; -/* 27*/ unsigned char ms_serno[4]; -/* 2b*/ char ms_label[11]; -/* 36*/ unsigned char ms_magic[8]; -/* 3d*/ unsigned char ms_dummy2[192]; -/*1fe*/ unsigned char ms_pmagic[2]; -}; - -struct minix_super_block { - __u16 ms_ninodes; - __u16 ms_nzones; - __u16 ms_imap_blocks; - __u16 ms_zmap_blocks; - __u16 ms_firstdatazone; - __u16 ms_log_zone_size; - __u32 ms_max_size; - unsigned char ms_magic[2]; - __u16 ms_state; - __u32 ms_zones; -}; - -struct mdp_superblock_s { - __u32 md_magic; - __u32 major_version; - __u32 minor_version; - __u32 patch_version; - __u32 gvalid_words; - __u32 set_uuid0; - __u32 ctime; - __u32 level; - __u32 size; - __u32 nr_disks; - __u32 raid_disks; - __u32 md_minor; - __u32 not_persistent; - __u32 set_uuid1; - __u32 set_uuid2; - __u32 set_uuid3; -}; - -struct hfs_super_block { - char h_magic[2]; - char h_dummy[18]; - __u32 h_blksize; -}; - -struct ocfs_volume_header { - unsigned char minor_version[4]; - unsigned char major_version[4]; - unsigned char signature[128]; - char mount[128]; - unsigned char mount_len[2]; -}; - -struct ocfs_volume_label { - unsigned char disk_lock[48]; - char label[64]; - unsigned char label_len[2]; - unsigned char vol_id[16]; - unsigned char vol_id_len[2]; -}; - -#define ocfsmajor(o) ((__u32)o.major_version[0] \ - + (((__u32) o.major_version[1]) << 8) \ - + (((__u32) o.major_version[2]) << 16) \ - + (((__u32) o.major_version[3]) << 24)) -#define ocfslabellen(o) ((__u32)o.label_len[0] + (((__u32) o.label_len[1]) << 8)) -#define ocfsmountlen(o) ((__u32)o.mount_len[0] + (((__u32) o.mount_len[1])<<8)) - -#define OCFS_MAGIC "OracleCFS" - -struct ocfs2_super_block { - unsigned char signature[8]; - unsigned char s_dummy1[184]; - unsigned char s_dummy2[80]; - char s_label[64]; - unsigned char s_uuid[16]; -}; - -#define OCFS2_MIN_BLOCKSIZE 512 -#define OCFS2_MAX_BLOCKSIZE 4096 - -#define OCFS2_SUPER_BLOCK_BLKNO 2 - -#define OCFS2_SUPER_BLOCK_SIGNATURE "OCFSV2" - -struct oracle_asm_disk_label { - char dummy[32]; - char dl_tag[8]; - char dl_id[24]; -}; - -#define ORACLE_ASM_DISK_LABEL_MARKED "ORCLDISK" -#define ORACLE_ASM_DISK_LABEL_OFFSET 32 - -#define ISODCL(from, to) (to - from + 1) -struct iso_volume_descriptor { - char type[ISODCL(1,1)]; /* 711 */ - char id[ISODCL(2,6)]; - char version[ISODCL(7,7)]; - char data[ISODCL(8,2048)]; -}; - -/* - * Byte swap functions - */ -#ifdef __GNUC__ -#define _INLINE_ static __inline__ -#else /* For Watcom C */ -#define _INLINE_ static inline -#endif - -static __u16 blkid_swab16(__u16 val); -static __u32 blkid_swab32(__u32 val); -static __u64 blkid_swab64(__u64 val); - -#if ((defined __GNUC__) && \ - (defined(__i386__) || defined(__i486__) || defined(__i586__))) - -#define _BLKID_HAVE_ASM_BITOPS_ - -_INLINE_ __u32 blkid_swab32(__u32 val) -{ -#ifdef EXT2FS_REQUIRE_486 - __asm__("bswap %0" : "=r" (val) : "0" (val)); -#else - __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */ - "rorl $16,%0\n\t" /* swap words */ - "xchgb %b0,%h0" /* swap higher bytes */ - :"=q" (val) - : "0" (val)); -#endif - return val; -} - -_INLINE_ __u16 blkid_swab16(__u16 val) -{ - __asm__("xchgb %b0,%h0" /* swap bytes */ - : "=q" (val) - : "0" (val)); - return val; -} - -_INLINE_ __u64 blkid_swab64(__u64 val) -{ - return blkid_swab32(val >> 32) | - ( ((__u64)blkid_swab32((__u32)val)) << 32 ); -} -#endif - -#if !defined(_BLKID_HAVE_ASM_BITOPS_) - -_INLINE_ __u16 blkid_swab16(__u16 val) -{ - return (val >> 8) | (val << 8); -} - -_INLINE_ __u32 blkid_swab32(__u32 val) -{ - return (val>>24) | ((val>>8) & 0xFF00) | - ((val<<8) & 0xFF0000) | (val<<24); -} - -_INLINE_ __u64 blkid_swab64(__u64 val) -{ - return blkid_swab32(val >> 32) | - ( ((__u64)blkid_swab32((__u32)val)) << 32 ); -} -#endif - - - -#if __BYTE_ORDER == __BIG_ENDIAN -#define blkid_le16(x) blkid_swab16(x) -#define blkid_le32(x) blkid_swab32(x) -#define blkid_le64(x) blkid_swab64(x) -#define blkid_be16(x) (x) -#define blkid_be32(x) (x) -#define blkid_be64(x) (x) -#else -#define blkid_le16(x) (x) -#define blkid_le32(x) (x) -#define blkid_le64(x) (x) -#define blkid_be16(x) blkid_swab16(x) -#define blkid_be32(x) blkid_swab32(x) -#define blkid_be64(x) blkid_swab64(x) -#endif - -#undef _INLINE_ - -#endif /* _BLKID_PROBE_H */ diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * read.c - read the blkid cache from disk, to avoid scanning all devices - * - * Copyright (C) 2001, 2003 Theodore Y. Ts'o - * Copyright (C) 2001 Andreas Dilger - * - * %Begin-Header% - * This file may be redistributed under the terms of the - * GNU Lesser General Public License. - * %End-Header% - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "blkidP.h" -#include "../uuid/uuid.h" - -#ifdef HAVE_STRTOULL -#define __USE_ISOC9X -#define STRTOULL strtoull /* defined in stdlib.h if you try hard enough */ -#else -/* FIXME: need to support real strtoull here */ -#define STRTOULL strtoul -#endif - -#include - -#ifdef TEST_PROGRAM -#define blkid_debug_dump_dev(dev) (debug_dump_dev(dev)) -static void debug_dump_dev(blkid_dev dev); -#endif - -/* - * File format: - * - * ...]>device_name - * - * The following tags are required for each entry: - * unique (within this file) ID number of this device - * (ascii time_t) time this entry was last read from disk - * (detected) type of filesystem/data for this partition - * - * The following tags may be present, depending on the device contents - * (user supplied) label (volume name, etc) - * (generated) universally unique identifier (serial no) - */ - -static char *skip_over_blank(char *cp) -{ - while (*cp && isspace(*cp)) - cp++; - return cp; -} - -static char *skip_over_word(char *cp) -{ - char ch; - - while ((ch = *cp)) { - /* If we see a backslash, skip the next character */ - if (ch == '\\') { - cp++; - if (*cp == '\0') - break; - cp++; - continue; - } - if (isspace(ch) || ch == '<' || ch == '>') - break; - cp++; - } - return cp; -} - -static char *strip_line(char *line) -{ - char *p; - - line = skip_over_blank(line); - - p = line + strlen(line) - 1; - - while (*line) { - if (isspace(*p)) - *p-- = '\0'; - else - break; - } - - return line; -} - -/* - * Start parsing a new line from the cache. - * - * line starts with " continue parsing line - * line starts with " skip line - * line starts with other, return -BLKID_ERR_CACHE -> error - */ -static int parse_start(char **cp) -{ - char *p; - - p = strip_line(*cp); - - /* Skip comment or blank lines. We can't just NUL the first '#' char, - * in case it is inside quotes, or escaped. - */ - if (*p == '\0' || *p == '#') - return 0; - - if (!strncmp(p, "", 9)) { - DBG(DEBUG_READ, printf("found device trailer %9s\n", *cp)); - *cp += 9; - return 0; - } - - return -BLKID_ERR_CACHE; -} - -/* - * Allocate a new device struct with device name filled in. Will handle - * finding the device on lines of the form: - * devname - * devnamebar - */ -static int parse_dev(blkid_cache cache, blkid_dev *dev, char **cp) -{ - char *start, *tmp, *end, *name; - int ret; - - if ((ret = parse_start(cp)) <= 0) - return ret; - - start = tmp = strchr(*cp, '>'); - if (!start) { - DBG(DEBUG_READ, - printf("blkid: short line parsing dev: %s\n", *cp)); - return -BLKID_ERR_CACHE; - } - start = skip_over_blank(start + 1); - end = skip_over_word(start); - - DBG(DEBUG_READ, printf("device should be %*s\n", end - start, start)); - - if (**cp == '>') - *cp = end; - else - (*cp)++; - - *tmp = '\0'; - - if (!(tmp = strrchr(end, '<')) || parse_end(&tmp) < 0) { - DBG(DEBUG_READ, - printf("blkid: missing ending: %s\n", end)); - } else if (tmp) - *tmp = '\0'; - - if (end - start <= 1) { - DBG(DEBUG_READ, printf("blkid: empty device name: %s\n", *cp)); - return -BLKID_ERR_CACHE; - } - - name = blkid_strndup(start, end-start); - if (name == NULL) - return -BLKID_ERR_MEM; - - DBG(DEBUG_READ, printf("found dev %s\n", name)); - - if (!(*dev = blkid_get_dev(cache, name, BLKID_DEV_CREATE))) - return -BLKID_ERR_MEM; - - free(name); - return 1; -} - -/* - * Extract a tag of the form NAME="value" from the line. - */ -static int parse_token(char **name, char **value, char **cp) -{ - char *end; - - if (!name || !value || !cp) - return -BLKID_ERR_PARAM; - - if (!(*value = strchr(*cp, '='))) - return 0; - - **value = '\0'; - *name = strip_line(*cp); - *value = skip_over_blank(*value + 1); - - if (**value == '"') { - end = strchr(*value + 1, '"'); - if (!end) { - DBG(DEBUG_READ, - printf("unbalanced quotes at: %s\n", *value)); - *cp = *value; - return -BLKID_ERR_CACHE; - } - (*value)++; - *end = '\0'; - end++; - } else { - end = skip_over_word(*value); - if (*end) { - *end = '\0'; - end++; - } - } - *cp = end; - - return 1; -} - -/* - * Extract a tag of the form value from the line. - */ -/* -static int parse_xml(char **name, char **value, char **cp) -{ - char *end; - - if (!name || !value || !cp) - return -BLKID_ERR_PARAM; - - *name = strip_line(*cp); - - if ((*name)[0] != '<' || (*name)[1] == '/') - return 0; - - FIXME: finish this. -} -*/ - -/* - * Extract a tag from the line. - * - * Return 1 if a valid tag was found. - * Return 0 if no tag found. - * Return -ve error code. - */ -static int parse_tag(blkid_cache cache, blkid_dev dev, char **cp) -{ - char *name; - char *value; - int ret; - - if (!cache || !dev) - return -BLKID_ERR_PARAM; - - if ((ret = parse_token(&name, &value, cp)) <= 0 /* && - (ret = parse_xml(&name, &value, cp)) <= 0 */) - return ret; - - /* Some tags are stored directly in the device struct */ - if (!strcmp(name, "DEVNO")) - dev->bid_devno = STRTOULL(value, 0, 0); - else if (!strcmp(name, "PRI")) - dev->bid_pri = strtol(value, 0, 0); - else if (!strcmp(name, "TIME")) - /* FIXME: need to parse a long long eventually */ - dev->bid_time = strtol(value, 0, 0); - else - ret = blkid_set_tag(dev, name, value, strlen(value)); - - DBG(DEBUG_READ, printf(" tag: %s=\"%s\"\n", name, value)); - - return ret < 0 ? ret : 1; -} - -/* - * Parse a single line of data, and return a newly allocated dev struct. - * Add the new device to the cache struct, if one was read. - * - * Lines are of the form /dev/foo - * - * Returns -ve value on error. - * Returns 0 otherwise. - * If a valid device was read, *dev_p is non-NULL, otherwise it is NULL - * (e.g. comment lines, unknown XML content, etc). - */ -static int blkid_parse_line(blkid_cache cache, blkid_dev *dev_p, char *cp) -{ - blkid_dev dev; - int ret; - - if (!cache || !dev_p) - return -BLKID_ERR_PARAM; - - *dev_p = NULL; - - DBG(DEBUG_READ, printf("line: %s\n", cp)); - - if ((ret = parse_dev(cache, dev_p, &cp)) <= 0) - return ret; - - dev = *dev_p; - - while ((ret = parse_tag(cache, dev, &cp)) > 0) { - ; - } - - if (dev->bid_type == NULL) { - DBG(DEBUG_READ, - printf("blkid: device %s has no TYPE\n",dev->bid_name)); - blkid_free_dev(dev); - } - - DBG(DEBUG_READ, blkid_debug_dump_dev(dev)); - - return ret; -} - -/* - * Parse the specified filename, and return the data in the supplied or - * a newly allocated cache struct. If the file doesn't exist, return a - * new empty cache struct. - */ -void blkid_read_cache(blkid_cache cache) -{ - FILE *file; - char buf[4096]; - int fd, lineno = 0; - struct stat st; - - if (!cache) - return; - - /* - * If the file doesn't exist, then we just return an empty - * struct so that the cache can be populated. - */ - if ((fd = open(cache->bic_filename, O_RDONLY)) < 0) - return; - if (fstat(fd, &st) < 0) - goto errout; - if ((st.st_mtime == cache->bic_ftime) || - (cache->bic_flags & BLKID_BIC_FL_CHANGED)) { - DBG(DEBUG_CACHE, printf("skipping re-read of %s\n", - cache->bic_filename)); - goto errout; - } - - DBG(DEBUG_CACHE, printf("reading cache file %s\n", - cache->bic_filename)); - - file = xfdopen_for_read(fd); - - while (fgets(buf, sizeof(buf), file)) { - blkid_dev dev; - unsigned int end; - - lineno++; - if (buf[0] == 0) - continue; - end = strlen(buf) - 1; - /* Continue reading next line if it ends with a backslash */ - while (end < sizeof(buf) - 2 && buf[end] == '\\' && - fgets(buf + end, sizeof(buf) - end, file)) { - end = strlen(buf) - 1; - lineno++; - } - - if (blkid_parse_line(cache, &dev, buf) < 0) { - DBG(DEBUG_READ, - printf("blkid: bad format on line %d\n", lineno)); - continue; - } - } - fclose(file); - - /* - * Initially we do not need to write out the cache file. - */ - cache->bic_flags &= ~BLKID_BIC_FL_CHANGED; - cache->bic_ftime = st.st_mtime; - - return; -errout: - close(fd); -} - -#ifdef TEST_PROGRAM -static void debug_dump_dev(blkid_dev dev) -{ - struct list_head *p; - - if (!dev) { - printf(" dev: NULL\n"); - return; - } - - printf(" dev: name = %s\n", dev->bid_name); - printf(" dev: DEVNO=\"0x%0llx\"\n", dev->bid_devno); - printf(" dev: TIME=\"%lu\"\n", dev->bid_time); - printf(" dev: PRI=\"%d\"\n", dev->bid_pri); - printf(" dev: flags = 0x%08X\n", dev->bid_flags); - - list_for_each(p, &dev->bid_tags) { - blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags); - if (tag) - printf(" tag: %s=\"%s\"\n", tag->bit_name, - tag->bit_val); - else - printf(" tag: NULL\n"); - } - bb_putchar('\n'); -} - -int main(int argc, char**argv) -{ - blkid_cache cache = NULL; - int ret; - - blkid_debug_mask = DEBUG_ALL; - if (argc > 2) { - fprintf(stderr, "Usage: %s [filename]\n" - "Test parsing of the cache (filename)\n", argv[0]); - exit(1); - } - if ((ret = blkid_get_cache(&cache, argv[1])) < 0) - fprintf(stderr, "error %d reading cache file %s\n", ret, - argv[1] ? argv[1] : BLKID_CACHE_FILE); - - blkid_put_cache(cache); - - return ret; -} -#endif diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * resolve.c - resolve names and tags into specific devices - * - * Copyright (C) 2001, 2003 Theodore Ts'o. - * Copyright (C) 2001 Andreas Dilger - * - * %Begin-Header% - * This file may be redistributed under the terms of the - * GNU Lesser General Public License. - * %End-Header% - */ - -#include -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#include -#include -#include -#include -#include "blkidP.h" -#include "probe.h" - -/* - * Find a tagname (e.g. LABEL or UUID) on a specific device. - */ -char *blkid_get_tag_value(blkid_cache cache, const char *tagname, - const char *devname) -{ - blkid_tag found; - blkid_dev dev; - blkid_cache c = cache; - char *ret = NULL; - - DBG(DEBUG_RESOLVE, printf("looking for %s on %s\n", tagname, devname)); - - if (!devname) - return NULL; - - if (!cache) { - if (blkid_get_cache(&c, NULL) < 0) - return NULL; - } - - if ((dev = blkid_get_dev(c, devname, BLKID_DEV_NORMAL)) && - (found = blkid_find_tag_dev(dev, tagname))) - ret = blkid_strdup(found->bit_val); - - if (!cache) - blkid_put_cache(c); - - return ret; -} - -/* - * Locate a device name from a token (NAME=value string), or (name, value) - * pair. In the case of a token, value is ignored. If the "token" is not - * of the form "NAME=value" and there is no value given, then it is assumed - * to be the actual devname and a copy is returned. - */ -char *blkid_get_devname(blkid_cache cache, const char *token, - const char *value) -{ - blkid_dev dev; - blkid_cache c = cache; - char *t = NULL, *v = NULL; - char *ret = NULL; - - if (!token) - return NULL; - - if (!cache) { - if (blkid_get_cache(&c, NULL) < 0) - return NULL; - } - - DBG(DEBUG_RESOLVE, - printf("looking for %s%s%s %s\n", token, value ? "=" : "", - value ? value : "", cache ? "in cache" : "from disk")); - - if (!value) { - if (!strchr(token, '=')) - return blkid_strdup(token); - blkid_parse_tag_string(token, &t, &v); - if (!t || !v) - goto errout; - token = t; - value = v; - } - - dev = blkid_find_dev_with_tag(c, token, value); - if (!dev) - goto errout; - - ret = blkid_strdup(blkid_dev_devname(dev)); - -errout: - free(t); - free(v); - if (!cache) { - blkid_put_cache(c); - } - return ret; -} - -#ifdef TEST_PROGRAM -int main(int argc, char **argv) -{ - char *value; - blkid_cache cache; - - blkid_debug_mask = DEBUG_ALL; - if (argc != 2 && argc != 3) { - fprintf(stderr, "Usage:\t%s tagname=value\n" - "\t%s tagname devname\n" - "Find which device holds a given token or\n" - "Find what the value of a tag is in a device\n", - argv[0], argv[0]); - exit(1); - } - if (blkid_get_cache(&cache, bb_dev_null) < 0) { - fprintf(stderr, "Can't get blkid cache\n"); - exit(1); - } - - if (argv[2]) { - value = blkid_get_tag_value(cache, argv[1], argv[2]); - printf("%s has tag %s=%s\n", argv[2], argv[1], - value ? value : ""); - } else { - value = blkid_get_devname(cache, argv[1], NULL); - printf("%s has tag %s\n", value ? value : "", argv[1]); - } - blkid_put_cache(cache); - return value ? 0 : 1; -} -#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 @@ -/* vi: set sw=4 ts=4: */ -/* - * save.c - write the cache struct to disk - * - * Copyright (C) 2001 by Andreas Dilger - * Copyright (C) 2003 Theodore Ts'o - * - * %Begin-Header% - * This file may be redistributed under the terms of the - * GNU Lesser General Public License. - * %End-Header% - */ - -#include -#include -#include -#include -#include -#ifdef HAVE_SYS_STAT_H -#include -#endif -#ifdef HAVE_SYS_MKDEV_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif -#include "blkidP.h" - -static int save_dev(blkid_dev dev, FILE *file) -{ - struct list_head *p; - - if (!dev || dev->bid_name[0] != '/') - return 0; - - DBG(DEBUG_SAVE, - printf("device %s, type %s\n", dev->bid_name, dev->bid_type)); - - fprintf(file, - "bid_devno, dev->bid_time); - if (dev->bid_pri) - fprintf(file, " PRI=\"%d\"", dev->bid_pri); - list_for_each(p, &dev->bid_tags) { - blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags); - fprintf(file, " %s=\"%s\"", tag->bit_name,tag->bit_val); - } - fprintf(file, ">%s\n", dev->bid_name); - - return 0; -} - -/* - * Write out the cache struct to the cache file on disk. - */ -int blkid_flush_cache(blkid_cache cache) -{ - struct list_head *p; - char *tmp = NULL; - const char *opened = NULL; - const char *filename; - FILE *file = NULL; - int fd, ret = 0; - struct stat st; - - if (!cache) - return -BLKID_ERR_PARAM; - - if (list_empty(&cache->bic_devs) || - !(cache->bic_flags & BLKID_BIC_FL_CHANGED)) { - DBG(DEBUG_SAVE, printf("skipping cache file write\n")); - return 0; - } - - filename = cache->bic_filename ? cache->bic_filename: BLKID_CACHE_FILE; - - /* If we can't write to the cache file, then don't even try */ - if (((ret = stat(filename, &st)) < 0 && errno != ENOENT) || - (ret == 0 && access(filename, W_OK) < 0)) { - DBG(DEBUG_SAVE, - printf("can't write to cache file %s\n", filename)); - return 0; - } - - /* - * Try and create a temporary file in the same directory so - * that in case of error we don't overwrite the cache file. - * If the cache file doesn't yet exist, it isn't a regular - * file (e.g. /dev/null or a socket), or we couldn't create - * a temporary file then we open it directly. - */ - if (ret == 0 && S_ISREG(st.st_mode)) { - tmp = xmalloc(strlen(filename) + 8); - sprintf(tmp, "%s-XXXXXX", filename); - fd = mkstemp(tmp); - if (fd >= 0) { - file = xfdopen_for_write(fd); - opened = tmp; - } - fchmod(fd, 0644); - } - - if (!file) { - file = fopen_for_write(filename); - opened = filename; - } - - DBG(DEBUG_SAVE, - printf("writing cache file %s (really %s)\n", - filename, opened)); - - if (!file) { - ret = errno; - goto errout; - } - - list_for_each(p, &cache->bic_devs) { - blkid_dev dev = list_entry(p, struct blkid_struct_dev, bid_devs); - if (!dev->bid_type) - continue; - if ((ret = save_dev(dev, file)) < 0) - break; - } - - if (ret >= 0) { - cache->bic_flags &= ~BLKID_BIC_FL_CHANGED; - ret = 1; - } - - fclose(file); - if (opened != filename) { - if (ret < 0) { - unlink(opened); - DBG(DEBUG_SAVE, - printf("unlinked temp cache %s\n", opened)); - } else { - char *backup; - - backup = xmalloc(strlen(filename) + 5); - sprintf(backup, "%s.old", filename); - unlink(backup); - link(filename, backup); - free(backup); - rename(opened, filename); - DBG(DEBUG_SAVE, - printf("moved temp cache %s\n", opened)); - } - } - -errout: - free(tmp); - return ret; -} - -#ifdef TEST_PROGRAM -int main(int argc, char **argv) -{ - blkid_cache cache = NULL; - int ret; - - blkid_debug_mask = DEBUG_ALL; - if (argc > 2) { - fprintf(stderr, "Usage: %s [filename]\n" - "Test loading/saving a cache (filename)\n", argv[0]); - exit(1); - } - - if ((ret = blkid_get_cache(&cache, bb_dev_null)) != 0) { - fprintf(stderr, "%s: error creating cache (%d)\n", - argv[0], ret); - exit(1); - } - if ((ret = blkid_probe_all(cache)) < 0) { - fprintf(stderr, "error (%d) probing devices\n", ret); - exit(1); - } - cache->bic_filename = blkid_strdup(argv[1]); - - if ((ret = blkid_flush_cache(cache)) < 0) { - fprintf(stderr, "error (%d) saving cache\n", ret); - exit(1); - } - - blkid_put_cache(cache); - - return ret; -} -#endif diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * tag.c - allocation/initialization/free routines for tag structs - * - * Copyright (C) 2001 Andreas Dilger - * Copyright (C) 2003 Theodore Ts'o - * - * %Begin-Header% - * This file may be redistributed under the terms of the - * GNU Lesser General Public License. - * %End-Header% - */ - -#include -#include -#include - -#include "blkidP.h" - -static blkid_tag blkid_new_tag(void) -{ - blkid_tag tag; - - tag = xzalloc(sizeof(struct blkid_struct_tag)); - - INIT_LIST_HEAD(&tag->bit_tags); - INIT_LIST_HEAD(&tag->bit_names); - - return tag; -} - -#ifdef CONFIG_BLKID_DEBUG -void blkid_debug_dump_tag(blkid_tag tag) -{ - if (!tag) { - printf(" tag: NULL\n"); - return; - } - - printf(" tag: %s=\"%s\"\n", tag->bit_name, tag->bit_val); -} -#endif - -void blkid_free_tag(blkid_tag tag) -{ - if (!tag) - return; - - DBG(DEBUG_TAG, printf(" freeing tag %s=%s\n", tag->bit_name, - tag->bit_val ? tag->bit_val : "(NULL)")); - DBG(DEBUG_TAG, blkid_debug_dump_tag(tag)); - - list_del(&tag->bit_tags); /* list of tags for this device */ - list_del(&tag->bit_names); /* list of tags with this type */ - - free(tag->bit_name); - free(tag->bit_val); - free(tag); -} - -/* - * Find the desired tag on a device. If value is NULL, then the - * first such tag is returned, otherwise return only exact tag if found. - */ -blkid_tag blkid_find_tag_dev(blkid_dev dev, const char *type) -{ - struct list_head *p; - - if (!dev || !type) - return NULL; - - list_for_each(p, &dev->bid_tags) { - blkid_tag tmp = list_entry(p, struct blkid_struct_tag, - bit_tags); - - if (!strcmp(tmp->bit_name, type)) - return tmp; - } - return NULL; -} - -/* - * Find the desired tag type in the cache. - * We return the head tag for this tag type. - */ -static blkid_tag blkid_find_head_cache(blkid_cache cache, const char *type) -{ - blkid_tag head = NULL, tmp; - struct list_head *p; - - if (!cache || !type) - return NULL; - - list_for_each(p, &cache->bic_tags) { - tmp = list_entry(p, struct blkid_struct_tag, bit_tags); - if (!strcmp(tmp->bit_name, type)) { - DBG(DEBUG_TAG, - printf(" found cache tag head %s\n", type)); - head = tmp; - break; - } - } - return head; -} - -/* - * Set a tag on an existing device. - * - * If value is NULL, then delete the tagsfrom the device. - */ -int blkid_set_tag(blkid_dev dev, const char *name, - const char *value, const int vlength) -{ - blkid_tag t = 0, head = 0; - char *val = NULL; - - if (!dev || !name) - return -BLKID_ERR_PARAM; - - if (!(val = blkid_strndup(value, vlength)) && value) - return -BLKID_ERR_MEM; - t = blkid_find_tag_dev(dev, name); - if (!value) { - blkid_free_tag(t); - } else if (t) { - if (!strcmp(t->bit_val, val)) { - /* Same thing, exit */ - free(val); - return 0; - } - free(t->bit_val); - t->bit_val = val; - } else { - /* Existing tag not present, add to device */ - if (!(t = blkid_new_tag())) - goto errout; - t->bit_name = blkid_strdup(name); - t->bit_val = val; - t->bit_dev = dev; - - list_add_tail(&t->bit_tags, &dev->bid_tags); - - if (dev->bid_cache) { - head = blkid_find_head_cache(dev->bid_cache, - t->bit_name); - if (!head) { - head = blkid_new_tag(); - if (!head) - goto errout; - - DBG(DEBUG_TAG, - printf(" creating new cache tag head %s\n", name)); - head->bit_name = blkid_strdup(name); - if (!head->bit_name) - goto errout; - list_add_tail(&head->bit_tags, - &dev->bid_cache->bic_tags); - } - list_add_tail(&t->bit_names, &head->bit_names); - } - } - - /* Link common tags directly to the device struct */ - if (!strcmp(name, "TYPE")) - dev->bid_type = val; - else if (!strcmp(name, "LABEL")) - dev->bid_label = val; - else if (!strcmp(name, "UUID")) - dev->bid_uuid = val; - - if (dev->bid_cache) - dev->bid_cache->bic_flags |= BLKID_BIC_FL_CHANGED; - return 0; - -errout: - blkid_free_tag(t); - if (!t) - free(val); - blkid_free_tag(head); - return -BLKID_ERR_MEM; -} - - -/* - * Parse a "NAME=value" string. This is slightly different than - * parse_token, because that will end an unquoted value at a space, while - * this will assume that an unquoted value is the rest of the token (e.g. - * if we are passed an already quoted string from the command-line we don't - * have to both quote and escape quote so that the quotes make it to - * us). - * - * Returns 0 on success, and -1 on failure. - */ -int blkid_parse_tag_string(const char *token, char **ret_type, char **ret_val) -{ - char *name, *value, *cp; - - DBG(DEBUG_TAG, printf("trying to parse '%s' as a tag\n", token)); - - if (!token || !(cp = strchr(token, '='))) - return -1; - - name = blkid_strdup(token); - if (!name) - return -1; - value = name + (cp - token); - *value++ = '\0'; - if (*value == '"' || *value == '\'') { - char c = *value++; - if (!(cp = strrchr(value, c))) - goto errout; /* missing closing quote */ - *cp = '\0'; - } - value = blkid_strdup(value); - if (!value) - goto errout; - - *ret_type = name; - *ret_val = value; - - return 0; - -errout: - free(name); - return -1; -} - -/* - * Tag iteration routines for the public libblkid interface. - * - * These routines do not expose the list.h implementation, which are a - * contamination of the namespace, and which force us to reveal far, far - * too much of our internal implementation. I'm not convinced I want - * to keep list.h in the long term, anyway. It's fine for kernel - * programming, but performance is not the #1 priority for this - * library, and I really don't like the tradeoff of type-safety for - * performance for this application. [tytso:20030125.2007EST] - */ - -/* - * This series of functions iterate over all tags in a device - */ -#define TAG_ITERATE_MAGIC 0x01a5284c - -struct blkid_struct_tag_iterate { - int magic; - blkid_dev dev; - struct list_head *p; -}; - -blkid_tag_iterate blkid_tag_iterate_begin(blkid_dev dev) -{ - blkid_tag_iterate iter; - - iter = xmalloc(sizeof(struct blkid_struct_tag_iterate)); - iter->magic = TAG_ITERATE_MAGIC; - iter->dev = dev; - iter->p = dev->bid_tags.next; - return iter; -} - -/* - * Return 0 on success, -1 on error - */ -extern int blkid_tag_next(blkid_tag_iterate iter, - const char **type, const char **value) -{ - blkid_tag tag; - - *type = 0; - *value = 0; - if (!iter || iter->magic != TAG_ITERATE_MAGIC || - iter->p == &iter->dev->bid_tags) - return -1; - tag = list_entry(iter->p, struct blkid_struct_tag, bit_tags); - *type = tag->bit_name; - *value = tag->bit_val; - iter->p = iter->p->next; - return 0; -} - -void blkid_tag_iterate_end(blkid_tag_iterate iter) -{ - if (!iter || iter->magic != TAG_ITERATE_MAGIC) - return; - iter->magic = 0; - free(iter); -} - -/* - * This function returns a device which matches a particular - * type/value pair. If there is more than one device that matches the - * search specification, it returns the one with the highest priority - * value. This allows us to give preference to EVMS or LVM devices. - * - * XXX there should also be an interface which uses an iterator so we - * can get all of the devices which match a type/value search parameter. - */ -extern blkid_dev blkid_find_dev_with_tag(blkid_cache cache, - const char *type, - const char *value) -{ - blkid_tag head; - blkid_dev dev; - int pri; - struct list_head *p; - - if (!cache || !type || !value) - return NULL; - - blkid_read_cache(cache); - - DBG(DEBUG_TAG, printf("looking for %s=%s in cache\n", type, value)); - -try_again: - pri = -1; - dev = 0; - head = blkid_find_head_cache(cache, type); - - if (head) { - list_for_each(p, &head->bit_names) { - blkid_tag tmp = list_entry(p, struct blkid_struct_tag, - bit_names); - - if (!strcmp(tmp->bit_val, value) && - tmp->bit_dev->bid_pri > pri) { - dev = tmp->bit_dev; - pri = dev->bid_pri; - } - } - } - if (dev && !(dev->bid_flags & BLKID_BID_FL_VERIFIED)) { - dev = blkid_verify(cache, dev); - if (dev && (dev->bid_flags & BLKID_BID_FL_VERIFIED)) - goto try_again; - } - - if (!dev && !(cache->bic_flags & BLKID_BIC_FL_PROBED)) { - if (blkid_probe_all(cache) < 0) - return NULL; - goto try_again; - } - return dev; -} - -#ifdef TEST_PROGRAM -#ifdef HAVE_GETOPT_H -#include -#else -extern char *optarg; -extern int optind; -#endif - -void usage(char *prog) -{ - fprintf(stderr, "Usage: %s [-f blkid_file] [-m debug_mask] device " - "[type value]\n", - prog); - fprintf(stderr, "\tList all tags for a device and exit\n"); - exit(1); -} - -int main(int argc, char **argv) -{ - blkid_tag_iterate iter; - blkid_cache cache = NULL; - blkid_dev dev; - int c, ret, found; - int flags = BLKID_DEV_FIND; - char *tmp; - char *file = NULL; - char *devname = NULL; - char *search_type = NULL; - char *search_value = NULL; - const char *type, *value; - - while ((c = getopt (argc, argv, "m:f:")) != EOF) - switch (c) { - case 'f': - file = optarg; - break; - case 'm': - blkid_debug_mask = strtoul (optarg, &tmp, 0); - if (*tmp) { - fprintf(stderr, "Invalid debug mask: %s\n", - optarg); - exit(1); - } - break; - case '?': - usage(argv[0]); - } - if (argc > optind) - devname = argv[optind++]; - if (argc > optind) - search_type = argv[optind++]; - if (argc > optind) - search_value = argv[optind++]; - if (!devname || (argc != optind)) - usage(argv[0]); - - if ((ret = blkid_get_cache(&cache, file)) != 0) { - fprintf(stderr, "%s: error creating cache (%d)\n", - argv[0], ret); - exit(1); - } - - dev = blkid_get_dev(cache, devname, flags); - if (!dev) { - fprintf(stderr, "%s: cannot find device in blkid cache\n", devname); - exit(1); - } - if (search_type) { - found = blkid_dev_has_tag(dev, search_type, search_value); - printf("Device %s: (%s, %s) %s\n", blkid_dev_devname(dev), - search_type, search_value ? search_value : "NULL", - found ? "FOUND" : "NOT FOUND"); - return !found; - } - printf("Device %s...\n", blkid_dev_devname(dev)); - - iter = blkid_tag_iterate_begin(dev); - while (blkid_tag_next(iter, &type, &value) == 0) { - printf("\tTag %s has value %s\n", type, value); - } - blkid_tag_iterate_end(iter); - - blkid_put_cache(cache); - return 0; -} -#endif diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * chattr.c - Change file attributes on an ext2 file system - * - * Copyright (C) 1993, 1994 Remy Card - * Laboratoire MASI, Institut Blaise Pascal - * Universite Pierre et Marie Curie (Paris VI) - * - * This file can be redistributed under the terms of the GNU General - * Public License - */ - -/* - * History: - * 93/10/30 - Creation - * 93/11/13 - Replace stat() calls by lstat() to avoid loops - * 94/02/27 - Integrated in Ted's distribution - * 98/12/29 - Ignore symlinks when working recursively (G M Sipe) - * 98/12/29 - Display version info only when -V specified (G M Sipe) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ext2fs/ext2_fs.h" - -#ifdef __GNUC__ -# define EXT2FS_ATTR(x) __attribute__(x) -#else -# define EXT2FS_ATTR(x) -#endif - -#include "e2fsbb.h" -#include "e2p/e2p.h" - -#define OPT_ADD 1 -#define OPT_REM 2 -#define OPT_SET 4 -#define OPT_SET_VER 8 -static int flags; -static int recursive; - -static unsigned long version; - -static unsigned long af; -static unsigned long rf; -static unsigned long sf; - -struct flags_char { - unsigned long flag; - char optchar; -}; - -static const struct flags_char flags_array[] = { - { EXT2_NOATIME_FL, 'A' }, - { EXT2_SYNC_FL, 'S' }, - { EXT2_DIRSYNC_FL, 'D' }, - { EXT2_APPEND_FL, 'a' }, - { EXT2_COMPR_FL, 'c' }, - { EXT2_NODUMP_FL, 'd' }, - { EXT2_IMMUTABLE_FL, 'i' }, - { EXT3_JOURNAL_DATA_FL, 'j' }, - { EXT2_SECRM_FL, 's' }, - { EXT2_UNRM_FL, 'u' }, - { EXT2_NOTAIL_FL, 't' }, - { EXT2_TOPDIR_FL, 'T' }, - { 0, 0 } -}; - -static unsigned long get_flag(char c) -{ - const struct flags_char *fp; - for (fp = flags_array; fp->flag; fp++) - if (fp->optchar == c) - return fp->flag; - bb_show_usage(); - return 0; -} - -static int decode_arg(char *arg) -{ - unsigned long *fl; - char opt = *arg++; - - if (opt == '-') { - flags |= OPT_REM; - fl = &rf; - } else if (opt == '+') { - flags |= OPT_ADD; - fl = ⁡ - } else if (opt == '=') { - flags |= OPT_SET; - fl = &sf; - } else - return EOF; - - for (; *arg; ++arg) - (*fl) |= get_flag(*arg); - - return 1; -} - -static int chattr_dir_proc(const char *, struct dirent *, void *); - -static void change_attributes(const char * name) -{ - unsigned long fsflags; - struct stat st; - - if (lstat(name, &st) == -1) { - bb_error_msg("stat %s failed", name); - return; - } - if (S_ISLNK(st.st_mode) && recursive) - return; - - /* Don't try to open device files, fifos etc. We probably - * ought to display an error if the file was explicitly given - * on the command line (whether or not recursive was - * requested). */ - if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) && !S_ISDIR(st.st_mode)) - return; - - if (flags & OPT_SET_VER) - if (fsetversion(name, version) == -1) - bb_error_msg("setting version on %s", name); - - if (flags & OPT_SET) { - fsflags = sf; - } else { - if (fgetflags(name, &fsflags) == -1) { - bb_error_msg("reading flags on %s", name); - goto skip_setflags; - } - if (flags & OPT_REM) - fsflags &= ~rf; - if (flags & OPT_ADD) - fsflags |= af; - if (!S_ISDIR(st.st_mode)) - fsflags &= ~EXT2_DIRSYNC_FL; - } - if (fsetflags(name, fsflags) == -1) - bb_error_msg("setting flags on %s", name); - -skip_setflags: - if (S_ISDIR(st.st_mode) && recursive) - iterate_on_dir(name, chattr_dir_proc, NULL); -} - -static int chattr_dir_proc(const char *dir_name, struct dirent *de, - void *private EXT2FS_ATTR((unused))) -{ - /*if (strcmp(de->d_name, ".") || strcmp(de->d_name, "..")) {*/ - if (de->d_name[0] == '.' - && (!de->d_name[1] || (de->d_name[1] == '.' && !de->d_name[2])) - ) { - char *path = concat_subpath_file(dir_name, de->d_name); - if (path) { - change_attributes(path); - free(path); - } - } - return 0; -} - -int chattr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -int chattr_main(int argc, char **argv) -{ - int i; - char *arg; - - /* parse the args */ - for (i = 1; i < argc; ++i) { - arg = argv[i]; - - /* take care of -R and -v */ - if (arg[0] == '-') { - if (arg[1] == 'R' && arg[2] == '\0') { - recursive = 1; - continue; - } else if (arg[1] == 'v' && arg[2] == '\0') { - char *tmp; - ++i; - if (i >= argc) - bb_show_usage(); - version = strtol(argv[i], &tmp, 0); - if (*tmp) - bb_error_msg_and_die("bad version '%s'", arg); - flags |= OPT_SET_VER; - continue; - } - } - - if (decode_arg(arg) == EOF) - break; - } - - /* run sanity checks on all the arguments given us */ - if (i >= argc) - bb_show_usage(); - if ((flags & OPT_SET) && ((flags & OPT_ADD) || (flags & OPT_REM))) - bb_error_msg_and_die("= is incompatible with - and +"); - if ((rf & af) != 0) - bb_error_msg_and_die("Can't set and unset a flag"); - if (!flags) - bb_error_msg_and_die("Must use '-v', =, - or +"); - - /* now run chattr on all the files passed to us */ - while (i < argc) - change_attributes(argv[i++]); - - return EXIT_SUCCESS; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * File: e2fsbb.h - * - * Redefine a bunch of e2fsprogs stuff to use busybox routines - * instead. This makes upgrade between e2fsprogs versions easy. - */ - -#ifndef E2FSBB_H -#define E2FSBB_H 1 - -#include "libbb.h" - -/* version we've last synced against */ -#define E2FSPROGS_VERSION "1.38" -#define E2FSPROGS_DATE "30-Jun-2005" - -typedef long errcode_t; -#define ERRCODE_RANGE 8 -#define error_message(code) strerror((int) (code & ((1< - * Free Software License: - * All rights are reserved by the author, with the following exceptions: - * Permission is granted to freely reproduce and distribute this software, - * possibly in exchange for a fee, provided that this copyright notice appears - * intact. Permission is also granted to adapt this software to produce - * derivative works, as long as the modified versions carry this copyright - * notice and additional notices stating that the work has been modified. - * This source code may be translated into executable form and incorporated - * into proprietary software; there is no requirement for such software to - * contain a copyright notice related to this source. - * - * linux/fs/recovery and linux/fs/revoke - * Written by Stephen C. Tweedie , 1999 - * - * Copyright 1999-2000 Red Hat Software --- All Rights Reserved - * - * Journal recovery routines for the generic filesystem journaling code; - * part of the ext2fs journaling system. - * - * Licensed under GPLv2 or later, see file LICENSE in this source tree. - */ - -/* -//usage:#define e2fsck_trivial_usage -//usage: "[-panyrcdfvstDFSV] [-b superblock] [-B blocksize] " -//usage: "[-I inode_buffer_blocks] [-P process_inode_size] " -//usage: "[-l|-L bad_blocks_file] [-C fd] [-j external_journal] " -//usage: "[-E extended-options] device" -//usage:#define e2fsck_full_usage "\n\n" -//usage: "Check ext2/ext3 file system\n" -//usage: "\n -p Automatic repair (no questions)" -//usage: "\n -n Make no changes to the filesystem" -//usage: "\n -y Assume 'yes' to all questions" -//usage: "\n -c Check for bad blocks and add them to the badblock list" -//usage: "\n -f Force checking even if filesystem is marked clean" -//usage: "\n -v Verbose" -//usage: "\n -b superblock Use alternative superblock" -//usage: "\n -B blocksize Force blocksize when looking for superblock" -//usage: "\n -j journal Set location of the external journal" -//usage: "\n -l file Add to badblocks list" -//usage: "\n -L file Set badblocks list" -*/ - -#include "e2fsck.h" /*Put all of our defines here to clean things up*/ - -#define _(x) x -#define N_(x) x - -/* - * Procedure declarations - */ - -static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf); - -/* pass1.c */ -static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool); - -/* pass2.c */ -static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir, - ext2_ino_t ino, char *buf); - -/* pass3.c */ -static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode); -static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir, - int num, int gauranteed_size); -static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix); -static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, - int adj); - -/* rehash.c */ -static void e2fsck_rehash_directories(e2fsck_t ctx); - -/* util.c */ -static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size, - const char *description); -static int ask(e2fsck_t ctx, const char * string, int def); -static void e2fsck_read_bitmaps(e2fsck_t ctx); -static void preenhalt(e2fsck_t ctx); -static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino, - struct ext2_inode * inode, const char * proc); -static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino, - struct ext2_inode * inode, const char * proc); -static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, - const char *name, io_manager manager); - -/* unix.c */ -static void e2fsck_clear_progbar(e2fsck_t ctx); -static int e2fsck_simple_progress(e2fsck_t ctx, const char *label, - float percent, unsigned int dpynum); - - -/* - * problem.h --- e2fsck problem error codes - */ - -typedef __u32 problem_t; - -struct problem_context { - errcode_t errcode; - ext2_ino_t ino, ino2, dir; - struct ext2_inode *inode; - struct ext2_dir_entry *dirent; - blk_t blk, blk2; - e2_blkcnt_t blkcount; - int group; - __u64 num; - const char *str; -}; - - -/* - * Function declarations - */ -static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx); -static int end_problem_latch(e2fsck_t ctx, int mask); -static int set_latch_flags(int mask, int setflags, int clearflags); -static void clear_problem_context(struct problem_context *ctx); - -/* - * Dictionary Abstract Data Type - * Copyright (C) 1997 Kaz Kylheku - * - * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz - * kazlib_1_20 - */ - -#ifndef DICT_H -#define DICT_H - -/* - * Blurb for inclusion into C++ translation units - */ - -typedef unsigned long dictcount_t; -#define DICTCOUNT_T_MAX ULONG_MAX - -/* - * The dictionary is implemented as a red-black tree - */ - -typedef enum { dnode_red, dnode_black } dnode_color_t; - -typedef struct dnode_t { - struct dnode_t *dict_left; - struct dnode_t *dict_right; - struct dnode_t *dict_parent; - dnode_color_t dict_color; - const void *dict_key; - void *dict_data; -} dnode_t; - -typedef int (*dict_comp_t)(const void *, const void *); -typedef void (*dnode_free_t)(dnode_t *); - -typedef struct dict_t { - dnode_t dict_nilnode; - dictcount_t dict_nodecount; - dictcount_t dict_maxcount; - dict_comp_t dict_compare; - dnode_free_t dict_freenode; - int dict_dupes; -} dict_t; - -typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *); - -typedef struct dict_load_t { - dict_t *dict_dictptr; - dnode_t dict_nilnode; -} dict_load_t; - -#define dict_count(D) ((D)->dict_nodecount) -#define dnode_get(N) ((N)->dict_data) -#define dnode_getkey(N) ((N)->dict_key) - -#endif - -/* - * Compatibility header file for e2fsck which should be included - * instead of linux/jfs.h - * - * Copyright (C) 2000 Stephen C. Tweedie - */ - -/* - * Pull in the definition of the e2fsck context structure - */ - -struct buffer_head { - char b_data[8192]; - e2fsck_t b_ctx; - io_channel b_io; - int b_size; - blk_t b_blocknr; - int b_dirty; - int b_uptodate; - int b_err; -}; - - -#define K_DEV_FS 1 -#define K_DEV_JOURNAL 2 - -#define lock_buffer(bh) do {} while (0) -#define unlock_buffer(bh) do {} while (0) -#define buffer_req(bh) 1 -#define do_readahead(journal, start) do {} while (0) - -static e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */ - -typedef struct { - int object_length; -} kmem_cache_t; - -#define kmem_cache_alloc(cache,flags) malloc((cache)->object_length) - -/* - * We use the standard libext2fs portability tricks for inline - * functions. - */ - -static kmem_cache_t * do_cache_create(int len) -{ - kmem_cache_t *new_cache; - - new_cache = xmalloc(sizeof(*new_cache)); - new_cache->object_length = len; - return new_cache; -} - -static void do_cache_destroy(kmem_cache_t *cache) -{ - free(cache); -} - - -/* - * Dictionary Abstract Data Type - */ - - -/* - * These macros provide short convenient names for structure members, - * which are embellished with dict_ prefixes so that they are - * properly confined to the documented namespace. It's legal for a - * program which uses dict to define, for instance, a macro called ``parent''. - * Such a macro would interfere with the dnode_t struct definition. - * In general, highly portable and reusable C modules which expose their - * structures need to confine structure member names to well-defined spaces. - * The resulting identifiers aren't necessarily convenient to use, nor - * readable, in the implementation, however! - */ - -#define left dict_left -#define right dict_right -#define parent dict_parent -#define color dict_color -#define key dict_key -#define data dict_data - -#define nilnode dict_nilnode -#define maxcount dict_maxcount -#define compare dict_compare -#define dupes dict_dupes - -#define dict_root(D) ((D)->nilnode.left) -#define dict_nil(D) (&(D)->nilnode) - -static void dnode_free(dnode_t *node); - -/* - * Perform a ``left rotation'' adjustment on the tree. The given node P and - * its right child C are rearranged so that the P instead becomes the left - * child of C. The left subtree of C is inherited as the new right subtree - * for P. The ordering of the keys within the tree is thus preserved. - */ - -static void rotate_left(dnode_t *upper) -{ - dnode_t *lower, *lowleft, *upparent; - - lower = upper->right; - upper->right = lowleft = lower->left; - lowleft->parent = upper; - - lower->parent = upparent = upper->parent; - - /* don't need to check for root node here because root->parent is - the sentinel nil node, and root->parent->left points back to root */ - - if (upper == upparent->left) { - upparent->left = lower; - } else { - assert (upper == upparent->right); - upparent->right = lower; - } - - lower->left = upper; - upper->parent = lower; -} - -/* - * This operation is the ``mirror'' image of rotate_left. It is - * the same procedure, but with left and right interchanged. - */ - -static void rotate_right(dnode_t *upper) -{ - dnode_t *lower, *lowright, *upparent; - - lower = upper->left; - upper->left = lowright = lower->right; - lowright->parent = upper; - - lower->parent = upparent = upper->parent; - - if (upper == upparent->right) { - upparent->right = lower; - } else { - assert (upper == upparent->left); - upparent->left = lower; - } - - lower->right = upper; - upper->parent = lower; -} - -/* - * Do a postorder traversal of the tree rooted at the specified - * node and free everything under it. Used by dict_free(). - */ - -static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil) -{ - if (node == nil) - return; - free_nodes(dict, node->left, nil); - free_nodes(dict, node->right, nil); - dict->dict_freenode(node); -} - -/* - * Verify that the tree contains the given node. This is done by - * traversing all of the nodes and comparing their pointers to the - * given pointer. Returns 1 if the node is found, otherwise - * returns zero. It is intended for debugging purposes. - */ - -static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node) -{ - if (root != nil) { - return root == node - || verify_dict_has_node(nil, root->left, node) - || verify_dict_has_node(nil, root->right, node); - } - return 0; -} - - -/* - * Select a different set of node allocator routines. - */ - -static void dict_set_allocator(dict_t *dict, dnode_free_t fr) -{ - assert(dict_count(dict) == 0); - dict->dict_freenode = fr; -} - -/* - * Free all the nodes in the dictionary by using the dictionary's - * installed free routine. The dictionary is emptied. - */ - -static void dict_free_nodes(dict_t *dict) -{ - dnode_t *nil = dict_nil(dict), *root = dict_root(dict); - free_nodes(dict, root, nil); - dict->dict_nodecount = 0; - dict->nilnode.left = &dict->nilnode; - dict->nilnode.right = &dict->nilnode; -} - -/* - * Initialize a user-supplied dictionary object. - */ - -static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp) -{ - dict->compare = comp; - dict->dict_freenode = dnode_free; - dict->dict_nodecount = 0; - dict->maxcount = maxcount; - dict->nilnode.left = &dict->nilnode; - dict->nilnode.right = &dict->nilnode; - dict->nilnode.parent = &dict->nilnode; - dict->nilnode.color = dnode_black; - dict->dupes = 0; - return dict; -} - -/* - * Locate a node in the dictionary having the given key. - * If the node is not found, a null a pointer is returned (rather than - * a pointer that dictionary's nil sentinel node), otherwise a pointer to the - * located node is returned. - */ - -static dnode_t *dict_lookup(dict_t *dict, const void *key) -{ - dnode_t *root = dict_root(dict); - dnode_t *nil = dict_nil(dict); - dnode_t *saved; - int result; - - /* simple binary search adapted for trees that contain duplicate keys */ - - while (root != nil) { - result = dict->compare(key, root->key); - if (result < 0) - root = root->left; - else if (result > 0) - root = root->right; - else { - if (!dict->dupes) { /* no duplicates, return match */ - return root; - } else { /* could be dupes, find leftmost one */ - do { - saved = root; - root = root->left; - while (root != nil && dict->compare(key, root->key)) - root = root->right; - } while (root != nil); - return saved; - } - } - } - - return NULL; -} - -/* - * Insert a node into the dictionary. The node should have been - * initialized with a data field. All other fields are ignored. - * The behavior is undefined if the user attempts to insert into - * a dictionary that is already full (for which the dict_isfull() - * function returns true). - */ - -static void dict_insert(dict_t *dict, dnode_t *node, const void *key) -{ - dnode_t *where = dict_root(dict), *nil = dict_nil(dict); - dnode_t *parent = nil, *uncle, *grandpa; - int result = -1; - - node->key = key; - - /* basic binary tree insert */ - - while (where != nil) { - parent = where; - result = dict->compare(key, where->key); - /* trap attempts at duplicate key insertion unless it's explicitly allowed */ - assert(dict->dupes || result != 0); - if (result < 0) - where = where->left; - else - where = where->right; - } - - assert(where == nil); - - if (result < 0) - parent->left = node; - else - parent->right = node; - - node->parent = parent; - node->left = nil; - node->right = nil; - - dict->dict_nodecount++; - - /* red black adjustments */ - - node->color = dnode_red; - - while (parent->color == dnode_red) { - grandpa = parent->parent; - if (parent == grandpa->left) { - uncle = grandpa->right; - if (uncle->color == dnode_red) { /* red parent, red uncle */ - parent->color = dnode_black; - uncle->color = dnode_black; - grandpa->color = dnode_red; - node = grandpa; - parent = grandpa->parent; - } else { /* red parent, black uncle */ - if (node == parent->right) { - rotate_left(parent); - parent = node; - assert (grandpa == parent->parent); - /* rotation between parent and child preserves grandpa */ - } - parent->color = dnode_black; - grandpa->color = dnode_red; - rotate_right(grandpa); - break; - } - } else { /* symmetric cases: parent == parent->parent->right */ - uncle = grandpa->left; - if (uncle->color == dnode_red) { - parent->color = dnode_black; - uncle->color = dnode_black; - grandpa->color = dnode_red; - node = grandpa; - parent = grandpa->parent; - } else { - if (node == parent->left) { - rotate_right(parent); - parent = node; - assert (grandpa == parent->parent); - } - parent->color = dnode_black; - grandpa->color = dnode_red; - rotate_left(grandpa); - break; - } - } - } - - dict_root(dict)->color = dnode_black; -} - -/* - * Allocate a node using the dictionary's allocator routine, give it - * the data item. - */ - -static dnode_t *dnode_init(dnode_t *dnode, void *data) -{ - dnode->data = data; - dnode->parent = NULL; - dnode->left = NULL; - dnode->right = NULL; - return dnode; -} - -static int dict_alloc_insert(dict_t *dict, const void *key, void *data) -{ - dnode_t *node = xmalloc(sizeof(dnode_t)); - - dnode_init(node, data); - dict_insert(dict, node, key); - return 1; -} - -/* - * Return the node with the lowest (leftmost) key. If the dictionary is empty - * (that is, dict_isempty(dict) returns 1) a null pointer is returned. - */ - -static dnode_t *dict_first(dict_t *dict) -{ - dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left; - - if (root != nil) - while ((left = root->left) != nil) - root = left; - - return (root == nil) ? NULL : root; -} - -/* - * Return the given node's successor node---the node which has the - * next key in the left to right ordering. If the node has - * no successor, a null pointer is returned rather than a pointer to - * the nil node. - */ - -static dnode_t *dict_next(dict_t *dict, dnode_t *curr) -{ - dnode_t *nil = dict_nil(dict), *parent, *left; - - if (curr->right != nil) { - curr = curr->right; - while ((left = curr->left) != nil) - curr = left; - return curr; - } - - parent = curr->parent; - - while (parent != nil && curr == parent->right) { - curr = parent; - parent = curr->parent; - } - - return (parent == nil) ? NULL : parent; -} - - -static void dnode_free(dnode_t *node) -{ - free(node); -} - - -#undef left -#undef right -#undef parent -#undef color -#undef key -#undef data - -#undef nilnode -#undef maxcount -#undef compare -#undef dupes - - -/* - * dirinfo.c --- maintains the directory information table for e2fsck. - */ - -/* - * This subroutine is called during pass1 to create a directory info - * entry. During pass1, the passed-in parent is 0; it will get filled - * in during pass2. - */ -static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent) -{ - struct dir_info *dir; - int i, j; - ext2_ino_t num_dirs; - errcode_t retval; - unsigned long old_size; - - if (!ctx->dir_info) { - ctx->dir_info_count = 0; - retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs); - if (retval) - num_dirs = 1024; /* Guess */ - ctx->dir_info_size = num_dirs + 10; - ctx->dir_info = (struct dir_info *) - e2fsck_allocate_memory(ctx, ctx->dir_info_size - * sizeof (struct dir_info), - "directory map"); - } - - if (ctx->dir_info_count >= ctx->dir_info_size) { - old_size = ctx->dir_info_size * sizeof(struct dir_info); - ctx->dir_info_size += 10; - retval = ext2fs_resize_mem(old_size, ctx->dir_info_size * - sizeof(struct dir_info), - &ctx->dir_info); - if (retval) { - ctx->dir_info_size -= 10; - return; - } - } - - /* - * Normally, add_dir_info is called with each inode in - * sequential order; but once in a while (like when pass 3 - * needs to recreate the root directory or lost+found - * directory) it is called out of order. In those cases, we - * need to move the dir_info entries down to make room, since - * the dir_info array needs to be sorted by inode number for - * get_dir_info()'s sake. - */ - if (ctx->dir_info_count && - ctx->dir_info[ctx->dir_info_count-1].ino >= ino) { - for (i = ctx->dir_info_count-1; i > 0; i--) - if (ctx->dir_info[i-1].ino < ino) - break; - dir = &ctx->dir_info[i]; - if (dir->ino != ino) - for (j = ctx->dir_info_count++; j > i; j--) - ctx->dir_info[j] = ctx->dir_info[j-1]; - } else - dir = &ctx->dir_info[ctx->dir_info_count++]; - - dir->ino = ino; - dir->dotdot = parent; - dir->parent = parent; -} - -/* - * get_dir_info() --- given an inode number, try to find the directory - * information entry for it. - */ -static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino) -{ - int low, high, mid; - - low = 0; - high = ctx->dir_info_count-1; - if (!ctx->dir_info) - return 0; - if (ino == ctx->dir_info[low].ino) - return &ctx->dir_info[low]; - if (ino == ctx->dir_info[high].ino) - return &ctx->dir_info[high]; - - while (low < high) { - mid = (low+high)/2; - if (mid == low || mid == high) - break; - if (ino == ctx->dir_info[mid].ino) - return &ctx->dir_info[mid]; - if (ino < ctx->dir_info[mid].ino) - high = mid; - else - low = mid; - } - return 0; -} - -/* - * Free the dir_info structure when it isn't needed any more. - */ -static void e2fsck_free_dir_info(e2fsck_t ctx) -{ - ext2fs_free_mem(&ctx->dir_info); - ctx->dir_info_size = 0; - ctx->dir_info_count = 0; -} - -/* - * Return the count of number of directories in the dir_info structure - */ -static int e2fsck_get_num_dirinfo(e2fsck_t ctx) -{ - return ctx->dir_info_count; -} - -/* - * A simple interator function - */ -static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control) -{ - if (*control >= ctx->dir_info_count) - return 0; - - return ctx->dir_info + (*control)++; -} - -/* - * dirinfo.c --- maintains the directory information table for e2fsck. - * - */ - -#ifdef ENABLE_HTREE - -/* - * This subroutine is called during pass1 to create a directory info - * entry. During pass1, the passed-in parent is 0; it will get filled - * in during pass2. - */ -static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks) -{ - struct dx_dir_info *dir; - int i, j; - errcode_t retval; - unsigned long old_size; - - if (!ctx->dx_dir_info) { - ctx->dx_dir_info_count = 0; - ctx->dx_dir_info_size = 100; /* Guess */ - ctx->dx_dir_info = (struct dx_dir_info *) - e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size - * sizeof (struct dx_dir_info), - "directory map"); - } - - if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) { - old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info); - ctx->dx_dir_info_size += 10; - retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size * - sizeof(struct dx_dir_info), - &ctx->dx_dir_info); - if (retval) { - ctx->dx_dir_info_size -= 10; - return; - } - } - - /* - * Normally, add_dx_dir_info is called with each inode in - * sequential order; but once in a while (like when pass 3 - * needs to recreate the root directory or lost+found - * directory) it is called out of order. In those cases, we - * need to move the dx_dir_info entries down to make room, since - * the dx_dir_info array needs to be sorted by inode number for - * get_dx_dir_info()'s sake. - */ - if (ctx->dx_dir_info_count && - ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) { - for (i = ctx->dx_dir_info_count-1; i > 0; i--) - if (ctx->dx_dir_info[i-1].ino < ino) - break; - dir = &ctx->dx_dir_info[i]; - if (dir->ino != ino) - for (j = ctx->dx_dir_info_count++; j > i; j--) - ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1]; - } else - dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++]; - - dir->ino = ino; - dir->numblocks = num_blocks; - dir->hashversion = 0; - dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks - * sizeof (struct dx_dirblock_info), - "dx_block info array"); -} - -/* - * get_dx_dir_info() --- given an inode number, try to find the directory - * information entry for it. - */ -static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino) -{ - int low, high, mid; - - low = 0; - high = ctx->dx_dir_info_count-1; - if (!ctx->dx_dir_info) - return 0; - if (ino == ctx->dx_dir_info[low].ino) - return &ctx->dx_dir_info[low]; - if (ino == ctx->dx_dir_info[high].ino) - return &ctx->dx_dir_info[high]; - - while (low < high) { - mid = (low+high)/2; - if (mid == low || mid == high) - break; - if (ino == ctx->dx_dir_info[mid].ino) - return &ctx->dx_dir_info[mid]; - if (ino < ctx->dx_dir_info[mid].ino) - high = mid; - else - low = mid; - } - return 0; -} - -/* - * Free the dx_dir_info structure when it isn't needed any more. - */ -static void e2fsck_free_dx_dir_info(e2fsck_t ctx) -{ - int i; - struct dx_dir_info *dir; - - if (ctx->dx_dir_info) { - dir = ctx->dx_dir_info; - for (i=0; i < ctx->dx_dir_info_count; i++) { - ext2fs_free_mem(&dir->dx_block); - } - ext2fs_free_mem(&ctx->dx_dir_info); - } - ctx->dx_dir_info_size = 0; - ctx->dx_dir_info_count = 0; -} - -/* - * A simple interator function - */ -static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control) -{ - if (*control >= ctx->dx_dir_info_count) - return 0; - - return ctx->dx_dir_info + (*control)++; -} - -#endif /* ENABLE_HTREE */ -/* - * e2fsck.c - a consistency checker for the new extended file system. - * - */ - -/* - * This function allocates an e2fsck context - */ -static errcode_t e2fsck_allocate_context(e2fsck_t *ret) -{ - e2fsck_t context; - errcode_t retval; - - retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context); - if (retval) - return retval; - - memset(context, 0, sizeof(struct e2fsck_struct)); - - context->process_inode_size = 256; - context->ext_attr_ver = 2; - - *ret = context; - return 0; -} - -struct ea_refcount_el { - blk_t ea_blk; - int ea_count; -}; - -struct ea_refcount { - blk_t count; - blk_t size; - blk_t cursor; - struct ea_refcount_el *list; -}; - -static void ea_refcount_free(ext2_refcount_t refcount) -{ - if (!refcount) - return; - - ext2fs_free_mem(&refcount->list); - ext2fs_free_mem(&refcount); -} - -/* - * This function resets an e2fsck context; it is called when e2fsck - * needs to be restarted. - */ -static errcode_t e2fsck_reset_context(e2fsck_t ctx) -{ - ctx->flags = 0; - ctx->lost_and_found = 0; - ctx->bad_lost_and_found = 0; - ext2fs_free_inode_bitmap(ctx->inode_used_map); - ctx->inode_used_map = 0; - ext2fs_free_inode_bitmap(ctx->inode_dir_map); - ctx->inode_dir_map = 0; - ext2fs_free_inode_bitmap(ctx->inode_reg_map); - ctx->inode_reg_map = 0; - ext2fs_free_block_bitmap(ctx->block_found_map); - ctx->block_found_map = 0; - ext2fs_free_icount(ctx->inode_link_info); - ctx->inode_link_info = 0; - if (ctx->journal_io) { - if (ctx->fs && ctx->fs->io != ctx->journal_io) - io_channel_close(ctx->journal_io); - ctx->journal_io = 0; - } - if (ctx->fs) { - ext2fs_free_dblist(ctx->fs->dblist); - ctx->fs->dblist = 0; - } - e2fsck_free_dir_info(ctx); -#ifdef ENABLE_HTREE - e2fsck_free_dx_dir_info(ctx); -#endif - ea_refcount_free(ctx->refcount); - ctx->refcount = 0; - ea_refcount_free(ctx->refcount_extra); - ctx->refcount_extra = 0; - ext2fs_free_block_bitmap(ctx->block_dup_map); - ctx->block_dup_map = 0; - ext2fs_free_block_bitmap(ctx->block_ea_map); - ctx->block_ea_map = 0; - ext2fs_free_inode_bitmap(ctx->inode_bad_map); - ctx->inode_bad_map = 0; - ext2fs_free_inode_bitmap(ctx->inode_imagic_map); - ctx->inode_imagic_map = 0; - ext2fs_u32_list_free(ctx->dirs_to_hash); - ctx->dirs_to_hash = 0; - - /* - * Clear the array of invalid meta-data flags - */ - ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag); - ext2fs_free_mem(&ctx->invalid_block_bitmap_flag); - ext2fs_free_mem(&ctx->invalid_inode_table_flag); - - /* Clear statistic counters */ - ctx->fs_directory_count = 0; - ctx->fs_regular_count = 0; - ctx->fs_blockdev_count = 0; - ctx->fs_chardev_count = 0; - ctx->fs_links_count = 0; - ctx->fs_symlinks_count = 0; - ctx->fs_fast_symlinks_count = 0; - ctx->fs_fifo_count = 0; - ctx->fs_total_count = 0; - ctx->fs_sockets_count = 0; - ctx->fs_ind_count = 0; - ctx->fs_dind_count = 0; - ctx->fs_tind_count = 0; - ctx->fs_fragmented = 0; - ctx->large_files = 0; - - /* Reset the superblock to the user's requested value */ - ctx->superblock = ctx->use_superblock; - - return 0; -} - -static void e2fsck_free_context(e2fsck_t ctx) -{ - if (!ctx) - return; - - e2fsck_reset_context(ctx); - if (ctx->blkid) - blkid_put_cache(ctx->blkid); - - ext2fs_free_mem(&ctx); -} - -/* - * ea_refcount.c - */ - -/* - * The strategy we use for keeping track of EA refcounts is as - * follows. We keep a sorted array of first EA blocks and its - * reference counts. Once the refcount has dropped to zero, it is - * removed from the array to save memory space. Once the EA block is - * checked, its bit is set in the block_ea_map bitmap. - */ - - -static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret) -{ - ext2_refcount_t refcount; - errcode_t retval; - size_t bytes; - - retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount); - if (retval) - return retval; - memset(refcount, 0, sizeof(struct ea_refcount)); - - if (!size) - size = 500; - refcount->size = size; - bytes = (size_t) (size * sizeof(struct ea_refcount_el)); -#ifdef DEBUG - printf("Refcount allocated %d entries, %lu bytes.\n", - refcount->size, bytes); -#endif - retval = ext2fs_get_mem(bytes, &refcount->list); - if (retval) - goto errout; - memset(refcount->list, 0, bytes); - - refcount->count = 0; - refcount->cursor = 0; - - *ret = refcount; - return 0; - -errout: - ea_refcount_free(refcount); - return retval; -} - -/* - * collapse_refcount() --- go through the refcount array, and get rid - * of any count == zero entries - */ -static void refcount_collapse(ext2_refcount_t refcount) -{ - unsigned int i, j; - struct ea_refcount_el *list; - - list = refcount->list; - for (i = 0, j = 0; i < refcount->count; i++) { - if (list[i].ea_count) { - if (i != j) - list[j] = list[i]; - j++; - } - } -#if defined(DEBUG) || defined(TEST_PROGRAM) - printf("Refcount_collapse: size was %d, now %d\n", - refcount->count, j); -#endif - refcount->count = j; -} - - -/* - * insert_refcount_el() --- Insert a new entry into the sorted list at a - * specified position. - */ -static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount, - blk_t blk, int pos) -{ - struct ea_refcount_el *el; - errcode_t retval; - blk_t new_size = 0; - int num; - - if (refcount->count >= refcount->size) { - new_size = refcount->size + 100; -#ifdef DEBUG - printf("Reallocating refcount %d entries...\n", new_size); -#endif - retval = ext2fs_resize_mem((size_t) refcount->size * - sizeof(struct ea_refcount_el), - (size_t) new_size * - sizeof(struct ea_refcount_el), - &refcount->list); - if (retval) - return 0; - refcount->size = new_size; - } - num = (int) refcount->count - pos; - if (num < 0) - return 0; /* should never happen */ - if (num) { - memmove(&refcount->list[pos+1], &refcount->list[pos], - sizeof(struct ea_refcount_el) * num); - } - refcount->count++; - el = &refcount->list[pos]; - el->ea_count = 0; - el->ea_blk = blk; - return el; -} - - -/* - * get_refcount_el() --- given an block number, try to find refcount - * information in the sorted list. If the create flag is set, - * and we can't find an entry, create one in the sorted list. - */ -static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount, - blk_t blk, int create) -{ - float range; - int low, high, mid; - blk_t lowval, highval; - - if (!refcount || !refcount->list) - return 0; -retry: - low = 0; - high = (int) refcount->count-1; - if (create && ((refcount->count == 0) || - (blk > refcount->list[high].ea_blk))) { - if (refcount->count >= refcount->size) - refcount_collapse(refcount); - - return insert_refcount_el(refcount, blk, - (unsigned) refcount->count); - } - if (refcount->count == 0) - return 0; - - if (refcount->cursor >= refcount->count) - refcount->cursor = 0; - if (blk == refcount->list[refcount->cursor].ea_blk) - return &refcount->list[refcount->cursor++]; -#ifdef DEBUG - printf("Non-cursor get_refcount_el: %u\n", blk); -#endif - while (low <= high) { - if (low == high) - mid = low; - else { - /* Interpolate for efficiency */ - lowval = refcount->list[low].ea_blk; - highval = refcount->list[high].ea_blk; - - if (blk < lowval) - range = 0; - else if (blk > highval) - range = 1; - else - range = ((float) (blk - lowval)) / - (highval - lowval); - mid = low + ((int) (range * (high-low))); - } - - if (blk == refcount->list[mid].ea_blk) { - refcount->cursor = mid+1; - return &refcount->list[mid]; - } - if (blk < refcount->list[mid].ea_blk) - high = mid-1; - else - low = mid+1; - } - /* - * If we need to create a new entry, it should be right at - * low (where high will be left at low-1). - */ - if (create) { - if (refcount->count >= refcount->size) { - refcount_collapse(refcount); - if (refcount->count < refcount->size) - goto retry; - } - return insert_refcount_el(refcount, blk, low); - } - return 0; -} - -static errcode_t -ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret) -{ - struct ea_refcount_el *el; - - el = get_refcount_el(refcount, blk, 1); - if (!el) - return EXT2_ET_NO_MEMORY; - el->ea_count++; - - if (ret) - *ret = el->ea_count; - return 0; -} - -static errcode_t -ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret) -{ - struct ea_refcount_el *el; - - el = get_refcount_el(refcount, blk, 0); - if (!el || el->ea_count == 0) - return EXT2_ET_INVALID_ARGUMENT; - - el->ea_count--; - - if (ret) - *ret = el->ea_count; - return 0; -} - -static errcode_t -ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count) -{ - struct ea_refcount_el *el; - - /* - * Get the refcount element - */ - el = get_refcount_el(refcount, blk, count ? 1 : 0); - if (!el) - return count ? EXT2_ET_NO_MEMORY : 0; - el->ea_count = count; - return 0; -} - -static inline void ea_refcount_intr_begin(ext2_refcount_t refcount) -{ - refcount->cursor = 0; -} - - -static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret) -{ - struct ea_refcount_el *list; - - while (1) { - if (refcount->cursor >= refcount->count) - return 0; - list = refcount->list; - if (list[refcount->cursor].ea_count) { - if (ret) - *ret = list[refcount->cursor].ea_count; - return list[refcount->cursor++].ea_blk; - } - refcount->cursor++; - } -} - - -/* - * ehandler.c --- handle bad block errors which come up during the - * course of an e2fsck session. - */ - - -static const char *operation; - -static errcode_t -e2fsck_handle_read_error(io_channel channel, unsigned long block, int count, - void *data, size_t size FSCK_ATTR((unused)), - int actual FSCK_ATTR((unused)), errcode_t error) -{ - int i; - char *p; - ext2_filsys fs = (ext2_filsys) channel->app_data; - e2fsck_t ctx; - - ctx = (e2fsck_t) fs->priv_data; - - /* - * If more than one block was read, try reading each block - * separately. We could use the actual bytes read to figure - * out where to start, but we don't bother. - */ - if (count > 1) { - p = (char *) data; - for (i=0; i < count; i++, p += channel->block_size, block++) { - error = io_channel_read_blk(channel, block, - 1, p); - if (error) - return error; - } - return 0; - } - if (operation) - printf(_("Error reading block %lu (%s) while %s. "), block, - error_message(error), operation); - else - printf(_("Error reading block %lu (%s). "), block, - error_message(error)); - preenhalt(ctx); - if (ask(ctx, _("Ignore error"), 1)) { - if (ask(ctx, _("Force rewrite"), 1)) - io_channel_write_blk(channel, block, 1, data); - return 0; - } - - return error; -} - -static errcode_t -e2fsck_handle_write_error(io_channel channel, unsigned long block, int count, - const void *data, size_t size FSCK_ATTR((unused)), - int actual FSCK_ATTR((unused)), errcode_t error) -{ - int i; - const char *p; - ext2_filsys fs = (ext2_filsys) channel->app_data; - e2fsck_t ctx; - - ctx = (e2fsck_t) fs->priv_data; - - /* - * If more than one block was written, try writing each block - * separately. We could use the actual bytes read to figure - * out where to start, but we don't bother. - */ - if (count > 1) { - p = (const char *) data; - for (i=0; i < count; i++, p += channel->block_size, block++) { - error = io_channel_write_blk(channel, block, - 1, p); - if (error) - return error; - } - return 0; - } - - if (operation) - printf(_("Error writing block %lu (%s) while %s. "), block, - error_message(error), operation); - else - printf(_("Error writing block %lu (%s). "), block, - error_message(error)); - preenhalt(ctx); - if (ask(ctx, _("Ignore error"), 1)) - return 0; - - return error; -} - -static const char *ehandler_operation(const char *op) -{ - const char *ret = operation; - - operation = op; - return ret; -} - -static void ehandler_init(io_channel channel) -{ - channel->read_error = e2fsck_handle_read_error; - channel->write_error = e2fsck_handle_write_error; -} - -/* - * journal.c --- code for handling the "ext3" journal - * - * Copyright (C) 2000 Andreas Dilger - * Copyright (C) 2000 Theodore Ts'o - * - * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie - * Copyright (C) 1999 Red Hat Software - * - * This file may be redistributed under the terms of the - * GNU General Public License version 2 or at your discretion - * any later version. - */ - -/* - * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths. - * This creates a larger static binary, and a smaller binary using - * shared libraries. It's also probably slightly less CPU-efficient, - * which is why it's not on by default. But, it's a good way of - * testing the functions in inode_io.c and fileio.c. - */ -#undef USE_INODE_IO - -/* Kernel compatibility functions for handling the journal. These allow us - * to use the recovery.c file virtually unchanged from the kernel, so we - * don't have to do much to keep kernel and user recovery in sync. - */ -static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys) -{ -#ifdef USE_INODE_IO - *phys = block; - return 0; -#else - struct inode *inode = journal->j_inode; - errcode_t retval; - blk_t pblk; - - if (!inode) { - *phys = block; - return 0; - } - - retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino, - &inode->i_ext2, NULL, 0, block, &pblk); - *phys = pblk; - return retval; -#endif -} - -static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize) -{ - struct buffer_head *bh; - - bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer"); - if (!bh) - return NULL; - - bh->b_ctx = kdev->k_ctx; - if (kdev->k_dev == K_DEV_FS) - bh->b_io = kdev->k_ctx->fs->io; - else - bh->b_io = kdev->k_ctx->journal_io; - bh->b_size = blocksize; - bh->b_blocknr = blocknr; - - return bh; -} - -static void sync_blockdev(kdev_t kdev) -{ - io_channel io; - - if (kdev->k_dev == K_DEV_FS) - io = kdev->k_ctx->fs->io; - else - io = kdev->k_ctx->journal_io; - - io_channel_flush(io); -} - -static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[]) -{ - int retval; - struct buffer_head *bh; - - for (; nr > 0; --nr) { - bh = *bhp++; - if (rw == READ && !bh->b_uptodate) { - retval = io_channel_read_blk(bh->b_io, - bh->b_blocknr, - 1, bh->b_data); - if (retval) { - bb_error_msg("while reading block %lu", - (unsigned long) bh->b_blocknr); - bh->b_err = retval; - continue; - } - bh->b_uptodate = 1; - } else if (rw == WRITE && bh->b_dirty) { - retval = io_channel_write_blk(bh->b_io, - bh->b_blocknr, - 1, bh->b_data); - if (retval) { - bb_error_msg("while writing block %lu", - (unsigned long) bh->b_blocknr); - bh->b_err = retval; - continue; - } - bh->b_dirty = 0; - bh->b_uptodate = 1; - } - } -} - -static void mark_buffer_dirty(struct buffer_head *bh) -{ - bh->b_dirty = 1; -} - -static inline void mark_buffer_clean(struct buffer_head * bh) -{ - bh->b_dirty = 0; -} - -static void brelse(struct buffer_head *bh) -{ - if (bh->b_dirty) - ll_rw_block(WRITE, 1, &bh); - ext2fs_free_mem(&bh); -} - -static int buffer_uptodate(struct buffer_head *bh) -{ - return bh->b_uptodate; -} - -static inline void mark_buffer_uptodate(struct buffer_head *bh, int val) -{ - bh->b_uptodate = val; -} - -static void wait_on_buffer(struct buffer_head *bh) -{ - if (!bh->b_uptodate) - ll_rw_block(READ, 1, &bh); -} - - -static void e2fsck_clear_recover(e2fsck_t ctx, int error) -{ - ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER; - - /* if we had an error doing journal recovery, we need a full fsck */ - if (error) - ctx->fs->super->s_state &= ~EXT2_VALID_FS; - ext2fs_mark_super_dirty(ctx->fs); -} - -static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal) -{ - struct ext2_super_block *sb = ctx->fs->super; - struct ext2_super_block jsuper; - struct problem_context pctx; - struct buffer_head *bh; - struct inode *j_inode = NULL; - struct kdev_s *dev_fs = NULL, *dev_journal; - const char *journal_name = NULL; - journal_t *journal = NULL; - errcode_t retval = 0; - io_manager io_ptr = 0; - unsigned long start = 0; - blk_t blk; - int ext_journal = 0; - int tried_backup_jnl = 0; - int i; - - clear_problem_context(&pctx); - - journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal"); - if (!journal) { - return EXT2_ET_NO_MEMORY; - } - - dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev"); - if (!dev_fs) { - retval = EXT2_ET_NO_MEMORY; - goto errout; - } - dev_journal = dev_fs+1; - - dev_fs->k_ctx = dev_journal->k_ctx = ctx; - dev_fs->k_dev = K_DEV_FS; - dev_journal->k_dev = K_DEV_JOURNAL; - - journal->j_dev = dev_journal; - journal->j_fs_dev = dev_fs; - journal->j_inode = NULL; - journal->j_blocksize = ctx->fs->blocksize; - - if (uuid_is_null(sb->s_journal_uuid)) { - if (!sb->s_journal_inum) - return EXT2_ET_BAD_INODE_NUM; - j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode), - "journal inode"); - if (!j_inode) { - retval = EXT2_ET_NO_MEMORY; - goto errout; - } - - j_inode->i_ctx = ctx; - j_inode->i_ino = sb->s_journal_inum; - - if ((retval = ext2fs_read_inode(ctx->fs, - sb->s_journal_inum, - &j_inode->i_ext2))) { - try_backup_journal: - if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS || - tried_backup_jnl) - goto errout; - memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode)); - memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks, - EXT2_N_BLOCKS*4); - j_inode->i_ext2.i_size = sb->s_jnl_blocks[16]; - j_inode->i_ext2.i_links_count = 1; - j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600; - tried_backup_jnl++; - } - if (!j_inode->i_ext2.i_links_count || - !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) { - retval = EXT2_ET_NO_JOURNAL; - goto try_backup_journal; - } - if (j_inode->i_ext2.i_size / journal->j_blocksize < - JFS_MIN_JOURNAL_BLOCKS) { - retval = EXT2_ET_JOURNAL_TOO_SMALL; - goto try_backup_journal; - } - for (i=0; i < EXT2_N_BLOCKS; i++) { - blk = j_inode->i_ext2.i_block[i]; - if (!blk) { - if (i < EXT2_NDIR_BLOCKS) { - retval = EXT2_ET_JOURNAL_TOO_SMALL; - goto try_backup_journal; - } - continue; - } - if (blk < sb->s_first_data_block || - blk >= sb->s_blocks_count) { - retval = EXT2_ET_BAD_BLOCK_NUM; - goto try_backup_journal; - } - } - journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize; - -#ifdef USE_INODE_IO - retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum, - &j_inode->i_ext2, - &journal_name); - if (retval) - goto errout; - - io_ptr = inode_io_manager; -#else - journal->j_inode = j_inode; - ctx->journal_io = ctx->fs->io; - if ((retval = journal_bmap(journal, 0, &start)) != 0) - goto errout; -#endif - } else { - ext_journal = 1; - if (!ctx->journal_name) { - char uuid[37]; - - uuid_unparse(sb->s_journal_uuid, uuid); - ctx->journal_name = blkid_get_devname(ctx->blkid, - "UUID", uuid); - if (!ctx->journal_name) - ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev); - } - journal_name = ctx->journal_name; - - if (!journal_name) { - fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx); - return EXT2_ET_LOAD_EXT_JOURNAL; - } - - io_ptr = unix_io_manager; - } - -#ifndef USE_INODE_IO - if (ext_journal) -#endif - retval = io_ptr->open(journal_name, IO_FLAG_RW, - &ctx->journal_io); - if (retval) - goto errout; - - io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize); - - if (ext_journal) { - if (ctx->fs->blocksize == 1024) - start = 1; - bh = getblk(dev_journal, start, ctx->fs->blocksize); - if (!bh) { - retval = EXT2_ET_NO_MEMORY; - goto errout; - } - ll_rw_block(READ, 1, &bh); - if ((retval = bh->b_err) != 0) - goto errout; - memcpy(&jsuper, start ? bh->b_data : bh->b_data + 1024, - sizeof(jsuper)); - brelse(bh); -#if BB_BIG_ENDIAN - if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC)) - ext2fs_swap_super(&jsuper); -#endif - if (jsuper.s_magic != EXT2_SUPER_MAGIC || - !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) { - fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx); - retval = EXT2_ET_LOAD_EXT_JOURNAL; - goto errout; - } - /* Make sure the journal UUID is correct */ - if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid, - sizeof(jsuper.s_uuid))) { - fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx); - retval = EXT2_ET_LOAD_EXT_JOURNAL; - goto errout; - } - - journal->j_maxlen = jsuper.s_blocks_count; - start++; - } - - if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) { - retval = EXT2_ET_NO_MEMORY; - goto errout; - } - - journal->j_sb_buffer = bh; - journal->j_superblock = (journal_superblock_t *)bh->b_data; - -#ifdef USE_INODE_IO - ext2fs_free_mem(&j_inode); -#endif - - *ret_journal = journal; - return 0; - -errout: - ext2fs_free_mem(&dev_fs); - ext2fs_free_mem(&j_inode); - ext2fs_free_mem(&journal); - return retval; -} - -static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx, - struct problem_context *pctx) -{ - struct ext2_super_block *sb = ctx->fs->super; - int recover = ctx->fs->super->s_feature_incompat & - EXT3_FEATURE_INCOMPAT_RECOVER; - int has_journal = ctx->fs->super->s_feature_compat & - EXT3_FEATURE_COMPAT_HAS_JOURNAL; - - if (has_journal || sb->s_journal_inum) { - /* The journal inode is bogus, remove and force full fsck */ - pctx->ino = sb->s_journal_inum; - if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) { - if (has_journal && sb->s_journal_inum) - printf("*** ext3 journal has been deleted - " - "filesystem is now ext2 only ***\n\n"); - sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL; - sb->s_journal_inum = 0; - ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */ - e2fsck_clear_recover(ctx, 1); - return 0; - } - return EXT2_ET_BAD_INODE_NUM; - } else if (recover) { - if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) { - e2fsck_clear_recover(ctx, 1); - return 0; - } - return EXT2_ET_UNSUPP_FEATURE; - } - return 0; -} - -#define V1_SB_SIZE 0x0024 -static void clear_v2_journal_fields(journal_t *journal) -{ - e2fsck_t ctx = journal->j_dev->k_ctx; - struct problem_context pctx; - - clear_problem_context(&pctx); - - if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx)) - return; - - memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0, - ctx->fs->blocksize-V1_SB_SIZE); - mark_buffer_dirty(journal->j_sb_buffer); -} - - -static errcode_t e2fsck_journal_load(journal_t *journal) -{ - e2fsck_t ctx = journal->j_dev->k_ctx; - journal_superblock_t *jsb; - struct buffer_head *jbh = journal->j_sb_buffer; - struct problem_context pctx; - - clear_problem_context(&pctx); - - ll_rw_block(READ, 1, &jbh); - if (jbh->b_err) { - bb_error_msg(_("reading journal superblock")); - return jbh->b_err; - } - - jsb = journal->j_superblock; - /* If we don't even have JFS_MAGIC, we probably have a wrong inode */ - if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER)) - return e2fsck_journal_fix_bad_inode(ctx, &pctx); - - switch (ntohl(jsb->s_header.h_blocktype)) { - case JFS_SUPERBLOCK_V1: - journal->j_format_version = 1; - if (jsb->s_feature_compat || - jsb->s_feature_incompat || - jsb->s_feature_ro_compat || - jsb->s_nr_users) - clear_v2_journal_fields(journal); - break; - - case JFS_SUPERBLOCK_V2: - journal->j_format_version = 2; - if (ntohl(jsb->s_nr_users) > 1 && - uuid_is_null(ctx->fs->super->s_journal_uuid)) - clear_v2_journal_fields(journal); - if (ntohl(jsb->s_nr_users) > 1) { - fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx); - return EXT2_ET_JOURNAL_UNSUPP_VERSION; - } - break; - - /* - * These should never appear in a journal super block, so if - * they do, the journal is badly corrupted. - */ - case JFS_DESCRIPTOR_BLOCK: - case JFS_COMMIT_BLOCK: - case JFS_REVOKE_BLOCK: - return EXT2_ET_CORRUPT_SUPERBLOCK; - - /* If we don't understand the superblock major type, but there - * is a magic number, then it is likely to be a new format we - * just don't understand, so leave it alone. */ - default: - return EXT2_ET_JOURNAL_UNSUPP_VERSION; - } - - if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES)) - return EXT2_ET_UNSUPP_FEATURE; - - if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES)) - return EXT2_ET_RO_UNSUPP_FEATURE; - - /* We have now checked whether we know enough about the journal - * format to be able to proceed safely, so any other checks that - * fail we should attempt to recover from. */ - if (jsb->s_blocksize != htonl(journal->j_blocksize)) { - bb_error_msg(_("%s: no valid journal superblock found"), - ctx->device_name); - return EXT2_ET_CORRUPT_SUPERBLOCK; - } - - if (ntohl(jsb->s_maxlen) < journal->j_maxlen) - journal->j_maxlen = ntohl(jsb->s_maxlen); - else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) { - bb_error_msg(_("%s: journal too short"), - ctx->device_name); - return EXT2_ET_CORRUPT_SUPERBLOCK; - } - - journal->j_tail_sequence = ntohl(jsb->s_sequence); - journal->j_transaction_sequence = journal->j_tail_sequence; - journal->j_tail = ntohl(jsb->s_start); - journal->j_first = ntohl(jsb->s_first); - journal->j_last = ntohl(jsb->s_maxlen); - - return 0; -} - -static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb, - journal_t *journal) -{ - char *p; - union { - uuid_t uuid; - __u32 val[4]; - } u; - __u32 new_seq = 0; - int i; - - /* Leave a valid existing V1 superblock signature alone. - * Anything unrecognizable we overwrite with a new V2 - * signature. */ - - if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) || - jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) { - jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER); - jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2); - } - - /* Zero out everything else beyond the superblock header */ - - p = ((char *) jsb) + sizeof(journal_header_t); - memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t)); - - jsb->s_blocksize = htonl(ctx->fs->blocksize); - jsb->s_maxlen = htonl(journal->j_maxlen); - jsb->s_first = htonl(1); - - /* Initialize the journal sequence number so that there is "no" - * chance we will find old "valid" transactions in the journal. - * This avoids the need to zero the whole journal (slow to do, - * and risky when we are just recovering the filesystem). - */ - uuid_generate(u.uuid); - for (i = 0; i < 4; i ++) - new_seq ^= u.val[i]; - jsb->s_sequence = htonl(new_seq); - - mark_buffer_dirty(journal->j_sb_buffer); - ll_rw_block(WRITE, 1, &journal->j_sb_buffer); -} - -static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx, - journal_t *journal, - struct problem_context *pctx) -{ - struct ext2_super_block *sb = ctx->fs->super; - int recover = ctx->fs->super->s_feature_incompat & - EXT3_FEATURE_INCOMPAT_RECOVER; - - if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) { - if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) { - e2fsck_journal_reset_super(ctx, journal->j_superblock, - journal); - journal->j_transaction_sequence = 1; - e2fsck_clear_recover(ctx, recover); - return 0; - } - return EXT2_ET_CORRUPT_SUPERBLOCK; - } else if (e2fsck_journal_fix_bad_inode(ctx, pctx)) - return EXT2_ET_CORRUPT_SUPERBLOCK; - - return 0; -} - -static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal, - int reset, int drop) -{ - journal_superblock_t *jsb; - - if (drop) - mark_buffer_clean(journal->j_sb_buffer); - else if (!(ctx->options & E2F_OPT_READONLY)) { - jsb = journal->j_superblock; - jsb->s_sequence = htonl(journal->j_transaction_sequence); - if (reset) - jsb->s_start = 0; /* this marks the journal as empty */ - mark_buffer_dirty(journal->j_sb_buffer); - } - brelse(journal->j_sb_buffer); - - if (ctx->journal_io) { - if (ctx->fs && ctx->fs->io != ctx->journal_io) - io_channel_close(ctx->journal_io); - ctx->journal_io = 0; - } - -#ifndef USE_INODE_IO - ext2fs_free_mem(&journal->j_inode); -#endif - ext2fs_free_mem(&journal->j_fs_dev); - ext2fs_free_mem(&journal); -} - -/* - * This function makes sure that the superblock fields regarding the - * journal are consistent. - */ -static int e2fsck_check_ext3_journal(e2fsck_t ctx) -{ - struct ext2_super_block *sb = ctx->fs->super; - journal_t *journal; - int recover = ctx->fs->super->s_feature_incompat & - EXT3_FEATURE_INCOMPAT_RECOVER; - struct problem_context pctx; - problem_t problem; - int reset = 0, force_fsck = 0; - int retval; - - /* If we don't have any journal features, don't do anything more */ - if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) && - !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 && - uuid_is_null(sb->s_journal_uuid)) - return 0; - - clear_problem_context(&pctx); - pctx.num = sb->s_journal_inum; - - retval = e2fsck_get_journal(ctx, &journal); - if (retval) { - if ((retval == EXT2_ET_BAD_INODE_NUM) || - (retval == EXT2_ET_BAD_BLOCK_NUM) || - (retval == EXT2_ET_JOURNAL_TOO_SMALL) || - (retval == EXT2_ET_NO_JOURNAL)) - return e2fsck_journal_fix_bad_inode(ctx, &pctx); - return retval; - } - - retval = e2fsck_journal_load(journal); - if (retval) { - if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) || - ((retval == EXT2_ET_UNSUPP_FEATURE) && - (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT, - &pctx))) || - ((retval == EXT2_ET_RO_UNSUPP_FEATURE) && - (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT, - &pctx))) || - ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) && - (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx)))) - retval = e2fsck_journal_fix_corrupt_super(ctx, journal, - &pctx); - e2fsck_journal_release(ctx, journal, 0, 1); - return retval; - } - - /* - * We want to make the flags consistent here. We will not leave with - * needs_recovery set but has_journal clear. We can't get in a loop - * with -y, -n, or -p, only if a user isn't making up their mind. - */ -no_has_journal: - if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) { - recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER; - pctx.str = "inode"; - if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) { - if (recover && - !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx)) - goto no_has_journal; - /* - * Need a full fsck if we are releasing a - * journal stored on a reserved inode. - */ - force_fsck = recover || - (sb->s_journal_inum < EXT2_FIRST_INODE(sb)); - /* Clear all of the journal fields */ - sb->s_journal_inum = 0; - sb->s_journal_dev = 0; - memset(sb->s_journal_uuid, 0, - sizeof(sb->s_journal_uuid)); - e2fsck_clear_recover(ctx, force_fsck); - } else if (!(ctx->options & E2F_OPT_READONLY)) { - sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL; - ext2fs_mark_super_dirty(ctx->fs); - } - } - - if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL && - !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) && - journal->j_superblock->s_start != 0) { - /* Print status information */ - fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx); - if (ctx->superblock) - problem = PR_0_JOURNAL_RUN_DEFAULT; - else - problem = PR_0_JOURNAL_RUN; - if (fix_problem(ctx, problem, &pctx)) { - ctx->options |= E2F_OPT_FORCE; - sb->s_feature_incompat |= - EXT3_FEATURE_INCOMPAT_RECOVER; - ext2fs_mark_super_dirty(ctx->fs); - } else if (fix_problem(ctx, - PR_0_JOURNAL_RESET_JOURNAL, &pctx)) { - reset = 1; - sb->s_state &= ~EXT2_VALID_FS; - ext2fs_mark_super_dirty(ctx->fs); - } - /* - * If the user answers no to the above question, we - * ignore the fact that journal apparently has data; - * accidentally replaying over valid data would be far - * worse than skipping a questionable recovery. - * - * XXX should we abort with a fatal error here? What - * will the ext3 kernel code do if a filesystem with - * !NEEDS_RECOVERY but with a non-zero - * journal->j_superblock->s_start is mounted? - */ - } - - e2fsck_journal_release(ctx, journal, reset, 0); - return retval; -} - -static errcode_t recover_ext3_journal(e2fsck_t ctx) -{ - journal_t *journal; - int retval; - - journal_init_revoke_caches(); - retval = e2fsck_get_journal(ctx, &journal); - if (retval) - return retval; - - retval = e2fsck_journal_load(journal); - if (retval) - goto errout; - - retval = journal_init_revoke(journal, 1024); - if (retval) - goto errout; - - retval = -journal_recover(journal); - if (retval) - goto errout; - - if (journal->j_superblock->s_errno) { - ctx->fs->super->s_state |= EXT2_ERROR_FS; - ext2fs_mark_super_dirty(ctx->fs); - journal->j_superblock->s_errno = 0; - mark_buffer_dirty(journal->j_sb_buffer); - } - -errout: - journal_destroy_revoke(journal); - journal_destroy_revoke_caches(); - e2fsck_journal_release(ctx, journal, 1, 0); - return retval; -} - -static int e2fsck_run_ext3_journal(e2fsck_t ctx) -{ - io_manager io_ptr = ctx->fs->io->manager; - int blocksize = ctx->fs->blocksize; - errcode_t retval, recover_retval; - - printf(_("%s: recovering journal\n"), ctx->device_name); - if (ctx->options & E2F_OPT_READONLY) { - printf(_("%s: won't do journal recovery while read-only\n"), - ctx->device_name); - return EXT2_ET_FILE_RO; - } - - if (ctx->fs->flags & EXT2_FLAG_DIRTY) - ext2fs_flush(ctx->fs); /* Force out any modifications */ - - recover_retval = recover_ext3_journal(ctx); - - /* - * Reload the filesystem context to get up-to-date data from disk - * because journal recovery will change the filesystem under us. - */ - ext2fs_close(ctx->fs); - retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW, - ctx->superblock, blocksize, io_ptr, - &ctx->fs); - - if (retval) { - bb_error_msg(_("while trying to re-open %s"), - ctx->device_name); - bb_error_msg_and_die(0); - } - ctx->fs->priv_data = ctx; - - /* Set the superblock flags */ - e2fsck_clear_recover(ctx, recover_retval); - return recover_retval; -} - -/* - * This function will move the journal inode from a visible file in - * the filesystem directory hierarchy to the reserved inode if necessary. - */ -static const char *const journal_names[] = { - ".journal", "journal", ".journal.dat", "journal.dat", 0 }; - -static void e2fsck_move_ext3_journal(e2fsck_t ctx) -{ - struct ext2_super_block *sb = ctx->fs->super; - struct problem_context pctx; - struct ext2_inode inode; - ext2_filsys fs = ctx->fs; - ext2_ino_t ino; - errcode_t retval; - const char *const * cpp; - int group, mount_flags; - - clear_problem_context(&pctx); - - /* - * If the filesystem is opened read-only, or there is no - * journal, then do nothing. - */ - if ((ctx->options & E2F_OPT_READONLY) || - (sb->s_journal_inum == 0) || - !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) - return; - - /* - * Read in the journal inode - */ - if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0) - return; - - /* - * If it's necessary to backup the journal inode, do so. - */ - if ((sb->s_jnl_backup_type == 0) || - ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) && - memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) { - if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) { - memcpy(sb->s_jnl_blocks, inode.i_block, - EXT2_N_BLOCKS*4); - sb->s_jnl_blocks[16] = inode.i_size; - sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS; - ext2fs_mark_super_dirty(fs); - fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; - } - } - - /* - * If the journal is already the hidden inode, then do nothing - */ - if (sb->s_journal_inum == EXT2_JOURNAL_INO) - return; - - /* - * The journal inode had better have only one link and not be readable. - */ - if (inode.i_links_count != 1) - return; - - /* - * If the filesystem is mounted, or we can't tell whether - * or not it's mounted, do nothing. - */ - retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags); - if (retval || (mount_flags & EXT2_MF_MOUNTED)) - return; - - /* - * If we can't find the name of the journal inode, then do - * nothing. - */ - for (cpp = journal_names; *cpp; cpp++) { - retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp, - strlen(*cpp), 0, &ino); - if ((retval == 0) && (ino == sb->s_journal_inum)) - break; - } - if (*cpp == 0) - return; - - /* We need the inode bitmap to be loaded */ - retval = ext2fs_read_bitmaps(fs); - if (retval) - return; - - pctx.str = *cpp; - if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx)) - return; - - /* - * OK, we've done all the checks, let's actually move the - * journal inode. Errors at this point mean we need to force - * an ext2 filesystem check. - */ - if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0) - goto err_out; - if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0) - goto err_out; - sb->s_journal_inum = EXT2_JOURNAL_INO; - ext2fs_mark_super_dirty(fs); - fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; - inode.i_links_count = 0; - inode.i_dtime = time(NULL); - if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0) - goto err_out; - - group = ext2fs_group_of_ino(fs, ino); - ext2fs_unmark_inode_bitmap(fs->inode_map, ino); - ext2fs_mark_ib_dirty(fs); - fs->group_desc[group].bg_free_inodes_count++; - fs->super->s_free_inodes_count++; - return; - -err_out: - pctx.errcode = retval; - fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx); - fs->super->s_state &= ~EXT2_VALID_FS; - ext2fs_mark_super_dirty(fs); -} - -/* - * message.c --- print e2fsck messages (with compression) - * - * print_e2fsck_message() prints a message to the user, using - * compression techniques and expansions of abbreviations. - * - * The following % expansions are supported: - * - * %b block number - * %B integer - * %c block number - * %Di ->ino inode number - * %Dn ->name string - * %Dr ->rec_len - * %Dl ->name_len - * %Dt ->filetype - * %d

    inode number - * %g integer - * %i inode number - * %Is -> i_size - * %IS -> i_extra_isize - * %Ib -> i_blocks - * %Il -> i_links_count - * %Im -> i_mode - * %IM -> i_mtime - * %IF -> i_faddr - * %If -> i_file_acl - * %Id -> i_dir_acl - * %Iu -> i_uid - * %Ig -> i_gid - * %j inode number - * %m - * %N - * %p ext2fs_get_pathname of directory - * %P ext2fs_get_pathname of ->ino with as - * the containing directory. (If dirent is NULL - * then return the pathname of directory ) - * %q ext2fs_get_pathname of directory - * %Q ext2fs_get_pathname of directory with as - * the containing directory. - * %s miscellaneous string - * %S backup superblock - * %X hexadecimal format - * - * The following '@' expansions are supported: - * - * @a extended attribute - * @A error allocating - * @b block - * @B bitmap - * @c compress - * @C conflicts with some other fs block - * @D deleted - * @d directory - * @e entry - * @E Entry '%Dn' in %p (%i) - * @f filesystem - * @F for @i %i (%Q) is - * @g group - * @h HTREE directory inode - * @i inode - * @I illegal - * @j journal - * @l lost+found - * @L is a link - * @m multiply-claimed - * @n invalid - * @o orphaned - * @p problem in - * @r root inode - * @s should be - * @S superblock - * @u unattached - * @v device - * @z zero-length - */ - - -/* - * This structure defines the abbreviations used by the text strings - * below. The first character in the string is the index letter. An - * abbreviation of the form '@' is expanded by looking up the index - * letter in the table below. - */ -static const char *const abbrevs[] = { - N_("aextended attribute"), - N_("Aerror allocating"), - N_("bblock"), - N_("Bbitmap"), - N_("ccompress"), - N_("Cconflicts with some other fs @b"), - N_("iinode"), - N_("Iillegal"), - N_("jjournal"), - N_("Ddeleted"), - N_("ddirectory"), - N_("eentry"), - N_("E@e '%Dn' in %p (%i)"), - N_("ffilesystem"), - N_("Ffor @i %i (%Q) is"), - N_("ggroup"), - N_("hHTREE @d @i"), - N_("llost+found"), - N_("Lis a link"), - N_("mmultiply-claimed"), - N_("ninvalid"), - N_("oorphaned"), - N_("pproblem in"), - N_("rroot @i"), - N_("sshould be"), - N_("Ssuper@b"), - N_("uunattached"), - N_("vdevice"), - N_("zzero-length"), - "@@", - 0 - }; - -/* - * Give more user friendly names to the "special" inodes. - */ -#define num_special_inodes 11 -static const char *const special_inode_name[] = -{ - N_(""), /* 0 */ - N_(""), /* 1 */ - "/", /* 2 */ - N_(""), /* 3 */ - N_(""), /* 4 */ - N_(""), /* 5 */ - N_(""), /* 6 */ - N_(""), /* 7 */ - N_(""), /* 8 */ - N_(""), /* 9 */ - N_(""), /* 10 */ -}; - -/* - * This function does "safe" printing. It will convert non-printable - * ASCII characters using '^' and M- notation. - */ -static void safe_print(const char *cp, int len) -{ - unsigned char ch; - - if (len < 0) - len = strlen(cp); - - while (len--) { - ch = *cp++; - if (ch > 128) { - fputs("M-", stdout); - ch -= 128; - } - if ((ch < 32) || (ch == 0x7f)) { - bb_putchar('^'); - ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */ - } - bb_putchar(ch); - } -} - - -/* - * This function prints a pathname, using the ext2fs_get_pathname - * function - */ -static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino) -{ - errcode_t retval; - char *path; - - if (!dir && (ino < num_special_inodes)) { - fputs(_(special_inode_name[ino]), stdout); - return; - } - - retval = ext2fs_get_pathname(fs, dir, ino, &path); - if (retval) - fputs("???", stdout); - else { - safe_print(path, -1); - ext2fs_free_mem(&path); - } -} - -static void print_e2fsck_message(e2fsck_t ctx, const char *msg, - struct problem_context *pctx, int first); -/* - * This function handles the '@' expansion. We allow recursive - * expansion; an @ expression can contain further '@' and '%' - * expressions. - */ -static void expand_at_expression(e2fsck_t ctx, char ch, - struct problem_context *pctx, - int *first) -{ - const char *const *cpp; - const char *str; - - /* Search for the abbreviation */ - for (cpp = abbrevs; *cpp; cpp++) { - if (ch == *cpp[0]) - break; - } - if (*cpp) { - str = _(*cpp) + 1; - if (*first && islower(*str)) { - *first = 0; - bb_putchar(toupper(*str++)); - } - print_e2fsck_message(ctx, str, pctx, *first); - } else - printf("@%c", ch); -} - -/* - * This function expands '%IX' expressions - */ -static void expand_inode_expression(char ch, - struct problem_context *ctx) -{ - struct ext2_inode *inode; - struct ext2_inode_large *large_inode; - char * time_str; - time_t t; - int do_gmt = -1; - - if (!ctx || !ctx->inode) - goto no_inode; - - inode = ctx->inode; - large_inode = (struct ext2_inode_large *) inode; - - switch (ch) { - case 's': - if (LINUX_S_ISDIR(inode->i_mode)) - printf("%u", inode->i_size); - else { - printf("%"PRIu64, (inode->i_size | - ((uint64_t) inode->i_size_high << 32))); - } - break; - case 'S': - printf("%u", large_inode->i_extra_isize); - break; - case 'b': - printf("%u", inode->i_blocks); - break; - case 'l': - printf("%d", inode->i_links_count); - break; - case 'm': - printf("0%o", inode->i_mode); - break; - case 'M': - /* The diet libc doesn't respect the TZ environemnt variable */ - if (do_gmt == -1) { - time_str = getenv("TZ"); - if (!time_str) - time_str = ""; - do_gmt = !strcmp(time_str, "GMT"); - } - t = inode->i_mtime; - time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t)); - printf("%.24s", time_str); - break; - case 'F': - printf("%u", inode->i_faddr); - break; - case 'f': - printf("%u", inode->i_file_acl); - break; - case 'd': - printf("%u", (LINUX_S_ISDIR(inode->i_mode) ? - inode->i_dir_acl : 0)); - break; - case 'u': - printf("%d", (inode->i_uid | - (inode->osd2.linux2.l_i_uid_high << 16))); - break; - case 'g': - printf("%d", (inode->i_gid | - (inode->osd2.linux2.l_i_gid_high << 16))); - break; - default: - no_inode: - printf("%%I%c", ch); - break; - } -} - -/* - * This function expands '%dX' expressions - */ -static void expand_dirent_expression(char ch, - struct problem_context *ctx) -{ - struct ext2_dir_entry *dirent; - int len; - - if (!ctx || !ctx->dirent) - goto no_dirent; - - dirent = ctx->dirent; - - switch (ch) { - case 'i': - printf("%u", dirent->inode); - break; - case 'n': - len = dirent->name_len & 0xFF; - if (len > EXT2_NAME_LEN) - len = EXT2_NAME_LEN; - if (len > dirent->rec_len) - len = dirent->rec_len; - safe_print(dirent->name, len); - break; - case 'r': - printf("%u", dirent->rec_len); - break; - case 'l': - printf("%u", dirent->name_len & 0xFF); - break; - case 't': - printf("%u", dirent->name_len >> 8); - break; - default: - no_dirent: - printf("%%D%c", ch); - break; - } -} - -static void expand_percent_expression(ext2_filsys fs, char ch, - struct problem_context *ctx) -{ - if (!ctx) - goto no_context; - - switch (ch) { - case '%': - bb_putchar('%'); - break; - case 'b': - printf("%u", ctx->blk); - break; - case 'B': - printf("%"PRIi64, ctx->blkcount); - break; - case 'c': - printf("%u", ctx->blk2); - break; - case 'd': - printf("%u", ctx->dir); - break; - case 'g': - printf("%d", ctx->group); - break; - case 'i': - printf("%u", ctx->ino); - break; - case 'j': - printf("%u", ctx->ino2); - break; - case 'm': - fputs(error_message(ctx->errcode), stdout); - break; - case 'N': - printf("%"PRIi64, ctx->num); - break; - case 'p': - print_pathname(fs, ctx->ino, 0); - break; - case 'P': - print_pathname(fs, ctx->ino2, - ctx->dirent ? ctx->dirent->inode : 0); - break; - case 'q': - print_pathname(fs, ctx->dir, 0); - break; - case 'Q': - print_pathname(fs, ctx->dir, ctx->ino); - break; - case 'S': - printf("%d", get_backup_sb(NULL, fs, NULL, NULL)); - break; - case 's': - fputs((ctx->str ? ctx->str : "NULL"), stdout); - break; - case 'X': - printf("0x%"PRIi64, ctx->num); - break; - default: - no_context: - printf("%%%c", ch); - break; - } -} - - -static void print_e2fsck_message(e2fsck_t ctx, const char *msg, - struct problem_context *pctx, int first) -{ - ext2_filsys fs = ctx->fs; - const char * cp; - int i; - - e2fsck_clear_progbar(ctx); - for (cp = msg; *cp; cp++) { - if (cp[0] == '@') { - cp++; - expand_at_expression(ctx, *cp, pctx, &first); - } else if (cp[0] == '%' && cp[1] == 'I') { - cp += 2; - expand_inode_expression(*cp, pctx); - } else if (cp[0] == '%' && cp[1] == 'D') { - cp += 2; - expand_dirent_expression(*cp, pctx); - } else if ((cp[0] == '%')) { - cp++; - expand_percent_expression(fs, *cp, pctx); - } else { - for (i=0; cp[i]; i++) - if ((cp[i] == '@') || cp[i] == '%') - break; - printf("%.*s", i, cp); - cp += i-1; - } - first = 0; - } -} - - -/* - * region.c --- code which manages allocations within a region. - */ - -struct region_el { - region_addr_t start; - region_addr_t end; - struct region_el *next; -}; - -struct region_struct { - region_addr_t min; - region_addr_t max; - struct region_el *allocated; -}; - -static region_t region_create(region_addr_t min, region_addr_t max) -{ - region_t region; - - region = xzalloc(sizeof(struct region_struct)); - region->min = min; - region->max = max; - return region; -} - -static void region_free(region_t region) -{ - struct region_el *r, *next; - - for (r = region->allocated; r; r = next) { - next = r->next; - free(r); - } - memset(region, 0, sizeof(struct region_struct)); - free(region); -} - -static int region_allocate(region_t region, region_addr_t start, int n) -{ - struct region_el *r, *new_region, *prev, *next; - region_addr_t end; - - end = start+n; - if ((start < region->min) || (end > region->max)) - return -1; - if (n == 0) - return 1; - - /* - * Search through the linked list. If we find that it - * conflicts witih something that's already allocated, return - * 1; if we can find an existing region which we can grow, do - * so. Otherwise, stop when we find the appropriate place - * insert a new region element into the linked list. - */ - for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) { - if (((start >= r->start) && (start < r->end)) || - ((end > r->start) && (end <= r->end)) || - ((start <= r->start) && (end >= r->end))) - return 1; - if (end == r->start) { - r->start = start; - return 0; - } - if (start == r->end) { - if ((next = r->next)) { - if (end > next->start) - return 1; - if (end == next->start) { - r->end = next->end; - r->next = next->next; - free(next); - return 0; - } - } - r->end = end; - return 0; - } - if (start < r->start) - break; - } - /* - * Insert a new region element structure into the linked list - */ - new_region = xmalloc(sizeof(struct region_el)); - new_region->start = start; - new_region->end = start + n; - new_region->next = r; - if (prev) - prev->next = new_region; - else - region->allocated = new_region; - return 0; -} - -/* - * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table - * - * Pass 1 of e2fsck iterates over all the inodes in the filesystems, - * and applies the following tests to each inode: - * - * - The mode field of the inode must be legal. - * - The size and block count fields of the inode are correct. - * - A data block must not be used by another inode - * - * Pass 1 also gathers the collects the following information: - * - * - A bitmap of which inodes are in use. (inode_used_map) - * - A bitmap of which inodes are directories. (inode_dir_map) - * - A bitmap of which inodes are regular files. (inode_reg_map) - * - A bitmap of which inodes have bad fields. (inode_bad_map) - * - A bitmap of which inodes are imagic inodes. (inode_imagic_map) - * - A bitmap of which blocks are in use. (block_found_map) - * - A bitmap of which blocks are in use by two inodes (block_dup_map) - * - The data blocks of the directory inodes. (dir_map) - * - * Pass 1 is designed to stash away enough information so that the - * other passes should not need to read in the inode information - * during the normal course of a filesystem check. (Althogh if an - * inconsistency is detected, other passes may need to read in an - * inode to fix it.) - * - * Note that pass 1B will be invoked if there are any duplicate blocks - * found. - */ - - -static int process_block(ext2_filsys fs, blk_t *blocknr, - e2_blkcnt_t blockcnt, blk_t ref_blk, - int ref_offset, void *priv_data); -static int process_bad_block(ext2_filsys fs, blk_t *block_nr, - e2_blkcnt_t blockcnt, blk_t ref_blk, - int ref_offset, void *priv_data); -static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, - char *block_buf); -static void mark_table_blocks(e2fsck_t ctx); -static void alloc_imagic_map(e2fsck_t ctx); -static void mark_inode_bad(e2fsck_t ctx, ino_t ino); -static void handle_fs_bad_blocks(e2fsck_t ctx); -static void process_inodes(e2fsck_t ctx, char *block_buf); -static int process_inode_cmp(const void *a, const void *b); -static errcode_t scan_callback(ext2_filsys fs, - dgrp_t group, void * priv_data); -static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount, - char *block_buf, int adjust_sign); -/* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */ - -static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino, - struct ext2_inode * inode, int bufsize, - const char *proc); - -struct process_block_struct_1 { - ext2_ino_t ino; - unsigned is_dir:1, is_reg:1, clear:1, suppress:1, - fragmented:1, compressed:1, bbcheck:1; - blk_t num_blocks; - blk_t max_blocks; - e2_blkcnt_t last_block; - int num_illegal_blocks; - blk_t previous_block; - struct ext2_inode *inode; - struct problem_context *pctx; - ext2fs_block_bitmap fs_meta_blocks; - e2fsck_t ctx; -}; - -struct process_inode_block { - ext2_ino_t ino; - struct ext2_inode inode; -}; - -struct scan_callback_struct { - e2fsck_t ctx; - char *block_buf; -}; - -/* - * For the inodes to process list. - */ -static struct process_inode_block *inodes_to_process; -static int process_inode_count; - -static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE - - EXT2_MIN_BLOCK_LOG_SIZE + 1]; - -/* - * Free all memory allocated by pass1 in preparation for restarting - * things. - */ -static void unwind_pass1(void) -{ - ext2fs_free_mem(&inodes_to_process); -} - -/* - * Check to make sure a device inode is real. Returns 1 if the device - * checks out, 0 if not. - * - * Note: this routine is now also used to check FIFO's and Sockets, - * since they have the same requirement; the i_block fields should be - * zero. - */ -static int -e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode) -{ - int i; - - /* - * If i_blocks is non-zero, or the index flag is set, then - * this is a bogus device/fifo/socket - */ - if ((ext2fs_inode_data_blocks(fs, inode) != 0) || - (inode->i_flags & EXT2_INDEX_FL)) - return 0; - - /* - * We should be able to do the test below all the time, but - * because the kernel doesn't forcibly clear the device - * inode's additional i_block fields, there are some rare - * occasions when a legitimate device inode will have non-zero - * additional i_block fields. So for now, we only complain - * when the immutable flag is set, which should never happen - * for devices. (And that's when the problem is caused, since - * you can't set or clear immutable flags for devices.) Once - * the kernel has been fixed we can change this... - */ - if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) { - for (i=4; i < EXT2_N_BLOCKS; i++) - if (inode->i_block[i]) - return 0; - } - return 1; -} - -/* - * Check to make sure a symlink inode is real. Returns 1 if the symlink - * checks out, 0 if not. - */ -static int -e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf) -{ - unsigned int len; - int i; - blk_t blocks; - - if ((inode->i_size_high || inode->i_size == 0) || - (inode->i_flags & EXT2_INDEX_FL)) - return 0; - - blocks = ext2fs_inode_data_blocks(fs, inode); - if (blocks) { - if ((inode->i_size >= fs->blocksize) || - (blocks != fs->blocksize >> 9) || - (inode->i_block[0] < fs->super->s_first_data_block) || - (inode->i_block[0] >= fs->super->s_blocks_count)) - return 0; - - for (i = 1; i < EXT2_N_BLOCKS; i++) - if (inode->i_block[i]) - return 0; - - if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf)) - return 0; - - len = strnlen(buf, fs->blocksize); - if (len == fs->blocksize) - return 0; - } else { - if (inode->i_size >= sizeof(inode->i_block)) - return 0; - - len = strnlen((char *)inode->i_block, sizeof(inode->i_block)); - if (len == sizeof(inode->i_block)) - return 0; - } - if (len != inode->i_size) - return 0; - return 1; -} - -/* - * If the immutable (or append-only) flag is set on the inode, offer - * to clear it. - */ -#define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL) -static void check_immutable(e2fsck_t ctx, struct problem_context *pctx) -{ - if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS)) - return; - - if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx)) - return; - - pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS; - e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1"); -} - -/* - * If device, fifo or socket, check size is zero -- if not offer to - * clear it - */ -static void check_size(e2fsck_t ctx, struct problem_context *pctx) -{ - struct ext2_inode *inode = pctx->inode; - - if ((inode->i_size == 0) && (inode->i_size_high == 0)) - return; - - if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx)) - return; - - inode->i_size = 0; - inode->i_size_high = 0; - e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1"); -} - -static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx) -{ - struct ext2_super_block *sb = ctx->fs->super; - struct ext2_inode_large *inode; - struct ext2_ext_attr_entry *entry; - char *start, *end; - int storage_size, remain, offs; - int problem = 0; - - inode = (struct ext2_inode_large *) pctx->inode; - storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE - - inode->i_extra_isize; - start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + - inode->i_extra_isize + sizeof(__u32); - end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super); - entry = (struct ext2_ext_attr_entry *) start; - - /* scan all entry's headers first */ - - /* take finish entry 0UL into account */ - remain = storage_size - sizeof(__u32); - offs = end - start; - - while (!EXT2_EXT_IS_LAST_ENTRY(entry)) { - - /* header eats this space */ - remain -= sizeof(struct ext2_ext_attr_entry); - - /* is attribute name valid? */ - if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) { - pctx->num = entry->e_name_len; - problem = PR_1_ATTR_NAME_LEN; - goto fix; - } - - /* attribute len eats this space */ - remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len); - - /* check value size */ - if (entry->e_value_size == 0 || entry->e_value_size > remain) { - pctx->num = entry->e_value_size; - problem = PR_1_ATTR_VALUE_SIZE; - goto fix; - } - - /* check value placement */ - if (entry->e_value_offs + - EXT2_XATTR_SIZE(entry->e_value_size) != offs) { - printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs); - pctx->num = entry->e_value_offs; - problem = PR_1_ATTR_VALUE_OFFSET; - goto fix; - } - - /* e_value_block must be 0 in inode's ea */ - if (entry->e_value_block != 0) { - pctx->num = entry->e_value_block; - problem = PR_1_ATTR_VALUE_BLOCK; - goto fix; - } - - /* e_hash must be 0 in inode's ea */ - if (entry->e_hash != 0) { - pctx->num = entry->e_hash; - problem = PR_1_ATTR_HASH; - goto fix; - } - - remain -= entry->e_value_size; - offs -= EXT2_XATTR_SIZE(entry->e_value_size); - - entry = EXT2_EXT_ATTR_NEXT(entry); - } -fix: - /* - * it seems like a corruption. it's very unlikely we could repair - * EA(s) in automatic fashion -bzzz - */ - if (problem == 0 || !fix_problem(ctx, problem, pctx)) - return; - - /* simple remove all possible EA(s) */ - *((__u32 *)start) = 0UL; - e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode, - EXT2_INODE_SIZE(sb), "pass1"); -} - -static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx) -{ - struct ext2_super_block *sb = ctx->fs->super; - struct ext2_inode_large *inode; - __u32 *eamagic; - int min, max; - - inode = (struct ext2_inode_large *) pctx->inode; - if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) { - /* this isn't large inode. so, nothing to check */ - return; - } - - /* i_extra_isize must cover i_extra_isize + i_pad1 at least */ - min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1); - max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE; - /* - * For now we will allow i_extra_isize to be 0, but really - * implementations should never allow i_extra_isize to be 0 - */ - if (inode->i_extra_isize && - (inode->i_extra_isize < min || inode->i_extra_isize > max)) { - if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx)) - return; - inode->i_extra_isize = min; - e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode, - EXT2_INODE_SIZE(sb), "pass1"); - return; - } - - eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + - inode->i_extra_isize); - if (*eamagic == EXT2_EXT_ATTR_MAGIC) { - /* it seems inode has an extended attribute(s) in body */ - check_ea_in_inode(ctx, pctx); - } -} - -static void e2fsck_pass1(e2fsck_t ctx) -{ - int i; - __u64 max_sizes; - ext2_filsys fs = ctx->fs; - ext2_ino_t ino; - struct ext2_inode *inode; - ext2_inode_scan scan; - char *block_buf; - unsigned char frag, fsize; - struct problem_context pctx; - struct scan_callback_struct scan_struct; - struct ext2_super_block *sb = ctx->fs->super; - int imagic_fs; - int busted_fs_time = 0; - int inode_size; - - clear_problem_context(&pctx); - - if (!(ctx->options & E2F_OPT_PREEN)) - fix_problem(ctx, PR_1_PASS_HEADER, &pctx); - - if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) && - !(ctx->options & E2F_OPT_NO)) { - if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50)) - ctx->dirs_to_hash = 0; - } - - /* Pass 1 */ - -#define EXT2_BPP(bits) (1ULL << ((bits) - 2)) - - for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) { - max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i); - max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i); - max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i); - max_sizes = (max_sizes * (1UL << i)) - 1; - ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes; - } -#undef EXT2_BPP - - imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES); - - /* - * Allocate bitmaps structures - */ - pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"), - &ctx->inode_used_map); - if (pctx.errcode) { - pctx.num = 1; - fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - pctx.errcode = ext2fs_allocate_inode_bitmap(fs, - _("directory inode map"), &ctx->inode_dir_map); - if (pctx.errcode) { - pctx.num = 2; - fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - pctx.errcode = ext2fs_allocate_inode_bitmap(fs, - _("regular file inode map"), &ctx->inode_reg_map); - if (pctx.errcode) { - pctx.num = 6; - fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"), - &ctx->block_found_map); - if (pctx.errcode) { - pctx.num = 1; - fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0, - &ctx->inode_link_info); - if (pctx.errcode) { - fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - inode_size = EXT2_INODE_SIZE(fs->super); - inode = (struct ext2_inode *) - e2fsck_allocate_memory(ctx, inode_size, "scratch inode"); - - inodes_to_process = (struct process_inode_block *) - e2fsck_allocate_memory(ctx, - (ctx->process_inode_size * - sizeof(struct process_inode_block)), - "array of inodes to process"); - process_inode_count = 0; - - pctx.errcode = ext2fs_init_dblist(fs, 0); - if (pctx.errcode) { - fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - - /* - * If the last orphan field is set, clear it, since the pass1 - * processing will automatically find and clear the orphans. - * In the future, we may want to try using the last_orphan - * linked list ourselves, but for now, we clear it so that the - * ext3 mount code won't get confused. - */ - if (!(ctx->options & E2F_OPT_READONLY)) { - if (fs->super->s_last_orphan) { - fs->super->s_last_orphan = 0; - ext2fs_mark_super_dirty(fs); - } - } - - mark_table_blocks(ctx); - block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3, - "block interate buffer"); - e2fsck_use_inode_shortcuts(ctx, 1); - ehandler_operation(_("doing inode scan")); - pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks, - &scan); - if (pctx.errcode) { - fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0); - ctx->stashed_inode = inode; - scan_struct.ctx = ctx; - scan_struct.block_buf = block_buf; - ext2fs_set_inode_callback(scan, scan_callback, &scan_struct); - if (ctx->progress) - if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count)) - return; - if ((fs->super->s_wtime < fs->super->s_inodes_count) || - (fs->super->s_mtime < fs->super->s_inodes_count)) - busted_fs_time = 1; - - while (1) { - pctx.errcode = ext2fs_get_next_inode_full(scan, &ino, - inode, inode_size); - if (ctx->flags & E2F_FLAG_SIGNAL_MASK) - return; - if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) { - continue; - } - if (pctx.errcode) { - fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - if (!ino) - break; - pctx.ino = ino; - pctx.inode = inode; - ctx->stashed_ino = ino; - if (inode->i_links_count) { - pctx.errcode = ext2fs_icount_store(ctx->inode_link_info, - ino, inode->i_links_count); - if (pctx.errcode) { - pctx.num = inode->i_links_count; - fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - } - if (ino == EXT2_BAD_INO) { - struct process_block_struct_1 pb; - - pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map, - &pb.fs_meta_blocks); - if (pctx.errcode) { - pctx.num = 4; - fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - pb.ino = EXT2_BAD_INO; - pb.num_blocks = pb.last_block = 0; - pb.num_illegal_blocks = 0; - pb.suppress = 0; pb.clear = 0; pb.is_dir = 0; - pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0; - pb.inode = inode; - pb.pctx = &pctx; - pb.ctx = ctx; - pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, - block_buf, process_bad_block, &pb); - ext2fs_free_block_bitmap(pb.fs_meta_blocks); - if (pctx.errcode) { - fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - if (pb.bbcheck) - if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) { - ctx->flags |= E2F_FLAG_ABORT; - return; - } - ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino); - clear_problem_context(&pctx); - continue; - } else if (ino == EXT2_ROOT_INO) { - /* - * Make sure the root inode is a directory; if - * not, offer to clear it. It will be - * regnerated in pass #3. - */ - if (!LINUX_S_ISDIR(inode->i_mode)) { - if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) { - inode->i_dtime = time(NULL); - inode->i_links_count = 0; - ext2fs_icount_store(ctx->inode_link_info, - ino, 0); - e2fsck_write_inode(ctx, ino, inode, - "pass1"); - } - } - /* - * If dtime is set, offer to clear it. mke2fs - * version 0.2b created filesystems with the - * dtime field set for the root and lost+found - * directories. We won't worry about - * /lost+found, since that can be regenerated - * easily. But we will fix the root directory - * as a special case. - */ - if (inode->i_dtime && inode->i_links_count) { - if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) { - inode->i_dtime = 0; - e2fsck_write_inode(ctx, ino, inode, - "pass1"); - } - } - } else if (ino == EXT2_JOURNAL_INO) { - ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino); - if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) { - if (!LINUX_S_ISREG(inode->i_mode) && - fix_problem(ctx, PR_1_JOURNAL_BAD_MODE, - &pctx)) { - inode->i_mode = LINUX_S_IFREG; - e2fsck_write_inode(ctx, ino, inode, - "pass1"); - } - check_blocks(ctx, &pctx, block_buf); - continue; - } - if ((inode->i_links_count || inode->i_blocks || - inode->i_block[0]) && - fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR, - &pctx)) { - memset(inode, 0, inode_size); - ext2fs_icount_store(ctx->inode_link_info, - ino, 0); - e2fsck_write_inode_full(ctx, ino, inode, - inode_size, "pass1"); - } - } else if (ino < EXT2_FIRST_INODE(fs->super)) { - int problem = 0; - - ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino); - if (ino == EXT2_BOOT_LOADER_INO) { - if (LINUX_S_ISDIR(inode->i_mode)) - problem = PR_1_RESERVED_BAD_MODE; - } else if (ino == EXT2_RESIZE_INO) { - if (inode->i_mode && - !LINUX_S_ISREG(inode->i_mode)) - problem = PR_1_RESERVED_BAD_MODE; - } else { - if (inode->i_mode != 0) - problem = PR_1_RESERVED_BAD_MODE; - } - if (problem) { - if (fix_problem(ctx, problem, &pctx)) { - inode->i_mode = 0; - e2fsck_write_inode(ctx, ino, inode, - "pass1"); - } - } - check_blocks(ctx, &pctx, block_buf); - continue; - } - /* - * Check for inodes who might have been part of the - * orphaned list linked list. They should have gotten - * dealt with by now, unless the list had somehow been - * corrupted. - * - * FIXME: In the future, inodes which are still in use - * (and which are therefore) pending truncation should - * be handled specially. Right now we just clear the - * dtime field, and the normal e2fsck handling of - * inodes where i_size and the inode blocks are - * inconsistent is to fix i_size, instead of releasing - * the extra blocks. This won't catch the inodes that - * was at the end of the orphan list, but it's better - * than nothing. The right answer is that there - * shouldn't be any bugs in the orphan list handling. :-) - */ - if (inode->i_dtime && !busted_fs_time && - inode->i_dtime < ctx->fs->super->s_inodes_count) { - if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) { - inode->i_dtime = inode->i_links_count ? - 0 : time(NULL); - e2fsck_write_inode(ctx, ino, inode, - "pass1"); - } - } - - /* - * This code assumes that deleted inodes have - * i_links_count set to 0. - */ - if (!inode->i_links_count) { - if (!inode->i_dtime && inode->i_mode) { - if (fix_problem(ctx, - PR_1_ZERO_DTIME, &pctx)) { - inode->i_dtime = time(NULL); - e2fsck_write_inode(ctx, ino, inode, - "pass1"); - } - } - continue; - } - /* - * n.b. 0.3c ext2fs code didn't clear i_links_count for - * deleted files. Oops. - * - * Since all new ext2 implementations get this right, - * we now assume that the case of non-zero - * i_links_count and non-zero dtime means that we - * should keep the file, not delete it. - * - */ - if (inode->i_dtime) { - if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) { - inode->i_dtime = 0; - e2fsck_write_inode(ctx, ino, inode, "pass1"); - } - } - - ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino); - switch (fs->super->s_creator_os) { - case EXT2_OS_LINUX: - frag = inode->osd2.linux2.l_i_frag; - fsize = inode->osd2.linux2.l_i_fsize; - break; - case EXT2_OS_HURD: - frag = inode->osd2.hurd2.h_i_frag; - fsize = inode->osd2.hurd2.h_i_fsize; - break; - case EXT2_OS_MASIX: - frag = inode->osd2.masix2.m_i_frag; - fsize = inode->osd2.masix2.m_i_fsize; - break; - default: - frag = fsize = 0; - } - - if (inode->i_faddr || frag || fsize || - (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl)) - mark_inode_bad(ctx, ino); - if (inode->i_flags & EXT2_IMAGIC_FL) { - if (imagic_fs) { - if (!ctx->inode_imagic_map) - alloc_imagic_map(ctx); - ext2fs_mark_inode_bitmap(ctx->inode_imagic_map, - ino); - } else { - if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) { - inode->i_flags &= ~EXT2_IMAGIC_FL; - e2fsck_write_inode(ctx, ino, - inode, "pass1"); - } - } - } - - check_inode_extra_space(ctx, &pctx); - - if (LINUX_S_ISDIR(inode->i_mode)) { - ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino); - e2fsck_add_dir_info(ctx, ino, 0); - ctx->fs_directory_count++; - } else if (LINUX_S_ISREG (inode->i_mode)) { - ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino); - ctx->fs_regular_count++; - } else if (LINUX_S_ISCHR (inode->i_mode) && - e2fsck_pass1_check_device_inode(fs, inode)) { - check_immutable(ctx, &pctx); - check_size(ctx, &pctx); - ctx->fs_chardev_count++; - } else if (LINUX_S_ISBLK (inode->i_mode) && - e2fsck_pass1_check_device_inode(fs, inode)) { - check_immutable(ctx, &pctx); - check_size(ctx, &pctx); - ctx->fs_blockdev_count++; - } else if (LINUX_S_ISLNK (inode->i_mode) && - e2fsck_pass1_check_symlink(fs, inode, block_buf)) { - check_immutable(ctx, &pctx); - ctx->fs_symlinks_count++; - if (ext2fs_inode_data_blocks(fs, inode) == 0) { - ctx->fs_fast_symlinks_count++; - check_blocks(ctx, &pctx, block_buf); - continue; - } - } - else if (LINUX_S_ISFIFO (inode->i_mode) && - e2fsck_pass1_check_device_inode(fs, inode)) { - check_immutable(ctx, &pctx); - check_size(ctx, &pctx); - ctx->fs_fifo_count++; - } else if ((LINUX_S_ISSOCK (inode->i_mode)) && - e2fsck_pass1_check_device_inode(fs, inode)) { - check_immutable(ctx, &pctx); - check_size(ctx, &pctx); - ctx->fs_sockets_count++; - } else - mark_inode_bad(ctx, ino); - if (inode->i_block[EXT2_IND_BLOCK]) - ctx->fs_ind_count++; - if (inode->i_block[EXT2_DIND_BLOCK]) - ctx->fs_dind_count++; - if (inode->i_block[EXT2_TIND_BLOCK]) - ctx->fs_tind_count++; - if (inode->i_block[EXT2_IND_BLOCK] || - inode->i_block[EXT2_DIND_BLOCK] || - inode->i_block[EXT2_TIND_BLOCK] || - inode->i_file_acl) { - inodes_to_process[process_inode_count].ino = ino; - inodes_to_process[process_inode_count].inode = *inode; - process_inode_count++; - } else - check_blocks(ctx, &pctx, block_buf); - - if (ctx->flags & E2F_FLAG_SIGNAL_MASK) - return; - - if (process_inode_count >= ctx->process_inode_size) { - process_inodes(ctx, block_buf); - - if (ctx->flags & E2F_FLAG_SIGNAL_MASK) - return; - } - } - process_inodes(ctx, block_buf); - ext2fs_close_inode_scan(scan); - ehandler_operation(0); - - /* - * If any extended attribute blocks' reference counts need to - * be adjusted, either up (ctx->refcount_extra), or down - * (ctx->refcount), then fix them. - */ - if (ctx->refcount) { - adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1); - ea_refcount_free(ctx->refcount); - ctx->refcount = 0; - } - if (ctx->refcount_extra) { - adjust_extattr_refcount(ctx, ctx->refcount_extra, - block_buf, +1); - ea_refcount_free(ctx->refcount_extra); - ctx->refcount_extra = 0; - } - - if (ctx->invalid_bitmaps) - handle_fs_bad_blocks(ctx); - - /* We don't need the block_ea_map any more */ - ext2fs_free_block_bitmap(ctx->block_ea_map); - ctx->block_ea_map = 0; - - if (ctx->flags & E2F_FLAG_RESIZE_INODE) { - ext2fs_block_bitmap save_bmap; - - save_bmap = fs->block_map; - fs->block_map = ctx->block_found_map; - clear_problem_context(&pctx); - pctx.errcode = ext2fs_create_resize_inode(fs); - if (pctx.errcode) { - fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx); - /* Should never get here */ - ctx->flags |= E2F_FLAG_ABORT; - return; - } - e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode, - "recreate inode"); - inode->i_mtime = time(NULL); - e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode, - "recreate inode"); - fs->block_map = save_bmap; - ctx->flags &= ~E2F_FLAG_RESIZE_INODE; - } - - if (ctx->flags & E2F_FLAG_RESTART) { - /* - * Only the master copy of the superblock and block - * group descriptors are going to be written during a - * restart, so set the superblock to be used to be the - * master superblock. - */ - ctx->use_superblock = 0; - unwind_pass1(); - goto endit; - } - - if (ctx->block_dup_map) { - if (ctx->options & E2F_OPT_PREEN) { - clear_problem_context(&pctx); - fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx); - } - e2fsck_pass1_dupblocks(ctx, block_buf); - } - ext2fs_free_mem(&inodes_to_process); -endit: - e2fsck_use_inode_shortcuts(ctx, 0); - - ext2fs_free_mem(&block_buf); - ext2fs_free_mem(&inode); -} - -/* - * When the inode_scan routines call this callback at the end of the - * glock group, call process_inodes. - */ -static errcode_t scan_callback(ext2_filsys fs, - dgrp_t group, void * priv_data) -{ - struct scan_callback_struct *scan_struct; - e2fsck_t ctx; - - scan_struct = (struct scan_callback_struct *) priv_data; - ctx = scan_struct->ctx; - - process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf); - - if (ctx->progress) - if ((ctx->progress)(ctx, 1, group+1, - ctx->fs->group_desc_count)) - return EXT2_ET_CANCEL_REQUESTED; - - return 0; -} - -/* - * Process the inodes in the "inodes to process" list. - */ -static void process_inodes(e2fsck_t ctx, char *block_buf) -{ - int i; - struct ext2_inode *old_stashed_inode; - ext2_ino_t old_stashed_ino; - const char *old_operation; - char buf[80]; - struct problem_context pctx; - - /* begin process_inodes */ - if (process_inode_count == 0) - return; - old_operation = ehandler_operation(0); - old_stashed_inode = ctx->stashed_inode; - old_stashed_ino = ctx->stashed_ino; - qsort(inodes_to_process, process_inode_count, - sizeof(struct process_inode_block), process_inode_cmp); - clear_problem_context(&pctx); - for (i=0; i < process_inode_count; i++) { - pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode; - pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino; - sprintf(buf, _("reading indirect blocks of inode %u"), - pctx.ino); - ehandler_operation(buf); - check_blocks(ctx, &pctx, block_buf); - if (ctx->flags & E2F_FLAG_SIGNAL_MASK) - break; - } - ctx->stashed_inode = old_stashed_inode; - ctx->stashed_ino = old_stashed_ino; - process_inode_count = 0; - /* end process inodes */ - - ehandler_operation(old_operation); -} - -static int process_inode_cmp(const void *a, const void *b) -{ - const struct process_inode_block *ib_a = - (const struct process_inode_block *) a; - const struct process_inode_block *ib_b = - (const struct process_inode_block *) b; - int ret; - - ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] - - ib_b->inode.i_block[EXT2_IND_BLOCK]); - if (ret == 0) - ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl; - return ret; -} - -/* - * Mark an inode as being bad in some what - */ -static void mark_inode_bad(e2fsck_t ctx, ino_t ino) -{ - struct problem_context pctx; - - if (!ctx->inode_bad_map) { - clear_problem_context(&pctx); - - pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs, - _("bad inode map"), &ctx->inode_bad_map); - if (pctx.errcode) { - pctx.num = 3; - fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx); - /* Should never get here */ - ctx->flags |= E2F_FLAG_ABORT; - return; - } - } - ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino); -} - - -/* - * This procedure will allocate the inode imagic table - */ -static void alloc_imagic_map(e2fsck_t ctx) -{ - struct problem_context pctx; - - clear_problem_context(&pctx); - pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs, - _("imagic inode map"), - &ctx->inode_imagic_map); - if (pctx.errcode) { - pctx.num = 5; - fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx); - /* Should never get here */ - ctx->flags |= E2F_FLAG_ABORT; - return; - } -} - -/* - * Marks a block as in use, setting the dup_map if it's been set - * already. Called by process_block and process_bad_block. - * - * WARNING: Assumes checks have already been done to make sure block - * is valid. This is true in both process_block and process_bad_block. - */ -static void mark_block_used(e2fsck_t ctx, blk_t block) -{ - struct problem_context pctx; - - clear_problem_context(&pctx); - - if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) { - if (!ctx->block_dup_map) { - pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs, - _("multiply claimed block map"), - &ctx->block_dup_map); - if (pctx.errcode) { - pctx.num = 3; - fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, - &pctx); - /* Should never get here */ - ctx->flags |= E2F_FLAG_ABORT; - return; - } - } - ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block); - } else { - ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block); - } -} - -/* - * Adjust the extended attribute block's reference counts at the end - * of pass 1, either by subtracting out references for EA blocks that - * are still referenced in ctx->refcount, or by adding references for - * EA blocks that had extra references as accounted for in - * ctx->refcount_extra. - */ -static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount, - char *block_buf, int adjust_sign) -{ - struct ext2_ext_attr_header *header; - struct problem_context pctx; - ext2_filsys fs = ctx->fs; - blk_t blk; - __u32 should_be; - int count; - - clear_problem_context(&pctx); - - ea_refcount_intr_begin(refcount); - while (1) { - if ((blk = ea_refcount_intr_next(refcount, &count)) == 0) - break; - pctx.blk = blk; - pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf); - if (pctx.errcode) { - fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx); - return; - } - header = (struct ext2_ext_attr_header *) block_buf; - pctx.blkcount = header->h_refcount; - should_be = header->h_refcount + adjust_sign * count; - pctx.num = should_be; - if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) { - header->h_refcount = should_be; - pctx.errcode = ext2fs_write_ext_attr(fs, blk, - block_buf); - if (pctx.errcode) { - fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx); - continue; - } - } - } -} - -/* - * Handle processing the extended attribute blocks - */ -static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx, - char *block_buf) -{ - ext2_filsys fs = ctx->fs; - ext2_ino_t ino = pctx->ino; - struct ext2_inode *inode = pctx->inode; - blk_t blk; - char * end; - struct ext2_ext_attr_header *header; - struct ext2_ext_attr_entry *entry; - int count; - region_t region; - - blk = inode->i_file_acl; - if (blk == 0) - return 0; - - /* - * If the Extended attribute flag isn't set, then a non-zero - * file acl means that the inode is corrupted. - * - * Or if the extended attribute block is an invalid block, - * then the inode is also corrupted. - */ - if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) || - (blk < fs->super->s_first_data_block) || - (blk >= fs->super->s_blocks_count)) { - mark_inode_bad(ctx, ino); - return 0; - } - - /* If ea bitmap hasn't been allocated, create it */ - if (!ctx->block_ea_map) { - pctx->errcode = ext2fs_allocate_block_bitmap(fs, - _("ext attr block map"), - &ctx->block_ea_map); - if (pctx->errcode) { - pctx->num = 2; - fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx); - ctx->flags |= E2F_FLAG_ABORT; - return 0; - } - } - - /* Create the EA refcount structure if necessary */ - if (!ctx->refcount) { - pctx->errcode = ea_refcount_create(0, &ctx->refcount); - if (pctx->errcode) { - pctx->num = 1; - fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx); - ctx->flags |= E2F_FLAG_ABORT; - return 0; - } - } - - /* Have we seen this EA block before? */ - if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) { - if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0) - return 1; - /* Ooops, this EA was referenced more than it stated */ - if (!ctx->refcount_extra) { - pctx->errcode = ea_refcount_create(0, - &ctx->refcount_extra); - if (pctx->errcode) { - pctx->num = 2; - fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx); - ctx->flags |= E2F_FLAG_ABORT; - return 0; - } - } - ea_refcount_increment(ctx->refcount_extra, blk, 0); - return 1; - } - - /* - * OK, we haven't seen this EA block yet. So we need to - * validate it - */ - pctx->blk = blk; - pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf); - if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx)) - goto clear_extattr; - header = (struct ext2_ext_attr_header *) block_buf; - pctx->blk = inode->i_file_acl; - if (((ctx->ext_attr_ver == 1) && - (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) || - ((ctx->ext_attr_ver == 2) && - (header->h_magic != EXT2_EXT_ATTR_MAGIC))) { - if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx)) - goto clear_extattr; - } - - if (header->h_blocks != 1) { - if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx)) - goto clear_extattr; - } - - region = region_create(0, fs->blocksize); - if (!region) { - fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx); - ctx->flags |= E2F_FLAG_ABORT; - return 0; - } - if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) { - if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx)) - goto clear_extattr; - } - - entry = (struct ext2_ext_attr_entry *)(header+1); - end = block_buf + fs->blocksize; - while ((char *)entry < end && *(__u32 *)entry) { - if (region_allocate(region, (char *)entry - (char *)header, - EXT2_EXT_ATTR_LEN(entry->e_name_len))) { - if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx)) - goto clear_extattr; - } - if ((ctx->ext_attr_ver == 1 && - (entry->e_name_len == 0 || entry->e_name_index != 0)) || - (ctx->ext_attr_ver == 2 && - entry->e_name_index == 0)) { - if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx)) - goto clear_extattr; - } - if (entry->e_value_block != 0) { - if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx)) - goto clear_extattr; - } - if (entry->e_value_size && - region_allocate(region, entry->e_value_offs, - EXT2_EXT_ATTR_SIZE(entry->e_value_size))) { - if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx)) - goto clear_extattr; - } - entry = EXT2_EXT_ATTR_NEXT(entry); - } - if (region_allocate(region, (char *)entry - (char *)header, 4)) { - if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx)) - goto clear_extattr; - } - region_free(region); - - count = header->h_refcount - 1; - if (count) - ea_refcount_store(ctx->refcount, blk, count); - mark_block_used(ctx, blk); - ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk); - - return 1; - -clear_extattr: - inode->i_file_acl = 0; - e2fsck_write_inode(ctx, ino, inode, "check_ext_attr"); - return 0; -} - -/* Returns 1 if bad htree, 0 if OK */ -static int handle_htree(e2fsck_t ctx, struct problem_context *pctx, - ext2_ino_t ino FSCK_ATTR((unused)), - struct ext2_inode *inode, - char *block_buf) -{ - struct ext2_dx_root_info *root; - ext2_filsys fs = ctx->fs; - errcode_t retval; - blk_t blk; - - if ((!LINUX_S_ISDIR(inode->i_mode) && - fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) || - (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) && - fix_problem(ctx, PR_1_HTREE_SET, pctx))) - return 1; - - blk = inode->i_block[0]; - if (((blk == 0) || - (blk < fs->super->s_first_data_block) || - (blk >= fs->super->s_blocks_count)) && - fix_problem(ctx, PR_1_HTREE_BADROOT, pctx)) - return 1; - - retval = io_channel_read_blk(fs->io, blk, 1, block_buf); - if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx)) - return 1; - - /* XXX should check that beginning matches a directory */ - root = (struct ext2_dx_root_info *) (block_buf + 24); - - if ((root->reserved_zero || root->info_length < 8) && - fix_problem(ctx, PR_1_HTREE_BADROOT, pctx)) - return 1; - - pctx->num = root->hash_version; - if ((root->hash_version != EXT2_HASH_LEGACY) && - (root->hash_version != EXT2_HASH_HALF_MD4) && - (root->hash_version != EXT2_HASH_TEA) && - fix_problem(ctx, PR_1_HTREE_HASHV, pctx)) - return 1; - - if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) && - fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx)) - return 1; - - pctx->num = root->indirect_levels; - if ((root->indirect_levels > 1) && - fix_problem(ctx, PR_1_HTREE_DEPTH, pctx)) - return 1; - - return 0; -} - -/* - * This subroutine is called on each inode to account for all of the - * blocks used by that inode. - */ -static void check_blocks(e2fsck_t ctx, struct problem_context *pctx, - char *block_buf) -{ - ext2_filsys fs = ctx->fs; - struct process_block_struct_1 pb; - ext2_ino_t ino = pctx->ino; - struct ext2_inode *inode = pctx->inode; - int bad_size = 0; - int dirty_inode = 0; - __u64 size; - - pb.ino = ino; - pb.num_blocks = 0; - pb.last_block = -1; - pb.num_illegal_blocks = 0; - pb.suppress = 0; pb.clear = 0; - pb.fragmented = 0; - pb.compressed = 0; - pb.previous_block = 0; - pb.is_dir = LINUX_S_ISDIR(inode->i_mode); - pb.is_reg = LINUX_S_ISREG(inode->i_mode); - pb.max_blocks = 1 << (31 - fs->super->s_log_block_size); - pb.inode = inode; - pb.pctx = pctx; - pb.ctx = ctx; - pctx->ino = ino; - pctx->errcode = 0; - - if (inode->i_flags & EXT2_COMPRBLK_FL) { - if (fs->super->s_feature_incompat & - EXT2_FEATURE_INCOMPAT_COMPRESSION) - pb.compressed = 1; - else { - if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) { - inode->i_flags &= ~EXT2_COMPRBLK_FL; - dirty_inode++; - } - } - } - - if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf)) - pb.num_blocks++; - - if (ext2fs_inode_has_valid_blocks(inode)) - pctx->errcode = ext2fs_block_iterate2(fs, ino, - pb.is_dir ? BLOCK_FLAG_HOLE : 0, - block_buf, process_block, &pb); - end_problem_latch(ctx, PR_LATCH_BLOCK); - end_problem_latch(ctx, PR_LATCH_TOOBIG); - if (ctx->flags & E2F_FLAG_SIGNAL_MASK) - goto out; - if (pctx->errcode) - fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx); - - if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group) - ctx->fs_fragmented++; - - if (pb.clear) { - inode->i_links_count = 0; - ext2fs_icount_store(ctx->inode_link_info, ino, 0); - inode->i_dtime = time(NULL); - dirty_inode++; - ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino); - ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino); - ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino); - /* - * The inode was probably partially accounted for - * before processing was aborted, so we need to - * restart the pass 1 scan. - */ - ctx->flags |= E2F_FLAG_RESTART; - goto out; - } - - if (inode->i_flags & EXT2_INDEX_FL) { - if (handle_htree(ctx, pctx, ino, inode, block_buf)) { - inode->i_flags &= ~EXT2_INDEX_FL; - dirty_inode++; - } else { -#ifdef ENABLE_HTREE - e2fsck_add_dx_dir(ctx, ino, pb.last_block+1); -#endif - } - } - if (ctx->dirs_to_hash && pb.is_dir && - !(inode->i_flags & EXT2_INDEX_FL) && - ((inode->i_size / fs->blocksize) >= 3)) - ext2fs_u32_list_add(ctx->dirs_to_hash, ino); - - if (!pb.num_blocks && pb.is_dir) { - if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) { - inode->i_links_count = 0; - ext2fs_icount_store(ctx->inode_link_info, ino, 0); - inode->i_dtime = time(NULL); - dirty_inode++; - ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino); - ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino); - ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino); - ctx->fs_directory_count--; - goto out; - } - } - - pb.num_blocks *= (fs->blocksize / 512); - - if (pb.is_dir) { - int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super); - if (nblock > (pb.last_block + 1)) - bad_size = 1; - else if (nblock < (pb.last_block + 1)) { - if (((pb.last_block + 1) - nblock) > - fs->super->s_prealloc_dir_blocks) - bad_size = 2; - } - } else { - size = EXT2_I_SIZE(inode); - if ((pb.last_block >= 0) && - (size < (__u64) pb.last_block * fs->blocksize)) - bad_size = 3; - else if (size > ext2_max_sizes[fs->super->s_log_block_size]) - bad_size = 4; - } - /* i_size for symlinks is checked elsewhere */ - if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) { - pctx->num = (pb.last_block+1) * fs->blocksize; - if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) { - inode->i_size = pctx->num; - if (!LINUX_S_ISDIR(inode->i_mode)) - inode->i_size_high = pctx->num >> 32; - dirty_inode++; - } - pctx->num = 0; - } - if (LINUX_S_ISREG(inode->i_mode) && - (inode->i_size_high || inode->i_size & 0x80000000UL)) - ctx->large_files++; - if (pb.num_blocks != inode->i_blocks) { - pctx->num = pb.num_blocks; - if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) { - inode->i_blocks = pb.num_blocks; - dirty_inode++; - } - pctx->num = 0; - } -out: - if (dirty_inode) - e2fsck_write_inode(ctx, ino, inode, "check_blocks"); -} - - -/* - * This is a helper function for check_blocks(). - */ -static int process_block(ext2_filsys fs, - blk_t *block_nr, - e2_blkcnt_t blockcnt, - blk_t ref_block FSCK_ATTR((unused)), - int ref_offset FSCK_ATTR((unused)), - void *priv_data) -{ - struct process_block_struct_1 *p; - struct problem_context *pctx; - blk_t blk = *block_nr; - int ret_code = 0; - int problem = 0; - e2fsck_t ctx; - - p = (struct process_block_struct_1 *) priv_data; - pctx = p->pctx; - ctx = p->ctx; - - if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) { - /* todo: Check that the comprblk_fl is high, that the - blkaddr pattern looks right (all non-holes up to - first EXT2FS_COMPRESSED_BLKADDR, then all - EXT2FS_COMPRESSED_BLKADDR up to end of cluster), - that the feature_incompat bit is high, and that the - inode is a regular file. If we're doing a "full - check" (a concept introduced to e2fsck by e2compr, - meaning that we look at data blocks as well as - metadata) then call some library routine that - checks the compressed data. I'll have to think - about this, because one particularly important - problem to be able to fix is to recalculate the - cluster size if necessary. I think that perhaps - we'd better do most/all e2compr-specific checks - separately, after the non-e2compr checks. If not - doing a full check, it may be useful to test that - the personality is linux; e.g. if it isn't then - perhaps this really is just an illegal block. */ - return 0; - } - - if (blk == 0) { - if (p->is_dir == 0) { - /* - * Should never happen, since only directories - * get called with BLOCK_FLAG_HOLE - */ -#ifdef DEBUG_E2FSCK - printf("process_block() called with blk == 0, " - "blockcnt=%d, inode %lu???\n", - blockcnt, p->ino); -#endif - return 0; - } - if (blockcnt < 0) - return 0; - if (blockcnt * fs->blocksize < p->inode->i_size) { - goto mark_dir; - } - return 0; - } - - /* - * Simplistic fragmentation check. We merely require that the - * file be contiguous. (Which can never be true for really - * big files that are greater than a block group.) - */ - if (!HOLE_BLKADDR(p->previous_block)) { - if (p->previous_block+1 != blk) - p->fragmented = 1; - } - p->previous_block = blk; - - if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size))) - problem = PR_1_TOOBIG_DIR; - if (p->is_reg && p->num_blocks+1 >= p->max_blocks) - problem = PR_1_TOOBIG_REG; - if (!p->is_dir && !p->is_reg && blockcnt > 0) - problem = PR_1_TOOBIG_SYMLINK; - - if (blk < fs->super->s_first_data_block || - blk >= fs->super->s_blocks_count) - problem = PR_1_ILLEGAL_BLOCK_NUM; - - if (problem) { - p->num_illegal_blocks++; - if (!p->suppress && (p->num_illegal_blocks % 12) == 0) { - if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) { - p->clear = 1; - return BLOCK_ABORT; - } - if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) { - p->suppress = 1; - set_latch_flags(PR_LATCH_BLOCK, - PRL_SUPPRESS, 0); - } - } - pctx->blk = blk; - pctx->blkcount = blockcnt; - if (fix_problem(ctx, problem, pctx)) { - blk = *block_nr = 0; - ret_code = BLOCK_CHANGED; - goto mark_dir; - } else - return 0; - } - - if (p->ino == EXT2_RESIZE_INO) { - /* - * The resize inode has already be sanity checked - * during pass #0 (the superblock checks). All we - * have to do is mark the double indirect block as - * being in use; all of the other blocks are handled - * by mark_table_blocks()). - */ - if (blockcnt == BLOCK_COUNT_DIND) - mark_block_used(ctx, blk); - } else - mark_block_used(ctx, blk); - p->num_blocks++; - if (blockcnt >= 0) - p->last_block = blockcnt; -mark_dir: - if (p->is_dir && (blockcnt >= 0)) { - pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino, - blk, blockcnt); - if (pctx->errcode) { - pctx->blk = blk; - pctx->num = blockcnt; - fix_problem(ctx, PR_1_ADD_DBLOCK, pctx); - /* Should never get here */ - ctx->flags |= E2F_FLAG_ABORT; - return BLOCK_ABORT; - } - } - return ret_code; -} - -static int process_bad_block(ext2_filsys fs FSCK_ATTR((unused)), - blk_t *block_nr, - e2_blkcnt_t blockcnt, - blk_t ref_block FSCK_ATTR((unused)), - int ref_offset FSCK_ATTR((unused)), - void *priv_data EXT2FS_ATTR((unused))) -{ - /* - * Note: This function processes blocks for the bad blocks - * inode, which is never compressed. So we don't use HOLE_BLKADDR(). - */ - - printf("Unrecoverable Error: Found %"PRIi64" bad blocks starting at block number: %u\n", blockcnt, *block_nr); - return BLOCK_ERROR; -} - -/* - * This routine gets called at the end of pass 1 if bad blocks are - * detected in the superblock, group descriptors, inode_bitmaps, or - * block bitmaps. At this point, all of the blocks have been mapped - * out, so we can try to allocate new block(s) to replace the bad - * blocks. - */ -static void handle_fs_bad_blocks(e2fsck_t ctx) -{ - printf("Bad blocks detected on your filesystem\n" - "You should get your data off as the device will soon die\n"); -} - -/* - * This routine marks all blocks which are used by the superblock, - * group descriptors, inode bitmaps, and block bitmaps. - */ -static void mark_table_blocks(e2fsck_t ctx) -{ - ext2_filsys fs = ctx->fs; - blk_t block, b; - dgrp_t i; - int j; - struct problem_context pctx; - - clear_problem_context(&pctx); - - block = fs->super->s_first_data_block; - for (i = 0; i < fs->group_desc_count; i++) { - pctx.group = i; - - ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map); - - /* - * Mark the blocks used for the inode table - */ - if (fs->group_desc[i].bg_inode_table) { - for (j = 0, b = fs->group_desc[i].bg_inode_table; - j < fs->inode_blocks_per_group; - j++, b++) { - if (ext2fs_test_block_bitmap(ctx->block_found_map, - b)) { - pctx.blk = b; - if (fix_problem(ctx, - PR_1_ITABLE_CONFLICT, &pctx)) { - ctx->invalid_inode_table_flag[i]++; - ctx->invalid_bitmaps++; - } - } else { - ext2fs_mark_block_bitmap(ctx->block_found_map, b); - } - } - } - - /* - * Mark block used for the block bitmap - */ - if (fs->group_desc[i].bg_block_bitmap) { - if (ext2fs_test_block_bitmap(ctx->block_found_map, - fs->group_desc[i].bg_block_bitmap)) { - pctx.blk = fs->group_desc[i].bg_block_bitmap; - if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) { - ctx->invalid_block_bitmap_flag[i]++; - ctx->invalid_bitmaps++; - } - } else { - ext2fs_mark_block_bitmap(ctx->block_found_map, - fs->group_desc[i].bg_block_bitmap); - } - } - /* - * Mark block used for the inode bitmap - */ - if (fs->group_desc[i].bg_inode_bitmap) { - if (ext2fs_test_block_bitmap(ctx->block_found_map, - fs->group_desc[i].bg_inode_bitmap)) { - pctx.blk = fs->group_desc[i].bg_inode_bitmap; - if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) { - ctx->invalid_inode_bitmap_flag[i]++; - ctx->invalid_bitmaps++; - } - } else { - ext2fs_mark_block_bitmap(ctx->block_found_map, - fs->group_desc[i].bg_inode_bitmap); - } - } - block += fs->super->s_blocks_per_group; - } -} - -/* - * Thes subroutines short circuits ext2fs_get_blocks and - * ext2fs_check_directory; we use them since we already have the inode - * structure, so there's no point in letting the ext2fs library read - * the inode again. - */ -static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino, - blk_t *blocks) -{ - e2fsck_t ctx = (e2fsck_t) fs->priv_data; - int i; - - if ((ino != ctx->stashed_ino) || !ctx->stashed_inode) - return EXT2_ET_CALLBACK_NOTHANDLED; - - for (i=0; i < EXT2_N_BLOCKS; i++) - blocks[i] = ctx->stashed_inode->i_block[i]; - return 0; -} - -static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino, - struct ext2_inode *inode) -{ - e2fsck_t ctx = (e2fsck_t) fs->priv_data; - - if ((ino != ctx->stashed_ino) || !ctx->stashed_inode) - return EXT2_ET_CALLBACK_NOTHANDLED; - *inode = *ctx->stashed_inode; - return 0; -} - -static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino, - struct ext2_inode *inode) -{ - e2fsck_t ctx = (e2fsck_t) fs->priv_data; - - if ((ino == ctx->stashed_ino) && ctx->stashed_inode) - *ctx->stashed_inode = *inode; - return EXT2_ET_CALLBACK_NOTHANDLED; -} - -static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino) -{ - e2fsck_t ctx = (e2fsck_t) fs->priv_data; - - if ((ino != ctx->stashed_ino) || !ctx->stashed_inode) - return EXT2_ET_CALLBACK_NOTHANDLED; - - if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode)) - return EXT2_ET_NO_DIRECTORY; - return 0; -} - -void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool) -{ - ext2_filsys fs = ctx->fs; - - if (bool) { - fs->get_blocks = pass1_get_blocks; - fs->check_directory = pass1_check_directory; - fs->read_inode = pass1_read_inode; - fs->write_inode = pass1_write_inode; - ctx->stashed_ino = 0; - } else { - fs->get_blocks = 0; - fs->check_directory = 0; - fs->read_inode = 0; - fs->write_inode = 0; - } -} - -/* - * pass1b.c --- Pass #1b of e2fsck - * - * This file contains pass1B, pass1C, and pass1D of e2fsck. They are - * only invoked if pass 1 discovered blocks which are in use by more - * than one inode. - * - * Pass1B scans the data blocks of all the inodes again, generating a - * complete list of duplicate blocks and which inodes have claimed - * them. - * - * Pass1C does a tree-traversal of the filesystem, to determine the - * parent directories of these inodes. This step is necessary so that - * e2fsck can print out the pathnames of affected inodes. - * - * Pass1D is a reconciliation pass. For each inode with duplicate - * blocks, the user is prompted if s/he would like to clone the file - * (so that the file gets a fresh copy of the duplicated blocks) or - * simply to delete the file. - * - */ - - -/* Needed for architectures where sizeof(int) != sizeof(void *) */ -#define INT_TO_VOIDPTR(val) ((void *)(intptr_t)(val)) -#define VOIDPTR_TO_INT(ptr) ((int)(intptr_t)(ptr)) - -/* Define an extension to the ext2 library's block count information */ -#define BLOCK_COUNT_EXTATTR (-5) - -struct block_el { - blk_t block; - struct block_el *next; -}; - -struct inode_el { - ext2_ino_t inode; - struct inode_el *next; -}; - -struct dup_block { - int num_bad; - struct inode_el *inode_list; -}; - -/* - * This structure stores information about a particular inode which - * is sharing blocks with other inodes. This information is collected - * to display to the user, so that the user knows what files he or she - * is dealing with, when trying to decide how to resolve the conflict - * of multiply-claimed blocks. - */ -struct dup_inode { - ext2_ino_t dir; - int num_dupblocks; - struct ext2_inode inode; - struct block_el *block_list; -}; - -static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr, - e2_blkcnt_t blockcnt, blk_t ref_blk, - int ref_offset, void *priv_data); -static void delete_file(e2fsck_t ctx, ext2_ino_t ino, - struct dup_inode *dp, char *block_buf); -static int clone_file(e2fsck_t ctx, ext2_ino_t ino, - struct dup_inode *dp, char* block_buf); -static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk); - -static void pass1b(e2fsck_t ctx, char *block_buf); -static void pass1c(e2fsck_t ctx, char *block_buf); -static void pass1d(e2fsck_t ctx, char *block_buf); - -static int dup_inode_count = 0; - -static dict_t blk_dict, ino_dict; - -static ext2fs_inode_bitmap inode_dup_map; - -static int dict_int_cmp(const void *a, const void *b) -{ - intptr_t ia, ib; - - ia = (intptr_t)a; - ib = (intptr_t)b; - - return (ia-ib); -} - -/* - * Add a duplicate block record - */ -static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk, - struct ext2_inode *inode) -{ - dnode_t *n; - struct dup_block *db; - struct dup_inode *di; - struct block_el *blk_el; - struct inode_el *ino_el; - - n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk)); - if (n) - db = (struct dup_block *) dnode_get(n); - else { - db = (struct dup_block *) e2fsck_allocate_memory(ctx, - sizeof(struct dup_block), "duplicate block header"); - db->num_bad = 0; - db->inode_list = 0; - dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db); - } - ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx, - sizeof(struct inode_el), "inode element"); - ino_el->inode = ino; - ino_el->next = db->inode_list; - db->inode_list = ino_el; - db->num_bad++; - - n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino)); - if (n) - di = (struct dup_inode *) dnode_get(n); - else { - di = (struct dup_inode *) e2fsck_allocate_memory(ctx, - sizeof(struct dup_inode), "duplicate inode header"); - di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0; - di->num_dupblocks = 0; - di->block_list = 0; - di->inode = *inode; - dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di); - } - blk_el = (struct block_el *) e2fsck_allocate_memory(ctx, - sizeof(struct block_el), "block element"); - blk_el->block = blk; - blk_el->next = di->block_list; - di->block_list = blk_el; - di->num_dupblocks++; -} - -/* - * Free a duplicate inode record - */ -static void inode_dnode_free(dnode_t *node) -{ - struct dup_inode *di; - struct block_el *p, *next; - - di = (struct dup_inode *) dnode_get(node); - for (p = di->block_list; p; p = next) { - next = p->next; - free(p); - } - free(node); -} - -/* - * Free a duplicate block record - */ -static void block_dnode_free(dnode_t *node) -{ - struct dup_block *db; - struct inode_el *p, *next; - - db = (struct dup_block *) dnode_get(node); - for (p = db->inode_list; p; p = next) { - next = p->next; - free(p); - } - free(node); -} - - -/* - * Main procedure for handling duplicate blocks - */ -void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf) -{ - ext2_filsys fs = ctx->fs; - struct problem_context pctx; - - clear_problem_context(&pctx); - - pctx.errcode = ext2fs_allocate_inode_bitmap(fs, - _("multiply claimed inode map"), &inode_dup_map); - if (pctx.errcode) { - fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - - dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp); - dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp); - dict_set_allocator(&ino_dict, inode_dnode_free); - dict_set_allocator(&blk_dict, block_dnode_free); - - pass1b(ctx, block_buf); - pass1c(ctx, block_buf); - pass1d(ctx, block_buf); - - /* - * Time to free all of the accumulated data structures that we - * don't need anymore. - */ - dict_free_nodes(&ino_dict); - dict_free_nodes(&blk_dict); -} - -/* - * Scan the inodes looking for inodes that contain duplicate blocks. - */ -struct process_block_struct_1b { - e2fsck_t ctx; - ext2_ino_t ino; - int dup_blocks; - struct ext2_inode *inode; - struct problem_context *pctx; -}; - -static void pass1b(e2fsck_t ctx, char *block_buf) -{ - ext2_filsys fs = ctx->fs; - ext2_ino_t ino; - struct ext2_inode inode; - ext2_inode_scan scan; - struct process_block_struct_1b pb; - struct problem_context pctx; - - clear_problem_context(&pctx); - - if (!(ctx->options & E2F_OPT_PREEN)) - fix_problem(ctx, PR_1B_PASS_HEADER, &pctx); - pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks, - &scan); - if (pctx.errcode) { - fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - ctx->stashed_inode = &inode; - pb.ctx = ctx; - pb.pctx = &pctx; - pctx.str = "pass1b"; - while (1) { - pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode); - if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) - continue; - if (pctx.errcode) { - fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - if (!ino) - break; - pctx.ino = ctx->stashed_ino = ino; - if ((ino != EXT2_BAD_INO) && - !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)) - continue; - - pb.ino = ino; - pb.dup_blocks = 0; - pb.inode = &inode; - - if (ext2fs_inode_has_valid_blocks(&inode) || - (ino == EXT2_BAD_INO)) - pctx.errcode = ext2fs_block_iterate2(fs, ino, - 0, block_buf, process_pass1b_block, &pb); - if (inode.i_file_acl) - process_pass1b_block(fs, &inode.i_file_acl, - BLOCK_COUNT_EXTATTR, 0, 0, &pb); - if (pb.dup_blocks) { - end_problem_latch(ctx, PR_LATCH_DBLOCK); - if (ino >= EXT2_FIRST_INODE(fs->super) || - ino == EXT2_ROOT_INO) - dup_inode_count++; - } - if (pctx.errcode) - fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx); - } - ext2fs_close_inode_scan(scan); - e2fsck_use_inode_shortcuts(ctx, 0); -} - -static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)), - blk_t *block_nr, - e2_blkcnt_t blockcnt FSCK_ATTR((unused)), - blk_t ref_blk FSCK_ATTR((unused)), - int ref_offset FSCK_ATTR((unused)), - void *priv_data) -{ - struct process_block_struct_1b *p; - e2fsck_t ctx; - - if (HOLE_BLKADDR(*block_nr)) - return 0; - p = (struct process_block_struct_1b *) priv_data; - ctx = p->ctx; - - if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) - return 0; - - /* OK, this is a duplicate block */ - if (p->ino != EXT2_BAD_INO) { - p->pctx->blk = *block_nr; - fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx); - } - p->dup_blocks++; - ext2fs_mark_inode_bitmap(inode_dup_map, p->ino); - - add_dupe(ctx, p->ino, *block_nr, p->inode); - - return 0; -} - -/* - * Pass 1c: Scan directories for inodes with duplicate blocks. This - * is used so that we can print pathnames when prompting the user for - * what to do. - */ -struct search_dir_struct { - int count; - ext2_ino_t first_inode; - ext2_ino_t max_inode; -}; - -static int search_dirent_proc(ext2_ino_t dir, int entry, - struct ext2_dir_entry *dirent, - int offset FSCK_ATTR((unused)), - int blocksize FSCK_ATTR((unused)), - char *buf FSCK_ATTR((unused)), - void *priv_data) -{ - struct search_dir_struct *sd; - struct dup_inode *p; - dnode_t *n; - - sd = (struct search_dir_struct *) priv_data; - - if (dirent->inode > sd->max_inode) - /* Should abort this inode, but not everything */ - return 0; - - if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) || - !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode)) - return 0; - - n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode)); - if (!n) - return 0; - p = (struct dup_inode *) dnode_get(n); - p->dir = dir; - sd->count--; - - return sd->count ? 0 : DIRENT_ABORT; -} - - -static void pass1c(e2fsck_t ctx, char *block_buf) -{ - ext2_filsys fs = ctx->fs; - struct search_dir_struct sd; - struct problem_context pctx; - - clear_problem_context(&pctx); - - if (!(ctx->options & E2F_OPT_PREEN)) - fix_problem(ctx, PR_1C_PASS_HEADER, &pctx); - - /* - * Search through all directories to translate inodes to names - * (by searching for the containing directory for that inode.) - */ - sd.count = dup_inode_count; - sd.first_inode = EXT2_FIRST_INODE(fs->super); - sd.max_inode = fs->super->s_inodes_count; - ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf, - search_dirent_proc, &sd); -} - -static void pass1d(e2fsck_t ctx, char *block_buf) -{ - ext2_filsys fs = ctx->fs; - struct dup_inode *p, *t; - struct dup_block *q; - ext2_ino_t *shared, ino; - int shared_len; - int i; - int file_ok; - int meta_data = 0; - struct problem_context pctx; - dnode_t *n, *m; - struct block_el *s; - struct inode_el *r; - - clear_problem_context(&pctx); - - if (!(ctx->options & E2F_OPT_PREEN)) - fix_problem(ctx, PR_1D_PASS_HEADER, &pctx); - e2fsck_read_bitmaps(ctx); - - pctx.num = dup_inode_count; /* dict_count(&ino_dict); */ - fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx); - shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx, - sizeof(ext2_ino_t) * dict_count(&ino_dict), - "Shared inode list"); - for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) { - p = (struct dup_inode *) dnode_get(n); - shared_len = 0; - file_ok = 1; - ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n)); - if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO) - continue; - - /* - * Find all of the inodes which share blocks with this - * one. First we find all of the duplicate blocks - * belonging to this inode, and then search each block - * get the list of inodes, and merge them together. - */ - for (s = p->block_list; s; s = s->next) { - m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block)); - if (!m) - continue; /* Should never happen... */ - q = (struct dup_block *) dnode_get(m); - if (q->num_bad > 1) - file_ok = 0; - if (check_if_fs_block(ctx, s->block)) { - file_ok = 0; - meta_data = 1; - } - - /* - * Add all inodes used by this block to the - * shared[] --- which is a unique list, so - * if an inode is already in shared[], don't - * add it again. - */ - for (r = q->inode_list; r; r = r->next) { - if (r->inode == ino) - continue; - for (i = 0; i < shared_len; i++) - if (shared[i] == r->inode) - break; - if (i == shared_len) { - shared[shared_len++] = r->inode; - } - } - } - - /* - * Report the inode that we are working on - */ - pctx.inode = &p->inode; - pctx.ino = ino; - pctx.dir = p->dir; - pctx.blkcount = p->num_dupblocks; - pctx.num = meta_data ? shared_len+1 : shared_len; - fix_problem(ctx, PR_1D_DUP_FILE, &pctx); - pctx.blkcount = 0; - pctx.num = 0; - - if (meta_data) - fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx); - - for (i = 0; i < shared_len; i++) { - m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i])); - if (!m) - continue; /* should never happen */ - t = (struct dup_inode *) dnode_get(m); - /* - * Report the inode that we are sharing with - */ - pctx.inode = &t->inode; - pctx.ino = shared[i]; - pctx.dir = t->dir; - fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx); - } - if (file_ok) { - fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx); - continue; - } - if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) { - pctx.errcode = clone_file(ctx, ino, p, block_buf); - if (pctx.errcode) - fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx); - else - continue; - } - if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx)) - delete_file(ctx, ino, p, block_buf); - else - ext2fs_unmark_valid(fs); - } - ext2fs_free_mem(&shared); -} - -/* - * Drop the refcount on the dup_block structure, and clear the entry - * in the block_dup_map if appropriate. - */ -static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p) -{ - p->num_bad--; - if (p->num_bad <= 0 || - (p->num_bad == 1 && !check_if_fs_block(ctx, block))) - ext2fs_unmark_block_bitmap(ctx->block_dup_map, block); -} - -static int delete_file_block(ext2_filsys fs, - blk_t *block_nr, - e2_blkcnt_t blockcnt FSCK_ATTR((unused)), - blk_t ref_block FSCK_ATTR((unused)), - int ref_offset FSCK_ATTR((unused)), - void *priv_data) -{ - struct process_block_struct_1b *pb; - struct dup_block *p; - dnode_t *n; - e2fsck_t ctx; - - pb = (struct process_block_struct_1b *) priv_data; - ctx = pb->ctx; - - if (HOLE_BLKADDR(*block_nr)) - return 0; - - if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) { - n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr)); - if (n) { - p = (struct dup_block *) dnode_get(n); - decrement_badcount(ctx, *block_nr, p); - } else - bb_error_msg(_("internal error; can't find dup_blk for %d"), - *block_nr); - } else { - ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr); - ext2fs_block_alloc_stats(fs, *block_nr, -1); - } - - return 0; -} - -static void delete_file(e2fsck_t ctx, ext2_ino_t ino, - struct dup_inode *dp, char* block_buf) -{ - ext2_filsys fs = ctx->fs; - struct process_block_struct_1b pb; - struct ext2_inode inode; - struct problem_context pctx; - unsigned int count; - - clear_problem_context(&pctx); - pctx.ino = pb.ino = ino; - pb.dup_blocks = dp->num_dupblocks; - pb.ctx = ctx; - pctx.str = "delete_file"; - - e2fsck_read_inode(ctx, ino, &inode, "delete_file"); - if (ext2fs_inode_has_valid_blocks(&inode)) - pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf, - delete_file_block, &pb); - if (pctx.errcode) - fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx); - ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino); - ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino); - if (ctx->inode_bad_map) - ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino); - ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode)); - - /* Inode may have changed by block_iterate, so reread it */ - e2fsck_read_inode(ctx, ino, &inode, "delete_file"); - inode.i_links_count = 0; - inode.i_dtime = time(NULL); - if (inode.i_file_acl && - (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) { - count = 1; - pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl, - block_buf, -1, &count); - if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) { - pctx.errcode = 0; - count = 1; - } - if (pctx.errcode) { - pctx.blk = inode.i_file_acl; - fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx); - } - /* - * If the count is zero, then arrange to have the - * block deleted. If the block is in the block_dup_map, - * also call delete_file_block since it will take care - * of keeping the accounting straight. - */ - if ((count == 0) || - ext2fs_test_block_bitmap(ctx->block_dup_map, - inode.i_file_acl)) - delete_file_block(fs, &inode.i_file_acl, - BLOCK_COUNT_EXTATTR, 0, 0, &pb); - } - e2fsck_write_inode(ctx, ino, &inode, "delete_file"); -} - -struct clone_struct { - errcode_t errcode; - ext2_ino_t dir; - char *buf; - e2fsck_t ctx; -}; - -static int clone_file_block(ext2_filsys fs, - blk_t *block_nr, - e2_blkcnt_t blockcnt, - blk_t ref_block FSCK_ATTR((unused)), - int ref_offset FSCK_ATTR((unused)), - void *priv_data) -{ - struct dup_block *p; - blk_t new_block; - errcode_t retval; - struct clone_struct *cs = (struct clone_struct *) priv_data; - dnode_t *n; - e2fsck_t ctx; - - ctx = cs->ctx; - - if (HOLE_BLKADDR(*block_nr)) - return 0; - - if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) { - n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr)); - if (n) { - p = (struct dup_block *) dnode_get(n); - retval = ext2fs_new_block(fs, 0, ctx->block_found_map, - &new_block); - if (retval) { - cs->errcode = retval; - return BLOCK_ABORT; - } - if (cs->dir && (blockcnt >= 0)) { - retval = ext2fs_set_dir_block(fs->dblist, - cs->dir, new_block, blockcnt); - if (retval) { - cs->errcode = retval; - return BLOCK_ABORT; - } - } - - retval = io_channel_read_blk(fs->io, *block_nr, 1, - cs->buf); - if (retval) { - cs->errcode = retval; - return BLOCK_ABORT; - } - retval = io_channel_write_blk(fs->io, new_block, 1, - cs->buf); - if (retval) { - cs->errcode = retval; - return BLOCK_ABORT; - } - decrement_badcount(ctx, *block_nr, p); - *block_nr = new_block; - ext2fs_mark_block_bitmap(ctx->block_found_map, - new_block); - ext2fs_mark_block_bitmap(fs->block_map, new_block); - return BLOCK_CHANGED; - } else - bb_error_msg(_("internal error; can't find dup_blk for %d"), - *block_nr); - } - return 0; -} - -static int clone_file(e2fsck_t ctx, ext2_ino_t ino, - struct dup_inode *dp, char* block_buf) -{ - ext2_filsys fs = ctx->fs; - errcode_t retval; - struct clone_struct cs; - struct problem_context pctx; - blk_t blk; - dnode_t *n; - struct inode_el *ino_el; - struct dup_block *db; - struct dup_inode *di; - - clear_problem_context(&pctx); - cs.errcode = 0; - cs.dir = 0; - cs.ctx = ctx; - retval = ext2fs_get_mem(fs->blocksize, &cs.buf); - if (retval) - return retval; - - if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) - cs.dir = ino; - - pctx.ino = ino; - pctx.str = "clone_file"; - if (ext2fs_inode_has_valid_blocks(&dp->inode)) - pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf, - clone_file_block, &cs); - ext2fs_mark_bb_dirty(fs); - if (pctx.errcode) { - fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx); - retval = pctx.errcode; - goto errout; - } - if (cs.errcode) { - bb_error_msg(_("returned from clone_file_block")); - retval = cs.errcode; - goto errout; - } - /* The inode may have changed on disk, so we have to re-read it */ - e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA"); - blk = dp->inode.i_file_acl; - if (blk && (clone_file_block(fs, &dp->inode.i_file_acl, - BLOCK_COUNT_EXTATTR, 0, 0, &cs) == - BLOCK_CHANGED)) { - e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA"); - /* - * If we cloned the EA block, find all other inodes - * which refered to that EA block, and modify - * them to point to the new EA block. - */ - n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk)); - db = (struct dup_block *) dnode_get(n); - for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) { - if (ino_el->inode == ino) - continue; - n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode)); - di = (struct dup_inode *) dnode_get(n); - if (di->inode.i_file_acl == blk) { - di->inode.i_file_acl = dp->inode.i_file_acl; - e2fsck_write_inode(ctx, ino_el->inode, - &di->inode, "clone file EA"); - decrement_badcount(ctx, blk, db); - } - } - } - retval = 0; -errout: - ext2fs_free_mem(&cs.buf); - return retval; -} - -/* - * This routine returns 1 if a block overlaps with one of the superblocks, - * group descriptors, inode bitmaps, or block bitmaps. - */ -static int check_if_fs_block(e2fsck_t ctx, blk_t test_block) -{ - ext2_filsys fs = ctx->fs; - blk_t block; - dgrp_t i; - - block = fs->super->s_first_data_block; - for (i = 0; i < fs->group_desc_count; i++) { - - /* Check superblocks/block group descriptros */ - if (ext2fs_bg_has_super(fs, i)) { - if (test_block >= block && - (test_block <= block + fs->desc_blocks)) - return 1; - } - - /* Check the inode table */ - if ((fs->group_desc[i].bg_inode_table) && - (test_block >= fs->group_desc[i].bg_inode_table) && - (test_block < (fs->group_desc[i].bg_inode_table + - fs->inode_blocks_per_group))) - return 1; - - /* Check the bitmap blocks */ - if ((test_block == fs->group_desc[i].bg_block_bitmap) || - (test_block == fs->group_desc[i].bg_inode_bitmap)) - return 1; - - block += fs->super->s_blocks_per_group; - } - return 0; -} -/* - * pass2.c --- check directory structure - * - * Pass 2 of e2fsck iterates through all active directory inodes, and - * applies to following tests to each directory entry in the directory - * blocks in the inodes: - * - * - The length of the directory entry (rec_len) should be at - * least 8 bytes, and no more than the remaining space - * left in the directory block. - * - The length of the name in the directory entry (name_len) - * should be less than (rec_len - 8). - * - The inode number in the directory entry should be within - * legal bounds. - * - The inode number should refer to a in-use inode. - * - The first entry should be '.', and its inode should be - * the inode of the directory. - * - The second entry should be '..'. - * - * To minimize disk seek time, the directory blocks are processed in - * sorted order of block numbers. - * - * Pass 2 also collects the following information: - * - The inode numbers of the subdirectories for each directory. - * - * Pass 2 relies on the following information from previous passes: - * - The directory information collected in pass 1. - * - The inode_used_map bitmap - * - The inode_bad_map bitmap - * - The inode_dir_map bitmap - * - * Pass 2 frees the following data structures - * - The inode_bad_map bitmap - * - The inode_reg_map bitmap - */ - -/* - * Keeps track of how many times an inode is referenced. - */ -static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf); -static int check_dir_block(ext2_filsys fs, - struct ext2_db_entry *dir_blocks_info, - void *priv_data); -static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info, - struct problem_context *pctx); -static int update_dir_block(ext2_filsys fs, - blk_t *block_nr, - e2_blkcnt_t blockcnt, - blk_t ref_block, - int ref_offset, - void *priv_data); -static void clear_htree(e2fsck_t ctx, ext2_ino_t ino); -static int htree_depth(struct dx_dir_info *dx_dir, - struct dx_dirblock_info *dx_db); -static int special_dir_block_cmp(const void *a, const void *b); - -struct check_dir_struct { - char *buf; - struct problem_context pctx; - int count, max; - e2fsck_t ctx; -}; - -static void e2fsck_pass2(e2fsck_t ctx) -{ - struct ext2_super_block *sb = ctx->fs->super; - struct problem_context pctx; - ext2_filsys fs = ctx->fs; - char *buf; - struct dir_info *dir; - struct check_dir_struct cd; - struct dx_dir_info *dx_dir; - struct dx_dirblock_info *dx_db, *dx_parent; - int b; - int i, depth; - problem_t code; - int bad_dir; - - clear_problem_context(&cd.pctx); - - /* Pass 2 */ - - if (!(ctx->options & E2F_OPT_PREEN)) - fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx); - - cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT, - 0, ctx->inode_link_info, - &ctx->inode_count); - if (cd.pctx.errcode) { - fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize, - "directory scan buffer"); - - /* - * Set up the parent pointer for the root directory, if - * present. (If the root directory is not present, we will - * create it in pass 3.) - */ - dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO); - if (dir) - dir->parent = EXT2_ROOT_INO; - - cd.buf = buf; - cd.ctx = ctx; - cd.count = 1; - cd.max = ext2fs_dblist_count(fs->dblist); - - if (ctx->progress) - (void) (ctx->progress)(ctx, 2, 0, cd.max); - - if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) - ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp); - - cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block, - &cd); - if (ctx->flags & E2F_FLAG_SIGNAL_MASK) - return; - if (cd.pctx.errcode) { - fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - -#ifdef ENABLE_HTREE - for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) { - if (ctx->flags & E2F_FLAG_SIGNAL_MASK) - return; - if (dx_dir->numblocks == 0) - continue; - clear_problem_context(&pctx); - bad_dir = 0; - pctx.dir = dx_dir->ino; - dx_db = dx_dir->dx_block; - if (dx_db->flags & DX_FLAG_REFERENCED) - dx_db->flags |= DX_FLAG_DUP_REF; - else - dx_db->flags |= DX_FLAG_REFERENCED; - /* - * Find all of the first and last leaf blocks, and - * update their parent's min and max hash values - */ - for (b=0, dx_db = dx_dir->dx_block; - b < dx_dir->numblocks; - b++, dx_db++) { - if ((dx_db->type != DX_DIRBLOCK_LEAF) || - !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST))) - continue; - dx_parent = &dx_dir->dx_block[dx_db->parent]; - /* - * XXX Make sure dx_parent->min_hash > dx_db->min_hash - */ - if (dx_db->flags & DX_FLAG_FIRST) - dx_parent->min_hash = dx_db->min_hash; - /* - * XXX Make sure dx_parent->max_hash < dx_db->max_hash - */ - if (dx_db->flags & DX_FLAG_LAST) - dx_parent->max_hash = dx_db->max_hash; - } - - for (b=0, dx_db = dx_dir->dx_block; - b < dx_dir->numblocks; - b++, dx_db++) { - pctx.blkcount = b; - pctx.group = dx_db->parent; - code = 0; - if (!(dx_db->flags & DX_FLAG_FIRST) && - (dx_db->min_hash < dx_db->node_min_hash)) { - pctx.blk = dx_db->min_hash; - pctx.blk2 = dx_db->node_min_hash; - code = PR_2_HTREE_MIN_HASH; - fix_problem(ctx, code, &pctx); - bad_dir++; - } - if (dx_db->type == DX_DIRBLOCK_LEAF) { - depth = htree_depth(dx_dir, dx_db); - if (depth != dx_dir->depth) { - code = PR_2_HTREE_BAD_DEPTH; - fix_problem(ctx, code, &pctx); - bad_dir++; - } - } - /* - * This test doesn't apply for the root block - * at block #0 - */ - if (b && - (dx_db->max_hash > dx_db->node_max_hash)) { - pctx.blk = dx_db->max_hash; - pctx.blk2 = dx_db->node_max_hash; - code = PR_2_HTREE_MAX_HASH; - fix_problem(ctx, code, &pctx); - bad_dir++; - } - if (!(dx_db->flags & DX_FLAG_REFERENCED)) { - code = PR_2_HTREE_NOTREF; - fix_problem(ctx, code, &pctx); - bad_dir++; - } else if (dx_db->flags & DX_FLAG_DUP_REF) { - code = PR_2_HTREE_DUPREF; - fix_problem(ctx, code, &pctx); - bad_dir++; - } - if (code == 0) - continue; - } - if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) { - clear_htree(ctx, dx_dir->ino); - dx_dir->numblocks = 0; - } - } -#endif - ext2fs_free_mem(&buf); - ext2fs_free_dblist(fs->dblist); - - ext2fs_free_inode_bitmap(ctx->inode_bad_map); - ctx->inode_bad_map = 0; - ext2fs_free_inode_bitmap(ctx->inode_reg_map); - ctx->inode_reg_map = 0; - - clear_problem_context(&pctx); - if (ctx->large_files) { - if (!(sb->s_feature_ro_compat & - EXT2_FEATURE_RO_COMPAT_LARGE_FILE) && - fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) { - sb->s_feature_ro_compat |= - EXT2_FEATURE_RO_COMPAT_LARGE_FILE; - ext2fs_mark_super_dirty(fs); - } - if (sb->s_rev_level == EXT2_GOOD_OLD_REV && - fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) { - ext2fs_update_dynamic_rev(fs); - ext2fs_mark_super_dirty(fs); - } - } else if (!ctx->large_files && - (sb->s_feature_ro_compat & - EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) { - if (fs->flags & EXT2_FLAG_RW) { - sb->s_feature_ro_compat &= - ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE; - ext2fs_mark_super_dirty(fs); - } - } -} - -#define MAX_DEPTH 32000 -static int htree_depth(struct dx_dir_info *dx_dir, - struct dx_dirblock_info *dx_db) -{ - int depth = 0; - - while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) { - dx_db = &dx_dir->dx_block[dx_db->parent]; - depth++; - } - return depth; -} - -static int dict_de_cmp(const void *a, const void *b) -{ - const struct ext2_dir_entry *de_a, *de_b; - int a_len, b_len; - - de_a = (const struct ext2_dir_entry *) a; - a_len = de_a->name_len & 0xFF; - de_b = (const struct ext2_dir_entry *) b; - b_len = de_b->name_len & 0xFF; - - if (a_len != b_len) - return (a_len - b_len); - - return strncmp(de_a->name, de_b->name, a_len); -} - -/* - * This is special sort function that makes sure that directory blocks - * with a dirblock of zero are sorted to the beginning of the list. - * This guarantees that the root node of the htree directories are - * processed first, so we know what hash version to use. - */ -static int special_dir_block_cmp(const void *a, const void *b) -{ - const struct ext2_db_entry *db_a = - (const struct ext2_db_entry *) a; - const struct ext2_db_entry *db_b = - (const struct ext2_db_entry *) b; - - if (db_a->blockcnt && !db_b->blockcnt) - return 1; - - if (!db_a->blockcnt && db_b->blockcnt) - return -1; - - if (db_a->blk != db_b->blk) - return (int) (db_a->blk - db_b->blk); - - if (db_a->ino != db_b->ino) - return (int) (db_a->ino - db_b->ino); - - return (int) (db_a->blockcnt - db_b->blockcnt); -} - - -/* - * Make sure the first entry in the directory is '.', and that the - * directory entry is sane. - */ -static int check_dot(e2fsck_t ctx, - struct ext2_dir_entry *dirent, - ext2_ino_t ino, struct problem_context *pctx) -{ - struct ext2_dir_entry *nextdir; - int status = 0; - int created = 0; - int new_len; - int problem = 0; - - if (!dirent->inode) - problem = PR_2_MISSING_DOT; - else if (((dirent->name_len & 0xFF) != 1) || - (dirent->name[0] != '.')) - problem = PR_2_1ST_NOT_DOT; - else if (dirent->name[1] != '\0') - problem = PR_2_DOT_NULL_TERM; - - if (problem) { - if (fix_problem(ctx, problem, pctx)) { - if (dirent->rec_len < 12) - dirent->rec_len = 12; - dirent->inode = ino; - dirent->name_len = 1; - dirent->name[0] = '.'; - dirent->name[1] = '\0'; - status = 1; - created = 1; - } - } - if (dirent->inode != ino) { - if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) { - dirent->inode = ino; - status = 1; - } - } - if (dirent->rec_len > 12) { - new_len = dirent->rec_len - 12; - if (new_len > 12) { - if (created || - fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) { - nextdir = (struct ext2_dir_entry *) - ((char *) dirent + 12); - dirent->rec_len = 12; - nextdir->rec_len = new_len; - nextdir->inode = 0; - nextdir->name_len = 0; - status = 1; - } - } - } - return status; -} - -/* - * Make sure the second entry in the directory is '..', and that the - * directory entry is sane. We do not check the inode number of '..' - * here; this gets done in pass 3. - */ -static int check_dotdot(e2fsck_t ctx, - struct ext2_dir_entry *dirent, - struct dir_info *dir, struct problem_context *pctx) -{ - int problem = 0; - - if (!dirent->inode) - problem = PR_2_MISSING_DOT_DOT; - else if (((dirent->name_len & 0xFF) != 2) || - (dirent->name[0] != '.') || - (dirent->name[1] != '.')) - problem = PR_2_2ND_NOT_DOT_DOT; - else if (dirent->name[2] != '\0') - problem = PR_2_DOT_DOT_NULL_TERM; - - if (problem) { - if (fix_problem(ctx, problem, pctx)) { - if (dirent->rec_len < 12) - dirent->rec_len = 12; - /* - * Note: we don't have the parent inode just - * yet, so we will fill it in with the root - * inode. This will get fixed in pass 3. - */ - dirent->inode = EXT2_ROOT_INO; - dirent->name_len = 2; - dirent->name[0] = '.'; - dirent->name[1] = '.'; - dirent->name[2] = '\0'; - return 1; - } - return 0; - } - dir->dotdot = dirent->inode; - return 0; -} - -/* - * Check to make sure a directory entry doesn't contain any illegal - * characters. - */ -static int check_name(e2fsck_t ctx, - struct ext2_dir_entry *dirent, - struct problem_context *pctx) -{ - int i; - int fixup = -1; - int ret = 0; - - for ( i = 0; i < (dirent->name_len & 0xFF); i++) { - if (dirent->name[i] == '/' || dirent->name[i] == '\0') { - if (fixup < 0) { - fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx); - } - if (fixup) { - dirent->name[i] = '.'; - ret = 1; - } - } - } - return ret; -} - -/* - * Check the directory filetype (if present) - */ - -/* - * Given a mode, return the ext2 file type - */ -static int ext2_file_type(unsigned int mode) -{ - if (LINUX_S_ISREG(mode)) - return EXT2_FT_REG_FILE; - - if (LINUX_S_ISDIR(mode)) - return EXT2_FT_DIR; - - if (LINUX_S_ISCHR(mode)) - return EXT2_FT_CHRDEV; - - if (LINUX_S_ISBLK(mode)) - return EXT2_FT_BLKDEV; - - if (LINUX_S_ISLNK(mode)) - return EXT2_FT_SYMLINK; - - if (LINUX_S_ISFIFO(mode)) - return EXT2_FT_FIFO; - - if (LINUX_S_ISSOCK(mode)) - return EXT2_FT_SOCK; - - return 0; -} - -static int check_filetype(e2fsck_t ctx, - struct ext2_dir_entry *dirent, - struct problem_context *pctx) -{ - int filetype = dirent->name_len >> 8; - int should_be = EXT2_FT_UNKNOWN; - struct ext2_inode inode; - - if (!(ctx->fs->super->s_feature_incompat & - EXT2_FEATURE_INCOMPAT_FILETYPE)) { - if (filetype == 0 || - !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx)) - return 0; - dirent->name_len = dirent->name_len & 0xFF; - return 1; - } - - if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) { - should_be = EXT2_FT_DIR; - } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map, - dirent->inode)) { - should_be = EXT2_FT_REG_FILE; - } else if (ctx->inode_bad_map && - ext2fs_test_inode_bitmap(ctx->inode_bad_map, - dirent->inode)) - should_be = 0; - else { - e2fsck_read_inode(ctx, dirent->inode, &inode, - "check_filetype"); - should_be = ext2_file_type(inode.i_mode); - } - if (filetype == should_be) - return 0; - pctx->num = should_be; - - if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE, - pctx) == 0) - return 0; - - dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8; - return 1; -} - -#ifdef ENABLE_HTREE -static void parse_int_node(ext2_filsys fs, - struct ext2_db_entry *db, - struct check_dir_struct *cd, - struct dx_dir_info *dx_dir, - char *block_buf) -{ - struct ext2_dx_root_info *root; - struct ext2_dx_entry *ent; - struct ext2_dx_countlimit *limit; - struct dx_dirblock_info *dx_db; - int i, expect_limit, count; - blk_t blk; - ext2_dirhash_t min_hash = 0xffffffff; - ext2_dirhash_t max_hash = 0; - ext2_dirhash_t hash = 0, prev_hash; - - if (db->blockcnt == 0) { - root = (struct ext2_dx_root_info *) (block_buf + 24); - ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length); - } else { - ent = (struct ext2_dx_entry *) (block_buf+8); - } - limit = (struct ext2_dx_countlimit *) ent; - - count = ext2fs_le16_to_cpu(limit->count); - expect_limit = (fs->blocksize - ((char *) ent - block_buf)) / - sizeof(struct ext2_dx_entry); - if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) { - cd->pctx.num = ext2fs_le16_to_cpu(limit->limit); - if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx)) - goto clear_and_exit; - } - if (count > expect_limit) { - cd->pctx.num = count; - if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx)) - goto clear_and_exit; - count = expect_limit; - } - - for (i=0; i < count; i++) { - prev_hash = hash; - hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0; - blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff; - /* Check to make sure the block is valid */ - if (blk > (blk_t) dx_dir->numblocks) { - cd->pctx.blk = blk; - if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK, - &cd->pctx)) - goto clear_and_exit; - } - if (hash < prev_hash && - fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx)) - goto clear_and_exit; - dx_db = &dx_dir->dx_block[blk]; - if (dx_db->flags & DX_FLAG_REFERENCED) { - dx_db->flags |= DX_FLAG_DUP_REF; - } else { - dx_db->flags |= DX_FLAG_REFERENCED; - dx_db->parent = db->blockcnt; - } - if (hash < min_hash) - min_hash = hash; - if (hash > max_hash) - max_hash = hash; - dx_db->node_min_hash = hash; - if ((i+1) < count) - dx_db->node_max_hash = - ext2fs_le32_to_cpu(ent[i+1].hash) & ~1; - else { - dx_db->node_max_hash = 0xfffffffe; - dx_db->flags |= DX_FLAG_LAST; - } - if (i == 0) - dx_db->flags |= DX_FLAG_FIRST; - } - dx_db = &dx_dir->dx_block[db->blockcnt]; - dx_db->min_hash = min_hash; - dx_db->max_hash = max_hash; - return; - -clear_and_exit: - clear_htree(cd->ctx, cd->pctx.ino); - dx_dir->numblocks = 0; -} -#endif /* ENABLE_HTREE */ - -/* - * Given a busted directory, try to salvage it somehow. - * - */ -static void salvage_directory(ext2_filsys fs, - struct ext2_dir_entry *dirent, - struct ext2_dir_entry *prev, - unsigned int *offset) -{ - char *cp = (char *) dirent; - int left = fs->blocksize - *offset - dirent->rec_len; - int name_len = dirent->name_len & 0xFF; - - /* - * Special case of directory entry of size 8: copy what's left - * of the directory block up to cover up the invalid hole. - */ - if ((left >= 12) && (dirent->rec_len == 8)) { - memmove(cp, cp+8, left); - memset(cp + left, 0, 8); - return; - } - /* - * If the directory entry overruns the end of the directory - * block, and the name is small enough to fit, then adjust the - * record length. - */ - if ((left < 0) && - (name_len + 8 <= dirent->rec_len + left) && - dirent->inode <= fs->super->s_inodes_count && - strnlen(dirent->name, name_len) == name_len) { - dirent->rec_len += left; - return; - } - /* - * If the directory entry is a multiple of four, so it is - * valid, let the previous directory entry absorb the invalid - * one. - */ - if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) { - prev->rec_len += dirent->rec_len; - *offset += dirent->rec_len; - return; - } - /* - * Default salvage method --- kill all of the directory - * entries for the rest of the block. We will either try to - * absorb it into the previous directory entry, or create a - * new empty directory entry the rest of the directory block. - */ - if (prev) { - prev->rec_len += fs->blocksize - *offset; - *offset = fs->blocksize; - } else { - dirent->rec_len = fs->blocksize - *offset; - dirent->name_len = 0; - dirent->inode = 0; - } -} - -static int check_dir_block(ext2_filsys fs, - struct ext2_db_entry *db, - void *priv_data) -{ - struct dir_info *subdir, *dir; - struct dx_dir_info *dx_dir; -#ifdef ENABLE_HTREE - struct dx_dirblock_info *dx_db = NULL; -#endif /* ENABLE_HTREE */ - struct ext2_dir_entry *dirent, *prev; - ext2_dirhash_t hash; - unsigned int offset = 0; - int dir_modified = 0; - int dot_state; - blk_t block_nr = db->blk; - ext2_ino_t ino = db->ino; - __u16 links; - struct check_dir_struct *cd; - char *buf; - e2fsck_t ctx; - int problem; - struct ext2_dx_root_info *root; - struct ext2_dx_countlimit *limit; - static dict_t de_dict; - struct problem_context pctx; - int dups_found = 0; - - cd = (struct check_dir_struct *) priv_data; - buf = cd->buf; - ctx = cd->ctx; - - if (ctx->flags & E2F_FLAG_SIGNAL_MASK) - return DIRENT_ABORT; - - if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max)) - return DIRENT_ABORT; - - /* - * Make sure the inode is still in use (could have been - * deleted in the duplicate/bad blocks pass. - */ - if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))) - return 0; - - cd->pctx.ino = ino; - cd->pctx.blk = block_nr; - cd->pctx.blkcount = db->blockcnt; - cd->pctx.ino2 = 0; - cd->pctx.dirent = 0; - cd->pctx.num = 0; - - if (db->blk == 0) { - if (allocate_dir_block(ctx, db, &cd->pctx)) - return 0; - block_nr = db->blk; - } - - if (db->blockcnt) - dot_state = 2; - else - dot_state = 0; - - if (ctx->dirs_to_hash && - ext2fs_u32_list_test(ctx->dirs_to_hash, ino)) - dups_found++; - - cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf); - if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED) - cd->pctx.errcode = 0; /* We'll handle this ourselves */ - if (cd->pctx.errcode) { - if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) { - ctx->flags |= E2F_FLAG_ABORT; - return DIRENT_ABORT; - } - memset(buf, 0, fs->blocksize); - } -#ifdef ENABLE_HTREE - dx_dir = e2fsck_get_dx_dir_info(ctx, ino); - if (dx_dir && dx_dir->numblocks) { - if (db->blockcnt >= dx_dir->numblocks) { - printf("XXX should never happen!!!\n"); - abort(); - } - dx_db = &dx_dir->dx_block[db->blockcnt]; - dx_db->type = DX_DIRBLOCK_LEAF; - dx_db->phys = block_nr; - dx_db->min_hash = ~0; - dx_db->max_hash = 0; - - dirent = (struct ext2_dir_entry *) buf; - limit = (struct ext2_dx_countlimit *) (buf+8); - if (db->blockcnt == 0) { - root = (struct ext2_dx_root_info *) (buf + 24); - dx_db->type = DX_DIRBLOCK_ROOT; - dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST; - if ((root->reserved_zero || - root->info_length < 8 || - root->indirect_levels > 1) && - fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) { - clear_htree(ctx, ino); - dx_dir->numblocks = 0; - dx_db = 0; - } - dx_dir->hashversion = root->hash_version; - dx_dir->depth = root->indirect_levels + 1; - } else if ((dirent->inode == 0) && - (dirent->rec_len == fs->blocksize) && - (dirent->name_len == 0) && - (ext2fs_le16_to_cpu(limit->limit) == - ((fs->blocksize-8) / - sizeof(struct ext2_dx_entry)))) - dx_db->type = DX_DIRBLOCK_NODE; - } -#endif /* ENABLE_HTREE */ - - dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp); - prev = 0; - do { - problem = 0; - dirent = (struct ext2_dir_entry *) (buf + offset); - cd->pctx.dirent = dirent; - cd->pctx.num = offset; - if (((offset + dirent->rec_len) > fs->blocksize) || - (dirent->rec_len < 12) || - ((dirent->rec_len % 4) != 0) || - (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) { - if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) { - salvage_directory(fs, dirent, prev, &offset); - dir_modified++; - continue; - } else - goto abort_free_dict; - } - if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) { - if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) { - dirent->name_len = EXT2_NAME_LEN; - dir_modified++; - } - } - - if (dot_state == 0) { - if (check_dot(ctx, dirent, ino, &cd->pctx)) - dir_modified++; - } else if (dot_state == 1) { - dir = e2fsck_get_dir_info(ctx, ino); - if (!dir) { - fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx); - goto abort_free_dict; - } - if (check_dotdot(ctx, dirent, dir, &cd->pctx)) - dir_modified++; - } else if (dirent->inode == ino) { - problem = PR_2_LINK_DOT; - if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) { - dirent->inode = 0; - dir_modified++; - goto next; - } - } - if (!dirent->inode) - goto next; - - /* - * Make sure the inode listed is a legal one. - */ - if (((dirent->inode != EXT2_ROOT_INO) && - (dirent->inode < EXT2_FIRST_INODE(fs->super))) || - (dirent->inode > fs->super->s_inodes_count)) { - problem = PR_2_BAD_INO; - } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, - dirent->inode))) { - /* - * If the inode is unused, offer to clear it. - */ - problem = PR_2_UNUSED_INODE; - } else if ((dot_state > 1) && - ((dirent->name_len & 0xFF) == 1) && - (dirent->name[0] == '.')) { - /* - * If there's a '.' entry in anything other - * than the first directory entry, it's a - * duplicate entry that should be removed. - */ - problem = PR_2_DUP_DOT; - } else if ((dot_state > 1) && - ((dirent->name_len & 0xFF) == 2) && - (dirent->name[0] == '.') && - (dirent->name[1] == '.')) { - /* - * If there's a '..' entry in anything other - * than the second directory entry, it's a - * duplicate entry that should be removed. - */ - problem = PR_2_DUP_DOT_DOT; - } else if ((dot_state > 1) && - (dirent->inode == EXT2_ROOT_INO)) { - /* - * Don't allow links to the root directory. - * We check this specially to make sure we - * catch this error case even if the root - * directory hasn't been created yet. - */ - problem = PR_2_LINK_ROOT; - } else if ((dot_state > 1) && - (dirent->name_len & 0xFF) == 0) { - /* - * Don't allow zero-length directory names. - */ - problem = PR_2_NULL_NAME; - } - - if (problem) { - if (fix_problem(ctx, problem, &cd->pctx)) { - dirent->inode = 0; - dir_modified++; - goto next; - } else { - ext2fs_unmark_valid(fs); - if (problem == PR_2_BAD_INO) - goto next; - } - } - - /* - * If the inode was marked as having bad fields in - * pass1, process it and offer to fix/clear it. - * (We wait until now so that we can display the - * pathname to the user.) - */ - if (ctx->inode_bad_map && - ext2fs_test_inode_bitmap(ctx->inode_bad_map, - dirent->inode)) { - if (e2fsck_process_bad_inode(ctx, ino, - dirent->inode, - buf + fs->blocksize)) { - dirent->inode = 0; - dir_modified++; - goto next; - } - if (ctx->flags & E2F_FLAG_SIGNAL_MASK) - return DIRENT_ABORT; - } - - if (check_name(ctx, dirent, &cd->pctx)) - dir_modified++; - - if (check_filetype(ctx, dirent, &cd->pctx)) - dir_modified++; - -#ifdef ENABLE_HTREE - if (dx_db) { - ext2fs_dirhash(dx_dir->hashversion, dirent->name, - (dirent->name_len & 0xFF), - fs->super->s_hash_seed, &hash, 0); - if (hash < dx_db->min_hash) - dx_db->min_hash = hash; - if (hash > dx_db->max_hash) - dx_db->max_hash = hash; - } -#endif - - /* - * If this is a directory, then mark its parent in its - * dir_info structure. If the parent field is already - * filled in, then this directory has more than one - * hard link. We assume the first link is correct, - * and ask the user if he/she wants to clear this one. - */ - if ((dot_state > 1) && - (ext2fs_test_inode_bitmap(ctx->inode_dir_map, - dirent->inode))) { - subdir = e2fsck_get_dir_info(ctx, dirent->inode); - if (!subdir) { - cd->pctx.ino = dirent->inode; - fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx); - goto abort_free_dict; - } - if (subdir->parent) { - cd->pctx.ino2 = subdir->parent; - if (fix_problem(ctx, PR_2_LINK_DIR, - &cd->pctx)) { - dirent->inode = 0; - dir_modified++; - goto next; - } - cd->pctx.ino2 = 0; - } else - subdir->parent = ino; - } - - if (dups_found) { - ; - } else if (dict_lookup(&de_dict, dirent)) { - clear_problem_context(&pctx); - pctx.ino = ino; - pctx.dirent = dirent; - fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx); - if (!ctx->dirs_to_hash) - ext2fs_u32_list_create(&ctx->dirs_to_hash, 50); - if (ctx->dirs_to_hash) - ext2fs_u32_list_add(ctx->dirs_to_hash, ino); - dups_found++; - } else - dict_alloc_insert(&de_dict, dirent, dirent); - - ext2fs_icount_increment(ctx->inode_count, dirent->inode, - &links); - if (links > 1) - ctx->fs_links_count++; - ctx->fs_total_count++; - next: - prev = dirent; - offset += dirent->rec_len; - dot_state++; - } while (offset < fs->blocksize); -#ifdef ENABLE_HTREE - if (dx_db) { - cd->pctx.dir = cd->pctx.ino; - if ((dx_db->type == DX_DIRBLOCK_ROOT) || - (dx_db->type == DX_DIRBLOCK_NODE)) - parse_int_node(fs, db, cd, dx_dir, buf); - } -#endif /* ENABLE_HTREE */ - if (offset != fs->blocksize) { - cd->pctx.num = dirent->rec_len - fs->blocksize + offset; - if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) { - dirent->rec_len = cd->pctx.num; - dir_modified++; - } - } - if (dir_modified) { - cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf); - if (cd->pctx.errcode) { - if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK, - &cd->pctx)) - goto abort_free_dict; - } - ext2fs_mark_changed(fs); - } - dict_free_nodes(&de_dict); - return 0; -abort_free_dict: - dict_free_nodes(&de_dict); - ctx->flags |= E2F_FLAG_ABORT; - return DIRENT_ABORT; -} - -/* - * This function is called to deallocate a block, and is an interator - * functioned called by deallocate inode via ext2fs_iterate_block(). - */ -static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr, - e2_blkcnt_t blockcnt FSCK_ATTR((unused)), - blk_t ref_block FSCK_ATTR((unused)), - int ref_offset FSCK_ATTR((unused)), - void *priv_data) -{ - e2fsck_t ctx = (e2fsck_t) priv_data; - - if (HOLE_BLKADDR(*block_nr)) - return 0; - if ((*block_nr < fs->super->s_first_data_block) || - (*block_nr >= fs->super->s_blocks_count)) - return 0; - ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr); - ext2fs_block_alloc_stats(fs, *block_nr, -1); - return 0; -} - -/* - * This function deallocates an inode - */ -static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf) -{ - ext2_filsys fs = ctx->fs; - struct ext2_inode inode; - struct problem_context pctx; - __u32 count; - - ext2fs_icount_store(ctx->inode_link_info, ino, 0); - e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode"); - inode.i_links_count = 0; - inode.i_dtime = time(NULL); - e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode"); - clear_problem_context(&pctx); - pctx.ino = ino; - - /* - * Fix up the bitmaps... - */ - e2fsck_read_bitmaps(ctx); - ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino); - ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino); - if (ctx->inode_bad_map) - ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino); - ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode)); - - if (inode.i_file_acl && - (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) { - pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl, - block_buf, -1, &count); - if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) { - pctx.errcode = 0; - count = 1; - } - if (pctx.errcode) { - pctx.blk = inode.i_file_acl; - fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - if (count == 0) { - ext2fs_unmark_block_bitmap(ctx->block_found_map, - inode.i_file_acl); - ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1); - } - inode.i_file_acl = 0; - } - - if (!ext2fs_inode_has_valid_blocks(&inode)) - return; - - if (LINUX_S_ISREG(inode.i_mode) && - (inode.i_size_high || inode.i_size & 0x80000000UL)) - ctx->large_files--; - - pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf, - deallocate_inode_block, ctx); - if (pctx.errcode) { - fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } -} - -/* - * This function clears the htree flag on an inode - */ -static void clear_htree(e2fsck_t ctx, ext2_ino_t ino) -{ - struct ext2_inode inode; - - e2fsck_read_inode(ctx, ino, &inode, "clear_htree"); - inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL; - e2fsck_write_inode(ctx, ino, &inode, "clear_htree"); - if (ctx->dirs_to_hash) - ext2fs_u32_list_add(ctx->dirs_to_hash, ino); -} - - -static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir, - ext2_ino_t ino, char *buf) -{ - ext2_filsys fs = ctx->fs; - struct ext2_inode inode; - int inode_modified = 0; - int not_fixed = 0; - unsigned char *frag, *fsize; - struct problem_context pctx; - int problem = 0; - - e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode"); - - clear_problem_context(&pctx); - pctx.ino = ino; - pctx.dir = dir; - pctx.inode = &inode; - - if (inode.i_file_acl && - !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) && - fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) { - inode.i_file_acl = 0; -#if BB_BIG_ENDIAN - /* - * This is a special kludge to deal with long symlinks - * on big endian systems. i_blocks had already been - * decremented earlier in pass 1, but since i_file_acl - * hadn't yet been cleared, ext2fs_read_inode() - * assumed that the file was short symlink and would - * not have byte swapped i_block[0]. Hence, we have - * to byte-swap it here. - */ - if (LINUX_S_ISLNK(inode.i_mode) && - (fs->flags & EXT2_FLAG_SWAP_BYTES) && - (inode.i_blocks == fs->blocksize >> 9)) - inode.i_block[0] = ext2fs_swab32(inode.i_block[0]); -#endif - inode_modified++; - } else - not_fixed++; - - if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) && - !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) && - !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) && - !(LINUX_S_ISSOCK(inode.i_mode))) - problem = PR_2_BAD_MODE; - else if (LINUX_S_ISCHR(inode.i_mode) - && !e2fsck_pass1_check_device_inode(fs, &inode)) - problem = PR_2_BAD_CHAR_DEV; - else if (LINUX_S_ISBLK(inode.i_mode) - && !e2fsck_pass1_check_device_inode(fs, &inode)) - problem = PR_2_BAD_BLOCK_DEV; - else if (LINUX_S_ISFIFO(inode.i_mode) - && !e2fsck_pass1_check_device_inode(fs, &inode)) - problem = PR_2_BAD_FIFO; - else if (LINUX_S_ISSOCK(inode.i_mode) - && !e2fsck_pass1_check_device_inode(fs, &inode)) - problem = PR_2_BAD_SOCKET; - else if (LINUX_S_ISLNK(inode.i_mode) - && !e2fsck_pass1_check_symlink(fs, &inode, buf)) { - problem = PR_2_INVALID_SYMLINK; - } - - if (problem) { - if (fix_problem(ctx, problem, &pctx)) { - deallocate_inode(ctx, ino, 0); - if (ctx->flags & E2F_FLAG_SIGNAL_MASK) - return 0; - return 1; - } else - not_fixed++; - problem = 0; - } - - if (inode.i_faddr) { - if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) { - inode.i_faddr = 0; - inode_modified++; - } else - not_fixed++; - } - - switch (fs->super->s_creator_os) { - case EXT2_OS_LINUX: - frag = &inode.osd2.linux2.l_i_frag; - fsize = &inode.osd2.linux2.l_i_fsize; - break; - case EXT2_OS_HURD: - frag = &inode.osd2.hurd2.h_i_frag; - fsize = &inode.osd2.hurd2.h_i_fsize; - break; - case EXT2_OS_MASIX: - frag = &inode.osd2.masix2.m_i_frag; - fsize = &inode.osd2.masix2.m_i_fsize; - break; - default: - frag = fsize = 0; - } - if (frag && *frag) { - pctx.num = *frag; - if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) { - *frag = 0; - inode_modified++; - } else - not_fixed++; - pctx.num = 0; - } - if (fsize && *fsize) { - pctx.num = *fsize; - if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) { - *fsize = 0; - inode_modified++; - } else - not_fixed++; - pctx.num = 0; - } - - if (inode.i_file_acl && - ((inode.i_file_acl < fs->super->s_first_data_block) || - (inode.i_file_acl >= fs->super->s_blocks_count))) { - if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) { - inode.i_file_acl = 0; - inode_modified++; - } else - not_fixed++; - } - if (inode.i_dir_acl && - LINUX_S_ISDIR(inode.i_mode)) { - if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) { - inode.i_dir_acl = 0; - inode_modified++; - } else - not_fixed++; - } - - if (inode_modified) - e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode"); - if (!not_fixed) - ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino); - return 0; -} - - -/* - * allocate_dir_block --- this function allocates a new directory - * block for a particular inode; this is done if a directory has - * a "hole" in it, or if a directory has a illegal block number - * that was zeroed out and now needs to be replaced. - */ -static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db, - struct problem_context *pctx) -{ - ext2_filsys fs = ctx->fs; - blk_t blk; - char *block; - struct ext2_inode inode; - - if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0) - return 1; - - /* - * Read the inode and block bitmaps in; we'll be messing with - * them. - */ - e2fsck_read_bitmaps(ctx); - - /* - * First, find a free block - */ - pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk); - if (pctx->errcode) { - pctx->str = "ext2fs_new_block"; - fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); - return 1; - } - ext2fs_mark_block_bitmap(ctx->block_found_map, blk); - ext2fs_mark_block_bitmap(fs->block_map, blk); - ext2fs_mark_bb_dirty(fs); - - /* - * Now let's create the actual data block for the inode - */ - if (db->blockcnt) - pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block); - else - pctx->errcode = ext2fs_new_dir_block(fs, db->ino, - EXT2_ROOT_INO, &block); - - if (pctx->errcode) { - pctx->str = "ext2fs_new_dir_block"; - fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); - return 1; - } - - pctx->errcode = ext2fs_write_dir_block(fs, blk, block); - ext2fs_free_mem(&block); - if (pctx->errcode) { - pctx->str = "ext2fs_write_dir_block"; - fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); - return 1; - } - - /* - * Update the inode block count - */ - e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block"); - inode.i_blocks += fs->blocksize / 512; - if (inode.i_size < (db->blockcnt+1) * fs->blocksize) - inode.i_size = (db->blockcnt+1) * fs->blocksize; - e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block"); - - /* - * Finally, update the block pointers for the inode - */ - db->blk = blk; - pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE, - 0, update_dir_block, db); - if (pctx->errcode) { - pctx->str = "ext2fs_block_iterate"; - fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); - return 1; - } - - return 0; -} - -/* - * This is a helper function for allocate_dir_block(). - */ -static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)), - blk_t *block_nr, - e2_blkcnt_t blockcnt, - blk_t ref_block FSCK_ATTR((unused)), - int ref_offset FSCK_ATTR((unused)), - void *priv_data) -{ - struct ext2_db_entry *db; - - db = (struct ext2_db_entry *) priv_data; - if (db->blockcnt == (int) blockcnt) { - *block_nr = db->blk; - return BLOCK_CHANGED; - } - return 0; -} - -/* - * pass3.c -- pass #3 of e2fsck: Check for directory connectivity - * - * Pass #3 assures that all directories are connected to the - * filesystem tree, using the following algorithm: - * - * First, the root directory is checked to make sure it exists; if - * not, e2fsck will offer to create a new one. It is then marked as - * "done". - * - * Then, pass3 interates over all directory inodes; for each directory - * it attempts to trace up the filesystem tree, using dirinfo.parent - * until it reaches a directory which has been marked "done". If it - * cannot do so, then the directory must be disconnected, and e2fsck - * will offer to reconnect it to /lost+found. While it is chasing - * parent pointers up the filesystem tree, if pass3 sees a directory - * twice, then it has detected a filesystem loop, and it will again - * offer to reconnect the directory to /lost+found in to break the - * filesystem loop. - * - * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to - * reconnect inodes to /lost+found; this subroutine is also used by - * pass 4. e2fsck_reconnect_file() calls get_lost_and_found(), which - * is responsible for creating /lost+found if it does not exist. - * - * Pass 3 frees the following data structures: - * - The dirinfo directory information cache. - */ - -static void check_root(e2fsck_t ctx); -static int check_directory(e2fsck_t ctx, struct dir_info *dir, - struct problem_context *pctx); -static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent); - -static ext2fs_inode_bitmap inode_loop_detect; -static ext2fs_inode_bitmap inode_done_map; - -static void e2fsck_pass3(e2fsck_t ctx) -{ - ext2_filsys fs = ctx->fs; - int i; - struct problem_context pctx; - struct dir_info *dir; - unsigned long maxdirs, count; - - clear_problem_context(&pctx); - - /* Pass 3 */ - - if (!(ctx->options & E2F_OPT_PREEN)) - fix_problem(ctx, PR_3_PASS_HEADER, &pctx); - - /* - * Allocate some bitmaps to do loop detection. - */ - pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"), - &inode_done_map); - if (pctx.errcode) { - pctx.num = 2; - fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - goto abort_exit; - } - check_root(ctx); - if (ctx->flags & E2F_FLAG_SIGNAL_MASK) - goto abort_exit; - - ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO); - - maxdirs = e2fsck_get_num_dirinfo(ctx); - count = 1; - - if (ctx->progress) - if ((ctx->progress)(ctx, 3, 0, maxdirs)) - goto abort_exit; - - for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) { - if (ctx->flags & E2F_FLAG_SIGNAL_MASK) - goto abort_exit; - if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs)) - goto abort_exit; - if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino)) - if (check_directory(ctx, dir, &pctx)) - goto abort_exit; - } - - /* - * Force the creation of /lost+found if not present - */ - if ((ctx->flags & E2F_OPT_READONLY) == 0) - e2fsck_get_lost_and_found(ctx, 1); - - /* - * If there are any directories that need to be indexed or - * optimized, do it here. - */ - e2fsck_rehash_directories(ctx); - -abort_exit: - e2fsck_free_dir_info(ctx); - ext2fs_free_inode_bitmap(inode_loop_detect); - inode_loop_detect = 0; - ext2fs_free_inode_bitmap(inode_done_map); - inode_done_map = 0; -} - -/* - * This makes sure the root inode is present; if not, we ask if the - * user wants us to create it. Not creating it is a fatal error. - */ -static void check_root(e2fsck_t ctx) -{ - ext2_filsys fs = ctx->fs; - blk_t blk; - struct ext2_inode inode; - char * block; - struct problem_context pctx; - - clear_problem_context(&pctx); - - if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) { - /* - * If the root inode is not a directory, die here. The - * user must have answered 'no' in pass1 when we - * offered to clear it. - */ - if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map, - EXT2_ROOT_INO))) { - fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - } - return; - } - - if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) { - fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - - e2fsck_read_bitmaps(ctx); - - /* - * First, find a free block - */ - pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk); - if (pctx.errcode) { - pctx.str = "ext2fs_new_block"; - fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - ext2fs_mark_block_bitmap(ctx->block_found_map, blk); - ext2fs_mark_block_bitmap(fs->block_map, blk); - ext2fs_mark_bb_dirty(fs); - - /* - * Now let's create the actual data block for the inode - */ - pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, - &block); - if (pctx.errcode) { - pctx.str = "ext2fs_new_dir_block"; - fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - - pctx.errcode = ext2fs_write_dir_block(fs, blk, block); - if (pctx.errcode) { - pctx.str = "ext2fs_write_dir_block"; - fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - ext2fs_free_mem(&block); - - /* - * Set up the inode structure - */ - memset(&inode, 0, sizeof(inode)); - inode.i_mode = 040755; - inode.i_size = fs->blocksize; - inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL); - inode.i_links_count = 2; - inode.i_blocks = fs->blocksize / 512; - inode.i_block[0] = blk; - - /* - * Write out the inode. - */ - pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode); - if (pctx.errcode) { - pctx.str = "ext2fs_write_inode"; - fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - - /* - * Miscellaneous bookkeeping... - */ - e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO); - ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2); - ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2); - - ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO); - ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO); - ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO); - ext2fs_mark_ib_dirty(fs); -} - -/* - * This subroutine is responsible for making sure that a particular - * directory is connected to the root; if it isn't we trace it up as - * far as we can go, and then offer to connect the resulting parent to - * the lost+found. We have to do loop detection; if we ever discover - * a loop, we treat that as a disconnected directory and offer to - * reparent it to lost+found. - * - * However, loop detection is expensive, because for very large - * filesystems, the inode_loop_detect bitmap is huge, and clearing it - * is non-trivial. Loops in filesystems are also a rare error case, - * and we shouldn't optimize for error cases. So we try two passes of - * the algorithm. The first time, we ignore loop detection and merely - * increment a counter; if the counter exceeds some extreme threshold, - * then we try again with the loop detection bitmap enabled. - */ -static int check_directory(e2fsck_t ctx, struct dir_info *dir, - struct problem_context *pctx) -{ - ext2_filsys fs = ctx->fs; - struct dir_info *p = dir; - int loop_pass = 0, parent_count = 0; - - if (!p) - return 0; - - while (1) { - /* - * Mark this inode as being "done"; by the time we - * return from this function, the inode we either be - * verified as being connected to the directory tree, - * or we will have offered to reconnect this to - * lost+found. - * - * If it was marked done already, then we've reached a - * parent we've already checked. - */ - if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino)) - break; - - /* - * If this directory doesn't have a parent, or we've - * seen the parent once already, then offer to - * reparent it to lost+found - */ - if (!p->parent || - (loop_pass && - (ext2fs_test_inode_bitmap(inode_loop_detect, - p->parent)))) { - pctx->ino = p->ino; - if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) { - if (e2fsck_reconnect_file(ctx, pctx->ino)) - ext2fs_unmark_valid(fs); - else { - p = e2fsck_get_dir_info(ctx, pctx->ino); - p->parent = ctx->lost_and_found; - fix_dotdot(ctx, p, ctx->lost_and_found); - } - } - break; - } - p = e2fsck_get_dir_info(ctx, p->parent); - if (!p) { - fix_problem(ctx, PR_3_NO_DIRINFO, pctx); - return 0; - } - if (loop_pass) { - ext2fs_mark_inode_bitmap(inode_loop_detect, - p->ino); - } else if (parent_count++ > 2048) { - /* - * If we've run into a path depth that's - * greater than 2048, try again with the inode - * loop bitmap turned on and start from the - * top. - */ - loop_pass = 1; - if (inode_loop_detect) - ext2fs_clear_inode_bitmap(inode_loop_detect); - else { - pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect); - if (pctx->errcode) { - pctx->num = 1; - fix_problem(ctx, - PR_3_ALLOCATE_IBITMAP_ERROR, pctx); - ctx->flags |= E2F_FLAG_ABORT; - return -1; - } - } - p = dir; - } - } - - /* - * Make sure that .. and the parent directory are the same; - * offer to fix it if not. - */ - if (dir->parent != dir->dotdot) { - pctx->ino = dir->ino; - pctx->ino2 = dir->dotdot; - pctx->dir = dir->parent; - if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx)) - fix_dotdot(ctx, dir, dir->parent); - } - return 0; -} - -/* - * This routine gets the lost_and_found inode, making it a directory - * if necessary - */ -ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix) -{ - ext2_filsys fs = ctx->fs; - ext2_ino_t ino; - blk_t blk; - errcode_t retval; - struct ext2_inode inode; - char * block; - static const char name[] = "lost+found"; - struct problem_context pctx; - struct dir_info *dirinfo; - - if (ctx->lost_and_found) - return ctx->lost_and_found; - - clear_problem_context(&pctx); - - retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name, - sizeof(name)-1, 0, &ino); - if (retval && !fix) - return 0; - if (!retval) { - if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) { - ctx->lost_and_found = ino; - return ino; - } - - /* Lost+found isn't a directory! */ - if (!fix) - return 0; - pctx.ino = ino; - if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx)) - return 0; - - /* OK, unlink the old /lost+found file. */ - pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0); - if (pctx.errcode) { - pctx.str = "ext2fs_unlink"; - fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx); - return 0; - } - dirinfo = e2fsck_get_dir_info(ctx, ino); - if (dirinfo) - dirinfo->parent = 0; - e2fsck_adjust_inode_count(ctx, ino, -1); - } else if (retval != EXT2_ET_FILE_NOT_FOUND) { - pctx.errcode = retval; - fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx); - } - if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0)) - return 0; - - /* - * Read the inode and block bitmaps in; we'll be messing with - * them. - */ - e2fsck_read_bitmaps(ctx); - - /* - * First, find a free block - */ - retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk); - if (retval) { - pctx.errcode = retval; - fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx); - return 0; - } - ext2fs_mark_block_bitmap(ctx->block_found_map, blk); - ext2fs_block_alloc_stats(fs, blk, +1); - - /* - * Next find a free inode. - */ - retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700, - ctx->inode_used_map, &ino); - if (retval) { - pctx.errcode = retval; - fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx); - return 0; - } - ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino); - ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino); - ext2fs_inode_alloc_stats2(fs, ino, +1, 1); - - /* - * Now let's create the actual data block for the inode - */ - retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block); - if (retval) { - pctx.errcode = retval; - fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx); - return 0; - } - - retval = ext2fs_write_dir_block(fs, blk, block); - ext2fs_free_mem(&block); - if (retval) { - pctx.errcode = retval; - fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx); - return 0; - } - - /* - * Set up the inode structure - */ - memset(&inode, 0, sizeof(inode)); - inode.i_mode = 040700; - inode.i_size = fs->blocksize; - inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL); - inode.i_links_count = 2; - inode.i_blocks = fs->blocksize / 512; - inode.i_block[0] = blk; - - /* - * Next, write out the inode. - */ - pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode); - if (pctx.errcode) { - pctx.str = "ext2fs_write_inode"; - fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx); - return 0; - } - /* - * Finally, create the directory link - */ - pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR); - if (pctx.errcode) { - pctx.str = "ext2fs_link"; - fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx); - return 0; - } - - /* - * Miscellaneous bookkeeping that needs to be kept straight. - */ - e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO); - e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1); - ext2fs_icount_store(ctx->inode_count, ino, 2); - ext2fs_icount_store(ctx->inode_link_info, ino, 2); - ctx->lost_and_found = ino; - return ino; -} - -/* - * This routine will connect a file to lost+found - */ -int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino) -{ - ext2_filsys fs = ctx->fs; - errcode_t retval; - char name[80]; - struct problem_context pctx; - struct ext2_inode inode; - int file_type = 0; - - clear_problem_context(&pctx); - pctx.ino = ino; - - if (!ctx->bad_lost_and_found && !ctx->lost_and_found) { - if (e2fsck_get_lost_and_found(ctx, 1) == 0) - ctx->bad_lost_and_found++; - } - if (ctx->bad_lost_and_found) { - fix_problem(ctx, PR_3_NO_LPF, &pctx); - return 1; - } - - sprintf(name, "#%u", ino); - if (ext2fs_read_inode(fs, ino, &inode) == 0) - file_type = ext2_file_type(inode.i_mode); - retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type); - if (retval == EXT2_ET_DIR_NO_SPACE) { - if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx)) - return 1; - retval = e2fsck_expand_directory(ctx, ctx->lost_and_found, - 1, 0); - if (retval) { - pctx.errcode = retval; - fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx); - return 1; - } - retval = ext2fs_link(fs, ctx->lost_and_found, name, - ino, file_type); - } - if (retval) { - pctx.errcode = retval; - fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx); - return 1; - } - e2fsck_adjust_inode_count(ctx, ino, 1); - - return 0; -} - -/* - * Utility routine to adjust the inode counts on an inode. - */ -errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj) -{ - ext2_filsys fs = ctx->fs; - errcode_t retval; - struct ext2_inode inode; - - if (!ino) - return 0; - - retval = ext2fs_read_inode(fs, ino, &inode); - if (retval) - return retval; - - if (adj == 1) { - ext2fs_icount_increment(ctx->inode_count, ino, 0); - if (inode.i_links_count == (__u16) ~0) - return 0; - ext2fs_icount_increment(ctx->inode_link_info, ino, 0); - inode.i_links_count++; - } else if (adj == -1) { - ext2fs_icount_decrement(ctx->inode_count, ino, 0); - if (inode.i_links_count == 0) - return 0; - ext2fs_icount_decrement(ctx->inode_link_info, ino, 0); - inode.i_links_count--; - } - - retval = ext2fs_write_inode(fs, ino, &inode); - if (retval) - return retval; - - return 0; -} - -/* - * Fix parent --- this routine fixes up the parent of a directory. - */ -struct fix_dotdot_struct { - ext2_filsys fs; - ext2_ino_t parent; - int done; - e2fsck_t ctx; -}; - -static int fix_dotdot_proc(struct ext2_dir_entry *dirent, - int offset FSCK_ATTR((unused)), - int blocksize FSCK_ATTR((unused)), - char *buf FSCK_ATTR((unused)), - void *priv_data) -{ - struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data; - errcode_t retval; - struct problem_context pctx; - - if ((dirent->name_len & 0xFF) != 2) - return 0; - if (strncmp(dirent->name, "..", 2)) - return 0; - - clear_problem_context(&pctx); - - retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1); - if (retval) { - pctx.errcode = retval; - fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx); - } - retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1); - if (retval) { - pctx.errcode = retval; - fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx); - } - dirent->inode = fp->parent; - - fp->done++; - return DIRENT_ABORT | DIRENT_CHANGED; -} - -static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent) -{ - ext2_filsys fs = ctx->fs; - errcode_t retval; - struct fix_dotdot_struct fp; - struct problem_context pctx; - - fp.fs = fs; - fp.parent = parent; - fp.done = 0; - fp.ctx = ctx; - - retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY, - 0, fix_dotdot_proc, &fp); - if (retval || !fp.done) { - clear_problem_context(&pctx); - pctx.ino = dir->ino; - pctx.errcode = retval; - fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR : - PR_3_FIX_PARENT_NOFIND, &pctx); - ext2fs_unmark_valid(fs); - } - dir->dotdot = parent; -} - -/* - * These routines are responsible for expanding a /lost+found if it is - * too small. - */ - -struct expand_dir_struct { - int num; - int guaranteed_size; - int newblocks; - int last_block; - errcode_t err; - e2fsck_t ctx; -}; - -static int expand_dir_proc(ext2_filsys fs, - blk_t *blocknr, - e2_blkcnt_t blockcnt, - blk_t ref_block FSCK_ATTR((unused)), - int ref_offset FSCK_ATTR((unused)), - void *priv_data) -{ - struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data; - blk_t new_blk; - static blk_t last_blk = 0; - char *block; - errcode_t retval; - e2fsck_t ctx; - - ctx = es->ctx; - - if (es->guaranteed_size && blockcnt >= es->guaranteed_size) - return BLOCK_ABORT; - - if (blockcnt > 0) - es->last_block = blockcnt; - if (*blocknr) { - last_blk = *blocknr; - return 0; - } - retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map, - &new_blk); - if (retval) { - es->err = retval; - return BLOCK_ABORT; - } - if (blockcnt > 0) { - retval = ext2fs_new_dir_block(fs, 0, 0, &block); - if (retval) { - es->err = retval; - return BLOCK_ABORT; - } - es->num--; - retval = ext2fs_write_dir_block(fs, new_blk, block); - } else { - retval = ext2fs_get_mem(fs->blocksize, &block); - if (retval) { - es->err = retval; - return BLOCK_ABORT; - } - memset(block, 0, fs->blocksize); - retval = io_channel_write_blk(fs->io, new_blk, 1, block); - } - if (retval) { - es->err = retval; - return BLOCK_ABORT; - } - ext2fs_free_mem(&block); - *blocknr = new_blk; - ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk); - ext2fs_block_alloc_stats(fs, new_blk, +1); - es->newblocks++; - - if (es->num == 0) - return (BLOCK_CHANGED | BLOCK_ABORT); - else - return BLOCK_CHANGED; -} - -errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir, - int num, int guaranteed_size) -{ - ext2_filsys fs = ctx->fs; - errcode_t retval; - struct expand_dir_struct es; - struct ext2_inode inode; - - if (!(fs->flags & EXT2_FLAG_RW)) - return EXT2_ET_RO_FILSYS; - - /* - * Read the inode and block bitmaps in; we'll be messing with - * them. - */ - e2fsck_read_bitmaps(ctx); - - retval = ext2fs_check_directory(fs, dir); - if (retval) - return retval; - - es.num = num; - es.guaranteed_size = guaranteed_size; - es.last_block = 0; - es.err = 0; - es.newblocks = 0; - es.ctx = ctx; - - retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND, - 0, expand_dir_proc, &es); - - if (es.err) - return es.err; - - /* - * Update the size and block count fields in the inode. - */ - retval = ext2fs_read_inode(fs, dir, &inode); - if (retval) - return retval; - - inode.i_size = (es.last_block + 1) * fs->blocksize; - inode.i_blocks += (fs->blocksize / 512) * es.newblocks; - - e2fsck_write_inode(ctx, dir, &inode, "expand_directory"); - - return 0; -} - -/* - * pass4.c -- pass #4 of e2fsck: Check reference counts - * - * Pass 4 frees the following data structures: - * - A bitmap of which inodes are imagic inodes. (inode_imagic_map) - */ - -/* - * This routine is called when an inode is not connected to the - * directory tree. - * - * This subroutine returns 1 then the caller shouldn't bother with the - * rest of the pass 4 tests. - */ -static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i) -{ - ext2_filsys fs = ctx->fs; - struct ext2_inode inode; - struct problem_context pctx; - - e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode"); - clear_problem_context(&pctx); - pctx.ino = i; - pctx.inode = &inode; - - /* - * Offer to delete any zero-length files that does not have - * blocks. If there is an EA block, it might have useful - * information, so we won't prompt to delete it, but let it be - * reconnected to lost+found. - */ - if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) || - LINUX_S_ISDIR(inode.i_mode))) { - if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) { - ext2fs_icount_store(ctx->inode_link_info, i, 0); - inode.i_links_count = 0; - inode.i_dtime = time(NULL); - e2fsck_write_inode(ctx, i, &inode, - "disconnect_inode"); - /* - * Fix up the bitmaps... - */ - e2fsck_read_bitmaps(ctx); - ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i); - ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i); - ext2fs_inode_alloc_stats2(fs, i, -1, - LINUX_S_ISDIR(inode.i_mode)); - return 0; - } - } - - /* - * Prompt to reconnect. - */ - if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) { - if (e2fsck_reconnect_file(ctx, i)) - ext2fs_unmark_valid(fs); - } else { - /* - * If we don't attach the inode, then skip the - * i_links_test since there's no point in trying to - * force i_links_count to zero. - */ - ext2fs_unmark_valid(fs); - return 1; - } - return 0; -} - - -static void e2fsck_pass4(e2fsck_t ctx) -{ - ext2_filsys fs = ctx->fs; - ext2_ino_t i; - struct ext2_inode inode; - struct problem_context pctx; - __u16 link_count, link_counted; - char *buf = NULL; - int group, maxgroup; - - /* Pass 4 */ - - clear_problem_context(&pctx); - - if (!(ctx->options & E2F_OPT_PREEN)) - fix_problem(ctx, PR_4_PASS_HEADER, &pctx); - - group = 0; - maxgroup = fs->group_desc_count; - if (ctx->progress) - if ((ctx->progress)(ctx, 4, 0, maxgroup)) - return; - - for (i=1; i <= fs->super->s_inodes_count; i++) { - if (ctx->flags & E2F_FLAG_SIGNAL_MASK) - return; - if ((i % fs->super->s_inodes_per_group) == 0) { - group++; - if (ctx->progress) - if ((ctx->progress)(ctx, 4, group, maxgroup)) - return; - } - if (i == EXT2_BAD_INO || - (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super))) - continue; - if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) || - (ctx->inode_imagic_map && - ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i))) - continue; - ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count); - ext2fs_icount_fetch(ctx->inode_count, i, &link_counted); - if (link_counted == 0) { - if (!buf) - buf = e2fsck_allocate_memory(ctx, - fs->blocksize, "bad_inode buffer"); - if (e2fsck_process_bad_inode(ctx, 0, i, buf)) - continue; - if (disconnect_inode(ctx, i)) - continue; - ext2fs_icount_fetch(ctx->inode_link_info, i, - &link_count); - ext2fs_icount_fetch(ctx->inode_count, i, - &link_counted); - } - if (link_counted != link_count) { - e2fsck_read_inode(ctx, i, &inode, "pass4"); - pctx.ino = i; - pctx.inode = &inode; - if (link_count != inode.i_links_count) { - pctx.num = link_count; - fix_problem(ctx, - PR_4_INCONSISTENT_COUNT, &pctx); - } - pctx.num = link_counted; - if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) { - inode.i_links_count = link_counted; - e2fsck_write_inode(ctx, i, &inode, "pass4"); - } - } - } - ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0; - ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0; - ext2fs_free_inode_bitmap(ctx->inode_imagic_map); - ctx->inode_imagic_map = 0; - ext2fs_free_mem(&buf); -} - -/* - * pass5.c --- check block and inode bitmaps against on-disk bitmaps - */ - -#define NO_BLK ((blk_t) -1) - -static void print_bitmap_problem(e2fsck_t ctx, int problem, - struct problem_context *pctx) -{ - switch (problem) { - case PR_5_BLOCK_UNUSED: - if (pctx->blk == pctx->blk2) - pctx->blk2 = 0; - else - problem = PR_5_BLOCK_RANGE_UNUSED; - break; - case PR_5_BLOCK_USED: - if (pctx->blk == pctx->blk2) - pctx->blk2 = 0; - else - problem = PR_5_BLOCK_RANGE_USED; - break; - case PR_5_INODE_UNUSED: - if (pctx->ino == pctx->ino2) - pctx->ino2 = 0; - else - problem = PR_5_INODE_RANGE_UNUSED; - break; - case PR_5_INODE_USED: - if (pctx->ino == pctx->ino2) - pctx->ino2 = 0; - else - problem = PR_5_INODE_RANGE_USED; - break; - } - fix_problem(ctx, problem, pctx); - pctx->blk = pctx->blk2 = NO_BLK; - pctx->ino = pctx->ino2 = 0; -} - -static void check_block_bitmaps(e2fsck_t ctx) -{ - ext2_filsys fs = ctx->fs; - blk_t i; - int *free_array; - int group = 0; - unsigned int blocks = 0; - unsigned int free_blocks = 0; - int group_free = 0; - int actual, bitmap; - struct problem_context pctx; - int problem, save_problem, fixit, had_problem; - errcode_t retval; - - clear_problem_context(&pctx); - free_array = (int *) e2fsck_allocate_memory(ctx, - fs->group_desc_count * sizeof(int), "free block count array"); - - if ((fs->super->s_first_data_block < - ext2fs_get_block_bitmap_start(ctx->block_found_map)) || - (fs->super->s_blocks_count-1 > - ext2fs_get_block_bitmap_end(ctx->block_found_map))) { - pctx.num = 1; - pctx.blk = fs->super->s_first_data_block; - pctx.blk2 = fs->super->s_blocks_count -1; - pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map); - pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map); - fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx); - - ctx->flags |= E2F_FLAG_ABORT; /* fatal */ - return; - } - - if ((fs->super->s_first_data_block < - ext2fs_get_block_bitmap_start(fs->block_map)) || - (fs->super->s_blocks_count-1 > - ext2fs_get_block_bitmap_end(fs->block_map))) { - pctx.num = 2; - pctx.blk = fs->super->s_first_data_block; - pctx.blk2 = fs->super->s_blocks_count -1; - pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map); - pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map); - fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx); - - ctx->flags |= E2F_FLAG_ABORT; /* fatal */ - return; - } - -redo_counts: - had_problem = 0; - save_problem = 0; - pctx.blk = pctx.blk2 = NO_BLK; - for (i = fs->super->s_first_data_block; - i < fs->super->s_blocks_count; - i++) { - actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i); - bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i); - - if (actual == bitmap) - goto do_counts; - - if (!actual && bitmap) { - /* - * Block not used, but marked in use in the bitmap. - */ - problem = PR_5_BLOCK_UNUSED; - } else { - /* - * Block used, but not marked in use in the bitmap. - */ - problem = PR_5_BLOCK_USED; - } - if (pctx.blk == NO_BLK) { - pctx.blk = pctx.blk2 = i; - save_problem = problem; - } else { - if ((problem == save_problem) && - (pctx.blk2 == i-1)) - pctx.blk2++; - else { - print_bitmap_problem(ctx, save_problem, &pctx); - pctx.blk = pctx.blk2 = i; - save_problem = problem; - } - } - ctx->flags |= E2F_FLAG_PROG_SUPPRESS; - had_problem++; - - do_counts: - if (!bitmap) { - group_free++; - free_blocks++; - } - blocks ++; - if ((blocks == fs->super->s_blocks_per_group) || - (i == fs->super->s_blocks_count-1)) { - free_array[group] = group_free; - group ++; - blocks = 0; - group_free = 0; - if (ctx->progress) - if ((ctx->progress)(ctx, 5, group, - fs->group_desc_count*2)) - return; - } - } - if (pctx.blk != NO_BLK) - print_bitmap_problem(ctx, save_problem, &pctx); - if (had_problem) - fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP); - else - fixit = -1; - ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS; - - if (fixit == 1) { - ext2fs_free_block_bitmap(fs->block_map); - retval = ext2fs_copy_bitmap(ctx->block_found_map, - &fs->block_map); - if (retval) { - clear_problem_context(&pctx); - fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - ext2fs_set_bitmap_padding(fs->block_map); - ext2fs_mark_bb_dirty(fs); - - /* Redo the counts */ - blocks = 0; free_blocks = 0; group_free = 0; group = 0; - memset(free_array, 0, fs->group_desc_count * sizeof(int)); - goto redo_counts; - } else if (fixit == 0) - ext2fs_unmark_valid(fs); - - for (i = 0; i < fs->group_desc_count; i++) { - if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) { - pctx.group = i; - pctx.blk = fs->group_desc[i].bg_free_blocks_count; - pctx.blk2 = free_array[i]; - - if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP, - &pctx)) { - fs->group_desc[i].bg_free_blocks_count = - free_array[i]; - ext2fs_mark_super_dirty(fs); - } else - ext2fs_unmark_valid(fs); - } - } - if (free_blocks != fs->super->s_free_blocks_count) { - pctx.group = 0; - pctx.blk = fs->super->s_free_blocks_count; - pctx.blk2 = free_blocks; - - if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) { - fs->super->s_free_blocks_count = free_blocks; - ext2fs_mark_super_dirty(fs); - } else - ext2fs_unmark_valid(fs); - } - ext2fs_free_mem(&free_array); -} - -static void check_inode_bitmaps(e2fsck_t ctx) -{ - ext2_filsys fs = ctx->fs; - ext2_ino_t i; - unsigned int free_inodes = 0; - int group_free = 0; - int dirs_count = 0; - int group = 0; - unsigned int inodes = 0; - int *free_array; - int *dir_array; - int actual, bitmap; - errcode_t retval; - struct problem_context pctx; - int problem, save_problem, fixit, had_problem; - - clear_problem_context(&pctx); - free_array = (int *) e2fsck_allocate_memory(ctx, - fs->group_desc_count * sizeof(int), "free inode count array"); - - dir_array = (int *) e2fsck_allocate_memory(ctx, - fs->group_desc_count * sizeof(int), "directory count array"); - - if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) || - (fs->super->s_inodes_count > - ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) { - pctx.num = 3; - pctx.blk = 1; - pctx.blk2 = fs->super->s_inodes_count; - pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map); - pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map); - fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx); - - ctx->flags |= E2F_FLAG_ABORT; /* fatal */ - return; - } - if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) || - (fs->super->s_inodes_count > - ext2fs_get_inode_bitmap_end(fs->inode_map))) { - pctx.num = 4; - pctx.blk = 1; - pctx.blk2 = fs->super->s_inodes_count; - pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map); - pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map); - fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx); - - ctx->flags |= E2F_FLAG_ABORT; /* fatal */ - return; - } - -redo_counts: - had_problem = 0; - save_problem = 0; - pctx.ino = pctx.ino2 = 0; - for (i = 1; i <= fs->super->s_inodes_count; i++) { - actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i); - bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i); - - if (actual == bitmap) - goto do_counts; - - if (!actual && bitmap) { - /* - * Inode wasn't used, but marked in bitmap - */ - problem = PR_5_INODE_UNUSED; - } else /* if (actual && !bitmap) */ { - /* - * Inode used, but not in bitmap - */ - problem = PR_5_INODE_USED; - } - if (pctx.ino == 0) { - pctx.ino = pctx.ino2 = i; - save_problem = problem; - } else { - if ((problem == save_problem) && - (pctx.ino2 == i-1)) - pctx.ino2++; - else { - print_bitmap_problem(ctx, save_problem, &pctx); - pctx.ino = pctx.ino2 = i; - save_problem = problem; - } - } - ctx->flags |= E2F_FLAG_PROG_SUPPRESS; - had_problem++; - -do_counts: - if (!bitmap) { - group_free++; - free_inodes++; - } else { - if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i)) - dirs_count++; - } - inodes++; - if ((inodes == fs->super->s_inodes_per_group) || - (i == fs->super->s_inodes_count)) { - free_array[group] = group_free; - dir_array[group] = dirs_count; - group ++; - inodes = 0; - group_free = 0; - dirs_count = 0; - if (ctx->progress) - if ((ctx->progress)(ctx, 5, - group + fs->group_desc_count, - fs->group_desc_count*2)) - return; - } - } - if (pctx.ino) - print_bitmap_problem(ctx, save_problem, &pctx); - - if (had_problem) - fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP); - else - fixit = -1; - ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS; - - if (fixit == 1) { - ext2fs_free_inode_bitmap(fs->inode_map); - retval = ext2fs_copy_bitmap(ctx->inode_used_map, - &fs->inode_map); - if (retval) { - clear_problem_context(&pctx); - fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - ext2fs_set_bitmap_padding(fs->inode_map); - ext2fs_mark_ib_dirty(fs); - - /* redo counts */ - inodes = 0; free_inodes = 0; group_free = 0; - dirs_count = 0; group = 0; - memset(free_array, 0, fs->group_desc_count * sizeof(int)); - memset(dir_array, 0, fs->group_desc_count * sizeof(int)); - goto redo_counts; - } else if (fixit == 0) - ext2fs_unmark_valid(fs); - - for (i = 0; i < fs->group_desc_count; i++) { - if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) { - pctx.group = i; - pctx.ino = fs->group_desc[i].bg_free_inodes_count; - pctx.ino2 = free_array[i]; - if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP, - &pctx)) { - fs->group_desc[i].bg_free_inodes_count = - free_array[i]; - ext2fs_mark_super_dirty(fs); - } else - ext2fs_unmark_valid(fs); - } - if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) { - pctx.group = i; - pctx.ino = fs->group_desc[i].bg_used_dirs_count; - pctx.ino2 = dir_array[i]; - - if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP, - &pctx)) { - fs->group_desc[i].bg_used_dirs_count = - dir_array[i]; - ext2fs_mark_super_dirty(fs); - } else - ext2fs_unmark_valid(fs); - } - } - if (free_inodes != fs->super->s_free_inodes_count) { - pctx.group = -1; - pctx.ino = fs->super->s_free_inodes_count; - pctx.ino2 = free_inodes; - - if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) { - fs->super->s_free_inodes_count = free_inodes; - ext2fs_mark_super_dirty(fs); - } else - ext2fs_unmark_valid(fs); - } - ext2fs_free_mem(&free_array); - ext2fs_free_mem(&dir_array); -} - -static void check_inode_end(e2fsck_t ctx) -{ - ext2_filsys fs = ctx->fs; - ext2_ino_t end, save_inodes_count, i; - struct problem_context pctx; - - clear_problem_context(&pctx); - - end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count; - pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end, - &save_inodes_count); - if (pctx.errcode) { - pctx.num = 1; - fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx); - ctx->flags |= E2F_FLAG_ABORT; /* fatal */ - return; - } - if (save_inodes_count == end) - return; - - for (i = save_inodes_count + 1; i <= end; i++) { - if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) { - if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) { - for (i = save_inodes_count + 1; i <= end; i++) - ext2fs_mark_inode_bitmap(fs->inode_map, - i); - ext2fs_mark_ib_dirty(fs); - } else - ext2fs_unmark_valid(fs); - break; - } - } - - pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, - save_inodes_count, 0); - if (pctx.errcode) { - pctx.num = 2; - fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx); - ctx->flags |= E2F_FLAG_ABORT; /* fatal */ - return; - } -} - -static void check_block_end(e2fsck_t ctx) -{ - ext2_filsys fs = ctx->fs; - blk_t end, save_blocks_count, i; - struct problem_context pctx; - - clear_problem_context(&pctx); - - end = fs->block_map->start + - (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1; - pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end, - &save_blocks_count); - if (pctx.errcode) { - pctx.num = 3; - fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx); - ctx->flags |= E2F_FLAG_ABORT; /* fatal */ - return; - } - if (save_blocks_count == end) - return; - - for (i = save_blocks_count + 1; i <= end; i++) { - if (!ext2fs_test_block_bitmap(fs->block_map, i)) { - if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) { - for (i = save_blocks_count + 1; i <= end; i++) - ext2fs_mark_block_bitmap(fs->block_map, - i); - ext2fs_mark_bb_dirty(fs); - } else - ext2fs_unmark_valid(fs); - break; - } - } - - pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, - save_blocks_count, 0); - if (pctx.errcode) { - pctx.num = 4; - fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx); - ctx->flags |= E2F_FLAG_ABORT; /* fatal */ - return; - } -} - -static void e2fsck_pass5(e2fsck_t ctx) -{ - struct problem_context pctx; - - /* Pass 5 */ - - clear_problem_context(&pctx); - - if (!(ctx->options & E2F_OPT_PREEN)) - fix_problem(ctx, PR_5_PASS_HEADER, &pctx); - - if (ctx->progress) - if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2)) - return; - - e2fsck_read_bitmaps(ctx); - - check_block_bitmaps(ctx); - if (ctx->flags & E2F_FLAG_SIGNAL_MASK) - return; - check_inode_bitmaps(ctx); - if (ctx->flags & E2F_FLAG_SIGNAL_MASK) - return; - check_inode_end(ctx); - if (ctx->flags & E2F_FLAG_SIGNAL_MASK) - return; - check_block_end(ctx); - if (ctx->flags & E2F_FLAG_SIGNAL_MASK) - return; - - ext2fs_free_inode_bitmap(ctx->inode_used_map); - ctx->inode_used_map = 0; - ext2fs_free_inode_bitmap(ctx->inode_dir_map); - ctx->inode_dir_map = 0; - ext2fs_free_block_bitmap(ctx->block_found_map); - ctx->block_found_map = 0; -} - -/* - * problem.c --- report filesystem problems to the user - */ - -#define PR_PREEN_OK 0x000001 /* Don't need to do preenhalt */ -#define PR_NO_OK 0x000002 /* If user answers no, don't make fs invalid */ -#define PR_NO_DEFAULT 0x000004 /* Default to no */ -#define PR_MSG_ONLY 0x000008 /* Print message only */ - -/* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */ - -#define PR_FATAL 0x001000 /* Fatal error */ -#define PR_AFTER_CODE 0x002000 /* After asking the first question, */ - /* ask another */ -#define PR_PREEN_NOMSG 0x004000 /* Don't print a message if we're preening */ -#define PR_NOCOLLATE 0x008000 /* Don't collate answers for this latch */ -#define PR_NO_NOMSG 0x010000 /* Don't print a message if e2fsck -n */ -#define PR_PREEN_NO 0x020000 /* Use No as an answer if preening */ -#define PR_PREEN_NOHDR 0x040000 /* Don't print the preen header */ - - -#define PROMPT_NONE 0 -#define PROMPT_FIX 1 -#define PROMPT_CLEAR 2 -#define PROMPT_RELOCATE 3 -#define PROMPT_ALLOCATE 4 -#define PROMPT_EXPAND 5 -#define PROMPT_CONNECT 6 -#define PROMPT_CREATE 7 -#define PROMPT_SALVAGE 8 -#define PROMPT_TRUNCATE 9 -#define PROMPT_CLEAR_INODE 10 -#define PROMPT_ABORT 11 -#define PROMPT_SPLIT 12 -#define PROMPT_CONTINUE 13 -#define PROMPT_CLONE 14 -#define PROMPT_DELETE 15 -#define PROMPT_SUPPRESS 16 -#define PROMPT_UNLINK 17 -#define PROMPT_CLEAR_HTREE 18 -#define PROMPT_RECREATE 19 -#define PROMPT_NULL 20 - -struct e2fsck_problem { - problem_t e2p_code; - const char * e2p_description; - char prompt; - int flags; - problem_t second_code; -}; - -struct latch_descr { - int latch_code; - problem_t question; - problem_t end_message; - int flags; -}; - -/* - * These are the prompts which are used to ask the user if they want - * to fix a problem. - */ -static const char *const prompt[] = { - N_("(no prompt)"), /* 0 */ - N_("Fix"), /* 1 */ - N_("Clear"), /* 2 */ - N_("Relocate"), /* 3 */ - N_("Allocate"), /* 4 */ - N_("Expand"), /* 5 */ - N_("Connect to /lost+found"), /* 6 */ - N_("Create"), /* 7 */ - N_("Salvage"), /* 8 */ - N_("Truncate"), /* 9 */ - N_("Clear inode"), /* 10 */ - N_("Abort"), /* 11 */ - N_("Split"), /* 12 */ - N_("Continue"), /* 13 */ - N_("Clone multiply-claimed blocks"), /* 14 */ - N_("Delete file"), /* 15 */ - N_("Suppress messages"),/* 16 */ - N_("Unlink"), /* 17 */ - N_("Clear HTree index"),/* 18 */ - N_("Recreate"), /* 19 */ - "", /* 20 */ -}; - -/* - * These messages are printed when we are preen mode and we will be - * automatically fixing the problem. - */ -static const char *const preen_msg[] = { - N_("(NONE)"), /* 0 */ - N_("FIXED"), /* 1 */ - N_("CLEARED"), /* 2 */ - N_("RELOCATED"), /* 3 */ - N_("ALLOCATED"), /* 4 */ - N_("EXPANDED"), /* 5 */ - N_("RECONNECTED"), /* 6 */ - N_("CREATED"), /* 7 */ - N_("SALVAGED"), /* 8 */ - N_("TRUNCATED"), /* 9 */ - N_("INODE CLEARED"), /* 10 */ - N_("ABORTED"), /* 11 */ - N_("SPLIT"), /* 12 */ - N_("CONTINUING"), /* 13 */ - N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */ - N_("FILE DELETED"), /* 15 */ - N_("SUPPRESSED"), /* 16 */ - N_("UNLINKED"), /* 17 */ - N_("HTREE INDEX CLEARED"),/* 18 */ - N_("WILL RECREATE"), /* 19 */ - "", /* 20 */ -}; - -static const struct e2fsck_problem problem_table[] = { - - /* Pre-Pass 1 errors */ - - /* Block bitmap not in group */ - { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g. (@b %b)\n"), - PROMPT_RELOCATE, PR_LATCH_RELOC }, - - /* Inode bitmap not in group */ - { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g. (@b %b)\n"), - PROMPT_RELOCATE, PR_LATCH_RELOC }, - - /* Inode table not in group */ - { PR_0_ITABLE_NOT_GROUP, - N_("@i table for @g %g is not in @g. (@b %b)\n" - "WARNING: SEVERE DATA LOSS POSSIBLE.\n"), - PROMPT_RELOCATE, PR_LATCH_RELOC }, - - /* Superblock corrupt */ - { PR_0_SB_CORRUPT, - N_("\nThe @S could not be read or does not describe a correct ext2\n" - "@f. If the @v is valid and it really contains an ext2\n" - "@f (and not swap or ufs or something else), then the @S\n" - "is corrupt, and you might try running e2fsck with an alternate @S:\n" - " e2fsck -b %S <@v>\n\n"), - PROMPT_NONE, PR_FATAL }, - - /* Filesystem size is wrong */ - { PR_0_FS_SIZE_WRONG, - N_("The @f size (according to the @S) is %b @bs\n" - "The physical size of the @v is %c @bs\n" - "Either the @S or the partition table is likely to be corrupt!\n"), - PROMPT_ABORT, 0 }, - - /* Fragments not supported */ - { PR_0_NO_FRAGMENTS, - N_("@S @b_size = %b, fragsize = %c.\n" - "This version of e2fsck does not support fragment sizes different\n" - "from the @b size.\n"), - PROMPT_NONE, PR_FATAL }, - - /* Bad blocks_per_group */ - { PR_0_BLOCKS_PER_GROUP, - N_("@S @bs_per_group = %b, should have been %c\n"), - PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT }, - - /* Bad first_data_block */ - { PR_0_FIRST_DATA_BLOCK, - N_("@S first_data_@b = %b, should have been %c\n"), - PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT }, - - /* Adding UUID to filesystem */ - { PR_0_ADD_UUID, - N_("@f did not have a UUID; generating one.\n\n"), - PROMPT_NONE, 0 }, - - /* Relocate hint */ - { PR_0_RELOCATE_HINT, - N_("Note: if several inode or block bitmap blocks or part\n" - "of the inode table require relocation, you may wish to try\n" - "running e2fsck with the '-b %S' option first. The problem\n" - "may lie only with the primary block group descriptors, and\n" - "the backup block group descriptors may be OK.\n\n"), - PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE }, - - /* Miscellaneous superblock corruption */ - { PR_0_MISC_CORRUPT_SUPER, - N_("Corruption found in @S. (%s = %N).\n"), - PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT }, - - /* Error determing physical device size of filesystem */ - { PR_0_GETSIZE_ERROR, - N_("Error determining size of the physical @v: %m\n"), - PROMPT_NONE, PR_FATAL }, - - /* Inode count in superblock is incorrect */ - { PR_0_INODE_COUNT_WRONG, - N_("@i count in @S is %i, @s %j.\n"), - PROMPT_FIX, 0 }, - - { PR_0_HURD_CLEAR_FILETYPE, - N_("The Hurd does not support the filetype feature.\n"), - PROMPT_CLEAR, 0 }, - - /* Journal inode is invalid */ - { PR_0_JOURNAL_BAD_INODE, - N_("@S has an @n ext3 @j (@i %i).\n"), - PROMPT_CLEAR, PR_PREEN_OK }, - - /* The external journal has (unsupported) multiple filesystems */ - { PR_0_JOURNAL_UNSUPP_MULTIFS, - N_("External @j has multiple @f users (unsupported).\n"), - PROMPT_NONE, PR_FATAL }, - - /* Can't find external journal */ - { PR_0_CANT_FIND_JOURNAL, - N_("Can't find external @j\n"), - PROMPT_NONE, PR_FATAL }, - - /* External journal has bad superblock */ - { PR_0_EXT_JOURNAL_BAD_SUPER, - N_("External @j has bad @S\n"), - PROMPT_NONE, PR_FATAL }, - - /* Superblock has a bad journal UUID */ - { PR_0_JOURNAL_BAD_UUID, - N_("External @j does not support this @f\n"), - PROMPT_NONE, PR_FATAL }, - - /* Journal has an unknown superblock type */ - { PR_0_JOURNAL_UNSUPP_SUPER, - N_("Ext3 @j @S is unknown type %N (unsupported).\n" - "It is likely that your copy of e2fsck is old and/or doesn't " - "support this @j format.\n" - "It is also possible the @j @S is corrupt.\n"), - PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER }, - - /* Journal superblock is corrupt */ - { PR_0_JOURNAL_BAD_SUPER, - N_("Ext3 @j @S is corrupt.\n"), - PROMPT_FIX, PR_PREEN_OK }, - - /* Superblock flag should be cleared */ - { PR_0_JOURNAL_HAS_JOURNAL, - N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"), - PROMPT_CLEAR, PR_PREEN_OK }, - - /* Superblock flag is incorrect */ - { PR_0_JOURNAL_RECOVER_SET, - N_("@S has ext3 needs_recovery flag set, but no @j.\n"), - PROMPT_CLEAR, PR_PREEN_OK }, - - /* Journal has data, but recovery flag is clear */ - { PR_0_JOURNAL_RECOVERY_CLEAR, - N_("ext3 recovery flag is clear, but @j has data.\n"), - PROMPT_NONE, 0 }, - - /* Ask if we should clear the journal */ - { PR_0_JOURNAL_RESET_JOURNAL, - N_("Clear @j"), - PROMPT_NULL, PR_PREEN_NOMSG }, - - /* Ask if we should run the journal anyway */ - { PR_0_JOURNAL_RUN, - N_("Run @j anyway"), - PROMPT_NULL, 0 }, - - /* Run the journal by default */ - { PR_0_JOURNAL_RUN_DEFAULT, - N_("Recovery flag not set in backup @S, so running @j anyway.\n"), - PROMPT_NONE, 0 }, - - /* Clearing orphan inode */ - { PR_0_ORPHAN_CLEAR_INODE, - N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"), - PROMPT_NONE, 0 }, - - /* Illegal block found in orphaned inode */ - { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, - N_("@I @b #%B (%b) found in @o @i %i.\n"), - PROMPT_NONE, 0 }, - - /* Already cleared block found in orphaned inode */ - { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, - N_("Already cleared @b #%B (%b) found in @o @i %i.\n"), - PROMPT_NONE, 0 }, - - /* Illegal orphan inode in superblock */ - { PR_0_ORPHAN_ILLEGAL_HEAD_INODE, - N_("@I @o @i %i in @S.\n"), - PROMPT_NONE, 0 }, - - /* Illegal inode in orphaned inode list */ - { PR_0_ORPHAN_ILLEGAL_INODE, - N_("@I @i %i in @o @i list.\n"), - PROMPT_NONE, 0 }, - - /* Filesystem revision is 0, but feature flags are set */ - { PR_0_FS_REV_LEVEL, - N_("@f has feature flag(s) set, but is a revision 0 @f. "), - PROMPT_FIX, PR_PREEN_OK | PR_NO_OK }, - - /* Journal superblock has an unknown read-only feature flag set */ - { PR_0_JOURNAL_UNSUPP_ROCOMPAT, - N_("Ext3 @j @S has an unknown read-only feature flag set.\n"), - PROMPT_ABORT, 0 }, - - /* Journal superblock has an unknown incompatible feature flag set */ - { PR_0_JOURNAL_UNSUPP_INCOMPAT, - N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"), - PROMPT_ABORT, 0 }, - - /* Journal has unsupported version number */ - { PR_0_JOURNAL_UNSUPP_VERSION, - N_("@j version not supported by this e2fsck.\n"), - PROMPT_ABORT, 0 }, - - /* Moving journal to hidden file */ - { PR_0_MOVE_JOURNAL, - N_("Moving @j from /%s to hidden @i.\n\n"), - PROMPT_NONE, 0 }, - - /* Error moving journal to hidden file */ - { PR_0_ERR_MOVE_JOURNAL, - N_("Error moving @j: %m\n\n"), - PROMPT_NONE, 0 }, - - /* Clearing V2 journal superblock */ - { PR_0_CLEAR_V2_JOURNAL, - N_("Found @n V2 @j @S fields (from V1 @j).\n" - "Clearing fields beyond the V1 @j @S...\n\n"), - PROMPT_NONE, 0 }, - - /* Backup journal inode blocks */ - { PR_0_BACKUP_JNL, - N_("Backing up @j @i @b information.\n\n"), - PROMPT_NONE, 0 }, - - /* Reserved blocks w/o resize_inode */ - { PR_0_NONZERO_RESERVED_GDT_BLOCKS, - N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n" - "is %N; @s zero. "), - PROMPT_FIX, 0 }, - - /* Resize_inode not enabled, but resize inode is non-zero */ - { PR_0_CLEAR_RESIZE_INODE, - N_("Resize_@i not enabled, but the resize @i is non-zero. "), - PROMPT_CLEAR, 0 }, - - /* Resize inode invalid */ - { PR_0_RESIZE_INODE_INVALID, - N_("Resize @i not valid. "), - PROMPT_RECREATE, 0 }, - - /* Pass 1 errors */ - - /* Pass 1: Checking inodes, blocks, and sizes */ - { PR_1_PASS_HEADER, - N_("Pass 1: Checking @is, @bs, and sizes\n"), - PROMPT_NONE, 0 }, - - /* Root directory is not an inode */ - { PR_1_ROOT_NO_DIR, N_("@r is not a @d. "), - PROMPT_CLEAR, 0 }, - - /* Root directory has dtime set */ - { PR_1_ROOT_DTIME, - N_("@r has dtime set (probably due to old mke2fs). "), - PROMPT_FIX, PR_PREEN_OK }, - - /* Reserved inode has bad mode */ - { PR_1_RESERVED_BAD_MODE, - N_("Reserved @i %i (%Q) has @n mode. "), - PROMPT_CLEAR, PR_PREEN_OK }, - - /* Deleted inode has zero dtime */ - { PR_1_ZERO_DTIME, - N_("@D @i %i has zero dtime. "), - PROMPT_FIX, PR_PREEN_OK }, - - /* Inode in use, but dtime set */ - { PR_1_SET_DTIME, - N_("@i %i is in use, but has dtime set. "), - PROMPT_FIX, PR_PREEN_OK }, - - /* Zero-length directory */ - { PR_1_ZERO_LENGTH_DIR, - N_("@i %i is a @z @d. "), - PROMPT_CLEAR, PR_PREEN_OK }, - - /* Block bitmap conflicts with some other fs block */ - { PR_1_BB_CONFLICT, - N_("@g %g's @b @B at %b @C.\n"), - PROMPT_RELOCATE, 0 }, - - /* Inode bitmap conflicts with some other fs block */ - { PR_1_IB_CONFLICT, - N_("@g %g's @i @B at %b @C.\n"), - PROMPT_RELOCATE, 0 }, - - /* Inode table conflicts with some other fs block */ - { PR_1_ITABLE_CONFLICT, - N_("@g %g's @i table at %b @C.\n"), - PROMPT_RELOCATE, 0 }, - - /* Block bitmap is on a bad block */ - { PR_1_BB_BAD_BLOCK, - N_("@g %g's @b @B (%b) is bad. "), - PROMPT_RELOCATE, 0 }, - - /* Inode bitmap is on a bad block */ - { PR_1_IB_BAD_BLOCK, - N_("@g %g's @i @B (%b) is bad. "), - PROMPT_RELOCATE, 0 }, - - /* Inode has incorrect i_size */ - { PR_1_BAD_I_SIZE, - N_("@i %i, i_size is %Is, @s %N. "), - PROMPT_FIX, PR_PREEN_OK }, - - /* Inode has incorrect i_blocks */ - { PR_1_BAD_I_BLOCKS, - N_("@i %i, i_@bs is %Ib, @s %N. "), - PROMPT_FIX, PR_PREEN_OK }, - - /* Illegal blocknumber in inode */ - { PR_1_ILLEGAL_BLOCK_NUM, - N_("@I @b #%B (%b) in @i %i. "), - PROMPT_CLEAR, PR_LATCH_BLOCK }, - - /* Block number overlaps fs metadata */ - { PR_1_BLOCK_OVERLAPS_METADATA, - N_("@b #%B (%b) overlaps @f metadata in @i %i. "), - PROMPT_CLEAR, PR_LATCH_BLOCK }, - - /* Inode has illegal blocks (latch question) */ - { PR_1_INODE_BLOCK_LATCH, - N_("@i %i has illegal @b(s). "), - PROMPT_CLEAR, 0 }, - - /* Too many bad blocks in inode */ - { PR_1_TOO_MANY_BAD_BLOCKS, - N_("Too many illegal @bs in @i %i.\n"), - PROMPT_CLEAR_INODE, PR_NO_OK }, - - /* Illegal block number in bad block inode */ - { PR_1_BB_ILLEGAL_BLOCK_NUM, - N_("@I @b #%B (%b) in bad @b @i. "), - PROMPT_CLEAR, PR_LATCH_BBLOCK }, - - /* Bad block inode has illegal blocks (latch question) */ - { PR_1_INODE_BBLOCK_LATCH, - N_("Bad @b @i has illegal @b(s). "), - PROMPT_CLEAR, 0 }, - - /* Duplicate or bad blocks in use! */ - { PR_1_DUP_BLOCKS_PREENSTOP, - N_("Duplicate or bad @b in use!\n"), - PROMPT_NONE, 0 }, - - /* Bad block used as bad block indirect block */ - { PR_1_BBINODE_BAD_METABLOCK, - N_("Bad @b %b used as bad @b @i indirect @b. "), - PROMPT_CLEAR, PR_LATCH_BBLOCK }, - - /* Inconsistency can't be fixed prompt */ - { PR_1_BBINODE_BAD_METABLOCK_PROMPT, - N_("\nThe bad @b @i has probably been corrupted. You probably\n" - "should stop now and run ""e2fsck -c"" to scan for bad blocks\n" - "in the @f.\n"), - PROMPT_CONTINUE, PR_PREEN_NOMSG }, - - /* Bad primary block */ - { PR_1_BAD_PRIMARY_BLOCK, - N_("\nIf the @b is really bad, the @f cannot be fixed.\n"), - PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT }, - - /* Bad primary block prompt */ - { PR_1_BAD_PRIMARY_BLOCK_PROMPT, - N_("You can remove this @b from the bad @b list and hope\n" - "that the @b is really OK. But there are no guarantees.\n\n"), - PROMPT_CLEAR, PR_PREEN_NOMSG }, - - /* Bad primary superblock */ - { PR_1_BAD_PRIMARY_SUPERBLOCK, - N_("The primary @S (%b) is on the bad @b list.\n"), - PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK }, - - /* Bad primary block group descriptors */ - { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR, - N_("Block %b in the primary @g descriptors " - "is on the bad @b list\n"), - PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK }, - - /* Bad superblock in group */ - { PR_1_BAD_SUPERBLOCK, - N_("Warning: Group %g's @S (%b) is bad.\n"), - PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG }, - - /* Bad block group descriptors in group */ - { PR_1_BAD_GROUP_DESCRIPTORS, - N_("Warning: Group %g's copy of the @g descriptors has a bad " - "@b (%b).\n"), - PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG }, - - /* Block claimed for no reason */ - { PR_1_PROGERR_CLAIMED_BLOCK, - N_("Programming error? @b #%b claimed for no reason in " - "process_bad_@b.\n"), - PROMPT_NONE, PR_PREEN_OK }, - - /* Error allocating blocks for relocating metadata */ - { PR_1_RELOC_BLOCK_ALLOCATE, - N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"), - PROMPT_NONE, PR_PREEN_OK }, - - /* Error allocating block buffer during relocation process */ - { PR_1_RELOC_MEMORY_ALLOCATE, - N_("@A @b buffer for relocating %s\n"), - PROMPT_NONE, PR_PREEN_OK }, - - /* Relocating metadata group information from X to Y */ - { PR_1_RELOC_FROM_TO, - N_("Relocating @g %g's %s from %b to %c...\n"), - PROMPT_NONE, PR_PREEN_OK }, - - /* Relocating metatdata group information to X */ - { PR_1_RELOC_TO, - N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */ - PROMPT_NONE, PR_PREEN_OK }, - - /* Block read error during relocation process */ - { PR_1_RELOC_READ_ERR, - N_("Warning: could not read @b %b of %s: %m\n"), - PROMPT_NONE, PR_PREEN_OK }, - - /* Block write error during relocation process */ - { PR_1_RELOC_WRITE_ERR, - N_("Warning: could not write @b %b for %s: %m\n"), - PROMPT_NONE, PR_PREEN_OK }, - - /* Error allocating inode bitmap */ - { PR_1_ALLOCATE_IBITMAP_ERROR, - N_("@A @i @B (%N): %m\n"), - PROMPT_NONE, PR_FATAL }, - - /* Error allocating block bitmap */ - { PR_1_ALLOCATE_BBITMAP_ERROR, - N_("@A @b @B (%N): %m\n"), - PROMPT_NONE, PR_FATAL }, - - /* Error allocating icount structure */ - { PR_1_ALLOCATE_ICOUNT, - N_("@A icount link information: %m\n"), - PROMPT_NONE, PR_FATAL }, - - /* Error allocating dbcount */ - { PR_1_ALLOCATE_DBCOUNT, - N_("@A @d @b array: %m\n"), - PROMPT_NONE, PR_FATAL }, - - /* Error while scanning inodes */ - { PR_1_ISCAN_ERROR, - N_("Error while scanning @is (%i): %m\n"), - PROMPT_NONE, PR_FATAL }, - - /* Error while iterating over blocks */ - { PR_1_BLOCK_ITERATE, - N_("Error while iterating over @bs in @i %i: %m\n"), - PROMPT_NONE, PR_FATAL }, - - /* Error while storing inode count information */ - { PR_1_ICOUNT_STORE, - N_("Error storing @i count information (@i=%i, count=%N): %m\n"), - PROMPT_NONE, PR_FATAL }, - - /* Error while storing directory block information */ - { PR_1_ADD_DBLOCK, - N_("Error storing @d @b information " - "(@i=%i, @b=%b, num=%N): %m\n"), - PROMPT_NONE, PR_FATAL }, - - /* Error while reading inode (for clearing) */ - { PR_1_READ_INODE, - N_("Error reading @i %i: %m\n"), - PROMPT_NONE, PR_FATAL }, - - /* Suppress messages prompt */ - { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK }, - - /* Imagic flag set on an inode when filesystem doesn't support it */ - { PR_1_SET_IMAGIC, - N_("@i %i has imagic flag set. "), - PROMPT_CLEAR, 0 }, - - /* Immutable flag set on a device or socket inode */ - { PR_1_SET_IMMUTABLE, - N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n" - "or append-only flag set. "), - PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK }, - - /* Compression flag set on an inode when filesystem doesn't support it */ - { PR_1_COMPR_SET, - N_("@i %i has @cion flag set on @f without @cion support. "), - PROMPT_CLEAR, 0 }, - - /* Non-zero size for device, fifo or socket inode */ - { PR_1_SET_NONZSIZE, - N_("Special (@v/socket/fifo) @i %i has non-zero size. "), - PROMPT_FIX, PR_PREEN_OK }, - - /* Filesystem revision is 0, but feature flags are set */ - { PR_1_FS_REV_LEVEL, - N_("@f has feature flag(s) set, but is a revision 0 @f. "), - PROMPT_FIX, PR_PREEN_OK | PR_NO_OK }, - - /* Journal inode is not in use, but contains data */ - { PR_1_JOURNAL_INODE_NOT_CLEAR, - N_("@j @i is not in use, but contains data. "), - PROMPT_CLEAR, PR_PREEN_OK }, - - /* Journal has bad mode */ - { PR_1_JOURNAL_BAD_MODE, - N_("@j is not regular file. "), - PROMPT_FIX, PR_PREEN_OK }, - - /* Deal with inodes that were part of orphan linked list */ - { PR_1_LOW_DTIME, - N_("@i %i was part of the @o @i list. "), - PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 }, - - /* Deal with inodes that were part of corrupted orphan linked - list (latch question) */ - { PR_1_ORPHAN_LIST_REFUGEES, - N_("@is that were part of a corrupted orphan linked list found. "), - PROMPT_FIX, 0 }, - - /* Error allocating refcount structure */ - { PR_1_ALLOCATE_REFCOUNT, - N_("@A refcount structure (%N): %m\n"), - PROMPT_NONE, PR_FATAL }, - - /* Error reading extended attribute block */ - { PR_1_READ_EA_BLOCK, - N_("Error reading @a @b %b for @i %i. "), - PROMPT_CLEAR, 0 }, - - /* Invalid extended attribute block */ - { PR_1_BAD_EA_BLOCK, - N_("@i %i has a bad @a @b %b. "), - PROMPT_CLEAR, 0 }, - - /* Error reading Extended Attribute block while fixing refcount */ - { PR_1_EXTATTR_READ_ABORT, - N_("Error reading @a @b %b (%m). "), - PROMPT_ABORT, 0 }, - - /* Extended attribute reference count incorrect */ - { PR_1_EXTATTR_REFCOUNT, - N_("@a @b %b has reference count %B, @s %N. "), - PROMPT_FIX, 0 }, - - /* Error writing Extended Attribute block while fixing refcount */ - { PR_1_EXTATTR_WRITE, - N_("Error writing @a @b %b (%m). "), - PROMPT_ABORT, 0 }, - - /* Multiple EA blocks not supported */ - { PR_1_EA_MULTI_BLOCK, - N_("@a @b %b has h_@bs > 1. "), - PROMPT_CLEAR, 0}, - - /* Error allocating EA region allocation structure */ - { PR_1_EA_ALLOC_REGION, - N_("@A @a @b %b. "), - PROMPT_ABORT, 0}, - - /* Error EA allocation collision */ - { PR_1_EA_ALLOC_COLLISION, - N_("@a @b %b is corrupt (allocation collision). "), - PROMPT_CLEAR, 0}, - - /* Bad extended attribute name */ - { PR_1_EA_BAD_NAME, - N_("@a @b %b is corrupt (@n name). "), - PROMPT_CLEAR, 0}, - - /* Bad extended attribute value */ - { PR_1_EA_BAD_VALUE, - N_("@a @b %b is corrupt (@n value). "), - PROMPT_CLEAR, 0}, - - /* Inode too big (latch question) */ - { PR_1_INODE_TOOBIG, - N_("@i %i is too big. "), PROMPT_TRUNCATE, 0 }, - - /* Directory too big */ - { PR_1_TOOBIG_DIR, - N_("@b #%B (%b) causes @d to be too big. "), - PROMPT_CLEAR, PR_LATCH_TOOBIG }, - - /* Regular file too big */ - { PR_1_TOOBIG_REG, - N_("@b #%B (%b) causes file to be too big. "), - PROMPT_CLEAR, PR_LATCH_TOOBIG }, - - /* Symlink too big */ - { PR_1_TOOBIG_SYMLINK, - N_("@b #%B (%b) causes symlink to be too big. "), - PROMPT_CLEAR, PR_LATCH_TOOBIG }, - - /* INDEX_FL flag set on a non-HTREE filesystem */ - { PR_1_HTREE_SET, - N_("@i %i has INDEX_FL flag set on @f without htree support.\n"), - PROMPT_CLEAR_HTREE, PR_PREEN_OK }, - - /* INDEX_FL flag set on a non-directory */ - { PR_1_HTREE_NODIR, - N_("@i %i has INDEX_FL flag set but is not a @d.\n"), - PROMPT_CLEAR_HTREE, PR_PREEN_OK }, - - /* Invalid root node in HTREE directory */ - { PR_1_HTREE_BADROOT, - N_("@h %i has an @n root node.\n"), - PROMPT_CLEAR_HTREE, PR_PREEN_OK }, - - /* Unsupported hash version in HTREE directory */ - { PR_1_HTREE_HASHV, - N_("@h %i has an unsupported hash version (%N)\n"), - PROMPT_CLEAR_HTREE, PR_PREEN_OK }, - - /* Incompatible flag in HTREE root node */ - { PR_1_HTREE_INCOMPAT, - N_("@h %i uses an incompatible htree root node flag.\n"), - PROMPT_CLEAR_HTREE, PR_PREEN_OK }, - - /* HTREE too deep */ - { PR_1_HTREE_DEPTH, - N_("@h %i has a tree depth (%N) which is too big\n"), - PROMPT_CLEAR_HTREE, PR_PREEN_OK }, - - /* Bad block has indirect block that conflicts with filesystem block */ - { PR_1_BB_FS_BLOCK, - N_("Bad @b @i has an indirect @b (%b) that conflicts with\n" - "@f metadata. "), - PROMPT_CLEAR, PR_LATCH_BBLOCK }, - - /* Resize inode failed */ - { PR_1_RESIZE_INODE_CREATE, - N_("Resize @i (re)creation failed: %m."), - PROMPT_ABORT, 0 }, - - /* invalid inode->i_extra_isize */ - { PR_1_EXTRA_ISIZE, - N_("@i %i has a extra size (%IS) which is @n\n"), - PROMPT_FIX, PR_PREEN_OK }, - - /* invalid ea entry->e_name_len */ - { PR_1_ATTR_NAME_LEN, - N_("@a in @i %i has a namelen (%N) which is @n\n"), - PROMPT_CLEAR, PR_PREEN_OK }, - - /* invalid ea entry->e_value_size */ - { PR_1_ATTR_VALUE_SIZE, - N_("@a in @i %i has a value size (%N) which is @n\n"), - PROMPT_CLEAR, PR_PREEN_OK }, - - /* invalid ea entry->e_value_offs */ - { PR_1_ATTR_VALUE_OFFSET, - N_("@a in @i %i has a value offset (%N) which is @n\n"), - PROMPT_CLEAR, PR_PREEN_OK }, - - /* invalid ea entry->e_value_block */ - { PR_1_ATTR_VALUE_BLOCK, - N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"), - PROMPT_CLEAR, PR_PREEN_OK }, - - /* invalid ea entry->e_hash */ - { PR_1_ATTR_HASH, - N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"), - PROMPT_CLEAR, PR_PREEN_OK }, - - /* Pass 1b errors */ - - /* Pass 1B: Rescan for duplicate/bad blocks */ - { PR_1B_PASS_HEADER, - N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n" - "Pass 1B: Rescanning for @m @bs\n"), - PROMPT_NONE, 0 }, - - /* Duplicate/bad block(s) header */ - { PR_1B_DUP_BLOCK_HEADER, - N_("@m @b(s) in @i %i:"), - PROMPT_NONE, 0 }, - - /* Duplicate/bad block(s) in inode */ - { PR_1B_DUP_BLOCK, - " %b", - PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR }, - - /* Duplicate/bad block(s) end */ - { PR_1B_DUP_BLOCK_END, - "\n", - PROMPT_NONE, PR_PREEN_NOHDR }, - - /* Error while scanning inodes */ - { PR_1B_ISCAN_ERROR, - N_("Error while scanning inodes (%i): %m\n"), - PROMPT_NONE, PR_FATAL }, - - /* Error allocating inode bitmap */ - { PR_1B_ALLOCATE_IBITMAP_ERROR, - N_("@A @i @B (@i_dup_map): %m\n"), - PROMPT_NONE, PR_FATAL }, - - /* Error while iterating over blocks */ - { PR_1B_BLOCK_ITERATE, - N_("Error while iterating over @bs in @i %i (%s): %m\n"), - PROMPT_NONE, 0 }, - - /* Error adjusting EA refcount */ - { PR_1B_ADJ_EA_REFCOUNT, - N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"), - PROMPT_NONE, 0 }, - - - /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */ - { PR_1C_PASS_HEADER, - N_("Pass 1C: Scanning directories for @is with @m @bs.\n"), - PROMPT_NONE, 0 }, - - - /* Pass 1D: Reconciling multiply-claimed blocks */ - { PR_1D_PASS_HEADER, - N_("Pass 1D: Reconciling @m @bs\n"), - PROMPT_NONE, 0 }, - - /* File has duplicate blocks */ - { PR_1D_DUP_FILE, - N_("File %Q (@i #%i, mod time %IM)\n" - " has %B @m @b(s), shared with %N file(s):\n"), - PROMPT_NONE, 0 }, - - /* List of files sharing duplicate blocks */ - { PR_1D_DUP_FILE_LIST, - N_("\t%Q (@i #%i, mod time %IM)\n"), - PROMPT_NONE, 0 }, - - /* File sharing blocks with filesystem metadata */ - { PR_1D_SHARE_METADATA, - N_("\t<@f metadata>\n"), - PROMPT_NONE, 0 }, - - /* Report of how many duplicate/bad inodes */ - { PR_1D_NUM_DUP_INODES, - N_("(There are %N @is containing @m @bs.)\n\n"), - PROMPT_NONE, 0 }, - - /* Duplicated blocks already reassigned or cloned. */ - { PR_1D_DUP_BLOCKS_DEALT, - N_("@m @bs already reassigned or cloned.\n\n"), - PROMPT_NONE, 0 }, - - /* Clone duplicate/bad blocks? */ - { PR_1D_CLONE_QUESTION, - "", PROMPT_CLONE, PR_NO_OK }, - - /* Delete file? */ - { PR_1D_DELETE_QUESTION, - "", PROMPT_DELETE, 0 }, - - /* Couldn't clone file (error) */ - { PR_1D_CLONE_ERROR, - N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 }, - - /* Pass 2 errors */ - - /* Pass 2: Checking directory structure */ - { PR_2_PASS_HEADER, - N_("Pass 2: Checking @d structure\n"), - PROMPT_NONE, 0 }, - - /* Bad inode number for '.' */ - { PR_2_BAD_INODE_DOT, - N_("@n @i number for '.' in @d @i %i.\n"), - PROMPT_FIX, 0 }, - - /* Directory entry has bad inode number */ - { PR_2_BAD_INO, - N_("@E has @n @i #: %Di.\n"), - PROMPT_CLEAR, 0 }, - - /* Directory entry has deleted or unused inode */ - { PR_2_UNUSED_INODE, - N_("@E has @D/unused @i %Di. "), - PROMPT_CLEAR, PR_PREEN_OK }, - - /* Directry entry is link to '.' */ - { PR_2_LINK_DOT, - N_("@E @L to '.' "), - PROMPT_CLEAR, 0 }, - - /* Directory entry points to inode now located in a bad block */ - { PR_2_BB_INODE, - N_("@E points to @i (%Di) located in a bad @b.\n"), - PROMPT_CLEAR, 0 }, - - /* Directory entry contains a link to a directory */ - { PR_2_LINK_DIR, - N_("@E @L to @d %P (%Di).\n"), - PROMPT_CLEAR, 0 }, - - /* Directory entry contains a link to the root directry */ - { PR_2_LINK_ROOT, - N_("@E @L to the @r.\n"), - PROMPT_CLEAR, 0 }, - - /* Directory entry has illegal characters in its name */ - { PR_2_BAD_NAME, - N_("@E has illegal characters in its name.\n"), - PROMPT_FIX, 0 }, - - /* Missing '.' in directory inode */ - { PR_2_MISSING_DOT, - N_("Missing '.' in @d @i %i.\n"), - PROMPT_FIX, 0 }, - - /* Missing '..' in directory inode */ - { PR_2_MISSING_DOT_DOT, - N_("Missing '..' in @d @i %i.\n"), - PROMPT_FIX, 0 }, - - /* First entry in directory inode doesn't contain '.' */ - { PR_2_1ST_NOT_DOT, - N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"), - PROMPT_FIX, 0 }, - - /* Second entry in directory inode doesn't contain '..' */ - { PR_2_2ND_NOT_DOT_DOT, - N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"), - PROMPT_FIX, 0 }, - - /* i_faddr should be zero */ - { PR_2_FADDR_ZERO, - N_("i_faddr @F %IF, @s zero.\n"), - PROMPT_CLEAR, 0 }, - - /* i_file_acl should be zero */ - { PR_2_FILE_ACL_ZERO, - N_("i_file_acl @F %If, @s zero.\n"), - PROMPT_CLEAR, 0 }, - - /* i_dir_acl should be zero */ - { PR_2_DIR_ACL_ZERO, - N_("i_dir_acl @F %Id, @s zero.\n"), - PROMPT_CLEAR, 0 }, - - /* i_frag should be zero */ - { PR_2_FRAG_ZERO, - N_("i_frag @F %N, @s zero.\n"), - PROMPT_CLEAR, 0 }, - - /* i_fsize should be zero */ - { PR_2_FSIZE_ZERO, - N_("i_fsize @F %N, @s zero.\n"), - PROMPT_CLEAR, 0 }, - - /* inode has bad mode */ - { PR_2_BAD_MODE, - N_("@i %i (%Q) has @n mode (%Im).\n"), - PROMPT_CLEAR, 0 }, - - /* directory corrupted */ - { PR_2_DIR_CORRUPTED, - N_("@d @i %i, @b %B, offset %N: @d corrupted\n"), - PROMPT_SALVAGE, 0 }, - - /* filename too long */ - { PR_2_FILENAME_LONG, - N_("@d @i %i, @b %B, offset %N: filename too long\n"), - PROMPT_TRUNCATE, 0 }, - - /* Directory inode has a missing block (hole) */ - { PR_2_DIRECTORY_HOLE, - N_("@d @i %i has an unallocated @b #%B. "), - PROMPT_ALLOCATE, 0 }, - - /* '.' is not NULL terminated */ - { PR_2_DOT_NULL_TERM, - N_("'.' @d @e in @d @i %i is not NULL terminated\n"), - PROMPT_FIX, 0 }, - - /* '..' is not NULL terminated */ - { PR_2_DOT_DOT_NULL_TERM, - N_("'..' @d @e in @d @i %i is not NULL terminated\n"), - PROMPT_FIX, 0 }, - - /* Illegal character device inode */ - { PR_2_BAD_CHAR_DEV, - N_("@i %i (%Q) is an @I character @v.\n"), - PROMPT_CLEAR, 0 }, - - /* Illegal block device inode */ - { PR_2_BAD_BLOCK_DEV, - N_("@i %i (%Q) is an @I @b @v.\n"), - PROMPT_CLEAR, 0 }, - - /* Duplicate '.' entry */ - { PR_2_DUP_DOT, - N_("@E is duplicate '.' @e.\n"), - PROMPT_FIX, 0 }, - - /* Duplicate '..' entry */ - { PR_2_DUP_DOT_DOT, - N_("@E is duplicate '..' @e.\n"), - PROMPT_FIX, 0 }, - - /* Internal error: couldn't find dir_info */ - { PR_2_NO_DIRINFO, - N_("Internal error: cannot find dir_info for %i.\n"), - PROMPT_NONE, PR_FATAL }, - - /* Final rec_len is wrong */ - { PR_2_FINAL_RECLEN, - N_("@E has rec_len of %Dr, @s %N.\n"), - PROMPT_FIX, 0 }, - - /* Error allocating icount structure */ - { PR_2_ALLOCATE_ICOUNT, - N_("@A icount structure: %m\n"), - PROMPT_NONE, PR_FATAL }, - - /* Error iterating over directory blocks */ - { PR_2_DBLIST_ITERATE, - N_("Error iterating over @d @bs: %m\n"), - PROMPT_NONE, PR_FATAL }, - - /* Error reading directory block */ - { PR_2_READ_DIRBLOCK, - N_("Error reading @d @b %b (@i %i): %m\n"), - PROMPT_CONTINUE, 0 }, - - /* Error writing directory block */ - { PR_2_WRITE_DIRBLOCK, - N_("Error writing @d @b %b (@i %i): %m\n"), - PROMPT_CONTINUE, 0 }, - - /* Error allocating new directory block */ - { PR_2_ALLOC_DIRBOCK, - N_("@A new @d @b for @i %i (%s): %m\n"), - PROMPT_NONE, 0 }, - - /* Error deallocating inode */ - { PR_2_DEALLOC_INODE, - N_("Error deallocating @i %i: %m\n"), - PROMPT_NONE, PR_FATAL }, - - /* Directory entry for '.' is big. Split? */ - { PR_2_SPLIT_DOT, - N_("@d @e for '.' is big. "), - PROMPT_SPLIT, PR_NO_OK }, - - /* Illegal FIFO inode */ - { PR_2_BAD_FIFO, - N_("@i %i (%Q) is an @I FIFO.\n"), - PROMPT_CLEAR, 0 }, - - /* Illegal socket inode */ - { PR_2_BAD_SOCKET, - N_("@i %i (%Q) is an @I socket.\n"), - PROMPT_CLEAR, 0 }, - - /* Directory filetype not set */ - { PR_2_SET_FILETYPE, - N_("Setting filetype for @E to %N.\n"), - PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG }, - - /* Directory filetype incorrect */ - { PR_2_BAD_FILETYPE, - N_("@E has an incorrect filetype (was %Dt, @s %N).\n"), - PROMPT_FIX, 0 }, - - /* Directory filetype set on filesystem */ - { PR_2_CLEAR_FILETYPE, - N_("@E has filetype set.\n"), - PROMPT_CLEAR, PR_PREEN_OK }, - - /* Directory filename is null */ - { PR_2_NULL_NAME, - N_("@E has a @z name.\n"), - PROMPT_CLEAR, 0 }, - - /* Invalid symlink */ - { PR_2_INVALID_SYMLINK, - N_("Symlink %Q (@i #%i) is @n.\n"), - PROMPT_CLEAR, 0 }, - - /* i_file_acl (extended attribute block) is bad */ - { PR_2_FILE_ACL_BAD, - N_("@a @b @F @n (%If).\n"), - PROMPT_CLEAR, 0 }, - - /* Filesystem contains large files, but has no such flag in sb */ - { PR_2_FEATURE_LARGE_FILES, - N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"), - PROMPT_FIX, 0 }, - - /* Node in HTREE directory not referenced */ - { PR_2_HTREE_NOTREF, - N_("@p @h %d: node (%B) not referenced\n"), - PROMPT_NONE, 0 }, - - /* Node in HTREE directory referenced twice */ - { PR_2_HTREE_DUPREF, - N_("@p @h %d: node (%B) referenced twice\n"), - PROMPT_NONE, 0 }, - - /* Node in HTREE directory has bad min hash */ - { PR_2_HTREE_MIN_HASH, - N_("@p @h %d: node (%B) has bad min hash\n"), - PROMPT_NONE, 0 }, - - /* Node in HTREE directory has bad max hash */ - { PR_2_HTREE_MAX_HASH, - N_("@p @h %d: node (%B) has bad max hash\n"), - PROMPT_NONE, 0 }, - - /* Clear invalid HTREE directory */ - { PR_2_HTREE_CLEAR, - N_("@n @h %d (%q). "), PROMPT_CLEAR, 0 }, - - /* Bad block in htree interior node */ - { PR_2_HTREE_BADBLK, - N_("@p @h %d (%q): bad @b number %b.\n"), - PROMPT_CLEAR_HTREE, 0 }, - - /* Error adjusting EA refcount */ - { PR_2_ADJ_EA_REFCOUNT, - N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"), - PROMPT_NONE, PR_FATAL }, - - /* Invalid HTREE root node */ - { PR_2_HTREE_BAD_ROOT, - N_("@p @h %d: root node is @n\n"), - PROMPT_CLEAR_HTREE, PR_PREEN_OK }, - - /* Invalid HTREE limit */ - { PR_2_HTREE_BAD_LIMIT, - N_("@p @h %d: node (%B) has @n limit (%N)\n"), - PROMPT_CLEAR_HTREE, PR_PREEN_OK }, - - /* Invalid HTREE count */ - { PR_2_HTREE_BAD_COUNT, - N_("@p @h %d: node (%B) has @n count (%N)\n"), - PROMPT_CLEAR_HTREE, PR_PREEN_OK }, - - /* HTREE interior node has out-of-order hashes in table */ - { PR_2_HTREE_HASH_ORDER, - N_("@p @h %d: node (%B) has an unordered hash table\n"), - PROMPT_CLEAR_HTREE, PR_PREEN_OK }, - - /* Node in HTREE directory has invalid depth */ - { PR_2_HTREE_BAD_DEPTH, - N_("@p @h %d: node (%B) has @n depth\n"), - PROMPT_NONE, 0 }, - - /* Duplicate directory entry found */ - { PR_2_DUPLICATE_DIRENT, - N_("Duplicate @E found. "), - PROMPT_CLEAR, 0 }, - - /* Non-unique filename found */ - { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */ - N_("@E has a non-unique filename.\nRename to %s"), - PROMPT_NULL, 0 }, - - /* Duplicate directory entry found */ - { PR_2_REPORT_DUP_DIRENT, - N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"), - PROMPT_NONE, 0 }, - - /* Pass 3 errors */ - - /* Pass 3: Checking directory connectivity */ - { PR_3_PASS_HEADER, - N_("Pass 3: Checking @d connectivity\n"), - PROMPT_NONE, 0 }, - - /* Root inode not allocated */ - { PR_3_NO_ROOT_INODE, - N_("@r not allocated. "), - PROMPT_ALLOCATE, 0 }, - - /* No room in lost+found */ - { PR_3_EXPAND_LF_DIR, - N_("No room in @l @d. "), - PROMPT_EXPAND, 0 }, - - /* Unconnected directory inode */ - { PR_3_UNCONNECTED_DIR, - N_("Unconnected @d @i %i (%p)\n"), - PROMPT_CONNECT, 0 }, - - /* /lost+found not found */ - { PR_3_NO_LF_DIR, - N_("/@l not found. "), - PROMPT_CREATE, PR_PREEN_OK }, - - /* .. entry is incorrect */ - { PR_3_BAD_DOT_DOT, - N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"), - PROMPT_FIX, 0 }, - - /* Bad or non-existent /lost+found. Cannot reconnect */ - { PR_3_NO_LPF, - N_("Bad or non-existent /@l. Cannot reconnect.\n"), - PROMPT_NONE, 0 }, - - /* Could not expand /lost+found */ - { PR_3_CANT_EXPAND_LPF, - N_("Could not expand /@l: %m\n"), - PROMPT_NONE, 0 }, - - /* Could not reconnect inode */ - { PR_3_CANT_RECONNECT, - N_("Could not reconnect %i: %m\n"), - PROMPT_NONE, 0 }, - - /* Error while trying to find /lost+found */ - { PR_3_ERR_FIND_LPF, - N_("Error while trying to find /@l: %m\n"), - PROMPT_NONE, 0 }, - - /* Error in ext2fs_new_block while creating /lost+found */ - { PR_3_ERR_LPF_NEW_BLOCK, - N_("ext2fs_new_@b: %m while trying to create /@l @d\n"), - PROMPT_NONE, 0 }, - - /* Error in ext2fs_new_inode while creating /lost+found */ - { PR_3_ERR_LPF_NEW_INODE, - N_("ext2fs_new_@i: %m while trying to create /@l @d\n"), - PROMPT_NONE, 0 }, - - /* Error in ext2fs_new_dir_block while creating /lost+found */ - { PR_3_ERR_LPF_NEW_DIR_BLOCK, - N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"), - PROMPT_NONE, 0 }, - - /* Error while writing directory block for /lost+found */ - { PR_3_ERR_LPF_WRITE_BLOCK, - N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"), - PROMPT_NONE, 0 }, - - /* Error while adjusting inode count */ - { PR_3_ADJUST_INODE, - N_("Error while adjusting @i count on @i %i\n"), - PROMPT_NONE, 0 }, - - /* Couldn't fix parent directory -- error */ - { PR_3_FIX_PARENT_ERR, - N_("Couldn't fix parent of @i %i: %m\n\n"), - PROMPT_NONE, 0 }, - - /* Couldn't fix parent directory -- couldn't find it */ - { PR_3_FIX_PARENT_NOFIND, - N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"), - PROMPT_NONE, 0 }, - - /* Error allocating inode bitmap */ - { PR_3_ALLOCATE_IBITMAP_ERROR, - N_("@A @i @B (%N): %m\n"), - PROMPT_NONE, PR_FATAL }, - - /* Error creating root directory */ - { PR_3_CREATE_ROOT_ERROR, - N_("Error creating root @d (%s): %m\n"), - PROMPT_NONE, PR_FATAL }, - - /* Error creating lost and found directory */ - { PR_3_CREATE_LPF_ERROR, - N_("Error creating /@l @d (%s): %m\n"), - PROMPT_NONE, PR_FATAL }, - - /* Root inode is not directory; aborting */ - { PR_3_ROOT_NOT_DIR_ABORT, - N_("@r is not a @d; aborting.\n"), - PROMPT_NONE, PR_FATAL }, - - /* Cannot proceed without a root inode. */ - { PR_3_NO_ROOT_INODE_ABORT, - N_("can't proceed without a @r.\n"), - PROMPT_NONE, PR_FATAL }, - - /* Internal error: couldn't find dir_info */ - { PR_3_NO_DIRINFO, - N_("Internal error: cannot find dir_info for %i.\n"), - PROMPT_NONE, PR_FATAL }, - - /* Lost+found not a directory */ - { PR_3_LPF_NOTDIR, - N_("/@l is not a @d (ino=%i)\n"), - PROMPT_UNLINK, 0 }, - - /* Pass 3A Directory Optimization */ - - /* Pass 3A: Optimizing directories */ - { PR_3A_PASS_HEADER, - N_("Pass 3A: Optimizing directories\n"), - PROMPT_NONE, PR_PREEN_NOMSG }, - - /* Error iterating over directories */ - { PR_3A_OPTIMIZE_ITER, - N_("Failed to create dirs_to_hash iterator: %m"), - PROMPT_NONE, 0 }, - - /* Error rehash directory */ - { PR_3A_OPTIMIZE_DIR_ERR, - N_("Failed to optimize directory %q (%d): %m"), - PROMPT_NONE, 0 }, - - /* Rehashing dir header */ - { PR_3A_OPTIMIZE_DIR_HEADER, - N_("Optimizing directories: "), - PROMPT_NONE, PR_MSG_ONLY }, - - /* Rehashing directory %d */ - { PR_3A_OPTIMIZE_DIR, - " %d", - PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR}, - - /* Rehashing dir end */ - { PR_3A_OPTIMIZE_DIR_END, - "\n", - PROMPT_NONE, PR_PREEN_NOHDR }, - - /* Pass 4 errors */ - - /* Pass 4: Checking reference counts */ - { PR_4_PASS_HEADER, - N_("Pass 4: Checking reference counts\n"), - PROMPT_NONE, 0 }, - - /* Unattached zero-length inode */ - { PR_4_ZERO_LEN_INODE, - N_("@u @z @i %i. "), - PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK }, - - /* Unattached inode */ - { PR_4_UNATTACHED_INODE, - N_("@u @i %i\n"), - PROMPT_CONNECT, 0 }, - - /* Inode ref count wrong */ - { PR_4_BAD_REF_COUNT, - N_("@i %i ref count is %Il, @s %N. "), - PROMPT_FIX, PR_PREEN_OK }, - - { PR_4_INCONSISTENT_COUNT, - N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n" - "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n" - "@i_link_info[%i] is %N, @i.i_links_count is %Il. " - "They @s the same!\n"), - PROMPT_NONE, 0 }, - - /* Pass 5 errors */ - - /* Pass 5: Checking group summary information */ - { PR_5_PASS_HEADER, - N_("Pass 5: Checking @g summary information\n"), - PROMPT_NONE, 0 }, - - /* Padding at end of inode bitmap is not set. */ - { PR_5_INODE_BMAP_PADDING, - N_("Padding at end of @i @B is not set. "), - PROMPT_FIX, PR_PREEN_OK }, - - /* Padding at end of block bitmap is not set. */ - { PR_5_BLOCK_BMAP_PADDING, - N_("Padding at end of @b @B is not set. "), - PROMPT_FIX, PR_PREEN_OK }, - - /* Block bitmap differences header */ - { PR_5_BLOCK_BITMAP_HEADER, - N_("@b @B differences: "), - PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG}, - - /* Block not used, but marked in bitmap */ - { PR_5_BLOCK_UNUSED, - " -%b", - PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG }, - - /* Block used, but not marked used in bitmap */ - { PR_5_BLOCK_USED, - " +%b", - PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG }, - - /* Block bitmap differences end */ - { PR_5_BLOCK_BITMAP_END, - "\n", - PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG }, - - /* Inode bitmap differences header */ - { PR_5_INODE_BITMAP_HEADER, - N_("@i @B differences: "), - PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG }, - - /* Inode not used, but marked in bitmap */ - { PR_5_INODE_UNUSED, - " -%i", - PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG }, - - /* Inode used, but not marked used in bitmap */ - { PR_5_INODE_USED, - " +%i", - PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG }, - - /* Inode bitmap differences end */ - { PR_5_INODE_BITMAP_END, - "\n", - PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG }, - - /* Free inodes count for group wrong */ - { PR_5_FREE_INODE_COUNT_GROUP, - N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"), - PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG }, - - /* Directories count for group wrong */ - { PR_5_FREE_DIR_COUNT_GROUP, - N_("Directories count wrong for @g #%g (%i, counted=%j).\n"), - PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG }, - - /* Free inodes count wrong */ - { PR_5_FREE_INODE_COUNT, - N_("Free @is count wrong (%i, counted=%j).\n"), - PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG }, - - /* Free blocks count for group wrong */ - { PR_5_FREE_BLOCK_COUNT_GROUP, - N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"), - PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG }, - - /* Free blocks count wrong */ - { PR_5_FREE_BLOCK_COUNT, - N_("Free @bs count wrong (%b, counted=%c).\n"), - PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG }, - - /* Programming error: bitmap endpoints don't match */ - { PR_5_BMAP_ENDPOINTS, - N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't " - "match calculated @B endpoints (%i, %j)\n"), - PROMPT_NONE, PR_FATAL }, - - /* Internal error: fudging end of bitmap */ - { PR_5_FUDGE_BITMAP_ERROR, - N_("Internal error: fudging end of bitmap (%N)\n"), - PROMPT_NONE, PR_FATAL }, - - /* Error copying in replacement inode bitmap */ - { PR_5_COPY_IBITMAP_ERROR, - N_("Error copying in replacement @i @B: %m\n"), - PROMPT_NONE, PR_FATAL }, - - /* Error copying in replacement block bitmap */ - { PR_5_COPY_BBITMAP_ERROR, - N_("Error copying in replacement @b @B: %m\n"), - PROMPT_NONE, PR_FATAL }, - - /* Block range not used, but marked in bitmap */ - { PR_5_BLOCK_RANGE_UNUSED, - " -(%b--%c)", - PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG }, - - /* Block range used, but not marked used in bitmap */ - { PR_5_BLOCK_RANGE_USED, - " +(%b--%c)", - PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG }, - - /* Inode range not used, but marked in bitmap */ - { PR_5_INODE_RANGE_UNUSED, - " -(%i--%j)", - PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG }, - - /* Inode range used, but not marked used in bitmap */ - { PR_5_INODE_RANGE_USED, - " +(%i--%j)", - PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG }, - - { 0 } -}; - -/* - * This is the latch flags register. It allows several problems to be - * "latched" together. This means that the user has to answer but one - * question for the set of problems, and all of the associated - * problems will be either fixed or not fixed. - */ -static struct latch_descr pr_latch_info[] = { - { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 }, - { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 }, - { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END }, - { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END }, - { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 }, - { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END }, - { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 }, - { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 }, - { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END }, - { -1, 0, 0 }, -}; - -static const struct e2fsck_problem *find_problem(problem_t code) -{ - int i; - - for (i=0; problem_table[i].e2p_code; i++) { - if (problem_table[i].e2p_code == code) - return &problem_table[i]; - } - return 0; -} - -static struct latch_descr *find_latch(int code) -{ - int i; - - for (i=0; pr_latch_info[i].latch_code >= 0; i++) { - if (pr_latch_info[i].latch_code == code) - return &pr_latch_info[i]; - } - return 0; -} - -int end_problem_latch(e2fsck_t ctx, int mask) -{ - struct latch_descr *ldesc; - struct problem_context pctx; - int answer = -1; - - ldesc = find_latch(mask); - if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) { - clear_problem_context(&pctx); - answer = fix_problem(ctx, ldesc->end_message, &pctx); - } - ldesc->flags &= ~(PRL_VARIABLE); - return answer; -} - -int set_latch_flags(int mask, int setflags, int clearflags) -{ - struct latch_descr *ldesc; - - ldesc = find_latch(mask); - if (!ldesc) - return -1; - ldesc->flags |= setflags; - ldesc->flags &= ~clearflags; - return 0; -} - -void clear_problem_context(struct problem_context *ctx) -{ - memset(ctx, 0, sizeof(struct problem_context)); - ctx->blkcount = -1; - ctx->group = -1; -} - -int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx) -{ - ext2_filsys fs = ctx->fs; - const struct e2fsck_problem *ptr; - struct latch_descr *ldesc = NULL; - const char *message; - int def_yn, answer, ans; - int print_answer = 0; - int suppress = 0; - - ptr = find_problem(code); - if (!ptr) { - printf(_("Unhandled error code (0x%x)!\n"), code); - return 0; - } - def_yn = 1; - if ((ptr->flags & PR_NO_DEFAULT) || - ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) || - (ctx->options & E2F_OPT_NO)) - def_yn= 0; - - /* - * Do special latch processing. This is where we ask the - * latch question, if it exists - */ - if (ptr->flags & PR_LATCH_MASK) { - ldesc = find_latch(ptr->flags & PR_LATCH_MASK); - if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) { - ans = fix_problem(ctx, ldesc->question, pctx); - if (ans == 1) - ldesc->flags |= PRL_YES; - if (ans == 0) - ldesc->flags |= PRL_NO; - ldesc->flags |= PRL_LATCHED; - } - if (ldesc->flags & PRL_SUPPRESS) - suppress++; - } - if ((ptr->flags & PR_PREEN_NOMSG) && - (ctx->options & E2F_OPT_PREEN)) - suppress++; - if ((ptr->flags & PR_NO_NOMSG) && - (ctx->options & E2F_OPT_NO)) - suppress++; - if (!suppress) { - message = ptr->e2p_description; - if ((ctx->options & E2F_OPT_PREEN) && - !(ptr->flags & PR_PREEN_NOHDR)) { - printf("%s: ", ctx->device_name ? - ctx->device_name : ctx->filesystem_name); - } - if (*message) - print_e2fsck_message(ctx, _(message), pctx, 1); - } - if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE)) - preenhalt(ctx); - - if (ptr->flags & PR_FATAL) - bb_error_msg_and_die(0); - - if (ptr->prompt == PROMPT_NONE) { - if (ptr->flags & PR_NOCOLLATE) - answer = -1; - else - answer = def_yn; - } else { - if (ctx->options & E2F_OPT_PREEN) { - answer = def_yn; - if (!(ptr->flags & PR_PREEN_NOMSG)) - print_answer = 1; - } else if ((ptr->flags & PR_LATCH_MASK) && - (ldesc->flags & (PRL_YES | PRL_NO))) { - if (!suppress) - print_answer = 1; - if (ldesc->flags & PRL_YES) - answer = 1; - else - answer = 0; - } else - answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn); - if (!answer && !(ptr->flags & PR_NO_OK)) - ext2fs_unmark_valid(fs); - - if (print_answer) - printf("%s.\n", answer ? - _(preen_msg[(int) ptr->prompt]) : _("IGNORED")); - } - - if ((ptr->prompt == PROMPT_ABORT) && answer) - bb_error_msg_and_die(0); - - if (ptr->flags & PR_AFTER_CODE) - answer = fix_problem(ctx, ptr->second_code, pctx); - - return answer; -} - -/* - * linux/fs/recovery.c - * - * Written by Stephen C. Tweedie , 1999 - */ - -/* - * Maintain information about the progress of the recovery job, so that - * the different passes can carry information between them. - */ -struct recovery_info -{ - tid_t start_transaction; - tid_t end_transaction; - - int nr_replays; - int nr_revokes; - int nr_revoke_hits; -}; - -enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY}; -static int do_one_pass(journal_t *journal, - struct recovery_info *info, enum passtype pass); -static int scan_revoke_records(journal_t *, struct buffer_head *, - tid_t, struct recovery_info *); - -/* - * Read a block from the journal - */ - -static int jread(struct buffer_head **bhp, journal_t *journal, - unsigned int offset) -{ - int err; - unsigned long blocknr; - struct buffer_head *bh; - - *bhp = NULL; - - err = journal_bmap(journal, offset, &blocknr); - - if (err) { - printf("JBD: bad block at offset %u\n", offset); - return err; - } - - bh = getblk(journal->j_dev, blocknr, journal->j_blocksize); - if (!bh) - return -ENOMEM; - - if (!buffer_uptodate(bh)) { - /* If this is a brand new buffer, start readahead. - Otherwise, we assume we are already reading it. */ - if (!buffer_req(bh)) - do_readahead(journal, offset); - wait_on_buffer(bh); - } - - if (!buffer_uptodate(bh)) { - printf("JBD: Failed to read block at offset %u\n", offset); - brelse(bh); - return -EIO; - } - - *bhp = bh; - return 0; -} - - -/* - * Count the number of in-use tags in a journal descriptor block. - */ - -static int count_tags(struct buffer_head *bh, int size) -{ - char * tagp; - journal_block_tag_t * tag; - int nr = 0; - - tagp = &bh->b_data[sizeof(journal_header_t)]; - - while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) { - tag = (journal_block_tag_t *) tagp; - - nr++; - tagp += sizeof(journal_block_tag_t); - if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID))) - tagp += 16; - - if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG)) - break; - } - - return nr; -} - - -/* Make sure we wrap around the log correctly! */ -#define wrap(journal, var) \ -do { \ - if (var >= (journal)->j_last) \ - var -= ((journal)->j_last - (journal)->j_first); \ -} while (0) - -/** - * int journal_recover(journal_t *journal) - recovers a on-disk journal - * @journal: the journal to recover - * - * The primary function for recovering the log contents when mounting a - * journaled device. - * - * Recovery is done in three passes. In the first pass, we look for the - * end of the log. In the second, we assemble the list of revoke - * blocks. In the third and final pass, we replay any un-revoked blocks - * in the log. - */ -int journal_recover(journal_t *journal) -{ - int err; - journal_superblock_t * sb; - - struct recovery_info info; - - memset(&info, 0, sizeof(info)); - sb = journal->j_superblock; - - /* - * The journal superblock's s_start field (the current log head) - * is always zero if, and only if, the journal was cleanly - * unmounted. - */ - - if (!sb->s_start) { - journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1; - return 0; - } - - err = do_one_pass(journal, &info, PASS_SCAN); - if (!err) - err = do_one_pass(journal, &info, PASS_REVOKE); - if (!err) - err = do_one_pass(journal, &info, PASS_REPLAY); - - /* Restart the log at the next transaction ID, thus invalidating - * any existing commit records in the log. */ - journal->j_transaction_sequence = ++info.end_transaction; - - journal_clear_revoke(journal); - sync_blockdev(journal->j_fs_dev); - return err; -} - -static int do_one_pass(journal_t *journal, - struct recovery_info *info, enum passtype pass) -{ - unsigned int first_commit_ID, next_commit_ID; - unsigned long next_log_block; - int err, success = 0; - journal_superblock_t * sb; - journal_header_t * tmp; - struct buffer_head * bh; - unsigned int sequence; - int blocktype; - - /* Precompute the maximum metadata descriptors in a descriptor block */ - int MAX_BLOCKS_PER_DESC; - MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t)) - / sizeof(journal_block_tag_t)); - - /* - * First thing is to establish what we expect to find in the log - * (in terms of transaction IDs), and where (in terms of log - * block offsets): query the superblock. - */ - - sb = journal->j_superblock; - next_commit_ID = ntohl(sb->s_sequence); - next_log_block = ntohl(sb->s_start); - - first_commit_ID = next_commit_ID; - if (pass == PASS_SCAN) - info->start_transaction = first_commit_ID; - - /* - * Now we walk through the log, transaction by transaction, - * making sure that each transaction has a commit block in the - * expected place. Each complete transaction gets replayed back - * into the main filesystem. - */ - - while (1) { - int flags; - char * tagp; - journal_block_tag_t * tag; - struct buffer_head * obh; - struct buffer_head * nbh; - - /* If we already know where to stop the log traversal, - * check right now that we haven't gone past the end of - * the log. */ - - if (pass != PASS_SCAN) - if (tid_geq(next_commit_ID, info->end_transaction)) - break; - - /* Skip over each chunk of the transaction looking - * either the next descriptor block or the final commit - * record. */ - - err = jread(&bh, journal, next_log_block); - if (err) - goto failed; - - next_log_block++; - wrap(journal, next_log_block); - - /* What kind of buffer is it? - * - * If it is a descriptor block, check that it has the - * expected sequence number. Otherwise, we're all done - * here. */ - - tmp = (journal_header_t *)bh->b_data; - - if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) { - brelse(bh); - break; - } - - blocktype = ntohl(tmp->h_blocktype); - sequence = ntohl(tmp->h_sequence); - - if (sequence != next_commit_ID) { - brelse(bh); - break; - } - - /* OK, we have a valid descriptor block which matches - * all of the sequence number checks. What are we going - * to do with it? That depends on the pass... */ - - switch (blocktype) { - case JFS_DESCRIPTOR_BLOCK: - /* If it is a valid descriptor block, replay it - * in pass REPLAY; otherwise, just skip over the - * blocks it describes. */ - if (pass != PASS_REPLAY) { - next_log_block += - count_tags(bh, journal->j_blocksize); - wrap(journal, next_log_block); - brelse(bh); - continue; - } - - /* A descriptor block: we can now write all of - * the data blocks. Yay, useful work is finally - * getting done here! */ - - tagp = &bh->b_data[sizeof(journal_header_t)]; - while ((tagp - bh->b_data +sizeof(journal_block_tag_t)) - <= journal->j_blocksize) { - unsigned long io_block; - - tag = (journal_block_tag_t *) tagp; - flags = ntohl(tag->t_flags); - - io_block = next_log_block++; - wrap(journal, next_log_block); - err = jread(&obh, journal, io_block); - if (err) { - /* Recover what we can, but - * report failure at the end. */ - success = err; - printf("JBD: IO error %d recovering " - "block %ld in log\n", - err, io_block); - } else { - unsigned long blocknr; - - blocknr = ntohl(tag->t_blocknr); - - /* If the block has been - * revoked, then we're all done - * here. */ - if (journal_test_revoke - (journal, blocknr, - next_commit_ID)) { - brelse(obh); - ++info->nr_revoke_hits; - goto skip_write; - } - - /* Find a buffer for the new - * data being restored */ - nbh = getblk(journal->j_fs_dev, - blocknr, - journal->j_blocksize); - if (nbh == NULL) { - printf("JBD: Out of memory " - "during recovery.\n"); - err = -ENOMEM; - brelse(bh); - brelse(obh); - goto failed; - } - - lock_buffer(nbh); - memcpy(nbh->b_data, obh->b_data, - journal->j_blocksize); - if (flags & JFS_FLAG_ESCAPE) { - *((unsigned int *)bh->b_data) = - htonl(JFS_MAGIC_NUMBER); - } - - mark_buffer_uptodate(nbh, 1); - mark_buffer_dirty(nbh); - ++info->nr_replays; - /* ll_rw_block(WRITE, 1, &nbh); */ - unlock_buffer(nbh); - brelse(obh); - brelse(nbh); - } - - skip_write: - tagp += sizeof(journal_block_tag_t); - if (!(flags & JFS_FLAG_SAME_UUID)) - tagp += 16; - - if (flags & JFS_FLAG_LAST_TAG) - break; - } - - brelse(bh); - continue; - - case JFS_COMMIT_BLOCK: - /* Found an expected commit block: not much to - * do other than move on to the next sequence - * number. */ - brelse(bh); - next_commit_ID++; - continue; - - case JFS_REVOKE_BLOCK: - /* If we aren't in the REVOKE pass, then we can - * just skip over this block. */ - if (pass != PASS_REVOKE) { - brelse(bh); - continue; - } - - err = scan_revoke_records(journal, bh, - next_commit_ID, info); - brelse(bh); - if (err) - goto failed; - continue; - - default: - goto done; - } - } - - done: - /* - * We broke out of the log scan loop: either we came to the - * known end of the log or we found an unexpected block in the - * log. If the latter happened, then we know that the "current" - * transaction marks the end of the valid log. - */ - - if (pass == PASS_SCAN) - info->end_transaction = next_commit_ID; - else { - /* It's really bad news if different passes end up at - * different places (but possible due to IO errors). */ - if (info->end_transaction != next_commit_ID) { - printf("JBD: recovery pass %d ended at " - "transaction %u, expected %u\n", - pass, next_commit_ID, info->end_transaction); - if (!success) - success = -EIO; - } - } - - return success; - - failed: - return err; -} - - -/* Scan a revoke record, marking all blocks mentioned as revoked. */ - -static int scan_revoke_records(journal_t *journal, struct buffer_head *bh, - tid_t sequence, struct recovery_info *info) -{ - journal_revoke_header_t *header; - int offset, max; - - header = (journal_revoke_header_t *) bh->b_data; - offset = sizeof(journal_revoke_header_t); - max = ntohl(header->r_count); - - while (offset < max) { - unsigned long blocknr; - int err; - - blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset))); - offset += 4; - err = journal_set_revoke(journal, blocknr, sequence); - if (err) - return err; - ++info->nr_revokes; - } - return 0; -} - - -/* - * rehash.c --- rebuild hash tree directories - * - * This algorithm is designed for simplicity of implementation and to - * pack the directory as much as possible. It however requires twice - * as much memory as the size of the directory. The maximum size - * directory supported using a 4k blocksize is roughly a gigabyte, and - * so there may very well be problems with machines that don't have - * virtual memory, and obscenely large directories. - * - * An alternate algorithm which is much more disk intensive could be - * written, and probably will need to be written in the future. The - * design goals of such an algorithm are: (a) use (roughly) constant - * amounts of memory, no matter how large the directory, (b) the - * directory must be safe at all times, even if e2fsck is interrupted - * in the middle, (c) we must use minimal amounts of extra disk - * blocks. This pretty much requires an incremental approach, where - * we are reading from one part of the directory, and inserting into - * the front half. So the algorithm will have to keep track of a - * moving block boundary between the new tree and the old tree, and - * files will need to be moved from the old directory and inserted - * into the new tree. If the new directory requires space which isn't - * yet available, blocks from the beginning part of the old directory - * may need to be moved to the end of the directory to make room for - * the new tree: - * - * -------------------------------------------------------- - * | new tree | | old tree | - * -------------------------------------------------------- - * ^ ptr ^ptr - * tail new head old - * - * This is going to be a pain in the tuckus to implement, and will - * require a lot more disk accesses. So I'm going to skip it for now; - * it's only really going to be an issue for really, really big - * filesystems (when we reach the level of tens of millions of files - * in a single directory). It will probably be easier to simply - * require that e2fsck use VM first. - */ - -struct fill_dir_struct { - char *buf; - struct ext2_inode *inode; - int err; - e2fsck_t ctx; - struct hash_entry *harray; - int max_array, num_array; - int dir_size; - int compress; - ino_t parent; -}; - -struct hash_entry { - ext2_dirhash_t hash; - ext2_dirhash_t minor_hash; - struct ext2_dir_entry *dir; -}; - -struct out_dir { - int num; - int max; - char *buf; - ext2_dirhash_t *hashes; -}; - -static int fill_dir_block(ext2_filsys fs, - blk_t *block_nr, - e2_blkcnt_t blockcnt, - blk_t ref_block FSCK_ATTR((unused)), - int ref_offset FSCK_ATTR((unused)), - void *priv_data) -{ - struct fill_dir_struct *fd = (struct fill_dir_struct *) priv_data; - struct hash_entry *new_array, *ent; - struct ext2_dir_entry *dirent; - char *dir; - unsigned int offset, dir_offset; - - if (blockcnt < 0) - return 0; - - offset = blockcnt * fs->blocksize; - if (offset + fs->blocksize > fd->inode->i_size) { - fd->err = EXT2_ET_DIR_CORRUPTED; - return BLOCK_ABORT; - } - dir = (fd->buf+offset); - if (HOLE_BLKADDR(*block_nr)) { - memset(dir, 0, fs->blocksize); - dirent = (struct ext2_dir_entry *) dir; - dirent->rec_len = fs->blocksize; - } else { - fd->err = ext2fs_read_dir_block(fs, *block_nr, dir); - if (fd->err) - return BLOCK_ABORT; - } - /* While the directory block is "hot", index it. */ - dir_offset = 0; - while (dir_offset < fs->blocksize) { - dirent = (struct ext2_dir_entry *) (dir + dir_offset); - if (((dir_offset + dirent->rec_len) > fs->blocksize) || - (dirent->rec_len < 8) || - ((dirent->rec_len % 4) != 0) || - (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) { - fd->err = EXT2_ET_DIR_CORRUPTED; - return BLOCK_ABORT; - } - dir_offset += dirent->rec_len; - if (dirent->inode == 0) - continue; - if (!fd->compress && ((dirent->name_len&0xFF) == 1) && - (dirent->name[0] == '.')) - continue; - if (!fd->compress && ((dirent->name_len&0xFF) == 2) && - (dirent->name[0] == '.') && (dirent->name[1] == '.')) { - fd->parent = dirent->inode; - continue; - } - if (fd->num_array >= fd->max_array) { - new_array = xrealloc(fd->harray, - sizeof(struct hash_entry) * (fd->max_array+500)); - fd->harray = new_array; - fd->max_array += 500; - } - ent = fd->harray + fd->num_array++; - ent->dir = dirent; - fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF); - if (fd->compress) - ent->hash = ent->minor_hash = 0; - else { - fd->err = ext2fs_dirhash(fs->super->s_def_hash_version, - dirent->name, - dirent->name_len & 0xFF, - fs->super->s_hash_seed, - &ent->hash, &ent->minor_hash); - if (fd->err) - return BLOCK_ABORT; - } - } - - return 0; -} - -/* Used for sorting the hash entry */ -static int name_cmp(const void *a, const void *b) -{ - const struct hash_entry *he_a = (const struct hash_entry *) a; - const struct hash_entry *he_b = (const struct hash_entry *) b; - int ret; - int min_len; - - min_len = he_a->dir->name_len; - if (min_len > he_b->dir->name_len) - min_len = he_b->dir->name_len; - - ret = strncmp(he_a->dir->name, he_b->dir->name, min_len); - if (ret == 0) { - if (he_a->dir->name_len > he_b->dir->name_len) - ret = 1; - else if (he_a->dir->name_len < he_b->dir->name_len) - ret = -1; - else - ret = he_b->dir->inode - he_a->dir->inode; - } - return ret; -} - -/* Used for sorting the hash entry */ -static int hash_cmp(const void *a, const void *b) -{ - const struct hash_entry *he_a = (const struct hash_entry *) a; - const struct hash_entry *he_b = (const struct hash_entry *) b; - int ret; - - if (he_a->hash > he_b->hash) - ret = 1; - else if (he_a->hash < he_b->hash) - ret = -1; - else { - if (he_a->minor_hash > he_b->minor_hash) - ret = 1; - else if (he_a->minor_hash < he_b->minor_hash) - ret = -1; - else - ret = name_cmp(a, b); - } - return ret; -} - -static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir, - int blocks) -{ - void *new_mem; - - if (outdir->max) { - new_mem = xrealloc(outdir->buf, blocks * fs->blocksize); - outdir->buf = new_mem; - new_mem = xrealloc(outdir->hashes, - blocks * sizeof(ext2_dirhash_t)); - outdir->hashes = new_mem; - } else { - outdir->buf = xmalloc(blocks * fs->blocksize); - outdir->hashes = xmalloc(blocks * sizeof(ext2_dirhash_t)); - outdir->num = 0; - } - outdir->max = blocks; - return 0; -} - -static void free_out_dir(struct out_dir *outdir) -{ - free(outdir->buf); - free(outdir->hashes); - outdir->max = 0; - outdir->num =0; -} - -static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir, - char ** ret) -{ - errcode_t retval; - - if (outdir->num >= outdir->max) { - retval = alloc_size_dir(fs, outdir, outdir->max + 50); - if (retval) - return retval; - } - *ret = outdir->buf + (outdir->num++ * fs->blocksize); - memset(*ret, 0, fs->blocksize); - return 0; -} - -/* - * This function is used to make a unique filename. We do this by - * appending ~0, and then incrementing the number. However, we cannot - * expand the length of the filename beyond the padding available in - * the directory entry. - */ -static void mutate_name(char *str, __u16 *len) -{ - int i; - __u16 l = *len & 0xFF, h = *len & 0xff00; - - /* - * First check to see if it looks the name has been mutated - * already - */ - for (i = l-1; i > 0; i--) { - if (!isdigit(str[i])) - break; - } - if ((i == l-1) || (str[i] != '~')) { - if (((l-1) & 3) < 2) - l += 2; - else - l = (l+3) & ~3; - str[l-2] = '~'; - str[l-1] = '0'; - *len = l | h; - return; - } - for (i = l-1; i >= 0; i--) { - if (isdigit(str[i])) { - if (str[i] == '9') - str[i] = '0'; - else { - str[i]++; - return; - } - continue; - } - if (i == 1) { - if (str[0] == 'z') - str[0] = 'A'; - else if (str[0] == 'Z') { - str[0] = '~'; - str[1] = '0'; - } else - str[0]++; - } else if (i > 0) { - str[i] = '1'; - str[i-1] = '~'; - } else { - if (str[0] == '~') - str[0] = 'a'; - else - str[0]++; - } - break; - } -} - -static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs, - ext2_ino_t ino, - struct fill_dir_struct *fd) -{ - struct problem_context pctx; - struct hash_entry *ent, *prev; - int i, j; - int fixed = 0; - char new_name[256]; - __u16 new_len; - - clear_problem_context(&pctx); - pctx.ino = ino; - - for (i=1; i < fd->num_array; i++) { - ent = fd->harray + i; - prev = ent - 1; - if (!ent->dir->inode || - ((ent->dir->name_len & 0xFF) != - (prev->dir->name_len & 0xFF)) || - (strncmp(ent->dir->name, prev->dir->name, - ent->dir->name_len & 0xFF))) - continue; - pctx.dirent = ent->dir; - if ((ent->dir->inode == prev->dir->inode) && - fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) { - e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1); - ent->dir->inode = 0; - fixed++; - continue; - } - memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF); - new_len = ent->dir->name_len; - mutate_name(new_name, &new_len); - for (j=0; j < fd->num_array; j++) { - if ((i==j) || - ((ent->dir->name_len & 0xFF) != - (fd->harray[j].dir->name_len & 0xFF)) || - (strncmp(new_name, fd->harray[j].dir->name, - new_len & 0xFF))) - continue; - mutate_name(new_name, &new_len); - - j = -1; - } - new_name[new_len & 0xFF] = 0; - pctx.str = new_name; - if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) { - memcpy(ent->dir->name, new_name, new_len & 0xFF); - ent->dir->name_len = new_len; - ext2fs_dirhash(fs->super->s_def_hash_version, - ent->dir->name, - ent->dir->name_len & 0xFF, - fs->super->s_hash_seed, - &ent->hash, &ent->minor_hash); - fixed++; - } - } - return fixed; -} - - -static errcode_t copy_dir_entries(ext2_filsys fs, - struct fill_dir_struct *fd, - struct out_dir *outdir) -{ - errcode_t retval; - char *block_start; - struct hash_entry *ent; - struct ext2_dir_entry *dirent; - int i, rec_len, left; - ext2_dirhash_t prev_hash; - int offset; - - outdir->max = 0; - retval = alloc_size_dir(fs, outdir, - (fd->dir_size / fs->blocksize) + 2); - if (retval) - return retval; - outdir->num = fd->compress ? 0 : 1; - offset = 0; - outdir->hashes[0] = 0; - prev_hash = 1; - if ((retval = get_next_block(fs, outdir, &block_start))) - return retval; - dirent = (struct ext2_dir_entry *) block_start; - left = fs->blocksize; - for (i=0; i < fd->num_array; i++) { - ent = fd->harray + i; - if (ent->dir->inode == 0) - continue; - rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF); - if (rec_len > left) { - if (left) - dirent->rec_len += left; - if ((retval = get_next_block(fs, outdir, - &block_start))) - return retval; - offset = 0; - } - left = fs->blocksize - offset; - dirent = (struct ext2_dir_entry *) (block_start + offset); - if (offset == 0) { - if (ent->hash == prev_hash) - outdir->hashes[outdir->num-1] = ent->hash | 1; - else - outdir->hashes[outdir->num-1] = ent->hash; - } - dirent->inode = ent->dir->inode; - dirent->name_len = ent->dir->name_len; - dirent->rec_len = rec_len; - memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF); - offset += rec_len; - left -= rec_len; - if (left < 12) { - dirent->rec_len += left; - offset += left; - left = 0; - } - prev_hash = ent->hash; - } - if (left) - dirent->rec_len += left; - - return 0; -} - - -static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf, - ext2_ino_t ino, ext2_ino_t parent) -{ - struct ext2_dir_entry *dir; - struct ext2_dx_root_info *root; - struct ext2_dx_countlimit *limits; - int filetype = 0; - - if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE) - filetype = EXT2_FT_DIR << 8; - - memset(buf, 0, fs->blocksize); - dir = (struct ext2_dir_entry *) buf; - dir->inode = ino; - dir->name[0] = '.'; - dir->name_len = 1 | filetype; - dir->rec_len = 12; - dir = (struct ext2_dir_entry *) (buf + 12); - dir->inode = parent; - dir->name[0] = '.'; - dir->name[1] = '.'; - dir->name_len = 2 | filetype; - dir->rec_len = fs->blocksize - 12; - - root = (struct ext2_dx_root_info *) (buf+24); - root->reserved_zero = 0; - root->hash_version = fs->super->s_def_hash_version; - root->info_length = 8; - root->indirect_levels = 0; - root->unused_flags = 0; - - limits = (struct ext2_dx_countlimit *) (buf+32); - limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry); - limits->count = 0; - - return root; -} - - -static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf) -{ - struct ext2_dir_entry *dir; - struct ext2_dx_countlimit *limits; - - memset(buf, 0, fs->blocksize); - dir = (struct ext2_dir_entry *) buf; - dir->inode = 0; - dir->rec_len = fs->blocksize; - - limits = (struct ext2_dx_countlimit *) (buf+8); - limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry); - limits->count = 0; - - return (struct ext2_dx_entry *) limits; -} - -/* - * This function takes the leaf nodes which have been written in - * outdir, and populates the root node and any necessary interior nodes. - */ -static errcode_t calculate_tree(ext2_filsys fs, - struct out_dir *outdir, - ext2_ino_t ino, - ext2_ino_t parent) -{ - struct ext2_dx_root_info *root_info; - struct ext2_dx_entry *root, *dx_ent = NULL; - struct ext2_dx_countlimit *root_limit, *limit; - errcode_t retval; - char * block_start; - int i, c1, c2, nblks; - int limit_offset, root_offset; - - root_info = set_root_node(fs, outdir->buf, ino, parent); - root_offset = limit_offset = ((char *) root_info - outdir->buf) + - root_info->info_length; - root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset); - c1 = root_limit->limit; - nblks = outdir->num; - - /* Write out the pointer blocks */ - if (nblks-1 <= c1) { - /* Just write out the root block, and we're done */ - root = (struct ext2_dx_entry *) (outdir->buf + root_offset); - for (i=1; i < nblks; i++) { - root->block = ext2fs_cpu_to_le32(i); - if (i != 1) - root->hash = - ext2fs_cpu_to_le32(outdir->hashes[i]); - root++; - c1--; - } - } else { - c2 = 0; - limit = 0; - root_info->indirect_levels = 1; - for (i=1; i < nblks; i++) { - if (c1 == 0) - return ENOSPC; - if (c2 == 0) { - if (limit) - limit->limit = limit->count = - ext2fs_cpu_to_le16(limit->limit); - root = (struct ext2_dx_entry *) - (outdir->buf + root_offset); - root->block = ext2fs_cpu_to_le32(outdir->num); - if (i != 1) - root->hash = - ext2fs_cpu_to_le32(outdir->hashes[i]); - if ((retval = get_next_block(fs, outdir, - &block_start))) - return retval; - dx_ent = set_int_node(fs, block_start); - limit = (struct ext2_dx_countlimit *) dx_ent; - c2 = limit->limit; - root_offset += sizeof(struct ext2_dx_entry); - c1--; - } - dx_ent->block = ext2fs_cpu_to_le32(i); - if (c2 != limit->limit) - dx_ent->hash = - ext2fs_cpu_to_le32(outdir->hashes[i]); - dx_ent++; - c2--; - } - limit->count = ext2fs_cpu_to_le16(limit->limit - c2); - limit->limit = ext2fs_cpu_to_le16(limit->limit); - } - root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset); - root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1); - root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit); - - return 0; -} - -struct write_dir_struct { - struct out_dir *outdir; - errcode_t err; - e2fsck_t ctx; - int cleared; -}; - -/* - * Helper function which writes out a directory block. - */ -static int write_dir_block(ext2_filsys fs, - blk_t *block_nr, - e2_blkcnt_t blockcnt, - blk_t ref_block FSCK_ATTR((unused)), - int ref_offset FSCK_ATTR((unused)), - void *priv_data) -{ - struct write_dir_struct *wd = (struct write_dir_struct *) priv_data; - blk_t blk; - char *dir; - - if (*block_nr == 0) - return 0; - if (blockcnt >= wd->outdir->num) { - e2fsck_read_bitmaps(wd->ctx); - blk = *block_nr; - ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk); - ext2fs_block_alloc_stats(fs, blk, -1); - *block_nr = 0; - wd->cleared++; - return BLOCK_CHANGED; - } - if (blockcnt < 0) - return 0; - - dir = wd->outdir->buf + (blockcnt * fs->blocksize); - wd->err = ext2fs_write_dir_block(fs, *block_nr, dir); - if (wd->err) - return BLOCK_ABORT; - return 0; -} - -static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs, - struct out_dir *outdir, - ext2_ino_t ino, int compress) -{ - struct write_dir_struct wd; - errcode_t retval; - struct ext2_inode inode; - - retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num); - if (retval) - return retval; - - wd.outdir = outdir; - wd.err = 0; - wd.ctx = ctx; - wd.cleared = 0; - - retval = ext2fs_block_iterate2(fs, ino, 0, 0, - write_dir_block, &wd); - if (retval) - return retval; - if (wd.err) - return wd.err; - - e2fsck_read_inode(ctx, ino, &inode, "rehash_dir"); - if (compress) - inode.i_flags &= ~EXT2_INDEX_FL; - else - inode.i_flags |= EXT2_INDEX_FL; - inode.i_size = outdir->num * fs->blocksize; - inode.i_blocks -= (fs->blocksize / 512) * wd.cleared; - e2fsck_write_inode(ctx, ino, &inode, "rehash_dir"); - - return 0; -} - -static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino) -{ - ext2_filsys fs = ctx->fs; - errcode_t retval; - struct ext2_inode inode; - char *dir_buf = NULL; - struct fill_dir_struct fd; - struct out_dir outdir; - - outdir.max = outdir.num = 0; - outdir.buf = 0; - outdir.hashes = 0; - e2fsck_read_inode(ctx, ino, &inode, "rehash_dir"); - - retval = ENOMEM; - fd.harray = 0; - dir_buf = xmalloc(inode.i_size); - - fd.max_array = inode.i_size / 32; - fd.num_array = 0; - fd.harray = xmalloc(fd.max_array * sizeof(struct hash_entry)); - - fd.ctx = ctx; - fd.buf = dir_buf; - fd.inode = &inode; - fd.err = 0; - fd.dir_size = 0; - fd.compress = 0; - if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) || - (inode.i_size / fs->blocksize) < 2) - fd.compress = 1; - fd.parent = 0; - - /* Read in the entire directory into memory */ - retval = ext2fs_block_iterate2(fs, ino, 0, 0, - fill_dir_block, &fd); - if (fd.err) { - retval = fd.err; - goto errout; - } - - /* Sort the list */ -resort: - if (fd.compress) - qsort(fd.harray+2, fd.num_array-2, - sizeof(struct hash_entry), name_cmp); - else - qsort(fd.harray, fd.num_array, - sizeof(struct hash_entry), hash_cmp); - - /* - * Look for duplicates - */ - if (duplicate_search_and_fix(ctx, fs, ino, &fd)) - goto resort; - - if (ctx->options & E2F_OPT_NO) { - retval = 0; - goto errout; - } - - /* - * Copy the directory entries. In a htree directory these - * will become the leaf nodes. - */ - retval = copy_dir_entries(fs, &fd, &outdir); - if (retval) - goto errout; - - free(dir_buf); dir_buf = 0; - - if (!fd.compress) { - /* Calculate the interior nodes */ - retval = calculate_tree(fs, &outdir, ino, fd.parent); - if (retval) - goto errout; - } - - retval = write_directory(ctx, fs, &outdir, ino, fd.compress); - -errout: - free(dir_buf); - free(fd.harray); - - free_out_dir(&outdir); - return retval; -} - -void e2fsck_rehash_directories(e2fsck_t ctx) -{ - struct problem_context pctx; - struct dir_info *dir; - ext2_u32_iterate iter; - ext2_ino_t ino; - errcode_t retval; - int i, cur, max, all_dirs, dir_index, first = 1; - - all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS; - - if (!ctx->dirs_to_hash && !all_dirs) - return; - - e2fsck_get_lost_and_found(ctx, 0); - - clear_problem_context(&pctx); - - dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX; - cur = 0; - if (all_dirs) { - i = 0; - max = e2fsck_get_num_dirinfo(ctx); - } else { - retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash, - &iter); - if (retval) { - pctx.errcode = retval; - fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx); - return; - } - max = ext2fs_u32_list_count(ctx->dirs_to_hash); - } - while (1) { - if (all_dirs) { - if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0) - break; - ino = dir->ino; - } else { - if (!ext2fs_u32_list_iterate(iter, &ino)) - break; - } - if (ino == ctx->lost_and_found) - continue; - pctx.dir = ino; - if (first) { - fix_problem(ctx, PR_3A_PASS_HEADER, &pctx); - first = 0; - } - pctx.errcode = e2fsck_rehash_dir(ctx, ino); - if (pctx.errcode) { - end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR); - fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx); - } - if (ctx->progress && !ctx->progress_fd) - e2fsck_simple_progress(ctx, "Rebuilding directory", - 100.0 * (float) (++cur) / (float) max, ino); - } - end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR); - if (!all_dirs) - ext2fs_u32_list_iterate_end(iter); - - ext2fs_u32_list_free(ctx->dirs_to_hash); - ctx->dirs_to_hash = 0; -} - -/* - * linux/fs/revoke.c - * - * Journal revoke routines for the generic filesystem journaling code; - * part of the ext2fs journaling system. - * - * Revoke is the mechanism used to prevent old log records for deleted - * metadata from being replayed on top of newer data using the same - * blocks. The revoke mechanism is used in two separate places: - * - * + Commit: during commit we write the entire list of the current - * transaction's revoked blocks to the journal - * - * + Recovery: during recovery we record the transaction ID of all - * revoked blocks. If there are multiple revoke records in the log - * for a single block, only the last one counts, and if there is a log - * entry for a block beyond the last revoke, then that log entry still - * gets replayed. - * - * We can get interactions between revokes and new log data within a - * single transaction: - * - * Block is revoked and then journaled: - * The desired end result is the journaling of the new block, so we - * cancel the revoke before the transaction commits. - * - * Block is journaled and then revoked: - * The revoke must take precedence over the write of the block, so we - * need either to cancel the journal entry or to write the revoke - * later in the log than the log block. In this case, we choose the - * latter: journaling a block cancels any revoke record for that block - * in the current transaction, so any revoke for that block in the - * transaction must have happened after the block was journaled and so - * the revoke must take precedence. - * - * Block is revoked and then written as data: - * The data write is allowed to succeed, but the revoke is _not_ - * cancelled. We still need to prevent old log records from - * overwriting the new data. We don't even need to clear the revoke - * bit here. - * - * Revoke information on buffers is a tri-state value: - * - * RevokeValid clear: no cached revoke status, need to look it up - * RevokeValid set, Revoked clear: - * buffer has not been revoked, and cancel_revoke - * need do nothing. - * RevokeValid set, Revoked set: - * buffer has been revoked. - */ - -static kmem_cache_t *revoke_record_cache; -static kmem_cache_t *revoke_table_cache; - -/* Each revoke record represents one single revoked block. During - journal replay, this involves recording the transaction ID of the - last transaction to revoke this block. */ - -struct jbd_revoke_record_s -{ - struct list_head hash; - tid_t sequence; /* Used for recovery only */ - unsigned long blocknr; -}; - - -/* The revoke table is just a simple hash table of revoke records. */ -struct jbd_revoke_table_s -{ - /* It is conceivable that we might want a larger hash table - * for recovery. Must be a power of two. */ - int hash_size; - int hash_shift; - struct list_head *hash_table; -}; - - -/* Utility functions to maintain the revoke table */ - -/* Borrowed from buffer.c: this is a tried and tested block hash function */ -static int hash(journal_t *journal, unsigned long block) -{ - struct jbd_revoke_table_s *table = journal->j_revoke; - int hash_shift = table->hash_shift; - - return ((block << (hash_shift - 6)) ^ - (block >> 13) ^ - (block << (hash_shift - 12))) & (table->hash_size - 1); -} - -static int insert_revoke_hash(journal_t *journal, unsigned long blocknr, - tid_t seq) -{ - struct list_head *hash_list; - struct jbd_revoke_record_s *record; - - record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS); - if (!record) - goto oom; - - record->sequence = seq; - record->blocknr = blocknr; - hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)]; - list_add(&record->hash, hash_list); - return 0; - -oom: - return -ENOMEM; -} - -/* Find a revoke record in the journal's hash table. */ - -static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal, - unsigned long blocknr) -{ - struct list_head *hash_list; - struct jbd_revoke_record_s *record; - - hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)]; - - record = (struct jbd_revoke_record_s *) hash_list->next; - while (&(record->hash) != hash_list) { - if (record->blocknr == blocknr) - return record; - record = (struct jbd_revoke_record_s *) record->hash.next; - } - return NULL; -} - -int journal_init_revoke_caches(void) -{ - revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s)); - if (revoke_record_cache == 0) - return -ENOMEM; - - revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s)); - if (revoke_table_cache == 0) { - do_cache_destroy(revoke_record_cache); - revoke_record_cache = NULL; - return -ENOMEM; - } - return 0; -} - -void journal_destroy_revoke_caches(void) -{ - do_cache_destroy(revoke_record_cache); - revoke_record_cache = 0; - do_cache_destroy(revoke_table_cache); - revoke_table_cache = 0; -} - -/* Initialise the revoke table for a given journal to a given size. */ - -int journal_init_revoke(journal_t *journal, int hash_size) -{ - int shift, tmp; - - journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL); - if (!journal->j_revoke) - return -ENOMEM; - - /* Check that the hash_size is a power of two */ - journal->j_revoke->hash_size = hash_size; - - shift = 0; - tmp = hash_size; - while ((tmp >>= 1UL) != 0UL) - shift++; - journal->j_revoke->hash_shift = shift; - - journal->j_revoke->hash_table = xmalloc(hash_size * sizeof(struct list_head)); - - for (tmp = 0; tmp < hash_size; tmp++) - INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]); - - return 0; -} - -/* Destoy a journal's revoke table. The table must already be empty! */ - -void journal_destroy_revoke(journal_t *journal) -{ - struct jbd_revoke_table_s *table; - struct list_head *hash_list; - int i; - - table = journal->j_revoke; - if (!table) - return; - - for (i=0; ihash_size; i++) { - hash_list = &table->hash_table[i]; - } - - free(table->hash_table); - free(table); - journal->j_revoke = NULL; -} - -/* - * Revoke support for recovery. - * - * Recovery needs to be able to: - * - * record all revoke records, including the tid of the latest instance - * of each revoke in the journal - * - * check whether a given block in a given transaction should be replayed - * (ie. has not been revoked by a revoke record in that or a subsequent - * transaction) - * - * empty the revoke table after recovery. - */ - -/* - * First, setting revoke records. We create a new revoke record for - * every block ever revoked in the log as we scan it for recovery, and - * we update the existing records if we find multiple revokes for a - * single block. - */ - -int journal_set_revoke(journal_t *journal, unsigned long blocknr, - tid_t sequence) -{ - struct jbd_revoke_record_s *record; - - record = find_revoke_record(journal, blocknr); - if (record) { - /* If we have multiple occurences, only record the - * latest sequence number in the hashed record */ - if (tid_gt(sequence, record->sequence)) - record->sequence = sequence; - return 0; - } - return insert_revoke_hash(journal, blocknr, sequence); -} - -/* - * Test revoke records. For a given block referenced in the log, has - * that block been revoked? A revoke record with a given transaction - * sequence number revokes all blocks in that transaction and earlier - * ones, but later transactions still need replayed. - */ - -int journal_test_revoke(journal_t *journal, unsigned long blocknr, - tid_t sequence) -{ - struct jbd_revoke_record_s *record; - - record = find_revoke_record(journal, blocknr); - if (!record) - return 0; - if (tid_gt(sequence, record->sequence)) - return 0; - return 1; -} - -/* - * Finally, once recovery is over, we need to clear the revoke table so - * that it can be reused by the running filesystem. - */ - -void journal_clear_revoke(journal_t *journal) -{ - int i; - struct list_head *hash_list; - struct jbd_revoke_record_s *record; - struct jbd_revoke_table_s *revoke_var; - - revoke_var = journal->j_revoke; - - for (i = 0; i < revoke_var->hash_size; i++) { - hash_list = &revoke_var->hash_table[i]; - while (!list_empty(hash_list)) { - record = (struct jbd_revoke_record_s*) hash_list->next; - list_del(&record->hash); - free(record); - } - } -} - -/* - * e2fsck.c - superblock checks - */ - -#define MIN_CHECK 1 -#define MAX_CHECK 2 - -static void check_super_value(e2fsck_t ctx, const char *descr, - unsigned long value, int flags, - unsigned long min_val, unsigned long max_val) -{ - struct problem_context pctx; - - if (((flags & MIN_CHECK) && (value < min_val)) || - ((flags & MAX_CHECK) && (value > max_val))) { - clear_problem_context(&pctx); - pctx.num = value; - pctx.str = descr; - fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx); - ctx->flags |= E2F_FLAG_ABORT; /* never get here! */ - } -} - -/* - * This routine may get stubbed out in special compilations of the - * e2fsck code.. - */ -#ifndef EXT2_SPECIAL_DEVICE_SIZE -static errcode_t e2fsck_get_device_size(e2fsck_t ctx) -{ - return (ext2fs_get_device_size(ctx->filesystem_name, - EXT2_BLOCK_SIZE(ctx->fs->super), - &ctx->num_blocks)); -} -#endif - -/* - * helper function to release an inode - */ -struct process_block_struct { - e2fsck_t ctx; - char *buf; - struct problem_context *pctx; - int truncating; - int truncate_offset; - e2_blkcnt_t truncate_block; - int truncated_blocks; - int abort; - errcode_t errcode; -}; - -static int release_inode_block(ext2_filsys fs, blk_t *block_nr, - e2_blkcnt_t blockcnt, - blk_t ref_blk FSCK_ATTR((unused)), - int ref_offset FSCK_ATTR((unused)), - void *priv_data) -{ - struct process_block_struct *pb; - e2fsck_t ctx; - struct problem_context *pctx; - blk_t blk = *block_nr; - int retval = 0; - - pb = (struct process_block_struct *) priv_data; - ctx = pb->ctx; - pctx = pb->pctx; - - pctx->blk = blk; - pctx->blkcount = blockcnt; - - if (HOLE_BLKADDR(blk)) - return 0; - - if ((blk < fs->super->s_first_data_block) || - (blk >= fs->super->s_blocks_count)) { - fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx); - return_abort: - pb->abort = 1; - return BLOCK_ABORT; - } - - if (!ext2fs_test_block_bitmap(fs->block_map, blk)) { - fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx); - goto return_abort; - } - - /* - * If we are deleting an orphan, then we leave the fields alone. - * If we are truncating an orphan, then update the inode fields - * and clean up any partial block data. - */ - if (pb->truncating) { - /* - * We only remove indirect blocks if they are - * completely empty. - */ - if (blockcnt < 0) { - int i, limit; - blk_t *bp; - - pb->errcode = io_channel_read_blk(fs->io, blk, 1, - pb->buf); - if (pb->errcode) - goto return_abort; - - limit = fs->blocksize >> 2; - for (i = 0, bp = (blk_t *) pb->buf; - i < limit; i++, bp++) - if (*bp) - return 0; - } - /* - * We don't remove direct blocks until we've reached - * the truncation block. - */ - if (blockcnt >= 0 && blockcnt < pb->truncate_block) - return 0; - /* - * If part of the last block needs truncating, we do - * it here. - */ - if ((blockcnt == pb->truncate_block) && pb->truncate_offset) { - pb->errcode = io_channel_read_blk(fs->io, blk, 1, - pb->buf); - if (pb->errcode) - goto return_abort; - memset(pb->buf + pb->truncate_offset, 0, - fs->blocksize - pb->truncate_offset); - pb->errcode = io_channel_write_blk(fs->io, blk, 1, - pb->buf); - if (pb->errcode) - goto return_abort; - } - pb->truncated_blocks++; - *block_nr = 0; - retval |= BLOCK_CHANGED; - } - - ext2fs_block_alloc_stats(fs, blk, -1); - return retval; -} - -/* - * This function releases an inode. Returns 1 if an inconsistency was - * found. If the inode has a link count, then it is being truncated and - * not deleted. - */ -static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, - struct ext2_inode *inode, char *block_buf, - struct problem_context *pctx) -{ - struct process_block_struct pb; - ext2_filsys fs = ctx->fs; - errcode_t retval; - __u32 count; - - if (!ext2fs_inode_has_valid_blocks(inode)) - return 0; - - pb.buf = block_buf + 3 * ctx->fs->blocksize; - pb.ctx = ctx; - pb.abort = 0; - pb.errcode = 0; - pb.pctx = pctx; - if (inode->i_links_count) { - pb.truncating = 1; - pb.truncate_block = (e2_blkcnt_t) - ((((long long)inode->i_size_high << 32) + - inode->i_size + fs->blocksize - 1) / - fs->blocksize); - pb.truncate_offset = inode->i_size % fs->blocksize; - } else { - pb.truncating = 0; - pb.truncate_block = 0; - pb.truncate_offset = 0; - } - pb.truncated_blocks = 0; - retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE, - block_buf, release_inode_block, &pb); - if (retval) { - bb_error_msg(_("while calling ext2fs_block_iterate for inode %d"), - ino); - return 1; - } - if (pb.abort) - return 1; - - /* Refresh the inode since ext2fs_block_iterate may have changed it */ - e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks"); - - if (pb.truncated_blocks) - inode->i_blocks -= pb.truncated_blocks * - (fs->blocksize / 512); - - if (inode->i_file_acl) { - retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl, - block_buf, -1, &count); - if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) { - retval = 0; - count = 1; - } - if (retval) { - bb_error_msg(_("while calling ext2fs_adjust_ea_refcount for inode %d"), - ino); - return 1; - } - if (count == 0) - ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1); - inode->i_file_acl = 0; - } - return 0; -} - -/* - * This function releases all of the orphan inodes. It returns 1 if - * it hit some error, and 0 on success. - */ -static int release_orphan_inodes(e2fsck_t ctx) -{ - ext2_filsys fs = ctx->fs; - ext2_ino_t ino, next_ino; - struct ext2_inode inode; - struct problem_context pctx; - char *block_buf; - - if ((ino = fs->super->s_last_orphan) == 0) - return 0; - - /* - * Win or lose, we won't be using the head of the orphan inode - * list again. - */ - fs->super->s_last_orphan = 0; - ext2fs_mark_super_dirty(fs); - - /* - * If the filesystem contains errors, don't run the orphan - * list, since the orphan list can't be trusted; and we're - * going to be running a full e2fsck run anyway... - */ - if (fs->super->s_state & EXT2_ERROR_FS) - return 0; - - if ((ino < EXT2_FIRST_INODE(fs->super)) || - (ino > fs->super->s_inodes_count)) { - clear_problem_context(&pctx); - pctx.ino = ino; - fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx); - return 1; - } - - block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4, - "block iterate buffer"); - e2fsck_read_bitmaps(ctx); - - while (ino) { - e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes"); - clear_problem_context(&pctx); - pctx.ino = ino; - pctx.inode = &inode; - pctx.str = inode.i_links_count ? _("Truncating") : - _("Clearing"); - - fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx); - - next_ino = inode.i_dtime; - if (next_ino && - ((next_ino < EXT2_FIRST_INODE(fs->super)) || - (next_ino > fs->super->s_inodes_count))) { - pctx.ino = next_ino; - fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx); - goto return_abort; - } - - if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx)) - goto return_abort; - - if (!inode.i_links_count) { - ext2fs_inode_alloc_stats2(fs, ino, -1, - LINUX_S_ISDIR(inode.i_mode)); - inode.i_dtime = time(NULL); - } else { - inode.i_dtime = 0; - } - e2fsck_write_inode(ctx, ino, &inode, "delete_file"); - ino = next_ino; - } - ext2fs_free_mem(&block_buf); - return 0; - return_abort: - ext2fs_free_mem(&block_buf); - return 1; -} - -/* - * Check the resize inode to make sure it is sane. We check both for - * the case where on-line resizing is not enabled (in which case the - * resize inode should be cleared) as well as the case where on-line - * resizing is enabled. - */ -static void check_resize_inode(e2fsck_t ctx) -{ - ext2_filsys fs = ctx->fs; - struct ext2_inode inode; - struct problem_context pctx; - int i, j, gdt_off, ind_off; - blk_t blk, pblk, expect; - __u32 *dind_buf = NULL, *ind_buf; - errcode_t retval; - - clear_problem_context(&pctx); - - /* - * If the resize inode feature isn't set, then - * s_reserved_gdt_blocks must be zero. - */ - if (!(fs->super->s_feature_compat & - EXT2_FEATURE_COMPAT_RESIZE_INO)) { - if (fs->super->s_reserved_gdt_blocks) { - pctx.num = fs->super->s_reserved_gdt_blocks; - if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS, - &pctx)) { - fs->super->s_reserved_gdt_blocks = 0; - ext2fs_mark_super_dirty(fs); - } - } - } - - /* Read the resize inode */ - pctx.ino = EXT2_RESIZE_INO; - retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode); - if (retval) { - if (fs->super->s_feature_compat & - EXT2_FEATURE_COMPAT_RESIZE_INO) - ctx->flags |= E2F_FLAG_RESIZE_INODE; - return; - } - - /* - * If the resize inode feature isn't set, check to make sure - * the resize inode is cleared; then we're done. - */ - if (!(fs->super->s_feature_compat & - EXT2_FEATURE_COMPAT_RESIZE_INO)) { - for (i=0; i < EXT2_N_BLOCKS; i++) { - if (inode.i_block[i]) - break; - } - if ((i < EXT2_N_BLOCKS) && - fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) { - memset(&inode, 0, sizeof(inode)); - e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode, - "clear_resize"); - } - return; - } - - /* - * The resize inode feature is enabled; check to make sure the - * only block in use is the double indirect block - */ - blk = inode.i_block[EXT2_DIND_BLOCK]; - for (i=0; i < EXT2_N_BLOCKS; i++) { - if (i != EXT2_DIND_BLOCK && inode.i_block[i]) - break; - } - if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count || - !(inode.i_mode & LINUX_S_IFREG) || - (blk < fs->super->s_first_data_block || - blk >= fs->super->s_blocks_count)) { - resize_inode_invalid: - if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) { - memset(&inode, 0, sizeof(inode)); - e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode, - "clear_resize"); - ctx->flags |= E2F_FLAG_RESIZE_INODE; - } - if (!(ctx->options & E2F_OPT_READONLY)) { - fs->super->s_state &= ~EXT2_VALID_FS; - ext2fs_mark_super_dirty(fs); - } - goto cleanup; - } - dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2, - "resize dind buffer"); - ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize); - - retval = ext2fs_read_ind_block(fs, blk, dind_buf); - if (retval) - goto resize_inode_invalid; - - gdt_off = fs->desc_blocks; - pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks; - for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4; - i++, gdt_off++, pblk++) { - gdt_off %= fs->blocksize/4; - if (dind_buf[gdt_off] != pblk) - goto resize_inode_invalid; - retval = ext2fs_read_ind_block(fs, pblk, ind_buf); - if (retval) - goto resize_inode_invalid; - ind_off = 0; - for (j = 1; j < fs->group_desc_count; j++) { - if (!ext2fs_bg_has_super(fs, j)) - continue; - expect = pblk + (j * fs->super->s_blocks_per_group); - if (ind_buf[ind_off] != expect) - goto resize_inode_invalid; - ind_off++; - } - } - - cleanup: - ext2fs_free_mem(&dind_buf); -} - -static void check_super_block(e2fsck_t ctx) -{ - ext2_filsys fs = ctx->fs; - blk_t first_block, last_block; - struct ext2_super_block *sb = fs->super; - struct ext2_group_desc *gd; - blk_t blocks_per_group = fs->super->s_blocks_per_group; - blk_t bpg_max; - int inodes_per_block; - int ipg_max; - int inode_size; - dgrp_t i; - blk_t should_be; - struct problem_context pctx; - __u32 free_blocks = 0, free_inodes = 0; - - inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super); - ipg_max = inodes_per_block * (blocks_per_group - 4); - if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb)) - ipg_max = EXT2_MAX_INODES_PER_GROUP(sb); - bpg_max = 8 * EXT2_BLOCK_SIZE(sb); - if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb)) - bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb); - - ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx, - sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap"); - ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx, - sizeof(int) * fs->group_desc_count, "invalid_block_bitmap"); - ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx, - sizeof(int) * fs->group_desc_count, "invalid_inode_table"); - - clear_problem_context(&pctx); - - /* - * Verify the super block constants... - */ - check_super_value(ctx, "inodes_count", sb->s_inodes_count, - MIN_CHECK, 1, 0); - check_super_value(ctx, "blocks_count", sb->s_blocks_count, - MIN_CHECK, 1, 0); - check_super_value(ctx, "first_data_block", sb->s_first_data_block, - MAX_CHECK, 0, sb->s_blocks_count); - check_super_value(ctx, "log_block_size", sb->s_log_block_size, - MIN_CHECK | MAX_CHECK, 0, - EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE); - check_super_value(ctx, "log_frag_size", sb->s_log_frag_size, - MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size); - check_super_value(ctx, "frags_per_group", sb->s_frags_per_group, - MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group, - bpg_max); - check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group, - MIN_CHECK | MAX_CHECK, 8, bpg_max); - check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group, - MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max); - check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count, - MAX_CHECK, 0, sb->s_blocks_count / 2); - check_super_value(ctx, "reserved_gdt_blocks", - sb->s_reserved_gdt_blocks, MAX_CHECK, 0, - fs->blocksize/4); - inode_size = EXT2_INODE_SIZE(sb); - check_super_value(ctx, "inode_size", - inode_size, MIN_CHECK | MAX_CHECK, - EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize); - if (inode_size & (inode_size - 1)) { - pctx.num = inode_size; - pctx.str = "inode_size"; - fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx); - ctx->flags |= E2F_FLAG_ABORT; /* never get here! */ - return; - } - - if (!ctx->num_blocks) { - pctx.errcode = e2fsck_get_device_size(ctx); - if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) { - fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) && - (ctx->num_blocks < sb->s_blocks_count)) { - pctx.blk = sb->s_blocks_count; - pctx.blk2 = ctx->num_blocks; - if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) { - ctx->flags |= E2F_FLAG_ABORT; - return; - } - } - } - - if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) { - pctx.blk = EXT2_BLOCK_SIZE(sb); - pctx.blk2 = EXT2_FRAG_SIZE(sb); - fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - - should_be = sb->s_frags_per_group >> - (sb->s_log_block_size - sb->s_log_frag_size); - if (sb->s_blocks_per_group != should_be) { - pctx.blk = sb->s_blocks_per_group; - pctx.blk2 = should_be; - fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - - should_be = (sb->s_log_block_size == 0) ? 1 : 0; - if (sb->s_first_data_block != should_be) { - pctx.blk = sb->s_first_data_block; - pctx.blk2 = should_be; - fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - - should_be = sb->s_inodes_per_group * fs->group_desc_count; - if (sb->s_inodes_count != should_be) { - pctx.ino = sb->s_inodes_count; - pctx.ino2 = should_be; - if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) { - sb->s_inodes_count = should_be; - ext2fs_mark_super_dirty(fs); - } - } - - /* - * Verify the group descriptors.... - */ - first_block = sb->s_first_data_block; - last_block = first_block + blocks_per_group; - - for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) { - pctx.group = i; - - if (i == fs->group_desc_count - 1) - last_block = sb->s_blocks_count; - if ((gd->bg_block_bitmap < first_block) || - (gd->bg_block_bitmap >= last_block)) { - pctx.blk = gd->bg_block_bitmap; - if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx)) - gd->bg_block_bitmap = 0; - } - if (gd->bg_block_bitmap == 0) { - ctx->invalid_block_bitmap_flag[i]++; - ctx->invalid_bitmaps++; - } - if ((gd->bg_inode_bitmap < first_block) || - (gd->bg_inode_bitmap >= last_block)) { - pctx.blk = gd->bg_inode_bitmap; - if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx)) - gd->bg_inode_bitmap = 0; - } - if (gd->bg_inode_bitmap == 0) { - ctx->invalid_inode_bitmap_flag[i]++; - ctx->invalid_bitmaps++; - } - if ((gd->bg_inode_table < first_block) || - ((gd->bg_inode_table + - fs->inode_blocks_per_group - 1) >= last_block)) { - pctx.blk = gd->bg_inode_table; - if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx)) - gd->bg_inode_table = 0; - } - if (gd->bg_inode_table == 0) { - ctx->invalid_inode_table_flag[i]++; - ctx->invalid_bitmaps++; - } - free_blocks += gd->bg_free_blocks_count; - free_inodes += gd->bg_free_inodes_count; - first_block += sb->s_blocks_per_group; - last_block += sb->s_blocks_per_group; - - if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) || - (gd->bg_free_inodes_count > sb->s_inodes_per_group) || - (gd->bg_used_dirs_count > sb->s_inodes_per_group)) - ext2fs_unmark_valid(fs); - } - - /* - * Update the global counts from the block group counts. This - * is needed for an experimental patch which eliminates - * locking the entire filesystem when allocating blocks or - * inodes; if the filesystem is not unmounted cleanly, the - * global counts may not be accurate. - */ - if ((free_blocks != sb->s_free_blocks_count) || - (free_inodes != sb->s_free_inodes_count)) { - if (ctx->options & E2F_OPT_READONLY) - ext2fs_unmark_valid(fs); - else { - sb->s_free_blocks_count = free_blocks; - sb->s_free_inodes_count = free_inodes; - ext2fs_mark_super_dirty(fs); - } - } - - if ((sb->s_free_blocks_count > sb->s_blocks_count) || - (sb->s_free_inodes_count > sb->s_inodes_count)) - ext2fs_unmark_valid(fs); - - - /* - * If we have invalid bitmaps, set the error state of the - * filesystem. - */ - if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) { - sb->s_state &= ~EXT2_VALID_FS; - ext2fs_mark_super_dirty(fs); - } - - clear_problem_context(&pctx); - - /* - * If the UUID field isn't assigned, assign it. - */ - if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) { - if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) { - uuid_generate(sb->s_uuid); - ext2fs_mark_super_dirty(fs); - fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; - } - } - - /* FIXME - HURD support? - * For the Hurd, check to see if the filetype option is set, - * since it doesn't support it. - */ - if (!(ctx->options & E2F_OPT_READONLY) && - fs->super->s_creator_os == EXT2_OS_HURD && - (fs->super->s_feature_incompat & - EXT2_FEATURE_INCOMPAT_FILETYPE)) { - if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) { - fs->super->s_feature_incompat &= - ~EXT2_FEATURE_INCOMPAT_FILETYPE; - ext2fs_mark_super_dirty(fs); - } - } - - /* - * If we have any of the compatibility flags set, we need to have a - * revision 1 filesystem. Most kernels will not check the flags on - * a rev 0 filesystem and we may have corruption issues because of - * the incompatible changes to the filesystem. - */ - if (!(ctx->options & E2F_OPT_READONLY) && - fs->super->s_rev_level == EXT2_GOOD_OLD_REV && - (fs->super->s_feature_compat || - fs->super->s_feature_ro_compat || - fs->super->s_feature_incompat) && - fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) { - ext2fs_update_dynamic_rev(fs); - ext2fs_mark_super_dirty(fs); - } - - check_resize_inode(ctx); - - /* - * Clean up any orphan inodes, if present. - */ - if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) { - fs->super->s_state &= ~EXT2_VALID_FS; - ext2fs_mark_super_dirty(fs); - } - - /* - * Move the ext3 journal file, if necessary. - */ - e2fsck_move_ext3_journal(ctx); -} - -/* - * swapfs.c --- byte-swap an ext2 filesystem - */ - -#ifdef ENABLE_SWAPFS - -struct swap_block_struct { - ext2_ino_t ino; - int isdir; - errcode_t errcode; - char *dir_buf; - struct ext2_inode *inode; -}; - -/* - * This is a helper function for block_iterate. We mark all of the - * indirect and direct blocks as changed, so that block_iterate will - * write them out. - */ -static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt, - void *priv_data) -{ - errcode_t retval; - - struct swap_block_struct *sb = (struct swap_block_struct *) priv_data; - - if (sb->isdir && (blockcnt >= 0) && *block_nr) { - retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf); - if (retval) { - sb->errcode = retval; - return BLOCK_ABORT; - } - retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf); - if (retval) { - sb->errcode = retval; - return BLOCK_ABORT; - } - } - if (blockcnt >= 0) { - if (blockcnt < EXT2_NDIR_BLOCKS) - return 0; - return BLOCK_CHANGED; - } - if (blockcnt == BLOCK_COUNT_IND) { - if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK]) - return 0; - return BLOCK_CHANGED; - } - if (blockcnt == BLOCK_COUNT_DIND) { - if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK]) - return 0; - return BLOCK_CHANGED; - } - if (blockcnt == BLOCK_COUNT_TIND) { - if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK]) - return 0; - return BLOCK_CHANGED; - } - return BLOCK_CHANGED; -} - -/* - * This function is responsible for byte-swapping all of the indirect, - * block pointers. It is also responsible for byte-swapping directories. - */ -static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf, - struct ext2_inode *inode) -{ - errcode_t retval; - struct swap_block_struct sb; - - sb.ino = ino; - sb.inode = inode; - sb.dir_buf = block_buf + ctx->fs->blocksize*3; - sb.errcode = 0; - sb.isdir = 0; - if (LINUX_S_ISDIR(inode->i_mode)) - sb.isdir = 1; - - retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf, - swap_block, &sb); - if (retval) { - bb_error_msg(_("while calling ext2fs_block_iterate")); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - if (sb.errcode) { - bb_error_msg(_("while calling iterator function")); - ctx->flags |= E2F_FLAG_ABORT; - return; - } -} - -static void swap_inodes(e2fsck_t ctx) -{ - ext2_filsys fs = ctx->fs; - dgrp_t group; - unsigned int i; - ext2_ino_t ino = 1; - char *buf, *block_buf; - errcode_t retval; - struct ext2_inode * inode; - - e2fsck_use_inode_shortcuts(ctx, 1); - - retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group, - &buf); - if (retval) { - bb_error_msg(_("while allocating inode buffer")); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4, - "block interate buffer"); - for (group = 0; group < fs->group_desc_count; group++) { - retval = io_channel_read_blk(fs->io, - fs->group_desc[group].bg_inode_table, - fs->inode_blocks_per_group, buf); - if (retval) { - bb_error_msg(_("while reading inode table (group %d)"), - group); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - inode = (struct ext2_inode *) buf; - for (i=0; i < fs->super->s_inodes_per_group; - i++, ino++, inode++) { - ctx->stashed_ino = ino; - ctx->stashed_inode = inode; - - if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ) - ext2fs_swap_inode(fs, inode, inode, 0); - - /* - * Skip deleted files. - */ - if (inode->i_links_count == 0) - continue; - - if (LINUX_S_ISDIR(inode->i_mode) || - ((inode->i_block[EXT2_IND_BLOCK] || - inode->i_block[EXT2_DIND_BLOCK] || - inode->i_block[EXT2_TIND_BLOCK]) && - ext2fs_inode_has_valid_blocks(inode))) - swap_inode_blocks(ctx, ino, block_buf, inode); - - if (ctx->flags & E2F_FLAG_SIGNAL_MASK) - return; - - if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE) - ext2fs_swap_inode(fs, inode, inode, 1); - } - retval = io_channel_write_blk(fs->io, - fs->group_desc[group].bg_inode_table, - fs->inode_blocks_per_group, buf); - if (retval) { - bb_error_msg(_("while writing inode table (group %d)"), - group); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - } - ext2fs_free_mem(&buf); - ext2fs_free_mem(&block_buf); - e2fsck_use_inode_shortcuts(ctx, 0); - ext2fs_flush_icache(fs); -} - -#if defined(__powerpc__) && BB_BIG_ENDIAN -/* - * On the PowerPC, the big-endian variant of the ext2 filesystem - * has its bitmaps stored as 32-bit words with bit 0 as the LSB - * of each word. Thus a bitmap with only bit 0 set would be, as - * a string of bytes, 00 00 00 01 00 ... - * To cope with this, we byte-reverse each word of a bitmap if - * we have a big-endian filesystem, that is, if we are *not* - * byte-swapping other word-sized numbers. - */ -#define EXT2_BIG_ENDIAN_BITMAPS -#endif - -#ifdef EXT2_BIG_ENDIAN_BITMAPS -static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap) -{ - __u32 *p = (__u32 *) bmap->bitmap; - int n, nbytes = (bmap->end - bmap->start + 7) / 8; - - for (n = nbytes / sizeof(__u32); n > 0; --n, ++p) - *p = ext2fs_swab32(*p); -} -#endif - - -#ifdef ENABLE_SWAPFS -static void swap_filesys(e2fsck_t ctx) -{ - ext2_filsys fs = ctx->fs; - if (!(ctx->options & E2F_OPT_PREEN)) - printf(_("Pass 0: Doing byte-swap of filesystem\n")); - - /* Byte swap */ - - if (fs->super->s_mnt_count) { - fprintf(stderr, _("%s: the filesystem must be freshly " - "checked using fsck\n" - "and not mounted before trying to " - "byte-swap it.\n"), ctx->device_name); - ctx->flags |= E2F_FLAG_ABORT; - return; - } - if (fs->flags & EXT2_FLAG_SWAP_BYTES) { - fs->flags &= ~(EXT2_FLAG_SWAP_BYTES| - EXT2_FLAG_SWAP_BYTES_WRITE); - fs->flags |= EXT2_FLAG_SWAP_BYTES_READ; - } else { - fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ; - fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE; - } - swap_inodes(ctx); - if (ctx->flags & E2F_FLAG_SIGNAL_MASK) - return; - if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE) - fs->flags |= EXT2_FLAG_SWAP_BYTES; - fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ| - EXT2_FLAG_SWAP_BYTES_WRITE); - -#ifdef EXT2_BIG_ENDIAN_BITMAPS - e2fsck_read_bitmaps(ctx); - ext2fs_swap_bitmap(fs->inode_map); - ext2fs_swap_bitmap(fs->block_map); - fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY; -#endif - fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; - ext2fs_flush(fs); - fs->flags |= EXT2_FLAG_MASTER_SB_ONLY; -} -#endif /* ENABLE_SWAPFS */ - -#endif - -/* - * util.c --- miscellaneous utilities - */ - - -void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size, - const char *description) -{ - return xzalloc(size); -} - -static char *string_copy(const char *str, int len) -{ - char *ret; - - if (!str) - return NULL; - if (!len) - len = strlen(str); - ret = xmalloc(len+1); - strncpy(ret, str, len); - ret[len] = 0; - return ret; -} - -#ifndef HAVE_CONIO_H -static int read_a_char(void) -{ - char c; - int r; - int fail = 0; - - while (1) { - if (e2fsck_global_ctx && - (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) { - return 3; - } - r = read(0, &c, 1); - if (r == 1) - return c; - if (fail++ > 100) - break; - } - return EOF; -} -#endif - -static int ask_yn(const char * string, int def) -{ - int c; - const char *defstr; - static const char short_yes[] = "yY"; - static const char short_no[] = "nN"; - -#ifdef HAVE_TERMIOS_H - struct termios termios, tmp; - - tcgetattr (0, &termios); - tmp = termios; - tmp.c_lflag &= ~(ICANON | ECHO); - tmp.c_cc[VMIN] = 1; - tmp.c_cc[VTIME] = 0; - tcsetattr_stdin_TCSANOW(&tmp); -#endif - - if (def == 1) - defstr = ""; - else if (def == 0) - defstr = ""; - else - defstr = " (y/n)"; - printf("%s%s? ", string, defstr); - while (1) { - fflush (stdout); - if ((c = read_a_char()) == EOF) - break; - if (c == 3) { -#ifdef HAVE_TERMIOS_H - tcsetattr_stdin_TCSANOW(&termios); -#endif - if (e2fsck_global_ctx && - e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) { - puts("\n"); - longjmp(e2fsck_global_ctx->abort_loc, 1); - } - puts(_("cancelled!\n")); - return 0; - } - if (strchr(short_yes, (char) c)) { - def = 1; - break; - } - else if (strchr(short_no, (char) c)) { - def = 0; - break; - } - else if ((c == ' ' || c == '\n') && (def != -1)) - break; - } - if (def) - puts("yes\n"); - else - puts ("no\n"); -#ifdef HAVE_TERMIOS_H - tcsetattr_stdin_TCSANOW(&termios); -#endif - return def; -} - -int ask (e2fsck_t ctx, const char * string, int def) -{ - if (ctx->options & E2F_OPT_NO) { - printf(_("%s? no\n\n"), string); - return 0; - } - if (ctx->options & E2F_OPT_YES) { - printf(_("%s? yes\n\n"), string); - return 1; - } - if (ctx->options & E2F_OPT_PREEN) { - printf("%s? %s\n\n", string, def ? _("yes") : _("no")); - return def; - } - return ask_yn(string, def); -} - -void e2fsck_read_bitmaps(e2fsck_t ctx) -{ - ext2_filsys fs = ctx->fs; - errcode_t retval; - - if (ctx->invalid_bitmaps) { - bb_error_msg(_("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"), - ctx->device_name); - bb_error_msg_and_die(0); - } - - ehandler_operation(_("reading inode and block bitmaps")); - retval = ext2fs_read_bitmaps(fs); - ehandler_operation(0); - if (retval) { - bb_error_msg(_("while retrying to read bitmaps for %s"), - ctx->device_name); - bb_error_msg_and_die(0); - } -} - -static void e2fsck_write_bitmaps(e2fsck_t ctx) -{ - ext2_filsys fs = ctx->fs; - errcode_t retval; - - if (ext2fs_test_bb_dirty(fs)) { - ehandler_operation(_("writing block bitmaps")); - retval = ext2fs_write_block_bitmap(fs); - ehandler_operation(0); - if (retval) { - bb_error_msg(_("while retrying to write block bitmaps for %s"), - ctx->device_name); - bb_error_msg_and_die(0); - } - } - - if (ext2fs_test_ib_dirty(fs)) { - ehandler_operation(_("writing inode bitmaps")); - retval = ext2fs_write_inode_bitmap(fs); - ehandler_operation(0); - if (retval) { - bb_error_msg(_("while retrying to write inode bitmaps for %s"), - ctx->device_name); - bb_error_msg_and_die(0); - } - } -} - -void preenhalt(e2fsck_t ctx) -{ - ext2_filsys fs = ctx->fs; - - if (!(ctx->options & E2F_OPT_PREEN)) - return; - fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; " - "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"), - ctx->device_name); - if (fs != NULL) { - fs->super->s_state |= EXT2_ERROR_FS; - ext2fs_mark_super_dirty(fs); - ext2fs_close(fs); - } - exit(EXIT_UNCORRECTED); -} - -void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino, - struct ext2_inode * inode, const char *proc) -{ - int retval; - - retval = ext2fs_read_inode(ctx->fs, ino, inode); - if (retval) { - bb_error_msg(_("while reading inode %ld in %s"), ino, proc); - bb_error_msg_and_die(0); - } -} - -extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino, - struct ext2_inode * inode, int bufsize, - const char *proc) -{ - int retval; - - retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize); - if (retval) { - bb_error_msg(_("while writing inode %ld in %s"), ino, proc); - bb_error_msg_and_die(0); - } -} - -extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino, - struct ext2_inode * inode, const char *proc) -{ - int retval; - - retval = ext2fs_write_inode(ctx->fs, ino, inode); - if (retval) { - bb_error_msg(_("while writing inode %ld in %s"), ino, proc); - bb_error_msg_and_die(0); - } -} - -blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name, - io_manager manager) -{ - struct ext2_super_block *sb; - io_channel io = NULL; - void *buf = NULL; - int blocksize; - blk_t superblock, ret_sb = 8193; - - if (fs && fs->super) { - ret_sb = (fs->super->s_blocks_per_group + - fs->super->s_first_data_block); - if (ctx) { - ctx->superblock = ret_sb; - ctx->blocksize = fs->blocksize; - } - return ret_sb; - } - - if (ctx) { - if (ctx->blocksize) { - ret_sb = ctx->blocksize * 8; - if (ctx->blocksize == 1024) - ret_sb++; - ctx->superblock = ret_sb; - return ret_sb; - } - ctx->superblock = ret_sb; - ctx->blocksize = 1024; - } - - if (!name || !manager) - goto cleanup; - - if (manager->open(name, 0, &io) != 0) - goto cleanup; - - if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf)) - goto cleanup; - sb = (struct ext2_super_block *) buf; - - for (blocksize = EXT2_MIN_BLOCK_SIZE; - blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) { - superblock = blocksize*8; - if (blocksize == 1024) - superblock++; - io_channel_set_blksize(io, blocksize); - if (io_channel_read_blk(io, superblock, - -SUPERBLOCK_SIZE, buf)) - continue; -#if BB_BIG_ENDIAN - if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC)) - ext2fs_swap_super(sb); -#endif - if (sb->s_magic == EXT2_SUPER_MAGIC) { - ret_sb = superblock; - if (ctx) { - ctx->superblock = superblock; - ctx->blocksize = blocksize; - } - break; - } - } - -cleanup: - if (io) - io_channel_close(io); - ext2fs_free_mem(&buf); - return ret_sb; -} - - -/* - * This function runs through the e2fsck passes and calls them all, - * returning restart, abort, or cancel as necessary... - */ -typedef void (*pass_t)(e2fsck_t ctx); - -static const pass_t e2fsck_passes[] = { - e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4, - e2fsck_pass5, 0 }; - -#define E2F_FLAG_RUN_RETURN (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART) - -static int e2fsck_run(e2fsck_t ctx) -{ - int i; - pass_t e2fsck_pass; - - if (setjmp(ctx->abort_loc)) { - ctx->flags &= ~E2F_FLAG_SETJMP_OK; - return (ctx->flags & E2F_FLAG_RUN_RETURN); - } - ctx->flags |= E2F_FLAG_SETJMP_OK; - - for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) { - if (ctx->flags & E2F_FLAG_RUN_RETURN) - break; - e2fsck_pass(ctx); - if (ctx->progress) - (void) (ctx->progress)(ctx, 0, 0, 0); - } - ctx->flags &= ~E2F_FLAG_SETJMP_OK; - - if (ctx->flags & E2F_FLAG_RUN_RETURN) - return (ctx->flags & E2F_FLAG_RUN_RETURN); - return 0; -} - - -/* - * unix.c - The unix-specific code for e2fsck - */ - - -/* Command line options */ -static int swapfs; -#ifdef ENABLE_SWAPFS -static int normalize_swapfs; -#endif -static int cflag; /* check disk */ -static int show_version_only; -static int verbose; - -#define P_E2(singular, plural, n) n, ((n) == 1 ? singular : plural) - -static void show_stats(e2fsck_t ctx) -{ - ext2_filsys fs = ctx->fs; - int inodes, inodes_used, blocks, blocks_used; - int dir_links; - int num_files, num_links; - int frag_percent; - - dir_links = 2 * ctx->fs_directory_count - 1; - num_files = ctx->fs_total_count - dir_links; - num_links = ctx->fs_links_count - dir_links; - inodes = fs->super->s_inodes_count; - inodes_used = (fs->super->s_inodes_count - - fs->super->s_free_inodes_count); - blocks = fs->super->s_blocks_count; - blocks_used = (fs->super->s_blocks_count - - fs->super->s_free_blocks_count); - - frag_percent = (10000 * ctx->fs_fragmented) / inodes_used; - frag_percent = (frag_percent + 5) / 10; - - if (!verbose) { - printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n", - ctx->device_name, inodes_used, inodes, - frag_percent / 10, frag_percent % 10, - blocks_used, blocks); - return; - } - printf("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used), - 100 * inodes_used / inodes); - printf("%8d non-contiguous inode%s (%0d.%d%%)\n", - P_E2("", "s", ctx->fs_fragmented), - frag_percent / 10, frag_percent % 10); - printf(_(" # of inodes with ind/dind/tind blocks: %d/%d/%d\n"), - ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count); - printf("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used), - (int) ((long long) 100 * blocks_used / blocks)); - printf("%8d large file%s\n", P_E2("", "s", ctx->large_files)); - printf("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count)); - printf("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count)); - printf("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count)); - printf("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count)); - printf("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count)); - printf("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links)); - printf("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count)); - printf(" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count)); - printf("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count)); - printf("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links)); -} - -static void check_mount(e2fsck_t ctx) -{ - errcode_t retval; - int cont; - - retval = ext2fs_check_if_mounted(ctx->filesystem_name, - &ctx->mount_flags); - if (retval) { - bb_error_msg(_("while determining whether %s is mounted"), - ctx->filesystem_name); - return; - } - - /* - * If the filesystem isn't mounted, or it's the root filesystem - * and it's mounted read-only, then everything's fine. - */ - if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) || - ((ctx->mount_flags & EXT2_MF_ISROOT) && - (ctx->mount_flags & EXT2_MF_READONLY))) - return; - - if (ctx->options & E2F_OPT_READONLY) { - printf(_("Warning! %s is mounted.\n"), ctx->filesystem_name); - return; - } - - printf(_("%s is mounted. "), ctx->filesystem_name); - if (!ctx->interactive) - bb_error_msg_and_die(_("can't continue, aborting")); - printf(_("\n\n\007\007\007\007WARNING!!! " - "Running e2fsck on a mounted filesystem may cause\n" - "SEVERE filesystem damage.\007\007\007\n\n")); - cont = ask_yn(_("Do you really want to continue"), -1); - if (!cont) { - printf(_("check aborted.\n")); - exit(0); - } -} - -static int is_on_batt(void) -{ - FILE *f; - DIR *d; - char tmp[80], tmp2[80], fname[80]; - unsigned int acflag; - struct dirent* de; - - f = fopen_for_read("/proc/apm"); - if (f) { - if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4) - acflag = 1; - fclose(f); - return (acflag != 1); - } - d = opendir("/proc/acpi/ac_adapter"); - if (d) { - while ((de=readdir(d)) != NULL) { - if (!strncmp(".", de->d_name, 1)) - continue; - snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state", - de->d_name); - f = fopen_for_read(fname); - if (!f) - continue; - if (fscanf(f, "%s %s", tmp2, tmp) != 2) - tmp[0] = 0; - fclose(f); - if (strncmp(tmp, "off-line", 8) == 0) { - closedir(d); - return 1; - } - } - closedir(d); - } - return 0; -} - -/* - * This routine checks to see if a filesystem can be skipped; if so, - * it will exit with EXIT_OK. Under some conditions it will print a - * message explaining why a check is being forced. - */ -static void check_if_skip(e2fsck_t ctx) -{ - ext2_filsys fs = ctx->fs; - const char *reason = NULL; - unsigned int reason_arg = 0; - long next_check; - int batt = is_on_batt(); - time_t now = time(NULL); - - if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs) - return; - - if ((fs->super->s_state & EXT2_ERROR_FS) || - !ext2fs_test_valid(fs)) - reason = _(" contains a file system with errors"); - else if ((fs->super->s_state & EXT2_VALID_FS) == 0) - reason = _(" was not cleanly unmounted"); - else if ((fs->super->s_max_mnt_count > 0) && - (fs->super->s_mnt_count >= - (unsigned) fs->super->s_max_mnt_count)) { - reason = _(" has been mounted %u times without being checked"); - reason_arg = fs->super->s_mnt_count; - if (batt && (fs->super->s_mnt_count < - (unsigned) fs->super->s_max_mnt_count*2)) - reason = 0; - } else if (fs->super->s_checkinterval && - ((now - fs->super->s_lastcheck) >= - fs->super->s_checkinterval)) { - reason = _(" has gone %u days without being checked"); - reason_arg = (now - fs->super->s_lastcheck)/(3600*24); - if (batt && ((now - fs->super->s_lastcheck) < - fs->super->s_checkinterval*2)) - reason = 0; - } - if (reason) { - fputs(ctx->device_name, stdout); - printf(reason, reason_arg); - fputs(_(", check forced.\n"), stdout); - return; - } - printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name, - fs->super->s_inodes_count - fs->super->s_free_inodes_count, - fs->super->s_inodes_count, - fs->super->s_blocks_count - fs->super->s_free_blocks_count, - fs->super->s_blocks_count); - next_check = 100000; - if (fs->super->s_max_mnt_count > 0) { - next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count; - if (next_check <= 0) - next_check = 1; - } - if (fs->super->s_checkinterval && - ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval)) - next_check = 1; - if (next_check <= 5) { - if (next_check == 1) - fputs(_(" (check after next mount)"), stdout); - else - printf(_(" (check in %ld mounts)"), next_check); - } - bb_putchar('\n'); - ext2fs_close(fs); - ctx->fs = NULL; - e2fsck_free_context(ctx); - exit(EXIT_OK); -} - -/* - * For completion notice - */ -struct percent_tbl { - int max_pass; - int table[32]; -}; -static const struct percent_tbl e2fsck_tbl = { - 5, { 0, 70, 90, 92, 95, 100 } -}; - -static char bar[128], spaces[128]; - -static float calc_percent(const struct percent_tbl *tbl, int pass, int curr, - int max) -{ - float percent; - - if (pass <= 0) - return 0.0; - if (pass > tbl->max_pass || max == 0) - return 100.0; - percent = ((float) curr) / ((float) max); - return ((percent * (tbl->table[pass] - tbl->table[pass-1])) - + tbl->table[pass-1]); -} - -void e2fsck_clear_progbar(e2fsck_t ctx) -{ - if (!(ctx->flags & E2F_FLAG_PROG_BAR)) - return; - - printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80), - ctx->stop_meta); - fflush(stdout); - ctx->flags &= ~E2F_FLAG_PROG_BAR; -} - -int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent, - unsigned int dpynum) -{ - static const char spinner[] = "\\|/-"; - int i; - unsigned int tick; - struct timeval tv; - int dpywidth; - int fixed_percent; - - if (ctx->flags & E2F_FLAG_PROG_SUPPRESS) - return 0; - - /* - * Calculate the new progress position. If the - * percentage hasn't changed, then we skip out right - * away. - */ - fixed_percent = (int) ((10 * percent) + 0.5); - if (ctx->progress_last_percent == fixed_percent) - return 0; - ctx->progress_last_percent = fixed_percent; - - /* - * If we've already updated the spinner once within - * the last 1/8th of a second, no point doing it - * again. - */ - gettimeofday(&tv, NULL); - tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8)); - if ((tick == ctx->progress_last_time) && - (fixed_percent != 0) && (fixed_percent != 1000)) - return 0; - ctx->progress_last_time = tick; - - /* - * Advance the spinner, and note that the progress bar - * will be on the screen - */ - ctx->progress_pos = (ctx->progress_pos+1) & 3; - ctx->flags |= E2F_FLAG_PROG_BAR; - - dpywidth = 66 - strlen(label); - dpywidth = 8 * (dpywidth / 8); - if (dpynum) - dpywidth -= 8; - - i = ((percent * dpywidth) + 50) / 100; - printf("%s%s: |%s%s", ctx->start_meta, label, - bar + (sizeof(bar) - (i+1)), - spaces + (sizeof(spaces) - (dpywidth - i + 1))); - if (fixed_percent == 1000) - bb_putchar('|'); - else - bb_putchar(spinner[ctx->progress_pos & 3]); - printf(" %4.1f%% ", percent); - if (dpynum) - printf("%u\r", dpynum); - else - fputs(" \r", stdout); - fputs(ctx->stop_meta, stdout); - - if (fixed_percent == 1000) - e2fsck_clear_progbar(ctx); - fflush(stdout); - - return 0; -} - -static int e2fsck_update_progress(e2fsck_t ctx, int pass, - unsigned long cur, unsigned long max) -{ - char buf[80]; - float percent; - - if (pass == 0) - return 0; - - if (ctx->progress_fd) { - sprintf(buf, "%d %lu %lu\n", pass, cur, max); - xwrite_str(ctx->progress_fd, buf); - } else { - percent = calc_percent(&e2fsck_tbl, pass, cur, max); - e2fsck_simple_progress(ctx, ctx->device_name, - percent, 0); - } - return 0; -} - -static void reserve_stdio_fds(void) -{ - int fd; - - while (1) { - fd = open(bb_dev_null, O_RDWR); - if (fd > 2) - break; - if (fd < 0) { - fprintf(stderr, _("ERROR: Cannot open " - "/dev/null (%s)\n"), - strerror(errno)); - break; - } - } - close(fd); -} - -static void signal_progress_on(int sig FSCK_ATTR((unused))) -{ - e2fsck_t ctx = e2fsck_global_ctx; - - if (!ctx) - return; - - ctx->progress = e2fsck_update_progress; - ctx->progress_fd = 0; -} - -static void signal_progress_off(int sig FSCK_ATTR((unused))) -{ - e2fsck_t ctx = e2fsck_global_ctx; - - if (!ctx) - return; - - e2fsck_clear_progbar(ctx); - ctx->progress = 0; -} - -static void signal_cancel(int sig FSCK_ATTR((unused))) -{ - e2fsck_t ctx = e2fsck_global_ctx; - - if (!ctx) - exit(FSCK_CANCELED); - - ctx->flags |= E2F_FLAG_CANCEL; -} - -static void parse_extended_opts(e2fsck_t ctx, const char *opts) -{ - char *buf, *token, *next, *p, *arg; - int ea_ver; - int extended_usage = 0; - - buf = string_copy(opts, 0); - for (token = buf; token && *token; token = next) { - p = strchr(token, ','); - next = 0; - if (p) { - *p = 0; - next = p+1; - } - arg = strchr(token, '='); - if (arg) { - *arg = 0; - arg++; - } - if (strcmp(token, "ea_ver") == 0) { - if (!arg) { - extended_usage++; - continue; - } - ea_ver = strtoul(arg, &p, 0); - if (*p || - ((ea_ver != 1) && (ea_ver != 2))) { - fprintf(stderr, - _("Invalid EA version.\n")); - extended_usage++; - continue; - } - ctx->ext_attr_ver = ea_ver; - } else { - fprintf(stderr, _("Unknown extended option: %s\n"), - token); - extended_usage++; - } - } - if (extended_usage) { - bb_error_msg_and_die( - "Extended options are separated by commas, " - "and may take an argument which\n" - "is set off by an equals ('=') sign. " - "Valid extended options are:\n" - "\tea_ver=\n\n"); - } -} - - -static errcode_t PRS(int argc, char **argv, e2fsck_t *ret_ctx) -{ - int flush = 0; - int c, fd; - e2fsck_t ctx; - errcode_t retval; - struct sigaction sa; - char *extended_opts = NULL; - - retval = e2fsck_allocate_context(&ctx); - if (retval) - return retval; - - *ret_ctx = ctx; - - setvbuf(stdout, NULL, _IONBF, BUFSIZ); - setvbuf(stderr, NULL, _IONBF, BUFSIZ); - if (isatty(0) && isatty(1)) { - ctx->interactive = 1; - } else { - ctx->start_meta[0] = '\001'; - ctx->stop_meta[0] = '\002'; - } - memset(bar, '=', sizeof(bar)-1); - memset(spaces, ' ', sizeof(spaces)-1); - blkid_get_cache(&ctx->blkid, NULL); - - if (argc && *argv) - ctx->program_name = *argv; - else - ctx->program_name = "e2fsck"; - while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF) - switch (c) { - case 'C': - ctx->progress = e2fsck_update_progress; - ctx->progress_fd = atoi(optarg); - if (!ctx->progress_fd) - break; - /* Validate the file descriptor to avoid disasters */ - fd = dup(ctx->progress_fd); - if (fd < 0) { - fprintf(stderr, - _("Error validating file descriptor %d: %s\n"), - ctx->progress_fd, - error_message(errno)); - bb_error_msg_and_die(_("Invalid completion information file descriptor")); - } else - close(fd); - break; - case 'D': - ctx->options |= E2F_OPT_COMPRESS_DIRS; - break; - case 'E': - extended_opts = optarg; - break; - case 'p': - case 'a': - if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) { - conflict_opt: - bb_error_msg_and_die(_("only one the options -p/-a, -n or -y may be specified")); - } - ctx->options |= E2F_OPT_PREEN; - break; - case 'n': - if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN)) - goto conflict_opt; - ctx->options |= E2F_OPT_NO; - break; - case 'y': - if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO)) - goto conflict_opt; - ctx->options |= E2F_OPT_YES; - break; - case 't': - /* FIXME - This needs to go away in a future path - will change binary */ - fprintf(stderr, _("The -t option is not " - "supported on this version of e2fsck.\n")); - break; - case 'c': - if (cflag++) - ctx->options |= E2F_OPT_WRITECHECK; - ctx->options |= E2F_OPT_CHECKBLOCKS; - break; - case 'r': - /* What we do by default, anyway! */ - break; - case 'b': - ctx->use_superblock = atoi(optarg); - ctx->flags |= E2F_FLAG_SB_SPECIFIED; - break; - case 'B': - ctx->blocksize = atoi(optarg); - break; - case 'I': - ctx->inode_buffer_blocks = atoi(optarg); - break; - case 'j': - ctx->journal_name = string_copy(optarg, 0); - break; - case 'P': - ctx->process_inode_size = atoi(optarg); - break; - case 'd': - ctx->options |= E2F_OPT_DEBUG; - break; - case 'f': - ctx->options |= E2F_OPT_FORCE; - break; - case 'F': - flush = 1; - break; - case 'v': - verbose = 1; - break; - case 'V': - show_version_only = 1; - break; - case 'N': - ctx->device_name = optarg; - break; -#ifdef ENABLE_SWAPFS - case 's': - normalize_swapfs = 1; - case 'S': - swapfs = 1; - break; -#else - case 's': - case 'S': - fprintf(stderr, _("Byte-swapping filesystems " - "not compiled in this version " - "of e2fsck\n")); - exit(1); -#endif - default: - bb_show_usage(); - } - if (show_version_only) - return 0; - if (optind != argc - 1) - bb_show_usage(); - if ((ctx->options & E2F_OPT_NO) && - !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS)) - ctx->options |= E2F_OPT_READONLY; - ctx->io_options = strchr(argv[optind], '?'); - if (ctx->io_options) - *ctx->io_options++ = 0; - ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0); - if (!ctx->filesystem_name) { - bb_error_msg(_("Unable to resolve '%s'"), argv[optind]); - bb_error_msg_and_die(0); - } - if (extended_opts) - parse_extended_opts(ctx, extended_opts); - - if (flush) { - fd = open(ctx->filesystem_name, O_RDONLY, 0); - if (fd < 0) { - bb_error_msg(_("while opening %s for flushing"), - ctx->filesystem_name); - bb_error_msg_and_die(0); - } - if ((retval = ext2fs_sync_device(fd, 1))) { - bb_error_msg(_("while trying to flush %s"), - ctx->filesystem_name); - bb_error_msg_and_die(0); - } - close(fd); - } -#ifdef ENABLE_SWAPFS - if (swapfs && cflag) { - fprintf(stderr, _("Incompatible options not " - "allowed when byte-swapping.\n")); - exit(EXIT_USAGE); - } -#endif - /* - * Set up signal action - */ - memset(&sa, 0, sizeof(struct sigaction)); - sa.sa_handler = signal_cancel; - sigaction(SIGINT, &sa, 0); - sigaction(SIGTERM, &sa, 0); -#ifdef SA_RESTART - sa.sa_flags = SA_RESTART; -#endif - e2fsck_global_ctx = ctx; - sa.sa_handler = signal_progress_on; - sigaction(SIGUSR1, &sa, 0); - sa.sa_handler = signal_progress_off; - sigaction(SIGUSR2, &sa, 0); - - /* Update our PATH to include /sbin if we need to run badblocks */ - if (cflag) - e2fs_set_sbin_path(); - return 0; -} - -static const char my_ver_string[] = E2FSPROGS_VERSION; -static const char my_ver_date[] = E2FSPROGS_DATE; - -int e2fsck_main (int argc, char **argv); -int e2fsck_main (int argc, char **argv) -{ - errcode_t retval; - int exit_value = EXIT_OK; - ext2_filsys fs = 0; - io_manager io_ptr; - struct ext2_super_block *sb; - const char *lib_ver_date; - int my_ver, lib_ver; - e2fsck_t ctx; - struct problem_context pctx; - int flags, run_result; - - clear_problem_context(&pctx); - - my_ver = ext2fs_parse_version_string(my_ver_string); - lib_ver = ext2fs_get_library_version(0, &lib_ver_date); - if (my_ver > lib_ver) { - fprintf( stderr, _("Error: ext2fs library version " - "out of date!\n")); - show_version_only++; - } - - retval = PRS(argc, argv, &ctx); - if (retval) { - bb_error_msg(_("while trying to initialize program")); - exit(EXIT_ERROR); - } - reserve_stdio_fds(); - - if (!(ctx->options & E2F_OPT_PREEN) || show_version_only) - fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string, - my_ver_date); - - if (show_version_only) { - fprintf(stderr, _("\tUsing %s, %s\n"), - error_message(EXT2_ET_BASE), lib_ver_date); - exit(EXIT_OK); - } - - check_mount(ctx); - - if (!(ctx->options & E2F_OPT_PREEN) && - !(ctx->options & E2F_OPT_NO) && - !(ctx->options & E2F_OPT_YES)) { - if (!ctx->interactive) - bb_error_msg_and_die(_("need terminal for interactive repairs")); - } - ctx->superblock = ctx->use_superblock; -restart: -#ifdef CONFIG_TESTIO_DEBUG - io_ptr = test_io_manager; - test_io_backing_manager = unix_io_manager; -#else - io_ptr = unix_io_manager; -#endif - flags = 0; - if ((ctx->options & E2F_OPT_READONLY) == 0) - flags |= EXT2_FLAG_RW; - - if (ctx->superblock && ctx->blocksize) { - retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options, - flags, ctx->superblock, ctx->blocksize, - io_ptr, &fs); - } else if (ctx->superblock) { - int blocksize; - for (blocksize = EXT2_MIN_BLOCK_SIZE; - blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) { - retval = ext2fs_open2(ctx->filesystem_name, - ctx->io_options, flags, - ctx->superblock, blocksize, - io_ptr, &fs); - if (!retval) - break; - } - } else - retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options, - flags, 0, 0, io_ptr, &fs); - if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) && - !(ctx->flags & E2F_FLAG_SB_SPECIFIED) && - ((retval == EXT2_ET_BAD_MAGIC) || - ((retval == 0) && ext2fs_check_desc(fs)))) { - if (!fs || (fs->group_desc_count > 1)) { - printf(_("%s trying backup blocks...\n"), - retval ? _("Couldn't find ext2 superblock,") : - _("Group descriptors look bad...")); - get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr); - if (fs) - ext2fs_close(fs); - goto restart; - } - } - if (retval) { - bb_error_msg(_("while trying to open %s"), - ctx->filesystem_name); - if (retval == EXT2_ET_REV_TOO_HIGH) { - printf(_("The filesystem revision is apparently " - "too high for this version of e2fsck.\n" - "(Or the filesystem superblock " - "is corrupt)\n\n")); - fix_problem(ctx, PR_0_SB_CORRUPT, &pctx); - } else if (retval == EXT2_ET_SHORT_READ) - printf(_("Could this be a zero-length partition?\n")); - else if ((retval == EPERM) || (retval == EACCES)) - printf(_("You must have %s access to the " - "filesystem or be root\n"), - (ctx->options & E2F_OPT_READONLY) ? - "r/o" : "r/w"); - else if (retval == ENXIO) - printf(_("Possibly non-existent or swap device?\n")); -#ifdef EROFS - else if (retval == EROFS) - printf(_("Disk write-protected; use the -n option " - "to do a read-only\n" - "check of the device.\n")); -#endif - else - fix_problem(ctx, PR_0_SB_CORRUPT, &pctx); - bb_error_msg_and_die(0); - } - ctx->fs = fs; - fs->priv_data = ctx; - sb = fs->super; - if (sb->s_rev_level > E2FSCK_CURRENT_REV) { - bb_error_msg(_("while trying to open %s"), - ctx->filesystem_name); - get_newer: - bb_error_msg_and_die(_("Get a newer version of e2fsck!")); - } - - /* - * Set the device name, which is used whenever we print error - * or informational messages to the user. - */ - if (ctx->device_name == 0 && - (sb->s_volume_name[0] != 0)) { - ctx->device_name = string_copy(sb->s_volume_name, - sizeof(sb->s_volume_name)); - } - if (ctx->device_name == 0) - ctx->device_name = ctx->filesystem_name; - - /* - * Make sure the ext3 superblock fields are consistent. - */ - retval = e2fsck_check_ext3_journal(ctx); - if (retval) { - bb_error_msg(_("while checking ext3 journal for %s"), - ctx->device_name); - bb_error_msg_and_die(0); - } - - /* - * Check to see if we need to do ext3-style recovery. If so, - * do it, and then restart the fsck. - */ - if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) { - if (ctx->options & E2F_OPT_READONLY) { - printf(_("Warning: skipping journal recovery " - "because doing a read-only filesystem " - "check.\n")); - io_channel_flush(ctx->fs->io); - } else { - if (ctx->flags & E2F_FLAG_RESTARTED) { - /* - * Whoops, we attempted to run the - * journal twice. This should never - * happen, unless the hardware or - * device driver is being bogus. - */ - bb_error_msg(_("can't set superblock flags on %s"), ctx->device_name); - bb_error_msg_and_die(0); - } - retval = e2fsck_run_ext3_journal(ctx); - if (retval) { - bb_error_msg(_("while recovering ext3 journal of %s"), - ctx->device_name); - bb_error_msg_and_die(0); - } - ext2fs_close(ctx->fs); - ctx->fs = 0; - ctx->flags |= E2F_FLAG_RESTARTED; - goto restart; - } - } - - /* - * Check for compatibility with the feature sets. We need to - * be more stringent than ext2fs_open(). - */ - if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) || - (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) { - bb_error_msg("(%s)", ctx->device_name); - goto get_newer; - } - if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) { - bb_error_msg("(%s)", ctx->device_name); - goto get_newer; - } -#ifdef ENABLE_COMPRESSION - /* FIXME - do we support this at all? */ - if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION) - bb_error_msg(_("warning: compression support is experimental")); -#endif -#ifndef ENABLE_HTREE - if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) { - bb_error_msg(_("E2fsck not compiled with HTREE support,\n\t" - "but filesystem %s has HTREE directories."), - ctx->device_name); - goto get_newer; - } -#endif - - /* - * If the user specified a specific superblock, presumably the - * master superblock has been trashed. So we mark the - * superblock as dirty, so it can be written out. - */ - if (ctx->superblock && - !(ctx->options & E2F_OPT_READONLY)) - ext2fs_mark_super_dirty(fs); - - /* - * We only update the master superblock because (a) paranoia; - * we don't want to corrupt the backup superblocks, and (b) we - * don't need to update the mount count and last checked - * fields in the backup superblock (the kernel doesn't - * update the backup superblocks anyway). - */ - fs->flags |= EXT2_FLAG_MASTER_SB_ONLY; - - ehandler_init(fs->io); - - if (ctx->superblock) - set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0); - ext2fs_mark_valid(fs); - check_super_block(ctx); - if (ctx->flags & E2F_FLAG_SIGNAL_MASK) - bb_error_msg_and_die(0); - check_if_skip(ctx); - if (ctx->flags & E2F_FLAG_SIGNAL_MASK) - bb_error_msg_and_die(0); -#ifdef ENABLE_SWAPFS - -#ifdef WORDS_BIGENDIAN -#define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES -#else -#define NATIVE_FLAG 0 -#endif - - - if (normalize_swapfs) { - if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) { - fprintf(stderr, _("%s: Filesystem byte order " - "already normalized.\n"), ctx->device_name); - bb_error_msg_and_die(0); - } - } - if (swapfs) { - swap_filesys(ctx); - if (ctx->flags & E2F_FLAG_SIGNAL_MASK) - bb_error_msg_and_die(0); - } -#endif - - /* - * Mark the system as valid, 'til proven otherwise - */ - ext2fs_mark_valid(fs); - - retval = ext2fs_read_bb_inode(fs, &fs->badblocks); - if (retval) { - bb_error_msg(_("while reading bad blocks inode")); - preenhalt(ctx); - printf(_("This doesn't bode well," - " but we'll try to go on...\n")); - } - - run_result = e2fsck_run(ctx); - e2fsck_clear_progbar(ctx); - if (run_result == E2F_FLAG_RESTART) { - printf(_("Restarting e2fsck from the beginning...\n")); - retval = e2fsck_reset_context(ctx); - if (retval) { - bb_error_msg(_("while resetting context")); - bb_error_msg_and_die(0); - } - ext2fs_close(fs); - goto restart; - } - if (run_result & E2F_FLAG_CANCEL) { - printf(_("%s: e2fsck canceled.\n"), ctx->device_name ? - ctx->device_name : ctx->filesystem_name); - exit_value |= FSCK_CANCELED; - } - if (run_result & E2F_FLAG_ABORT) - bb_error_msg_and_die(_("aborted")); - - /* Cleanup */ - if (ext2fs_test_changed(fs)) { - exit_value |= EXIT_NONDESTRUCT; - if (!(ctx->options & E2F_OPT_PREEN)) - printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"), - ctx->device_name); - if (ctx->mount_flags & EXT2_MF_ISROOT) { - printf(_("%s: ***** REBOOT LINUX *****\n"), - ctx->device_name); - exit_value |= EXIT_DESTRUCT; - } - } - if (!ext2fs_test_valid(fs)) { - printf(_("\n%s: ********** WARNING: Filesystem still has " - "errors **********\n\n"), ctx->device_name); - exit_value |= EXIT_UNCORRECTED; - exit_value &= ~EXIT_NONDESTRUCT; - } - if (exit_value & FSCK_CANCELED) - exit_value &= ~EXIT_NONDESTRUCT; - else { - show_stats(ctx); - if (!(ctx->options & E2F_OPT_READONLY)) { - if (ext2fs_test_valid(fs)) { - if (!(sb->s_state & EXT2_VALID_FS)) - exit_value |= EXIT_NONDESTRUCT; - sb->s_state = EXT2_VALID_FS; - } else - sb->s_state &= ~EXT2_VALID_FS; - sb->s_mnt_count = 0; - sb->s_lastcheck = time(NULL); - ext2fs_mark_super_dirty(fs); - } - } - - e2fsck_write_bitmaps(ctx); - - ext2fs_close(fs); - ctx->fs = NULL; - free(ctx->filesystem_name); - free(ctx->journal_name); - e2fsck_free_context(ctx); - - return exit_value; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ext2fs/kernel-list.h" -#include -#include - -/* - * Now pull in the real linux/jfs.h definitions. - */ -#include "ext2fs/kernel-jbd.h" - - - -#include "fsck.h" - -#include "ext2fs/ext2_fs.h" -#include "blkid/blkid.h" -#include "ext2fs/ext2_ext_attr.h" -#include "uuid/uuid.h" -#include "libbb.h" - -#ifdef HAVE_CONIO_H -#undef HAVE_TERMIOS_H -#include -#define read_a_char() getch() -#else -#ifdef HAVE_TERMIOS_H -#include -#endif -#endif - - -/* - * The last ext2fs revision level that this version of e2fsck is able to - * support - */ -#define E2FSCK_CURRENT_REV 1 - -/* Used by the region allocation code */ -typedef __u32 region_addr_t; -typedef struct region_struct *region_t; - -struct dx_dirblock_info { - int type; - blk_t phys; - int flags; - blk_t parent; - ext2_dirhash_t min_hash; - ext2_dirhash_t max_hash; - ext2_dirhash_t node_min_hash; - ext2_dirhash_t node_max_hash; -}; - -/* -These defines are used in the type field of dx_dirblock_info -*/ - -#define DX_DIRBLOCK_ROOT 1 -#define DX_DIRBLOCK_LEAF 2 -#define DX_DIRBLOCK_NODE 3 - - -/* -The following defines are used in the 'flags' field of a dx_dirblock_info -*/ -#define DX_FLAG_REFERENCED 1 -#define DX_FLAG_DUP_REF 2 -#define DX_FLAG_FIRST 4 -#define DX_FLAG_LAST 8 - -/* - * E2fsck options - */ -#define E2F_OPT_READONLY 0x0001 -#define E2F_OPT_PREEN 0x0002 -#define E2F_OPT_YES 0x0004 -#define E2F_OPT_NO 0x0008 -#define E2F_OPT_TIME 0x0010 -#define E2F_OPT_CHECKBLOCKS 0x0040 -#define E2F_OPT_DEBUG 0x0080 -#define E2F_OPT_FORCE 0x0100 -#define E2F_OPT_WRITECHECK 0x0200 -#define E2F_OPT_COMPRESS_DIRS 0x0400 - -/* - * E2fsck flags - */ -#define E2F_FLAG_ABORT 0x0001 /* Abort signaled */ -#define E2F_FLAG_CANCEL 0x0002 /* Cancel signaled */ -#define E2F_FLAG_SIGNAL_MASK 0x0003 -#define E2F_FLAG_RESTART 0x0004 /* Restart signaled */ - -#define E2F_FLAG_SETJMP_OK 0x0010 /* Setjmp valid for abort */ - -#define E2F_FLAG_PROG_BAR 0x0020 /* Progress bar on screen */ -#define E2F_FLAG_PROG_SUPPRESS 0x0040 /* Progress suspended */ -#define E2F_FLAG_JOURNAL_INODE 0x0080 /* Create a new ext3 journal inode */ -#define E2F_FLAG_SB_SPECIFIED 0x0100 /* The superblock was explicitly - * specified by the user */ -#define E2F_FLAG_RESTARTED 0x0200 /* E2fsck has been restarted */ -#define E2F_FLAG_RESIZE_INODE 0x0400 /* Request to recreate resize inode */ - - -/*Don't know where these come from*/ -#define READ 0 -#define WRITE 1 -#define cpu_to_be32(n) htonl(n) -#define be32_to_cpu(n) ntohl(n) - -/* - * We define a set of "latch groups"; these are problems which are - * handled as a set. The user answers once for a particular latch - * group. - */ -#define PR_LATCH_MASK 0x0ff0 /* Latch mask */ -#define PR_LATCH_BLOCK 0x0010 /* Latch for illegal blocks (pass 1) */ -#define PR_LATCH_BBLOCK 0x0020 /* Latch for bad block inode blocks (pass 1) */ -#define PR_LATCH_IBITMAP 0x0030 /* Latch for pass 5 inode bitmap proc. */ -#define PR_LATCH_BBITMAP 0x0040 /* Latch for pass 5 inode bitmap proc. */ -#define PR_LATCH_RELOC 0x0050 /* Latch for superblock relocate hint */ -#define PR_LATCH_DBLOCK 0x0060 /* Latch for pass 1b dup block headers */ -#define PR_LATCH_LOW_DTIME 0x0070 /* Latch for pass1 orphaned list refugees */ -#define PR_LATCH_TOOBIG 0x0080 /* Latch for file to big errors */ -#define PR_LATCH_OPTIMIZE_DIR 0x0090 /* Latch for optimize directories */ - -#define PR_LATCH(x) ((((x) & PR_LATCH_MASK) >> 4) - 1) - -/* - * Latch group descriptor flags - */ -#define PRL_YES 0x0001 /* Answer yes */ -#define PRL_NO 0x0002 /* Answer no */ -#define PRL_LATCHED 0x0004 /* The latch group is latched */ -#define PRL_SUPPRESS 0x0008 /* Suppress all latch group questions */ - -#define PRL_VARIABLE 0x000f /* All the flags that need to be reset */ - -/* - * Pre-Pass 1 errors - */ - -#define PR_0_BB_NOT_GROUP 0x000001 /* Block bitmap not in group */ -#define PR_0_IB_NOT_GROUP 0x000002 /* Inode bitmap not in group */ -#define PR_0_ITABLE_NOT_GROUP 0x000003 /* Inode table not in group */ -#define PR_0_SB_CORRUPT 0x000004 /* Superblock corrupt */ -#define PR_0_FS_SIZE_WRONG 0x000005 /* Filesystem size is wrong */ -#define PR_0_NO_FRAGMENTS 0x000006 /* Fragments not supported */ -#define PR_0_BLOCKS_PER_GROUP 0x000007 /* Bad blocks_per_group */ -#define PR_0_FIRST_DATA_BLOCK 0x000008 /* Bad first_data_block */ -#define PR_0_ADD_UUID 0x000009 /* Adding UUID to filesystem */ -#define PR_0_RELOCATE_HINT 0x00000A /* Relocate hint */ -#define PR_0_MISC_CORRUPT_SUPER 0x00000B /* Miscellaneous superblock corruption */ -#define PR_0_GETSIZE_ERROR 0x00000C /* Error determing physical device size of filesystem */ -#define PR_0_INODE_COUNT_WRONG 0x00000D /* Inode count in the superblock incorrect */ -#define PR_0_HURD_CLEAR_FILETYPE 0x00000E /* The Hurd does not support the filetype feature */ -#define PR_0_JOURNAL_BAD_INODE 0x00000F /* The Hurd does not support the filetype feature */ -#define PR_0_JOURNAL_UNSUPP_MULTIFS 0x000010 /* The external journal has multiple filesystems (which we can't handle yet) */ -#define PR_0_CANT_FIND_JOURNAL 0x000011 /* Can't find external journal */ -#define PR_0_EXT_JOURNAL_BAD_SUPER 0x000012/* External journal has bad superblock */ -#define PR_0_JOURNAL_BAD_UUID 0x000013 /* Superblock has a bad journal UUID */ -#define PR_0_JOURNAL_UNSUPP_SUPER 0x000014 /* Journal has an unknown superblock type */ -#define PR_0_JOURNAL_BAD_SUPER 0x000015 /* Journal superblock is corrupt */ -#define PR_0_JOURNAL_HAS_JOURNAL 0x000016 /* Journal superblock is corrupt */ -#define PR_0_JOURNAL_RECOVER_SET 0x000017 /* Superblock has recovery flag set but no journal */ -#define PR_0_JOURNAL_RECOVERY_CLEAR 0x000018 /* Journal has data, but recovery flag is clear */ -#define PR_0_JOURNAL_RESET_JOURNAL 0x000019 /* Ask if we should clear the journal */ -#define PR_0_FS_REV_LEVEL 0x00001A /* Filesystem revision is 0, but feature flags are set */ -#define PR_0_ORPHAN_CLEAR_INODE 0x000020 /* Clearing orphan inode */ -#define PR_0_ORPHAN_ILLEGAL_BLOCK_NUM 0x000021 /* Illegal block found in orphaned inode */ -#define PR_0_ORPHAN_ALREADY_CLEARED_BLOCK 0x000022 /* Already cleared block found in orphaned inode */ -#define PR_0_ORPHAN_ILLEGAL_HEAD_INODE 0x000023 /* Illegal orphan inode in superblock */ -#define PR_0_ORPHAN_ILLEGAL_INODE 0x000024 /* Illegal inode in orphaned inode list */ -#define PR_0_JOURNAL_UNSUPP_ROCOMPAT 0x000025 /* Journal has unsupported read-only feature - abort */ -#define PR_0_JOURNAL_UNSUPP_INCOMPAT 0x000026 /* Journal has unsupported incompatible feature - abort */ -#define PR_0_JOURNAL_UNSUPP_VERSION 0x000027 /* Journal has unsupported version number */ -#define PR_0_MOVE_JOURNAL 0x000028 /* Moving journal to hidden file */ -#define PR_0_ERR_MOVE_JOURNAL 0x000029 /* Error moving journal */ -#define PR_0_CLEAR_V2_JOURNAL 0x00002A /* Clearing V2 journal superblock */ -#define PR_0_JOURNAL_RUN 0x00002B /* Run journal anyway */ -#define PR_0_JOURNAL_RUN_DEFAULT 0x00002C /* Run journal anyway by default */ -#define PR_0_BACKUP_JNL 0x00002D /* Backup journal inode blocks */ -#define PR_0_NONZERO_RESERVED_GDT_BLOCKS 0x00002E /* Reserved blocks w/o resize_inode */ -#define PR_0_CLEAR_RESIZE_INODE 0x00002F /* Resize_inode not enabled, but resize inode is non-zero */ -#define PR_0_RESIZE_INODE_INVALID 0x000030 /* Resize inode invalid */ - -/* - * Pass 1 errors - */ - -#define PR_1_PASS_HEADER 0x010000 /* Pass 1: Checking inodes, blocks, and sizes */ -#define PR_1_ROOT_NO_DIR 0x010001 /* Root directory is not an inode */ -#define PR_1_ROOT_DTIME 0x010002 /* Root directory has dtime set */ -#define PR_1_RESERVED_BAD_MODE 0x010003 /* Reserved inode has bad mode */ -#define PR_1_ZERO_DTIME 0x010004 /* Deleted inode has zero dtime */ -#define PR_1_SET_DTIME 0x010005 /* Inode in use, but dtime set */ -#define PR_1_ZERO_LENGTH_DIR 0x010006 /* Zero-length directory */ -#define PR_1_BB_CONFLICT 0x010007 /* Block bitmap conflicts with some other fs block */ -#define PR_1_IB_CONFLICT 0x010008 /* Inode bitmap conflicts with some other fs block */ -#define PR_1_ITABLE_CONFLICT 0x010009 /* Inode table conflicts with some other fs block */ -#define PR_1_BB_BAD_BLOCK 0x01000A /* Block bitmap is on a bad block */ -#define PR_1_IB_BAD_BLOCK 0x01000B /* Inode bitmap is on a bad block */ -#define PR_1_BAD_I_SIZE 0x01000C /* Inode has incorrect i_size */ -#define PR_1_BAD_I_BLOCKS 0x01000D /* Inode has incorrect i_blocks */ -#define PR_1_ILLEGAL_BLOCK_NUM 0x01000E /* Illegal block number in inode */ -#define PR_1_BLOCK_OVERLAPS_METADATA 0x01000F /* Block number overlaps fs metadata */ -#define PR_1_INODE_BLOCK_LATCH 0x010010 /* Inode has illegal blocks (latch question) */ -#define PR_1_TOO_MANY_BAD_BLOCKS 0x010011 /* Too many bad blocks in inode */ -#define PR_1_BB_ILLEGAL_BLOCK_NUM 0x010012 /* Illegal block number in bad block inode */ -#define PR_1_INODE_BBLOCK_LATCH 0x010013 /* Bad block inode has illegal blocks (latch question) */ -#define PR_1_DUP_BLOCKS_PREENSTOP 0x010014 /* Duplicate or bad blocks in use! */ -#define PR_1_BBINODE_BAD_METABLOCK 0x010015 /* Bad block used as bad block indirect block */ -#define PR_1_BBINODE_BAD_METABLOCK_PROMPT 0x010016 /* Inconsistency can't be fixed prompt */ -#define PR_1_BAD_PRIMARY_BLOCK 0x010017 /* Bad primary block */ -#define PR_1_BAD_PRIMARY_BLOCK_PROMPT 0x010018 /* Bad primary block prompt */ -#define PR_1_BAD_PRIMARY_SUPERBLOCK 0x010019 /* Bad primary superblock */ -#define PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR 0x01001A /* Bad primary block group descriptors */ -#define PR_1_BAD_SUPERBLOCK 0x01001B /* Bad superblock in group */ -#define PR_1_BAD_GROUP_DESCRIPTORS 0x01001C /* Bad block group descriptors in group */ -#define PR_1_PROGERR_CLAIMED_BLOCK 0x01001D /* Block claimed for no reason */ -#define PR_1_RELOC_BLOCK_ALLOCATE 0x01001E /* Error allocating blocks for relocating metadata */ -#define PR_1_RELOC_MEMORY_ALLOCATE 0x01001F /* Error allocating block buffer during relocation process */ -#define PR_1_RELOC_FROM_TO 0x010020 /* Relocating metadata group information from X to Y */ -#define PR_1_RELOC_TO 0x010021 /* Relocating metatdata group information to X */ -#define PR_1_RELOC_READ_ERR 0x010022 /* Block read error during relocation process */ -#define PR_1_RELOC_WRITE_ERR 0x010023 /* Block write error during relocation process */ -#define PR_1_ALLOCATE_IBITMAP_ERROR 0x010024 /* Error allocating inode bitmap */ -#define PR_1_ALLOCATE_BBITMAP_ERROR 0x010025 /* Error allocating block bitmap */ -#define PR_1_ALLOCATE_ICOUNT 0x010026 /* Error allocating icount structure */ -#define PR_1_ALLOCATE_DBCOUNT 0x010027 /* Error allocating dbcount */ -#define PR_1_ISCAN_ERROR 0x010028 /* Error while scanning inodes */ -#define PR_1_BLOCK_ITERATE 0x010029 /* Error while iterating over blocks */ -#define PR_1_ICOUNT_STORE 0x01002A /* Error while storing inode count information */ -#define PR_1_ADD_DBLOCK 0x01002B /* Error while storing directory block information */ -#define PR_1_READ_INODE 0x01002C /* Error while reading inode (for clearing) */ -#define PR_1_SUPPRESS_MESSAGES 0x01002D /* Suppress messages prompt */ -#define PR_1_SET_IMAGIC 0x01002F /* Imagic flag set on an inode when filesystem doesn't support it */ -#define PR_1_SET_IMMUTABLE 0x010030 /* Immutable flag set on a device or socket inode */ -#define PR_1_COMPR_SET 0x010031 /* Compression flag set on a non-compressed filesystem */ -#define PR_1_SET_NONZSIZE 0x010032 /* Non-zero size on device, fifo or socket inode */ -#define PR_1_FS_REV_LEVEL 0x010033 /* Filesystem revision is 0, but feature flags are set */ -#define PR_1_JOURNAL_INODE_NOT_CLEAR 0x010034 /* Journal inode not in use, needs clearing */ -#define PR_1_JOURNAL_BAD_MODE 0x010035 /* Journal inode has wrong mode */ -#define PR_1_LOW_DTIME 0x010036 /* Inode that was part of orphan linked list */ -#define PR_1_ORPHAN_LIST_REFUGEES 0x010037 /* Latch question which asks how to deal with low dtime inodes */ -#define PR_1_ALLOCATE_REFCOUNT 0x010038 /* Error allocating refcount structure */ -#define PR_1_READ_EA_BLOCK 0x010039 /* Error reading Extended Attribute block */ -#define PR_1_BAD_EA_BLOCK 0x01003A /* Invalid Extended Attribute block */ -#define PR_1_EXTATTR_READ_ABORT 0x01003B /* Error reading Extended Attribute block while fixing refcount -- abort */ -#define PR_1_EXTATTR_REFCOUNT 0x01003C /* Extended attribute reference count incorrect */ -#define PR_1_EXTATTR_WRITE 0x01003D /* Error writing Extended Attribute block while fixing refcount */ -#define PR_1_EA_MULTI_BLOCK 0x01003E /* Multiple EA blocks not supported */ -#define PR_1_EA_ALLOC_REGION 0x01003F /* Error allocating EA region allocation structure */ -#define PR_1_EA_ALLOC_COLLISION 0x010040 /* Error EA allocation collision */ -#define PR_1_EA_BAD_NAME 0x010041 /* Bad extended attribute name */ -#define PR_1_EA_BAD_VALUE 0x010042 /* Bad extended attribute value */ -#define PR_1_INODE_TOOBIG 0x010043 /* Inode too big (latch question) */ -#define PR_1_TOOBIG_DIR 0x010044 /* Directory too big */ -#define PR_1_TOOBIG_REG 0x010045 /* Regular file too big */ -#define PR_1_TOOBIG_SYMLINK 0x010046 /* Symlink too big */ -#define PR_1_HTREE_SET 0x010047 /* INDEX_FL flag set on a non-HTREE filesystem */ -#define PR_1_HTREE_NODIR 0x010048 /* INDEX_FL flag set on a non-directory */ -#define PR_1_HTREE_BADROOT 0x010049 /* Invalid root node in HTREE directory */ -#define PR_1_HTREE_HASHV 0x01004A /* Unsupported hash version in HTREE directory */ -#define PR_1_HTREE_INCOMPAT 0x01004B /* Incompatible flag in HTREE root node */ -#define PR_1_HTREE_DEPTH 0x01004C /* HTREE too deep */ -#define PR_1_BB_FS_BLOCK 0x01004D /* Bad block has indirect block that conflicts with filesystem block */ -#define PR_1_RESIZE_INODE_CREATE 0x01004E /* Resize inode failed */ -#define PR_1_EXTRA_ISIZE 0x01004F /* inode->i_size is too long */ -#define PR_1_ATTR_NAME_LEN 0x010050 /* attribute name is too long */ -#define PR_1_ATTR_VALUE_OFFSET 0x010051 /* wrong EA value offset */ -#define PR_1_ATTR_VALUE_BLOCK 0x010052 /* wrong EA blocknumber */ -#define PR_1_ATTR_VALUE_SIZE 0x010053 /* wrong EA value size */ -#define PR_1_ATTR_HASH 0x010054 /* wrong EA hash value */ - -/* - * Pass 1b errors - */ - -#define PR_1B_PASS_HEADER 0x011000 /* Pass 1B: Rescan for duplicate/bad blocks */ -#define PR_1B_DUP_BLOCK_HEADER 0x011001 /* Duplicate/bad block(s) header */ -#define PR_1B_DUP_BLOCK 0x011002 /* Duplicate/bad block(s) in inode */ -#define PR_1B_DUP_BLOCK_END 0x011003 /* Duplicate/bad block(s) end */ -#define PR_1B_ISCAN_ERROR 0x011004 /* Error while scanning inodes */ -#define PR_1B_ALLOCATE_IBITMAP_ERROR 0x011005 /* Error allocating inode bitmap */ -#define PR_1B_BLOCK_ITERATE 0x0110006 /* Error while iterating over blocks */ -#define PR_1B_ADJ_EA_REFCOUNT 0x0110007 /* Error adjusting EA refcount */ -#define PR_1C_PASS_HEADER 0x012000 /* Pass 1C: Scan directories for inodes with dup blocks. */ -#define PR_1D_PASS_HEADER 0x013000 /* Pass 1D: Reconciling duplicate blocks */ -#define PR_1D_DUP_FILE 0x013001 /* File has duplicate blocks */ -#define PR_1D_DUP_FILE_LIST 0x013002 /* List of files sharing duplicate blocks */ -#define PR_1D_SHARE_METADATA 0x013003 /* File sharing blocks with filesystem metadata */ -#define PR_1D_NUM_DUP_INODES 0x013004 /* Report of how many duplicate/bad inodes */ -#define PR_1D_DUP_BLOCKS_DEALT 0x013005 /* Duplicated blocks already reassigned or cloned. */ -#define PR_1D_CLONE_QUESTION 0x013006 /* Clone duplicate/bad blocks? */ -#define PR_1D_DELETE_QUESTION 0x013007 /* Delete file? */ -#define PR_1D_CLONE_ERROR 0x013008 /* Couldn't clone file (error) */ - -/* - * Pass 2 errors - */ - -#define PR_2_PASS_HEADER 0x020000 /* Pass 2: Checking directory structure */ -#define PR_2_BAD_INODE_DOT 0x020001 /* Bad inode number for '.' */ -#define PR_2_BAD_INO 0x020002 /* Directory entry has bad inode number */ -#define PR_2_UNUSED_INODE 0x020003 /* Directory entry has deleted or unused inode */ -#define PR_2_LINK_DOT 0x020004 /* Directry entry is link to '.' */ -#define PR_2_BB_INODE 0x020005 /* Directory entry points to inode now located in a bad block */ -#define PR_2_LINK_DIR 0x020006 /* Directory entry contains a link to a directory */ -#define PR_2_LINK_ROOT 0x020007 /* Directory entry contains a link to the root directry */ -#define PR_2_BAD_NAME 0x020008 /* Directory entry has illegal characters in its name */ -#define PR_2_MISSING_DOT 0x020009 /* Missing '.' in directory inode */ -#define PR_2_MISSING_DOT_DOT 0x02000A /* Missing '..' in directory inode */ -#define PR_2_1ST_NOT_DOT 0x02000B /* First entry in directory inode doesn't contain '.' */ -#define PR_2_2ND_NOT_DOT_DOT 0x02000C /* Second entry in directory inode doesn't contain '..' */ -#define PR_2_FADDR_ZERO 0x02000D /* i_faddr should be zero */ -#define PR_2_FILE_ACL_ZERO 0x02000E /* i_file_acl should be zero */ -#define PR_2_DIR_ACL_ZERO 0x02000F /* i_dir_acl should be zero */ -#define PR_2_FRAG_ZERO 0x020010 /* i_frag should be zero */ -#define PR_2_FSIZE_ZERO 0x020011 /* i_fsize should be zero */ -#define PR_2_BAD_MODE 0x020012 /* inode has bad mode */ -#define PR_2_DIR_CORRUPTED 0x020013 /* directory corrupted */ -#define PR_2_FILENAME_LONG 0x020014 /* filename too long */ -#define PR_2_DIRECTORY_HOLE 0x020015 /* Directory inode has a missing block (hole) */ -#define PR_2_DOT_NULL_TERM 0x020016 /* '.' is not NULL terminated */ -#define PR_2_DOT_DOT_NULL_TERM 0x020017 /* '..' is not NULL terminated */ -#define PR_2_BAD_CHAR_DEV 0x020018 /* Illegal character device in inode */ -#define PR_2_BAD_BLOCK_DEV 0x020019 /* Illegal block device in inode */ -#define PR_2_DUP_DOT 0x02001A /* Duplicate '.' entry */ -#define PR_2_DUP_DOT_DOT 0x02001B /* Duplicate '..' entry */ -#define PR_2_NO_DIRINFO 0x02001C /* Internal error: couldn't find dir_info */ -#define PR_2_FINAL_RECLEN 0x02001D /* Final rec_len is wrong */ -#define PR_2_ALLOCATE_ICOUNT 0x02001E /* Error allocating icount structure */ -#define PR_2_DBLIST_ITERATE 0x02001F /* Error iterating over directory blocks */ -#define PR_2_READ_DIRBLOCK 0x020020 /* Error reading directory block */ -#define PR_2_WRITE_DIRBLOCK 0x020021 /* Error writing directory block */ -#define PR_2_ALLOC_DIRBOCK 0x020022 /* Error allocating new directory block */ -#define PR_2_DEALLOC_INODE 0x020023 /* Error deallocating inode */ -#define PR_2_SPLIT_DOT 0x020024 /* Directory entry for '.' is big. Split? */ -#define PR_2_BAD_FIFO 0x020025 /* Illegal FIFO */ -#define PR_2_BAD_SOCKET 0x020026 /* Illegal socket */ -#define PR_2_SET_FILETYPE 0x020027 /* Directory filetype not set */ -#define PR_2_BAD_FILETYPE 0x020028 /* Directory filetype incorrect */ -#define PR_2_CLEAR_FILETYPE 0x020029 /* Directory filetype set when it shouldn't be */ -#define PR_2_NULL_NAME 0x020030 /* Directory filename can't be zero-length */ -#define PR_2_INVALID_SYMLINK 0x020031 /* Invalid symlink */ -#define PR_2_FILE_ACL_BAD 0x020032 /* i_file_acl (extended attribute) is bad */ -#define PR_2_FEATURE_LARGE_FILES 0x020033 /* Filesystem contains large files, but has no such flag in sb */ -#define PR_2_HTREE_NOTREF 0x020034 /* Node in HTREE directory not referenced */ -#define PR_2_HTREE_DUPREF 0x020035 /* Node in HTREE directory referenced twice */ -#define PR_2_HTREE_MIN_HASH 0x020036 /* Node in HTREE directory has bad min hash */ -#define PR_2_HTREE_MAX_HASH 0x020037 /* Node in HTREE directory has bad max hash */ -#define PR_2_HTREE_CLEAR 0x020038 /* Clear invalid HTREE directory */ -#define PR_2_HTREE_BADBLK 0x02003A /* Bad block in htree interior node */ -#define PR_2_ADJ_EA_REFCOUNT 0x02003B /* Error adjusting EA refcount */ -#define PR_2_HTREE_BAD_ROOT 0x02003C /* Invalid HTREE root node */ -#define PR_2_HTREE_BAD_LIMIT 0x02003D /* Invalid HTREE limit */ -#define PR_2_HTREE_BAD_COUNT 0x02003E /* Invalid HTREE count */ -#define PR_2_HTREE_HASH_ORDER 0x02003F /* HTREE interior node has out-of-order hashes in table */ -#define PR_2_HTREE_BAD_DEPTH 0x020040 /* Node in HTREE directory has bad depth */ -#define PR_2_DUPLICATE_DIRENT 0x020041 /* Duplicate directory entry found */ -#define PR_2_NON_UNIQUE_FILE 0x020042 /* Non-unique filename found */ -#define PR_2_REPORT_DUP_DIRENT 0x020043 /* Duplicate directory entry found */ - -/* - * Pass 3 errors - */ - -#define PR_3_PASS_HEADER 0x030000 /* Pass 3: Checking directory connectivity */ -#define PR_3_NO_ROOT_INODE 0x030001 /* Root inode not allocated */ -#define PR_3_EXPAND_LF_DIR 0x030002 /* No room in lost+found */ -#define PR_3_UNCONNECTED_DIR 0x030003 /* Unconnected directory inode */ -#define PR_3_NO_LF_DIR 0x030004 /* /lost+found not found */ -#define PR_3_BAD_DOT_DOT 0x030005 /* .. entry is incorrect */ -#define PR_3_NO_LPF 0x030006 /* Bad or non-existent /lost+found. Cannot reconnect */ -#define PR_3_CANT_EXPAND_LPF 0x030007 /* Could not expand /lost+found */ -#define PR_3_CANT_RECONNECT 0x030008 /* Could not reconnect inode */ -#define PR_3_ERR_FIND_LPF 0x030009 /* Error while trying to find /lost+found */ -#define PR_3_ERR_LPF_NEW_BLOCK 0x03000A /* Error in ext2fs_new_block while creating /lost+found */ -#define PR_3_ERR_LPF_NEW_INODE 0x03000B /* Error in ext2fs_new_inode while creating /lost+found */ -#define PR_3_ERR_LPF_NEW_DIR_BLOCK 0x03000C /* Error in ext2fs_new_dir_block while creating /lost+found */ -#define PR_3_ERR_LPF_WRITE_BLOCK 0x03000D /* Error while writing directory block for /lost+found */ -#define PR_3_ADJUST_INODE 0x03000E /* Error while adjusting inode count */ -#define PR_3_FIX_PARENT_ERR 0x03000F /* Couldn't fix parent directory -- error */ -#define PR_3_FIX_PARENT_NOFIND 0x030010 /* Couldn't fix parent directory -- couldn't find it */ -#define PR_3_ALLOCATE_IBITMAP_ERROR 0x030011 /* Error allocating inode bitmap */ -#define PR_3_CREATE_ROOT_ERROR 0x030012 /* Error creating root directory */ -#define PR_3_CREATE_LPF_ERROR 0x030013 /* Error creating lost and found directory */ -#define PR_3_ROOT_NOT_DIR_ABORT 0x030014 /* Root inode is not directory; aborting */ -#define PR_3_NO_ROOT_INODE_ABORT 0x030015 /* Cannot proceed without a root inode. */ -#define PR_3_NO_DIRINFO 0x030016 /* Internal error: couldn't find dir_info */ -#define PR_3_LPF_NOTDIR 0x030017 /* Lost+found is not a directory */ - -/* - * Pass 3a --- rehashing diretories - */ -#define PR_3A_PASS_HEADER 0x031000 /* Pass 3a: Reindexing directories */ -#define PR_3A_OPTIMIZE_ITER 0x031001 /* Error iterating over directories */ -#define PR_3A_OPTIMIZE_DIR_ERR 0x031002 /* Error rehash directory */ -#define PR_3A_OPTIMIZE_DIR_HEADER 0x031003 /* Rehashing dir header */ -#define PR_3A_OPTIMIZE_DIR 0x031004 /* Rehashing directory %d */ -#define PR_3A_OPTIMIZE_DIR_END 0x031005 /* Rehashing dir end */ - -/* - * Pass 4 errors - */ - -#define PR_4_PASS_HEADER 0x040000 /* Pass 4: Checking reference counts */ -#define PR_4_ZERO_LEN_INODE 0x040001 /* Unattached zero-length inode */ -#define PR_4_UNATTACHED_INODE 0x040002 /* Unattached inode */ -#define PR_4_BAD_REF_COUNT 0x040003 /* Inode ref count wrong */ -#define PR_4_INCONSISTENT_COUNT 0x040004 /* Inconsistent inode count information cached */ - -/* - * Pass 5 errors - */ - -#define PR_5_PASS_HEADER 0x050000 /* Pass 5: Checking group summary information */ -#define PR_5_INODE_BMAP_PADDING 0x050001 /* Padding at end of inode bitmap is not set. */ -#define PR_5_BLOCK_BMAP_PADDING 0x050002 /* Padding at end of block bitmap is not set. */ -#define PR_5_BLOCK_BITMAP_HEADER 0x050003 /* Block bitmap differences header */ -#define PR_5_BLOCK_UNUSED 0x050004 /* Block not used, but marked in bitmap */ -#define PR_5_BLOCK_USED 0x050005 /* Block used, but not marked used in bitmap */ -#define PR_5_BLOCK_BITMAP_END 0x050006 /* Block bitmap differences end */ -#define PR_5_INODE_BITMAP_HEADER 0x050007 /* Inode bitmap differences header */ -#define PR_5_INODE_UNUSED 0x050008 /* Inode not used, but marked in bitmap */ -#define PR_5_INODE_USED 0x050009 /* Inode used, but not marked used in bitmap */ -#define PR_5_INODE_BITMAP_END 0x05000A /* Inode bitmap differences end */ -#define PR_5_FREE_INODE_COUNT_GROUP 0x05000B /* Free inodes count for group wrong */ -#define PR_5_FREE_DIR_COUNT_GROUP 0x05000C /* Directories count for group wrong */ -#define PR_5_FREE_INODE_COUNT 0x05000D /* Free inodes count wrong */ -#define PR_5_FREE_BLOCK_COUNT_GROUP 0x05000E /* Free blocks count for group wrong */ -#define PR_5_FREE_BLOCK_COUNT 0x05000F /* Free blocks count wrong */ -#define PR_5_BMAP_ENDPOINTS 0x050010 /* Programming error: bitmap endpoints don't match */ -#define PR_5_FUDGE_BITMAP_ERROR 0x050011 /* Internal error: fudging end of bitmap */ -#define PR_5_COPY_IBITMAP_ERROR 0x050012 /* Error copying in replacement inode bitmap */ -#define PR_5_COPY_BBITMAP_ERROR 0x050013 /* Error copying in replacement block bitmap */ -#define PR_5_BLOCK_RANGE_UNUSED 0x050014 /* Block range not used, but marked in bitmap */ -#define PR_5_BLOCK_RANGE_USED 0x050015 /* Block range used, but not marked used in bitmap */ -#define PR_5_INODE_RANGE_UNUSED 0x050016 /* Inode range not used, but marked in bitmap */ -#define PR_5_INODE_RANGE_USED 0x050017 /* Inode rangeused, but not marked used in bitmap */ - - -/* - * The directory information structure; stores directory information - * collected in earlier passes, to avoid disk i/o in fetching the - * directory information. - */ -struct dir_info { - ext2_ino_t ino; /* Inode number */ - ext2_ino_t dotdot; /* Parent according to '..' */ - ext2_ino_t parent; /* Parent according to treewalk */ -}; - - - -/* - * The indexed directory information structure; stores information for - * directories which contain a hash tree index. - */ -struct dx_dir_info { - ext2_ino_t ino; /* Inode number */ - int numblocks; /* number of blocks */ - int hashversion; - short depth; /* depth of tree */ - struct dx_dirblock_info *dx_block; /* Array of size numblocks */ -}; - -/* - * Define the extended attribute refcount structure - */ -typedef struct ea_refcount *ext2_refcount_t; - -struct e2fsck_struct { - ext2_filsys fs; - const char *program_name; - char *filesystem_name; - char *device_name; - char *io_options; - int flags; /* E2fsck internal flags */ - int options; - blk_t use_superblock; /* sb requested by user */ - blk_t superblock; /* sb used to open fs */ - int blocksize; /* blocksize */ - blk_t num_blocks; /* Total number of blocks */ - int mount_flags; - blkid_cache blkid; /* blkid cache */ - - jmp_buf abort_loc; - - unsigned long abort_code; - - int (*progress)(e2fsck_t ctx, int pass, unsigned long cur, - unsigned long max); - - ext2fs_inode_bitmap inode_used_map; /* Inodes which are in use */ - ext2fs_inode_bitmap inode_bad_map; /* Inodes which are bad somehow */ - ext2fs_inode_bitmap inode_dir_map; /* Inodes which are directories */ - ext2fs_inode_bitmap inode_imagic_map; /* AFS inodes */ - ext2fs_inode_bitmap inode_reg_map; /* Inodes which are regular files*/ - - ext2fs_block_bitmap block_found_map; /* Blocks which are in use */ - ext2fs_block_bitmap block_dup_map; /* Blks referenced more than once */ - ext2fs_block_bitmap block_ea_map; /* Blocks which are used by EA's */ - - /* - * Inode count arrays - */ - ext2_icount_t inode_count; - ext2_icount_t inode_link_info; - - ext2_refcount_t refcount; - ext2_refcount_t refcount_extra; - - /* - * Array of flags indicating whether an inode bitmap, block - * bitmap, or inode table is invalid - */ - int *invalid_inode_bitmap_flag; - int *invalid_block_bitmap_flag; - int *invalid_inode_table_flag; - int invalid_bitmaps; /* There are invalid bitmaps/itable */ - - /* - * Block buffer - */ - char *block_buf; - - /* - * For pass1_check_directory and pass1_get_blocks - */ - ext2_ino_t stashed_ino; - struct ext2_inode *stashed_inode; - - /* - * Location of the lost and found directory - */ - ext2_ino_t lost_and_found; - int bad_lost_and_found; - - /* - * Directory information - */ - int dir_info_count; - int dir_info_size; - struct dir_info *dir_info; - - /* - * Indexed directory information - */ - int dx_dir_info_count; - int dx_dir_info_size; - struct dx_dir_info *dx_dir_info; - - /* - * Directories to hash - */ - ext2_u32_list dirs_to_hash; - - /* - * Tuning parameters - */ - int process_inode_size; - int inode_buffer_blocks; - - /* - * ext3 journal support - */ - io_channel journal_io; - char *journal_name; - - /* - * How we display the progress update (for unix) - */ - int progress_fd; - int progress_pos; - int progress_last_percent; - unsigned int progress_last_time; - int interactive; /* Are we connected directly to a tty? */ - char start_meta[2], stop_meta[2]; - - /* File counts */ - int fs_directory_count; - int fs_regular_count; - int fs_blockdev_count; - int fs_chardev_count; - int fs_links_count; - int fs_symlinks_count; - int fs_fast_symlinks_count; - int fs_fifo_count; - int fs_total_count; - int fs_sockets_count; - int fs_ind_count; - int fs_dind_count; - int fs_tind_count; - int fs_fragmented; - int large_files; - int fs_ext_attr_inodes; - int fs_ext_attr_blocks; - - int ext_attr_ver; - - /* - * For the use of callers of the e2fsck functions; not used by - * e2fsck functions themselves. - */ - void *priv_data; -}; - - -#define tid_gt(x, y) ((x - y) > 0) - -static inline int tid_geq(tid_t x, tid_t y) -{ - int difference = (x - y); - return (difference >= 0); -} diff --git a/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 @@ -# Makefile for busybox -# -# Copyright (C) 1999-2005 by Erik Andersen -# -# Licensed under GPLv2, see file LICENSE in this source tree. - -NEEDED-$(CONFIG_CHATTR) = y -NEEDED-$(CONFIG_LSATTR) = y -NEEDED-$(CONFIG_MKE2FS) = y -NEEDED-$(CONFIG_TUNE2FS) = y - -lib-y:= - -INSERT - -lib-$(NEEDED-y) += fgetsetflags.o fgetsetversion.o pf.o iod.o mntopts.o \ - feature.o ls.o uuid.o pe.o ostype.o ps.o hashstr.o \ - 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 @@ -/* vi: set sw=4 ts=4: */ -#include "libbb.h" -#include /* Needed by dirent.h on netbsd */ -#include -#include - -#include "../ext2fs/ext2_fs.h" - -#define E2P_FEATURE_COMPAT 0 -#define E2P_FEATURE_INCOMPAT 1 -#define E2P_FEATURE_RO_INCOMPAT 2 -#ifndef EXT3_FEATURE_INCOMPAT_EXTENTS -#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040 -#endif - -/* `options' for print_e2flags() */ - -#define PFOPT_LONG 1 /* Must be 1 for compatibility with `int long_format'. */ - -/*int fgetversion (const char * name, unsigned long * version);*/ -/*int fsetversion (const char * name, unsigned long version);*/ -int fgetsetversion(const char * name, unsigned long * get_version, unsigned long set_version); -#define fgetversion(name, version) fgetsetversion(name, version, 0) -#define fsetversion(name, version) fgetsetversion(name, NULL, version) - -/*int fgetflags (const char * name, unsigned long * flags);*/ -/*int fsetflags (const char * name, unsigned long flags);*/ -int fgetsetflags(const char * name, unsigned long * get_flags, unsigned long set_flags); -#define fgetflags(name, flags) fgetsetflags(name, flags, 0) -#define fsetflags(name, flags) fgetsetflags(name, NULL, flags) - -int getflags (int fd, unsigned long * flags); -int getversion (int fd, unsigned long * version); -int iterate_on_dir (const char * dir_name, - int (*func) (const char *, struct dirent *, void *), - void * private); -/*void list_super(struct ext2_super_block * s);*/ -void list_super2(struct ext2_super_block * s, FILE *f); -#define list_super(s) list_super2(s, stdout) -void print_fs_errors (FILE *f, unsigned short errors); -void print_flags (FILE *f, unsigned long flags, unsigned options); -void print_fs_state (FILE *f, unsigned short state); -int setflags (int fd, unsigned long flags); -int setversion (int fd, unsigned long version); - -const char *e2p_feature2string(int compat, unsigned int mask); -int e2p_string2feature(char *string, int *compat, unsigned int *mask); -int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array); - -int e2p_is_null_uuid(void *uu); -void e2p_uuid_to_str(void *uu, char *out); -const char *e2p_uuid2str(void *uu); - -const char *e2p_hash2string(int num); -int e2p_string2hash(char *string); - -const char *e2p_mntopt2string(unsigned int mask); -int e2p_string2mntopt(char *string, unsigned int *mask); -int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok); - -unsigned long parse_num_blocks(const char *arg, int log_block_size); - -char *e2p_os2string(int os_type); -int e2p_string2os(char *str); diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * feature.c --- convert between features and strings - * - * Copyright (C) 1999 Theodore Ts'o - * - * This file can be redistributed under the terms of the GNU Library General - * Public License - * - */ - -#include -#include -#include -#include -#include - -#include "e2p.h" - -struct feature { - int compat; - unsigned int mask; - const char *string; -}; - -static const struct feature feature_list[] = { - { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_PREALLOC, - "dir_prealloc" }, - { E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL, - "has_journal" }, - { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_IMAGIC_INODES, - "imagic_inodes" }, - { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_EXT_ATTR, - "ext_attr" }, - { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_INDEX, - "dir_index" }, - { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_RESIZE_INO, - "resize_inode" }, - { E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER, - "sparse_super" }, - { E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_LARGE_FILE, - "large_file" }, - { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_COMPRESSION, - "compression" }, - { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_FILETYPE, - "filetype" }, - { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_RECOVER, - "needs_recovery" }, - { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV, - "journal_dev" }, - { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS, - "extents" }, - { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_META_BG, - "meta_bg" }, - { 0, 0, 0 }, -}; - -const char *e2p_feature2string(int compat, unsigned int mask) -{ - const struct feature *f; - static char buf[20]; - char fchar; - int fnum; - - for (f = feature_list; f->string; f++) { - if ((compat == f->compat) && - (mask == f->mask)) - return f->string; - } - switch (compat) { - case E2P_FEATURE_COMPAT: - fchar = 'C'; - break; - case E2P_FEATURE_INCOMPAT: - fchar = 'I'; - break; - case E2P_FEATURE_RO_INCOMPAT: - fchar = 'R'; - break; - default: - fchar = '?'; - break; - } - for (fnum = 0; mask >>= 1; fnum++); - sprintf(buf, "FEATURE_%c%d", fchar, fnum); - return buf; -} - -int e2p_string2feature(char *string, int *compat_type, unsigned int *mask) -{ - const struct feature *f; - char *eptr; - int num; - - for (f = feature_list; f->string; f++) { - if (!strcasecmp(string, f->string)) { - *compat_type = f->compat; - *mask = f->mask; - return 0; - } - } - if (strncasecmp(string, "FEATURE_", 8)) - return 1; - - switch (string[8]) { - case 'c': - case 'C': - *compat_type = E2P_FEATURE_COMPAT; - break; - case 'i': - case 'I': - *compat_type = E2P_FEATURE_INCOMPAT; - break; - case 'r': - case 'R': - *compat_type = E2P_FEATURE_RO_INCOMPAT; - break; - default: - return 1; - } - if (string[9] == 0) - return 1; - num = strtol(string+9, &eptr, 10); - if (num > 32 || num < 0) - return 1; - if (*eptr) - return 1; - *mask = 1 << num; - return 0; -} - -static inline char *skip_over_blanks(char *cp) -{ - while (*cp && isspace(*cp)) - cp++; - return cp; -} - -static inline char *skip_over_word(char *cp) -{ - while (*cp && !isspace(*cp) && *cp != ',') - cp++; - return cp; -} - -/* - * Edit a feature set array as requested by the user. The ok_array, - * if set, allows the application to limit what features the user is - * allowed to set or clear using this function. - */ -int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array) -{ - char *cp, *buf, *next; - int neg; - unsigned int mask; - int compat_type; - - buf = xstrdup(str); - cp = buf; - while (cp && *cp) { - neg = 0; - cp = skip_over_blanks(cp); - next = skip_over_word(cp); - if (*next == 0) - next = 0; - else - *next = 0; - switch (*cp) { - case '-': - case '^': - neg++; - case '+': - cp++; - break; - } - if (e2p_string2feature(cp, &compat_type, &mask)) - return 1; - if (ok_array && !(ok_array[compat_type] & mask)) - return 1; - if (neg) - compat_array[compat_type] &= ~mask; - else - compat_array[compat_type] |= mask; - cp = next ? next+1 : 0; - } - return 0; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * fgetflags.c - Get a file flags on an ext2 file system - * fsetflags.c - Set a file flags on an ext2 file system - * - * Copyright (C) 1993, 1994 Remy Card - * Laboratoire MASI, Institut Blaise Pascal - * Universite Pierre et Marie Curie (Paris VI) - * - * This file can be redistributed under the terms of the GNU Library General - * Public License - */ - -/* - * History: - * 93/10/30 - Creation - */ - -#ifdef HAVE_ERRNO_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#include -#ifdef HAVE_EXT2_IOCTLS -#include -#include -#endif - -#include "e2p.h" - -#ifdef O_LARGEFILE -#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE) -#else -#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK) -#endif - -int fgetsetflags (const char * name, unsigned long * get_flags, unsigned long set_flags) -{ -#ifdef HAVE_EXT2_IOCTLS - struct stat buf; - int fd, r, f, save_errno = 0; - - if (!stat(name, &buf) && - !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) { - goto notsupp; - } - fd = open (name, OPEN_FLAGS); - if (fd == -1) - return -1; - if (!get_flags) { - f = (int) set_flags; - r = ioctl (fd, EXT2_IOC_SETFLAGS, &f); - } else { - r = ioctl (fd, EXT2_IOC_GETFLAGS, &f); - *get_flags = f; - } - if (r == -1) - save_errno = errno; - close (fd); - if (save_errno) - errno = save_errno; - return r; -notsupp: -#endif /* HAVE_EXT2_IOCTLS */ - errno = EOPNOTSUPP; - return -1; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * fgetversion.c - Get a file version on an ext2 file system - * fsetversion.c - Set a file version on an ext2 file system - * - * - * Copyright (C) 1993, 1994 Remy Card - * Laboratoire MASI, Institut Blaise Pascal - * Universite Pierre et Marie Curie (Paris VI) - * - * This file can be redistributed under the terms of the GNU Library General - * Public License - */ - -/* - * History: - * 93/10/30 - Creation - */ - -#ifdef HAVE_ERRNO_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#include - -#include "e2p.h" - -#ifdef O_LARGEFILE -#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE) -#else -#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK) -#endif - -/* - To do fsetversion: unsigned long *ptr_version must be set to NULL. - and unsigned long version must be set to a value - To do fgetversion: unsigned long *ptr_version must NOT be set to NULL - and unsigned long version is ignored. - TITO. -*/ - -int fgetsetversion (const char * name, unsigned long * get_version, unsigned long set_version) -{ -#ifdef HAVE_EXT2_IOCTLS - int fd, r, ver, save_errno = 0; - - fd = open (name, OPEN_FLAGS); - if (fd == -1) - return -1; - if (!get_version) { - ver = (int) set_version; - r = ioctl (fd, EXT2_IOC_SETVERSION, &ver); - } else { - r = ioctl (fd, EXT2_IOC_GETVERSION, &ver); - *get_version = ver; - } - if (r == -1) - save_errno = errno; - close (fd); - if (save_errno) - errno = save_errno; - return r; -#else /* ! HAVE_EXT2_IOCTLS */ - errno = EOPNOTSUPP; - return -1; -#endif /* ! HAVE_EXT2_IOCTLS */ -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * feature.c --- convert between features and strings - * - * Copyright (C) 1999 Theodore Ts'o - * - * This file can be redistributed under the terms of the GNU Library General - * Public License - * - */ - -#include -#include -#include -#include -#include - -#include "e2p.h" - -struct hash { - int num; - const char *string; -}; - -static const struct hash hash_list[] = { - { EXT2_HASH_LEGACY, "legacy" }, - { EXT2_HASH_HALF_MD4, "half_md4" }, - { EXT2_HASH_TEA, "tea" }, - { 0, 0 }, -}; - -const char *e2p_hash2string(int num) -{ - const struct hash *p; - static char buf[20]; - - for (p = hash_list; p->string; p++) { - if (num == p->num) - return p->string; - } - sprintf(buf, "HASHALG_%d", num); - return buf; -} - -/* - * Returns the hash algorithm, or -1 on error - */ -int e2p_string2hash(char *string) -{ - const struct hash *p; - char *eptr; - int num; - - for (p = hash_list; p->string; p++) { - if (!strcasecmp(string, p->string)) { - return p->num; - } - } - if (strncasecmp(string, "HASHALG_", 8)) - return -1; - - if (string[8] == 0) - return -1; - num = strtol(string+8, &eptr, 10); - if (num > 255 || num < 0) - return -1; - if (*eptr) - return -1; - return num; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * iod.c - Iterate a function on each entry of a directory - * - * Copyright (C) 1993, 1994 Remy Card - * Laboratoire MASI, Institut Blaise Pascal - * Universite Pierre et Marie Curie (Paris VI) - * - * This file can be redistributed under the terms of the GNU Library General - * Public License - */ - -/* - * History: - * 93/10/30 - Creation - */ - -#include "e2p.h" -#include -#include -#include - -int iterate_on_dir (const char * dir_name, - int (*func) (const char *, struct dirent *, void *), - void * private) -{ - DIR * dir; - struct dirent *de, *dep; - int max_len, len; - - max_len = PATH_MAX + sizeof(struct dirent); - de = xmalloc(max_len+1); - memset(de, 0, max_len+1); - - dir = opendir (dir_name); - if (dir == NULL) { - free(de); - return -1; - } - while ((dep = readdir (dir))) { - len = sizeof(struct dirent); - if (len < dep->d_reclen) - len = dep->d_reclen; - if (len > max_len) - len = max_len; - memcpy(de, dep, len); - (*func) (dir_name, de, private); - } - free(de); - closedir(dir); - return 0; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * ls.c - List the contents of an ext2fs superblock - * - * Copyright (C) 1992, 1993, 1994 Remy Card - * Laboratoire MASI, Institut Blaise Pascal - * Universite Pierre et Marie Curie (Paris VI) - * - * Copyright (C) 1995, 1996, 1997 Theodore Ts'o - * - * This file can be redistributed under the terms of the GNU Library General - * Public License - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "e2p.h" - -static void print_user(unsigned short uid, FILE *f) -{ - struct passwd *pw = getpwuid(uid); - fprintf(f, "%u (user %s)\n", uid, - (pw == NULL ? "unknown" : pw->pw_name)); -} - -static void print_group(unsigned short gid, FILE *f) -{ - struct group *gr = getgrgid(gid); - fprintf(f, "%u (group %s)\n", gid, - (gr == NULL ? "unknown" : gr->gr_name)); -} - -#define MONTH_INT (86400 * 30) -#define WEEK_INT (86400 * 7) -#define DAY_INT (86400) -#define HOUR_INT (60 * 60) -#define MINUTE_INT (60) - -static const char *interval_string(unsigned int secs) -{ - static char buf[256], tmp[80]; - int hr, min, num; - - buf[0] = 0; - - if (secs == 0) - return ""; - - if (secs >= MONTH_INT) { - num = secs / MONTH_INT; - secs -= num*MONTH_INT; - sprintf(buf, "%d month%s", num, (num>1) ? "s" : ""); - } - if (secs >= WEEK_INT) { - num = secs / WEEK_INT; - secs -= num*WEEK_INT; - sprintf(tmp, "%s%d week%s", buf[0] ? ", " : "", - num, (num>1) ? "s" : ""); - strcat(buf, tmp); - } - if (secs >= DAY_INT) { - num = secs / DAY_INT; - secs -= num*DAY_INT; - sprintf(tmp, "%s%d day%s", buf[0] ? ", " : "", - num, (num>1) ? "s" : ""); - strcat(buf, tmp); - } - if (secs > 0) { - hr = secs / HOUR_INT; - secs -= hr*HOUR_INT; - min = secs / MINUTE_INT; - secs -= min*MINUTE_INT; - sprintf(tmp, "%s%d:%02d:%02d", buf[0] ? ", " : "", - hr, min, secs); - strcat(buf, tmp); - } - return buf; -} - -static void print_features(struct ext2_super_block * s, FILE *f) -{ -#ifdef EXT2_DYNAMIC_REV - int i, j, printed=0; - __u32 *mask = &s->s_feature_compat, m; - - fprintf(f, "Filesystem features: "); - for (i=0; i <3; i++,mask++) { - for (j=0,m=1; j < 32; j++, m<<=1) { - if (*mask & m) { - fprintf(f, " %s", e2p_feature2string(i, m)); - printed++; - } - } - } - if (printed == 0) - fprintf(f, " (none)"); - fprintf(f, "\n"); -#endif -} - -static void print_mntopts(struct ext2_super_block * s, FILE *f) -{ -#ifdef EXT2_DYNAMIC_REV - int i, printed=0; - __u32 mask = s->s_default_mount_opts, m; - - fprintf(f, "Default mount options: "); - if (mask & EXT3_DEFM_JMODE) { - fprintf(f, " %s", e2p_mntopt2string(mask & EXT3_DEFM_JMODE)); - printed++; - } - for (i=0,m=1; i < 32; i++, m<<=1) { - if (m & EXT3_DEFM_JMODE) - continue; - if (mask & m) { - fprintf(f, " %s", e2p_mntopt2string(m)); - printed++; - } - } - if (printed == 0) - fprintf(f, " (none)"); - fprintf(f, "\n"); -#endif -} - - -#ifndef EXT2_INODE_SIZE -#define EXT2_INODE_SIZE(s) sizeof(struct ext2_inode) -#endif - -#ifndef EXT2_GOOD_OLD_REV -#define EXT2_GOOD_OLD_REV 0 -#endif - -void list_super2(struct ext2_super_block * sb, FILE *f) -{ - int inode_blocks_per_group; - char buf[80], *str; - time_t tm; - - inode_blocks_per_group = (((sb->s_inodes_per_group * - EXT2_INODE_SIZE(sb)) + - EXT2_BLOCK_SIZE(sb) - 1) / - EXT2_BLOCK_SIZE(sb)); - if (sb->s_volume_name[0]) { - memset(buf, 0, sizeof(buf)); - strncpy(buf, sb->s_volume_name, sizeof(sb->s_volume_name)); - } else - strcpy(buf, ""); - fprintf(f, "Filesystem volume name: %s\n", buf); - if (sb->s_last_mounted[0]) { - memset(buf, 0, sizeof(buf)); - strncpy(buf, sb->s_last_mounted, sizeof(sb->s_last_mounted)); - } else - strcpy(buf, ""); - fprintf(f, - "Last mounted on: %s\n" - "Filesystem UUID: %s\n" - "Filesystem magic number: 0x%04X\n" - "Filesystem revision #: %d", - buf, e2p_uuid2str(sb->s_uuid), sb->s_magic, sb->s_rev_level); - if (sb->s_rev_level == EXT2_GOOD_OLD_REV) { - fprintf(f, " (original)\n"); -#ifdef EXT2_DYNAMIC_REV - } else if (sb->s_rev_level == EXT2_DYNAMIC_REV) { - fprintf(f, " (dynamic)\n"); -#endif - } else - fprintf(f, " (unknown)\n"); - print_features(sb, f); - print_mntopts(sb, f); - fprintf(f, "Filesystem state: "); - print_fs_state (f, sb->s_state); - fprintf(f, "\nErrors behavior: "); - print_fs_errors(f, sb->s_errors); - str = e2p_os2string(sb->s_creator_os); - fprintf(f, - "\n" - "Filesystem OS type: %s\n" - "Inode count: %u\n" - "Block count: %u\n" - "Reserved block count: %u\n" - "Free blocks: %u\n" - "Free inodes: %u\n" - "First block: %u\n" - "Block size: %u\n" - "Fragment size: %u\n", - str, sb->s_inodes_count, sb->s_blocks_count, sb->s_r_blocks_count, - sb->s_free_blocks_count, sb->s_free_inodes_count, - sb->s_first_data_block, EXT2_BLOCK_SIZE(sb), EXT2_FRAG_SIZE(sb)); - free(str); - if (sb->s_reserved_gdt_blocks) - fprintf(f, "Reserved GDT blocks: %u\n", - sb->s_reserved_gdt_blocks); - fprintf(f, - "Blocks per group: %u\n" - "Fragments per group: %u\n" - "Inodes per group: %u\n" - "Inode blocks per group: %u\n", - sb->s_blocks_per_group, sb->s_frags_per_group, - sb->s_inodes_per_group, inode_blocks_per_group); - if (sb->s_first_meta_bg) - fprintf(f, "First meta block group: %u\n", - sb->s_first_meta_bg); - if (sb->s_mkfs_time) { - tm = sb->s_mkfs_time; - fprintf(f, "Filesystem created: %s", ctime(&tm)); - } - tm = sb->s_mtime; - fprintf(f, "Last mount time: %s", - sb->s_mtime ? ctime(&tm) : "n/a\n"); - tm = sb->s_wtime; - fprintf(f, - "Last write time: %s" - "Mount count: %u\n" - "Maximum mount count: %d\n", - ctime(&tm), sb->s_mnt_count, sb->s_max_mnt_count); - tm = sb->s_lastcheck; - fprintf(f, - "Last checked: %s" - "Check interval: %u (%s)\n", - ctime(&tm), - sb->s_checkinterval, interval_string(sb->s_checkinterval)); - if (sb->s_checkinterval) - { - time_t next; - - next = sb->s_lastcheck + sb->s_checkinterval; - fprintf(f, "Next check after: %s", ctime(&next)); - } - fprintf(f, "Reserved blocks uid: "); - print_user(sb->s_def_resuid, f); - fprintf(f, "Reserved blocks gid: "); - print_group(sb->s_def_resgid, f); - if (sb->s_rev_level >= EXT2_DYNAMIC_REV) { - fprintf(f, - "First inode: %d\n" - "Inode size: %d\n", - sb->s_first_ino, sb->s_inode_size); - } - if (!e2p_is_null_uuid(sb->s_journal_uuid)) - fprintf(f, "Journal UUID: %s\n", - e2p_uuid2str(sb->s_journal_uuid)); - if (sb->s_journal_inum) - fprintf(f, "Journal inode: %u\n", - sb->s_journal_inum); - if (sb->s_journal_dev) - fprintf(f, "Journal device: 0x%04x\n", - sb->s_journal_dev); - if (sb->s_last_orphan) - fprintf(f, "First orphan inode: %u\n", - sb->s_last_orphan); - if ((sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) || - sb->s_def_hash_version) - fprintf(f, "Default directory hash: %s\n", - e2p_hash2string(sb->s_def_hash_version)); - if (!e2p_is_null_uuid(sb->s_hash_seed)) - fprintf(f, "Directory Hash Seed: %s\n", - e2p_uuid2str(sb->s_hash_seed)); - if (sb->s_jnl_backup_type) { - fprintf(f, "Journal backup: "); - if (sb->s_jnl_backup_type == 1) - fprintf(f, "inode blocks\n"); - else - fprintf(f, "type %u\n", sb->s_jnl_backup_type); - } -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * mountopts.c --- convert between default mount options and strings - * - * Copyright (C) 2002 Theodore Ts'o - * - * This file can be redistributed under the terms of the GNU Library General - * Public License - * - */ - -#include -#include -#include -#include -#include - -#include "e2p.h" - -struct mntopt { - unsigned int mask; - const char *string; -}; - -static const struct mntopt mntopt_list[] = { - { EXT2_DEFM_DEBUG, "debug" }, - { EXT2_DEFM_BSDGROUPS, "bsdgroups" }, - { EXT2_DEFM_XATTR_USER, "user_xattr" }, - { EXT2_DEFM_ACL, "acl" }, - { EXT2_DEFM_UID16, "uid16" }, - { EXT3_DEFM_JMODE_DATA, "journal_data" }, - { EXT3_DEFM_JMODE_ORDERED, "journal_data_ordered" }, - { EXT3_DEFM_JMODE_WBACK, "journal_data_writeback" }, - { 0, 0 }, -}; - -const char *e2p_mntopt2string(unsigned int mask) -{ - const struct mntopt *f; - static char buf[20]; - int fnum; - - for (f = mntopt_list; f->string; f++) { - if (mask == f->mask) - return f->string; - } - for (fnum = 0; mask >>= 1; fnum++); - sprintf(buf, "MNTOPT_%d", fnum); - return buf; -} - -int e2p_string2mntopt(char *string, unsigned int *mask) -{ - const struct mntopt *f; - char *eptr; - int num; - - for (f = mntopt_list; f->string; f++) { - if (!strcasecmp(string, f->string)) { - *mask = f->mask; - return 0; - } - } - if (strncasecmp(string, "MNTOPT_", 8)) - return 1; - - if (string[8] == 0) - return 1; - num = strtol(string+8, &eptr, 10); - if (num > 32 || num < 0) - return 1; - if (*eptr) - return 1; - *mask = 1 << num; - return 0; -} - -static char *skip_over_blanks(char *cp) -{ - while (*cp && isspace(*cp)) - cp++; - return cp; -} - -static char *skip_over_word(char *cp) -{ - while (*cp && !isspace(*cp) && *cp != ',') - cp++; - return cp; -} - -/* - * Edit a mntopt set array as requested by the user. The ok - * parameter, if non-zero, allows the application to limit what - * mntopts the user is allowed to set or clear using this function. - */ -int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok) -{ - char *cp, *buf, *next; - int neg; - unsigned int mask; - - buf = xstrdup(str); - cp = buf; - while (cp && *cp) { - neg = 0; - cp = skip_over_blanks(cp); - next = skip_over_word(cp); - if (*next == 0) - next = 0; - else - *next = 0; - switch (*cp) { - case '-': - case '^': - neg++; - case '+': - cp++; - break; - } - if (e2p_string2mntopt(cp, &mask)) - return 1; - if (ok && !(ok & mask)) - return 1; - if (mask & EXT3_DEFM_JMODE) - *mntopts &= ~EXT3_DEFM_JMODE; - if (neg) - *mntopts &= ~mask; - else - *mntopts |= mask; - cp = next ? next+1 : 0; - } - return 0; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * getostype.c - Get the Filesystem OS type - * - * Copyright (C) 2004,2005 Theodore Ts'o - * - * This file can be redistributed under the terms of the GNU Library General - * Public License - */ - -#include "e2p.h" -#include -#include - -static const char *const os_tab[] = - { "Linux", - "Hurd", - "Masix", - "FreeBSD", - "Lites", - 0 }; - -/* - * Convert an os_type to a string - */ -char *e2p_os2string(int os_type) -{ - const char *os; - char *ret; - - if (os_type <= EXT2_OS_LITES) - os = os_tab[os_type]; - else - os = "(unknown os)"; - - ret = xstrdup(os); - return ret; -} - -/* - * Convert an os_type to a string - */ -int e2p_string2os(char *str) -{ - const char *const *cpp; - int i = 0; - - for (cpp = os_tab; *cpp; cpp++, i++) { - if (!strcasecmp(str, *cpp)) - return i; - } - return -1; -} - -#ifdef TEST_PROGRAM -int main(int argc, char **argv) -{ - char *s; - int i, os; - - for (i=0; i <= EXT2_OS_LITES; i++) { - s = e2p_os2string(i); - os = e2p_string2os(s); - printf("%d: %s (%d)\n", i, s, os); - if (i != os) { - fprintf(stderr, "Failure!\n"); - exit(1); - } - } - exit(0); -} -#endif diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * parse_num.c - Parse the number of blocks - * - * Copyright (C) 2004,2005 Theodore Ts'o - * - * This file can be redistributed under the terms of the GNU Library General - * Public License - */ - -#include "e2p.h" - -#include - -unsigned long parse_num_blocks(const char *arg, int log_block_size) -{ - char *p; - unsigned long long num; - - num = strtoull(arg, &p, 0); - - if (p[0] && p[1]) - return 0; - - switch (*p) { /* Using fall-through logic */ - case 'T': case 't': - num <<= 10; - case 'G': case 'g': - num <<= 10; - case 'M': case 'm': - num <<= 10; - case 'K': case 'k': - num >>= log_block_size; - break; - case 's': - num >>= 1; - break; - case '\0': - break; - default: - return 0; - } - return num; -} - -#ifdef DEBUG -#include -#include - -main(int argc, char **argv) -{ - unsigned long num; - int log_block_size = 0; - - if (argc != 2) { - fprintf(stderr, "Usage: %s arg\n", argv[0]); - exit(1); - } - - num = parse_num_blocks(argv[1], log_block_size); - - printf("Parsed number: %lu\n", num); - exit(0); -} -#endif diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * pe.c - Print a second extended filesystem errors behavior - * - * Copyright (C) 1992, 1993, 1994 Remy Card - * Laboratoire MASI, Institut Blaise Pascal - * Universite Pierre et Marie Curie (Paris VI) - * - * This file can be redistributed under the terms of the GNU Library General - * Public License - */ - -/* - * History: - * 94/01/09 - Creation - */ - -#include - -#include "e2p.h" - -void print_fs_errors(FILE *f, unsigned short errors) -{ - char *disp = NULL; - switch (errors) { - case EXT2_ERRORS_CONTINUE: disp = "Continue"; break; - case EXT2_ERRORS_RO: disp = "Remount read-only"; break; - case EXT2_ERRORS_PANIC: disp = "Panic"; break; - default: disp = "Unknown (continue)"; - } - fprintf(f, disp); -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * pf.c - Print file attributes on an ext2 file system - * - * Copyright (C) 1993, 1994 Remy Card - * Laboratoire MASI, Institut Blaise Pascal - * Universite Pierre et Marie Curie (Paris VI) - * - * This file can be redistributed under the terms of the GNU Library General - * Public License - */ - -/* - * History: - * 93/10/30 - Creation - */ - -#include - -#include "e2p.h" - -struct flags_name { - unsigned long flag; - const char *short_name; - const char *long_name; -}; - -static const struct flags_name flags_array[] = { - { EXT2_SECRM_FL, "s", "Secure_Deletion" }, - { EXT2_UNRM_FL, "u" , "Undelete" }, - { EXT2_SYNC_FL, "S", "Synchronous_Updates" }, - { EXT2_DIRSYNC_FL, "D", "Synchronous_Directory_Updates" }, - { EXT2_IMMUTABLE_FL, "i", "Immutable" }, - { EXT2_APPEND_FL, "a", "Append_Only" }, - { EXT2_NODUMP_FL, "d", "No_Dump" }, - { EXT2_NOATIME_FL, "A", "No_Atime" }, - { EXT2_COMPR_FL, "c", "Compression_Requested" }, -#ifdef ENABLE_COMPRESSION - { EXT2_COMPRBLK_FL, "B", "Compressed_File" }, - { EXT2_DIRTY_FL, "Z", "Compressed_Dirty_File" }, - { EXT2_NOCOMPR_FL, "X", "Compression_Raw_Access" }, - { EXT2_ECOMPR_FL, "E", "Compression_Error" }, -#endif - { EXT3_JOURNAL_DATA_FL, "j", "Journaled_Data" }, - { EXT2_INDEX_FL, "I", "Indexed_direcctory" }, - { EXT2_NOTAIL_FL, "t", "No_Tailmerging" }, - { EXT2_TOPDIR_FL, "T", "Top_of_Directory_Hierarchies" }, - { 0, NULL, NULL } -}; - -void print_flags (FILE *f, unsigned long flags, unsigned options) -{ - int long_opt = (options & PFOPT_LONG); - const struct flags_name *fp; - int first = 1; - - for (fp = flags_array; fp->flag != 0; fp++) { - if (flags & fp->flag) { - if (long_opt) { - if (first) - first = 0; - else - fputs(", ", f); - fputs(fp->long_name, f); - } else - fputs(fp->short_name, f); - } else { - if (!long_opt) - fputs("-", f); - } - } - if (long_opt && first) - fputs("---", f); -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * ps.c - Print filesystem state - * - * Copyright (C) 1993, 1994 Remy Card - * Laboratoire MASI, Institut Blaise Pascal - * Universite Pierre et Marie Curie (Paris VI) - * - * This file can be redistributed under the terms of the GNU Library General - * Public License - */ - -/* - * History: - * 93/12/22 - Creation - */ - -#include - -#include "e2p.h" - -void print_fs_state(FILE *f, unsigned short state) -{ - fprintf(f, (state & EXT2_VALID_FS ? " clean" : " not clean")); - if (state & EXT2_ERROR_FS) - fprintf(f, " with errors"); -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * uuid.c -- utility routines for manipulating UUID's. - */ - -#include -#include -#include "../ext2fs/ext2_types.h" - -#include "e2p.h" - -struct uuid { - __u32 time_low; - __u16 time_mid; - __u16 time_hi_and_version; - __u16 clock_seq; - __u8 node[6]; -}; - -/* Returns 1 if the uuid is the NULL uuid */ -int e2p_is_null_uuid(void *uu) -{ - __u8 *cp; - int i; - - for (i=0, cp = uu; i < 16; i++) - if (*cp) - return 0; - return 1; -} - -static void e2p_unpack_uuid(void *in, struct uuid *uu) -{ - __u8 *ptr = in; - __u32 tmp; - - tmp = *ptr++; - tmp = (tmp << 8) | *ptr++; - tmp = (tmp << 8) | *ptr++; - tmp = (tmp << 8) | *ptr++; - uu->time_low = tmp; - - tmp = *ptr++; - tmp = (tmp << 8) | *ptr++; - uu->time_mid = tmp; - - tmp = *ptr++; - tmp = (tmp << 8) | *ptr++; - uu->time_hi_and_version = tmp; - - tmp = *ptr++; - tmp = (tmp << 8) | *ptr++; - uu->clock_seq = tmp; - - memcpy(uu->node, ptr, 6); -} - -void e2p_uuid_to_str(void *uu, char *out) -{ - struct uuid uuid; - - e2p_unpack_uuid(uu, &uuid); - sprintf(out, - "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", - uuid.time_low, uuid.time_mid, uuid.time_hi_and_version, - uuid.clock_seq >> 8, uuid.clock_seq & 0xFF, - uuid.node[0], uuid.node[1], uuid.node[2], - uuid.node[3], uuid.node[4], uuid.node[5]); -} - -const char *e2p_uuid2str(void *uu) -{ - static char buf[80]; - if (e2p_is_null_uuid(uu)) - return ""; - e2p_uuid_to_str(uu, buf); - return buf; -} 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 @@ -# Makefile for busybox -# -# Copyright (C) 1999-2005 by Erik Andersen -# -# Licensed under GPLv2, see file LICENSE in this source tree. - -NEEDED-$(CONFIG_E2FSCK) = y -NEEDED-$(CONFIG_FSCK) = y -NEEDED-$(CONFIG_MKE2FS) = y -NEEDED-$(CONFIG_TUNE2FS) = y - -lib-y:= - -INSERT - -lib-$(NEEDED-y) += gen_bitmap.o bitops.o ismounted.o mkjournal.o unix_io.o \ - rw_bitmaps.o initialize.o bitmaps.o block.o \ - ind_block.o inode.o freefs.o alloc_stats.o closefs.o \ - openfs.o io_manager.o finddev.o read_bb.o alloc.o badblocks.o \ - getsize.o getsectsize.o alloc_tables.o read_bb_file.o mkdir.o \ - bb_inode.o newdir.o alloc_sb.o lookup.o dirblock.o expanddir.o \ - dir_iterate.o link.o res_gdt.o icount.o get_pathname.o dblist.o \ - dirhash.o version.o flushb.o unlink.o check_desc.o valid_blk.o \ - ext_attr.o bmap.o dblist_dir.o ext2fs_inline.o swapfs.o - -CFLAGS += -include $(srctree)/e2fsprogs/e2fsbb.h diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * alloc.c --- allocate new inodes, blocks for ext2fs - * - * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - * - */ - -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -/* - * Right now, just search forward from the parent directory's block - * group to find the next free inode. - * - * Should have a special policy for directories. - */ -errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir, - int mode EXT2FS_ATTR((unused)), - ext2fs_inode_bitmap map, ext2_ino_t *ret) -{ - ext2_ino_t dir_group = 0; - ext2_ino_t i; - ext2_ino_t start_inode; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - if (!map) - map = fs->inode_map; - if (!map) - return EXT2_ET_NO_INODE_BITMAP; - - if (dir > 0) - dir_group = (dir - 1) / EXT2_INODES_PER_GROUP(fs->super); - - start_inode = (dir_group * EXT2_INODES_PER_GROUP(fs->super)) + 1; - if (start_inode < EXT2_FIRST_INODE(fs->super)) - start_inode = EXT2_FIRST_INODE(fs->super); - i = start_inode; - - do { - if (!ext2fs_fast_test_inode_bitmap(map, i)) - break; - i++; - if (i > fs->super->s_inodes_count) - i = EXT2_FIRST_INODE(fs->super); - } while (i != start_inode); - - if (ext2fs_test_inode_bitmap(map, i)) - return EXT2_ET_INODE_ALLOC_FAIL; - *ret = i; - return 0; -} - -/* - * Stupid algorithm --- we now just search forward starting from the - * goal. Should put in a smarter one someday.... - */ -errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal, - ext2fs_block_bitmap map, blk_t *ret) -{ - blk_t i; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - if (!map) - map = fs->block_map; - if (!map) - return EXT2_ET_NO_BLOCK_BITMAP; - if (!goal || (goal >= fs->super->s_blocks_count)) - goal = fs->super->s_first_data_block; - i = goal; - do { - if (!ext2fs_fast_test_block_bitmap(map, i)) { - *ret = i; - return 0; - } - i++; - if (i >= fs->super->s_blocks_count) - i = fs->super->s_first_data_block; - } while (i != goal); - return EXT2_ET_BLOCK_ALLOC_FAIL; -} - -/* - * This function zeros out the allocated block, and updates all of the - * appropriate filesystem records. - */ -errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal, - char *block_buf, blk_t *ret) -{ - errcode_t retval; - blk_t block; - char *buf = NULL; - - if (!block_buf) { - retval = ext2fs_get_mem(fs->blocksize, &buf); - if (retval) - return retval; - block_buf = buf; - } - memset(block_buf, 0, fs->blocksize); - - if (!fs->block_map) { - retval = ext2fs_read_block_bitmap(fs); - if (retval) - goto fail; - } - - retval = ext2fs_new_block(fs, goal, 0, &block); - if (retval) - goto fail; - - retval = io_channel_write_blk(fs->io, block, 1, block_buf); - if (retval) - goto fail; - - ext2fs_block_alloc_stats(fs, block, +1); - *ret = block; - return 0; - -fail: - if (buf) - ext2fs_free_mem(&buf); - return retval; -} - -errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, blk_t finish, - int num, ext2fs_block_bitmap map, blk_t *ret) -{ - blk_t b = start; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - if (!map) - map = fs->block_map; - if (!map) - return EXT2_ET_NO_BLOCK_BITMAP; - if (!b) - b = fs->super->s_first_data_block; - if (!finish) - finish = start; - if (!num) - num = 1; - do { - if (b+num-1 > fs->super->s_blocks_count) - b = fs->super->s_first_data_block; - if (ext2fs_fast_test_block_bitmap_range(map, b, num)) { - *ret = b; - return 0; - } - b++; - } while (b != finish); - return EXT2_ET_BLOCK_ALLOC_FAIL; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * alloc_sb.c --- Allocate the superblock and block group descriptors for a - * newly initialized filesystem. Used by mke2fs when initializing a filesystem - * - * Copyright (C) 1994, 1995, 1996, 2003 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -int ext2fs_reserve_super_and_bgd(ext2_filsys fs, - dgrp_t group, - ext2fs_block_bitmap bmap) -{ - blk_t super_blk, old_desc_blk, new_desc_blk; - int j, old_desc_blocks, num_blocks; - - num_blocks = ext2fs_super_and_bgd_loc(fs, group, &super_blk, - &old_desc_blk, &new_desc_blk, 0); - - if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) - old_desc_blocks = fs->super->s_first_meta_bg; - else - old_desc_blocks = - fs->desc_blocks + fs->super->s_reserved_gdt_blocks; - - if (super_blk || (group == 0)) - ext2fs_mark_block_bitmap(bmap, super_blk); - - if (old_desc_blk) { - for (j=0; j < old_desc_blocks; j++) - ext2fs_mark_block_bitmap(bmap, old_desc_blk + j); - } - if (new_desc_blk) - ext2fs_mark_block_bitmap(bmap, new_desc_blk); - - return num_blocks; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * alloc_stats.c --- Update allocation statistics for ext2fs - * - * Copyright (C) 2001 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - * - */ - -#include - -#include "ext2_fs.h" -#include "ext2fs.h" - -void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino, - int inuse, int isdir) -{ - int group = ext2fs_group_of_ino(fs, ino); - - if (inuse > 0) - ext2fs_mark_inode_bitmap(fs->inode_map, ino); - else - ext2fs_unmark_inode_bitmap(fs->inode_map, ino); - fs->group_desc[group].bg_free_inodes_count -= inuse; - if (isdir) - fs->group_desc[group].bg_used_dirs_count += inuse; - fs->super->s_free_inodes_count -= inuse; - ext2fs_mark_super_dirty(fs); - ext2fs_mark_ib_dirty(fs); -} - -void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse) -{ - ext2fs_inode_alloc_stats2(fs, ino, inuse, 0); -} - -void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse) -{ - int group = ext2fs_group_of_blk(fs, blk); - - if (inuse > 0) - ext2fs_mark_block_bitmap(fs->block_map, blk); - else - ext2fs_unmark_block_bitmap(fs->block_map, blk); - fs->group_desc[group].bg_free_blocks_count -= inuse; - fs->super->s_free_blocks_count -= inuse; - ext2fs_mark_super_dirty(fs); - ext2fs_mark_bb_dirty(fs); -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * alloc_tables.c --- Allocate tables for a newly initialized - * filesystem. Used by mke2fs when initializing a filesystem - * - * Copyright (C) 1996 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group, - ext2fs_block_bitmap bmap) -{ - errcode_t retval; - blk_t group_blk, start_blk, last_blk, new_blk, blk; - int j; - - group_blk = fs->super->s_first_data_block + - (group * fs->super->s_blocks_per_group); - - last_blk = group_blk + fs->super->s_blocks_per_group; - if (last_blk >= fs->super->s_blocks_count) - last_blk = fs->super->s_blocks_count - 1; - - if (!bmap) - bmap = fs->block_map; - - /* - * Allocate the block and inode bitmaps, if necessary - */ - if (fs->stride) { - start_blk = group_blk + fs->inode_blocks_per_group; - start_blk += ((fs->stride * group) % - (last_blk - start_blk)); - if (start_blk > last_blk) - start_blk = group_blk; - } else - start_blk = group_blk; - - if (!fs->group_desc[group].bg_block_bitmap) { - retval = ext2fs_get_free_blocks(fs, start_blk, last_blk, - 1, bmap, &new_blk); - if (retval == EXT2_ET_BLOCK_ALLOC_FAIL) - retval = ext2fs_get_free_blocks(fs, group_blk, - last_blk, 1, bmap, &new_blk); - if (retval) - return retval; - ext2fs_mark_block_bitmap(bmap, new_blk); - fs->group_desc[group].bg_block_bitmap = new_blk; - } - - if (!fs->group_desc[group].bg_inode_bitmap) { - retval = ext2fs_get_free_blocks(fs, start_blk, last_blk, - 1, bmap, &new_blk); - if (retval == EXT2_ET_BLOCK_ALLOC_FAIL) - retval = ext2fs_get_free_blocks(fs, group_blk, - last_blk, 1, bmap, &new_blk); - if (retval) - return retval; - ext2fs_mark_block_bitmap(bmap, new_blk); - fs->group_desc[group].bg_inode_bitmap = new_blk; - } - - /* - * Allocate the inode table - */ - if (!fs->group_desc[group].bg_inode_table) { - retval = ext2fs_get_free_blocks(fs, group_blk, last_blk, - fs->inode_blocks_per_group, - bmap, &new_blk); - if (retval) - return retval; - for (j=0, blk = new_blk; - j < fs->inode_blocks_per_group; - j++, blk++) - ext2fs_mark_block_bitmap(bmap, blk); - fs->group_desc[group].bg_inode_table = new_blk; - } - - return 0; -} - -errcode_t ext2fs_allocate_tables(ext2_filsys fs) -{ - errcode_t retval; - dgrp_t i; - - for (i = 0; i < fs->group_desc_count; i++) { - retval = ext2fs_allocate_group_table(fs, i, fs->block_map); - if (retval) - return retval; - } - return 0; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * badblocks.c --- routines to manipulate the bad block structure - * - * Copyright (C) 1994, 1995, 1996 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fsP.h" - -/* - * Helper function for making a badblocks list - */ -static errcode_t make_u32_list(int size, int num, __u32 *list, - ext2_u32_list *ret) -{ - ext2_u32_list bb; - errcode_t retval; - - retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_list), &bb); - if (retval) - return retval; - memset(bb, 0, sizeof(struct ext2_struct_u32_list)); - bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST; - bb->size = size ? size : 10; - bb->num = num; - retval = ext2fs_get_mem(bb->size * sizeof(blk_t), &bb->list); - if (!bb->list) { - ext2fs_free_mem(&bb); - return retval; - } - if (list) - memcpy(bb->list, list, bb->size * sizeof(blk_t)); - else - memset(bb->list, 0, bb->size * sizeof(blk_t)); - *ret = bb; - return 0; -} - - -/* - * This procedure creates an empty u32 list. - */ -errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size) -{ - return make_u32_list(size, 0, 0, ret); -} - -/* - * This procedure creates an empty badblocks list. - */ -errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size) -{ - return make_u32_list(size, 0, 0, (ext2_badblocks_list *) ret); -} - - -/* - * This procedure copies a badblocks list - */ -errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest) -{ - errcode_t retval; - - retval = make_u32_list(src->size, src->num, src->list, dest); - if (retval) - return retval; - (*dest)->badblocks_flags = src->badblocks_flags; - return 0; -} - -errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src, - ext2_badblocks_list *dest) -{ - return ext2fs_u32_copy((ext2_u32_list) src, - (ext2_u32_list *) dest); -} - -/* - * This procedure frees a badblocks list. - * - * (note: moved to closefs.c) - */ - - -/* - * This procedure adds a block to a badblocks list. - */ -errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk) -{ - errcode_t retval; - int i, j; - unsigned long old_size; - - EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST); - - if (bb->num >= bb->size) { - old_size = bb->size * sizeof(__u32); - bb->size += 100; - retval = ext2fs_resize_mem(old_size, bb->size * sizeof(__u32), - &bb->list); - if (retval) { - bb->size -= 100; - return retval; - } - } - - /* - * Add special case code for appending to the end of the list - */ - i = bb->num-1; - if ((bb->num != 0) && (bb->list[i] == blk)) - return 0; - if ((bb->num == 0) || (bb->list[i] < blk)) { - bb->list[bb->num++] = blk; - return 0; - } - - j = bb->num; - for (i=0; i < bb->num; i++) { - if (bb->list[i] == blk) - return 0; - if (bb->list[i] > blk) { - j = i; - break; - } - } - for (i=bb->num; i > j; i--) - bb->list[i] = bb->list[i-1]; - bb->list[j] = blk; - bb->num++; - return 0; -} - -errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk) -{ - return ext2fs_u32_list_add((ext2_u32_list) bb, (__u32) blk); -} - -/* - * This procedure finds a particular block is on a badblocks - * list. - */ -int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk) -{ - int low, high, mid; - - if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST) - return -1; - - if (bb->num == 0) - return -1; - - low = 0; - high = bb->num-1; - if (blk == bb->list[low]) - return low; - if (blk == bb->list[high]) - return high; - - while (low < high) { - mid = (low+high)/2; - if (mid == low || mid == high) - break; - if (blk == bb->list[mid]) - return mid; - if (blk < bb->list[mid]) - high = mid; - else - low = mid; - } - return -1; -} - -/* - * This procedure tests to see if a particular block is on a badblocks - * list. - */ -int ext2fs_u32_list_test(ext2_u32_list bb, __u32 blk) -{ - if (ext2fs_u32_list_find(bb, blk) < 0) - return 0; - else - return 1; -} - -int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk) -{ - return ext2fs_u32_list_test((ext2_u32_list) bb, (__u32) blk); -} - - -/* - * Remove a block from the badblock list - */ -int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk) -{ - int remloc, i; - - if (bb->num == 0) - return -1; - - remloc = ext2fs_u32_list_find(bb, blk); - if (remloc < 0) - return -1; - - for (i = remloc; i < bb->num - 1; i++) - bb->list[i] = bb->list[i+1]; - bb->num--; - return 0; -} - -void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk) -{ - ext2fs_u32_list_del(bb, blk); -} - -errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb, - ext2_u32_iterate *ret) -{ - ext2_u32_iterate iter; - errcode_t retval; - - EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST); - - retval = ext2fs_get_mem(sizeof(struct ext2_struct_u32_iterate), &iter); - if (retval) - return retval; - - iter->magic = EXT2_ET_MAGIC_BADBLOCKS_ITERATE; - iter->bb = bb; - iter->ptr = 0; - *ret = iter; - return 0; -} - -errcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb, - ext2_badblocks_iterate *ret) -{ - return ext2fs_u32_list_iterate_begin((ext2_u32_list) bb, - (ext2_u32_iterate *) ret); -} - - -int ext2fs_u32_list_iterate(ext2_u32_iterate iter, __u32 *blk) -{ - ext2_u32_list bb; - - if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE) - return 0; - - bb = iter->bb; - - if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST) - return 0; - - if (iter->ptr < bb->num) { - *blk = bb->list[iter->ptr++]; - return 1; - } - *blk = 0; - return 0; -} - -int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk) -{ - return ext2fs_u32_list_iterate((ext2_u32_iterate) iter, - (__u32 *) blk); -} - - -void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter) -{ - if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)) - return; - - iter->bb = 0; - ext2fs_free_mem(&iter); -} - -void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter) -{ - ext2fs_u32_list_iterate_end((ext2_u32_iterate) iter); -} - - -int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2) -{ - EXT2_CHECK_MAGIC(bb1, EXT2_ET_MAGIC_BADBLOCKS_LIST); - EXT2_CHECK_MAGIC(bb2, EXT2_ET_MAGIC_BADBLOCKS_LIST); - - if (bb1->num != bb2->num) - return 0; - - if (memcmp(bb1->list, bb2->list, bb1->num * sizeof(blk_t)) != 0) - return 0; - return 1; -} - -int ext2fs_badblocks_equal(ext2_badblocks_list bb1, ext2_badblocks_list bb2) -{ - return ext2fs_u32_list_equal((ext2_u32_list) bb1, - (ext2_u32_list) bb2); -} - -int ext2fs_u32_list_count(ext2_u32_list bb) -{ - return bb->num; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * bb_compat.c --- compatibility badblocks routines - * - * Copyright (C) 1997 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fsP.h" - -errcode_t badblocks_list_create(badblocks_list *ret, int size) -{ - return ext2fs_badblocks_list_create(ret, size); -} - -void badblocks_list_free(badblocks_list bb) -{ - ext2fs_badblocks_list_free(bb); -} - -errcode_t badblocks_list_add(badblocks_list bb, blk_t blk) -{ - return ext2fs_badblocks_list_add(bb, blk); -} - -int badblocks_list_test(badblocks_list bb, blk_t blk) -{ - return ext2fs_badblocks_list_test(bb, blk); -} - -errcode_t badblocks_list_iterate_begin(badblocks_list bb, - badblocks_iterate *ret) -{ - return ext2fs_badblocks_list_iterate_begin(bb, ret); -} - -int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk) -{ - return ext2fs_badblocks_list_iterate(iter, blk); -} - -void badblocks_list_iterate_end(badblocks_iterate iter) -{ - ext2fs_badblocks_list_iterate_end(iter); -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * bb_inode.c --- routines to update the bad block inode. - * - * WARNING: This routine modifies a lot of state in the filesystem; if - * this routine returns an error, the bad block inode may be in an - * inconsistent state. - * - * Copyright (C) 1994, 1995 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -struct set_badblock_record { - ext2_badblocks_iterate bb_iter; - int bad_block_count; - blk_t *ind_blocks; - int max_ind_blocks; - int ind_blocks_size; - int ind_blocks_ptr; - char *block_buf; - errcode_t err; -}; - -static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr, - e2_blkcnt_t blockcnt, - blk_t ref_block, int ref_offset, - void *priv_data); -static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr, - e2_blkcnt_t blockcnt, - blk_t ref_block, int ref_offset, - void *priv_data); - -/* - * Given a bad blocks bitmap, update the bad blocks inode to reflect - * the map. - */ -errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list) -{ - errcode_t retval; - struct set_badblock_record rec; - struct ext2_inode inode; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - if (!fs->block_map) - return EXT2_ET_NO_BLOCK_BITMAP; - - rec.bad_block_count = 0; - rec.ind_blocks_size = rec.ind_blocks_ptr = 0; - rec.max_ind_blocks = 10; - retval = ext2fs_get_mem(rec.max_ind_blocks * sizeof(blk_t), - &rec.ind_blocks); - if (retval) - return retval; - memset(rec.ind_blocks, 0, rec.max_ind_blocks * sizeof(blk_t)); - retval = ext2fs_get_mem(fs->blocksize, &rec.block_buf); - if (retval) - goto cleanup; - memset(rec.block_buf, 0, fs->blocksize); - rec.err = 0; - - /* - * First clear the old bad blocks (while saving the indirect blocks) - */ - retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, - BLOCK_FLAG_DEPTH_TRAVERSE, 0, - clear_bad_block_proc, &rec); - if (retval) - goto cleanup; - if (rec.err) { - retval = rec.err; - goto cleanup; - } - - /* - * Now set the bad blocks! - * - * First, mark the bad blocks as used. This prevents a bad - * block from being used as an indirecto block for the bad - * block inode (!). - */ - if (bb_list) { - retval = ext2fs_badblocks_list_iterate_begin(bb_list, - &rec.bb_iter); - if (retval) - goto cleanup; - retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, - BLOCK_FLAG_APPEND, 0, - set_bad_block_proc, &rec); - ext2fs_badblocks_list_iterate_end(rec.bb_iter); - if (retval) - goto cleanup; - if (rec.err) { - retval = rec.err; - goto cleanup; - } - } - - /* - * Update the bad block inode's mod time and block count - * field. - */ - retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode); - if (retval) - goto cleanup; - - inode.i_atime = inode.i_mtime = time(NULL); - if (!inode.i_ctime) - inode.i_ctime = time(NULL); - inode.i_blocks = rec.bad_block_count * (fs->blocksize / 512); - inode.i_size = rec.bad_block_count * fs->blocksize; - - retval = ext2fs_write_inode(fs, EXT2_BAD_INO, &inode); - if (retval) - goto cleanup; - -cleanup: - ext2fs_free_mem(&rec.ind_blocks); - ext2fs_free_mem(&rec.block_buf); - return retval; -} - -/* - * Helper function for update_bb_inode() - * - * Clear the bad blocks in the bad block inode, while saving the - * indirect blocks. - */ -#ifdef __TURBOC__ -# pragma argsused -#endif -static int clear_bad_block_proc(ext2_filsys fs, blk_t *block_nr, - e2_blkcnt_t blockcnt, - blk_t ref_block EXT2FS_ATTR((unused)), - int ref_offset EXT2FS_ATTR((unused)), - void *priv_data) -{ - struct set_badblock_record *rec = (struct set_badblock_record *) - priv_data; - errcode_t retval; - unsigned long old_size; - - if (!*block_nr) - return 0; - - /* - * If the block number is outrageous, clear it and ignore it. - */ - if (*block_nr >= fs->super->s_blocks_count || - *block_nr < fs->super->s_first_data_block) { - *block_nr = 0; - return BLOCK_CHANGED; - } - - if (blockcnt < 0) { - if (rec->ind_blocks_size >= rec->max_ind_blocks) { - old_size = rec->max_ind_blocks * sizeof(blk_t); - rec->max_ind_blocks += 10; - retval = ext2fs_resize_mem(old_size, - rec->max_ind_blocks * sizeof(blk_t), - &rec->ind_blocks); - if (retval) { - rec->max_ind_blocks -= 10; - rec->err = retval; - return BLOCK_ABORT; - } - } - rec->ind_blocks[rec->ind_blocks_size++] = *block_nr; - } - - /* - * Mark the block as unused, and update accounting information - */ - ext2fs_block_alloc_stats(fs, *block_nr, -1); - - *block_nr = 0; - return BLOCK_CHANGED; -} - - -/* - * Helper function for update_bb_inode() - * - * Set the block list in the bad block inode, using the supplied bitmap. - */ -#ifdef __TURBOC__ - #pragma argsused -#endif -static int set_bad_block_proc(ext2_filsys fs, blk_t *block_nr, - e2_blkcnt_t blockcnt, - blk_t ref_block EXT2FS_ATTR((unused)), - int ref_offset EXT2FS_ATTR((unused)), - void *priv_data) -{ - struct set_badblock_record *rec = (struct set_badblock_record *) - priv_data; - errcode_t retval; - blk_t blk; - - if (blockcnt >= 0) { - /* - * Get the next bad block. - */ - if (!ext2fs_badblocks_list_iterate(rec->bb_iter, &blk)) - return BLOCK_ABORT; - rec->bad_block_count++; - } else { - /* - * An indirect block; fetch a block from the - * previously used indirect block list. The block - * most be not marked as used; if so, get another one. - * If we run out of reserved indirect blocks, allocate - * a new one. - */ - retry: - if (rec->ind_blocks_ptr < rec->ind_blocks_size) { - blk = rec->ind_blocks[rec->ind_blocks_ptr++]; - if (ext2fs_test_block_bitmap(fs->block_map, blk)) - goto retry; - } else { - retval = ext2fs_new_block(fs, 0, 0, &blk); - if (retval) { - rec->err = retval; - return BLOCK_ABORT; - } - } - retval = io_channel_write_blk(fs->io, blk, 1, rec->block_buf); - if (retval) { - rec->err = retval; - return BLOCK_ABORT; - } - } - - /* - * Update block counts - */ - ext2fs_block_alloc_stats(fs, blk, +1); - - *block_nr = blk; - return BLOCK_CHANGED; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * bitmaps.c --- routines to read, write, and manipulate the inode and - * block bitmaps. - * - * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -static errcode_t make_bitmap(__u32 start, __u32 end, __u32 real_end, - const char *descr, char *init_map, - ext2fs_generic_bitmap *ret) -{ - ext2fs_generic_bitmap bitmap; - errcode_t retval; - size_t size; - - retval = ext2fs_get_mem(sizeof(struct ext2fs_struct_generic_bitmap), - &bitmap); - if (retval) - return retval; - - bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP; - bitmap->fs = NULL; - bitmap->start = start; - bitmap->end = end; - bitmap->real_end = real_end; - bitmap->base_error_code = EXT2_ET_BAD_GENERIC_MARK; - if (descr) { - retval = ext2fs_get_mem(strlen(descr)+1, &bitmap->description); - if (retval) { - ext2fs_free_mem(&bitmap); - return retval; - } - strcpy(bitmap->description, descr); - } else - bitmap->description = 0; - - size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1); - retval = ext2fs_get_mem(size, &bitmap->bitmap); - if (retval) { - ext2fs_free_mem(&bitmap->description); - ext2fs_free_mem(&bitmap); - return retval; - } - - if (init_map) - memcpy(bitmap->bitmap, init_map, size); - else - memset(bitmap->bitmap, 0, size); - *ret = bitmap; - return 0; -} - -errcode_t ext2fs_allocate_generic_bitmap(__u32 start, - __u32 end, - __u32 real_end, - const char *descr, - ext2fs_generic_bitmap *ret) -{ - return make_bitmap(start, end, real_end, descr, 0, ret); -} - -errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src, - ext2fs_generic_bitmap *dest) -{ - errcode_t retval; - ext2fs_generic_bitmap new_map; - - retval = make_bitmap(src->start, src->end, src->real_end, - src->description, src->bitmap, &new_map); - if (retval) - return retval; - new_map->magic = src->magic; - new_map->fs = src->fs; - new_map->base_error_code = src->base_error_code; - *dest = new_map; - return 0; -} - -void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map) -{ - __u32 i, j; - - for (i=map->end+1, j = i - map->start; i <= map->real_end; i++, j++) - ext2fs_set_bit(j, map->bitmap); -} - -errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs, - const char *descr, - ext2fs_inode_bitmap *ret) -{ - ext2fs_inode_bitmap bitmap; - errcode_t retval; - __u32 start, end, real_end; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - fs->write_bitmaps = ext2fs_write_bitmaps; - - start = 1; - end = fs->super->s_inodes_count; - real_end = (EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count); - - retval = ext2fs_allocate_generic_bitmap(start, end, real_end, - descr, &bitmap); - if (retval) - return retval; - - bitmap->magic = EXT2_ET_MAGIC_INODE_BITMAP; - bitmap->fs = fs; - bitmap->base_error_code = EXT2_ET_BAD_INODE_MARK; - - *ret = bitmap; - return 0; -} - -errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs, - const char *descr, - ext2fs_block_bitmap *ret) -{ - ext2fs_block_bitmap bitmap; - errcode_t retval; - __u32 start, end, real_end; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - fs->write_bitmaps = ext2fs_write_bitmaps; - - start = fs->super->s_first_data_block; - end = fs->super->s_blocks_count-1; - real_end = (EXT2_BLOCKS_PER_GROUP(fs->super) - * fs->group_desc_count)-1 + start; - - retval = ext2fs_allocate_generic_bitmap(start, end, real_end, - descr, &bitmap); - if (retval) - return retval; - - bitmap->magic = EXT2_ET_MAGIC_BLOCK_BITMAP; - bitmap->fs = fs; - bitmap->base_error_code = EXT2_ET_BAD_BLOCK_MARK; - - *ret = bitmap; - return 0; -} - -errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap, - ext2_ino_t end, ext2_ino_t *oend) -{ - EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_INODE_BITMAP); - - if (end > bitmap->real_end) - return EXT2_ET_FUDGE_INODE_BITMAP_END; - if (oend) - *oend = bitmap->end; - bitmap->end = end; - return 0; -} - -errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap, - blk_t end, blk_t *oend) -{ - EXT2_CHECK_MAGIC(bitmap, EXT2_ET_MAGIC_BLOCK_BITMAP); - - if (end > bitmap->real_end) - return EXT2_ET_FUDGE_BLOCK_BITMAP_END; - if (oend) - *oend = bitmap->end; - bitmap->end = end; - return 0; -} - -void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap) -{ - if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_INODE_BITMAP)) - return; - - memset(bitmap->bitmap, 0, - (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1)); -} - -void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap) -{ - if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_BLOCK_BITMAP)) - return; - - memset(bitmap->bitmap, 0, - (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1)); -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * bitops.c --- Bitmap frobbing code. See bitops.h for the inlined - * routines. - * - * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#if HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -#ifndef _EXT2_HAVE_ASM_BITOPS_ - -/* - * For the benefit of those who are trying to port Linux to another - * architecture, here are some C-language equivalents. You should - * recode these in the native assmebly language, if at all possible. - * - * C language equivalents written by Theodore Ts'o, 9/26/92. - * Modified by Pete A. Zaitcev 7/14/95 to be portable to big endian - * systems, as well as non-32 bit systems. - */ - -int ext2fs_set_bit(unsigned int nr,void * addr) -{ - int mask, retval; - unsigned char *ADDR = (unsigned char *) addr; - - ADDR += nr >> 3; - mask = 1 << (nr & 0x07); - retval = mask & *ADDR; - *ADDR |= mask; - return retval; -} - -int ext2fs_clear_bit(unsigned int nr, void * addr) -{ - int mask, retval; - unsigned char *ADDR = (unsigned char *) addr; - - ADDR += nr >> 3; - mask = 1 << (nr & 0x07); - retval = mask & *ADDR; - *ADDR &= ~mask; - return retval; -} - -int ext2fs_test_bit(unsigned int nr, const void * addr) -{ - int mask; - const unsigned char *ADDR = (const unsigned char *) addr; - - ADDR += nr >> 3; - mask = 1 << (nr & 0x07); - return (mask & *ADDR); -} - -#endif /* !_EXT2_HAVE_ASM_BITOPS_ */ - -void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg, - const char *description) -{ -#ifndef OMIT_COM_ERR - if (description) - bb_error_msg("#%lu for %s", arg, description); - else - bb_error_msg("#%lu", arg); -#endif -} - -void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap, - int code, unsigned long arg) -{ -#ifndef OMIT_COM_ERR - if (bitmap->description) - bb_error_msg("#%lu for %s", arg, bitmap->description); - else - bb_error_msg("#%lu", arg); -#endif -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * bitops.h --- Bitmap frobbing code. The byte swapping routines are - * also included here. - * - * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - * - * i386 bitops operations taken from , Copyright 1992, - * Linus Torvalds. - */ -#include - -extern int ext2fs_set_bit(unsigned int nr,void * addr); -extern int ext2fs_clear_bit(unsigned int nr, void * addr); -extern int ext2fs_test_bit(unsigned int nr, const void * addr); -extern __u16 ext2fs_swab16(__u16 val); -extern __u32 ext2fs_swab32(__u32 val); - -#ifdef WORDS_BIGENDIAN -#define ext2fs_cpu_to_le32(x) ext2fs_swab32((x)) -#define ext2fs_le32_to_cpu(x) ext2fs_swab32((x)) -#define ext2fs_cpu_to_le16(x) ext2fs_swab16((x)) -#define ext2fs_le16_to_cpu(x) ext2fs_swab16((x)) -#define ext2fs_cpu_to_be32(x) ((__u32)(x)) -#define ext2fs_be32_to_cpu(x) ((__u32)(x)) -#define ext2fs_cpu_to_be16(x) ((__u16)(x)) -#define ext2fs_be16_to_cpu(x) ((__u16)(x)) -#else -#define ext2fs_cpu_to_le32(x) ((__u32)(x)) -#define ext2fs_le32_to_cpu(x) ((__u32)(x)) -#define ext2fs_cpu_to_le16(x) ((__u16)(x)) -#define ext2fs_le16_to_cpu(x) ((__u16)(x)) -#define ext2fs_cpu_to_be32(x) ext2fs_swab32((x)) -#define ext2fs_be32_to_cpu(x) ext2fs_swab32((x)) -#define ext2fs_cpu_to_be16(x) ext2fs_swab16((x)) -#define ext2fs_be16_to_cpu(x) ext2fs_swab16((x)) -#endif - -/* - * EXT2FS bitmap manipulation routines. - */ - -/* Support for sending warning messages from the inline subroutines */ -extern const char *ext2fs_block_string; -extern const char *ext2fs_inode_string; -extern const char *ext2fs_mark_string; -extern const char *ext2fs_unmark_string; -extern const char *ext2fs_test_string; -extern void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg, - const char *description); -extern void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap, - int code, unsigned long arg); - -extern int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block); -extern int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap, - blk_t block); -extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block); - -extern int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode); -extern int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap, - ext2_ino_t inode); -extern int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode); - -extern void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap, - blk_t block); -extern void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap, - blk_t block); -extern int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap, - blk_t block); - -extern void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, - ext2_ino_t inode); -extern void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap, - ext2_ino_t inode); -extern int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap, - ext2_ino_t inode); -extern blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap); -extern ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap); -extern blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap); -extern ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap); - -extern void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap, - blk_t block, int num); -extern void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap, - blk_t block, int num); -extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap, - blk_t block, int num); -extern void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap, - blk_t block, int num); -extern void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap, - blk_t block, int num); -extern int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap, - blk_t block, int num); -extern void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map); - -/* These two routines moved to gen_bitmap.c */ -extern int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap, - __u32 bitno); -extern int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap, - blk_t bitno); diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * block.c --- iterate over all blocks in an inode - * - * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -struct block_context { - ext2_filsys fs; - int (*func)(ext2_filsys fs, - blk_t *blocknr, - e2_blkcnt_t bcount, - blk_t ref_blk, - int ref_offset, - void *priv_data); - e2_blkcnt_t bcount; - int bsize; - int flags; - errcode_t errcode; - char *ind_buf; - char *dind_buf; - char *tind_buf; - void *priv_data; -}; - -static int block_iterate_ind(blk_t *ind_block, blk_t ref_block, - int ref_offset, struct block_context *ctx) -{ - int ret = 0, changed = 0; - int i, flags, limit, offset; - blk_t *block_nr; - - limit = ctx->fs->blocksize >> 2; - if (!(ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) && - !(ctx->flags & BLOCK_FLAG_DATA_ONLY)) - ret = (*ctx->func)(ctx->fs, ind_block, - BLOCK_COUNT_IND, ref_block, - ref_offset, ctx->priv_data); - if (!*ind_block || (ret & BLOCK_ABORT)) { - ctx->bcount += limit; - return ret; - } - if (*ind_block >= ctx->fs->super->s_blocks_count || - *ind_block < ctx->fs->super->s_first_data_block) { - ctx->errcode = EXT2_ET_BAD_IND_BLOCK; - ret |= BLOCK_ERROR; - return ret; - } - ctx->errcode = ext2fs_read_ind_block(ctx->fs, *ind_block, - ctx->ind_buf); - if (ctx->errcode) { - ret |= BLOCK_ERROR; - return ret; - } - - block_nr = (blk_t *) ctx->ind_buf; - offset = 0; - if (ctx->flags & BLOCK_FLAG_APPEND) { - for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) { - flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount, - *ind_block, offset, - ctx->priv_data); - changed |= flags; - if (flags & BLOCK_ABORT) { - ret |= BLOCK_ABORT; - break; - } - offset += sizeof(blk_t); - } - } else { - for (i = 0; i < limit; i++, ctx->bcount++, block_nr++) { - if (*block_nr == 0) - continue; - flags = (*ctx->func)(ctx->fs, block_nr, ctx->bcount, - *ind_block, offset, - ctx->priv_data); - changed |= flags; - if (flags & BLOCK_ABORT) { - ret |= BLOCK_ABORT; - break; - } - offset += sizeof(blk_t); - } - } - if (changed & BLOCK_CHANGED) { - ctx->errcode = ext2fs_write_ind_block(ctx->fs, *ind_block, - ctx->ind_buf); - if (ctx->errcode) - ret |= BLOCK_ERROR | BLOCK_ABORT; - } - if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) && - !(ctx->flags & BLOCK_FLAG_DATA_ONLY) && - !(ret & BLOCK_ABORT)) - ret |= (*ctx->func)(ctx->fs, ind_block, - BLOCK_COUNT_IND, ref_block, - ref_offset, ctx->priv_data); - return ret; -} - -static int block_iterate_dind(blk_t *dind_block, blk_t ref_block, - int ref_offset, struct block_context *ctx) -{ - int ret = 0, changed = 0; - int i, flags, limit, offset; - blk_t *block_nr; - - limit = ctx->fs->blocksize >> 2; - if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE | - BLOCK_FLAG_DATA_ONLY))) - ret = (*ctx->func)(ctx->fs, dind_block, - BLOCK_COUNT_DIND, ref_block, - ref_offset, ctx->priv_data); - if (!*dind_block || (ret & BLOCK_ABORT)) { - ctx->bcount += limit*limit; - return ret; - } - if (*dind_block >= ctx->fs->super->s_blocks_count || - *dind_block < ctx->fs->super->s_first_data_block) { - ctx->errcode = EXT2_ET_BAD_DIND_BLOCK; - ret |= BLOCK_ERROR; - return ret; - } - ctx->errcode = ext2fs_read_ind_block(ctx->fs, *dind_block, - ctx->dind_buf); - if (ctx->errcode) { - ret |= BLOCK_ERROR; - return ret; - } - - block_nr = (blk_t *) ctx->dind_buf; - offset = 0; - if (ctx->flags & BLOCK_FLAG_APPEND) { - for (i = 0; i < limit; i++, block_nr++) { - flags = block_iterate_ind(block_nr, - *dind_block, offset, - ctx); - changed |= flags; - if (flags & (BLOCK_ABORT | BLOCK_ERROR)) { - ret |= flags & (BLOCK_ABORT | BLOCK_ERROR); - break; - } - offset += sizeof(blk_t); - } - } else { - for (i = 0; i < limit; i++, block_nr++) { - if (*block_nr == 0) { - ctx->bcount += limit; - continue; - } - flags = block_iterate_ind(block_nr, - *dind_block, offset, - ctx); - changed |= flags; - if (flags & (BLOCK_ABORT | BLOCK_ERROR)) { - ret |= flags & (BLOCK_ABORT | BLOCK_ERROR); - break; - } - offset += sizeof(blk_t); - } - } - if (changed & BLOCK_CHANGED) { - ctx->errcode = ext2fs_write_ind_block(ctx->fs, *dind_block, - ctx->dind_buf); - if (ctx->errcode) - ret |= BLOCK_ERROR | BLOCK_ABORT; - } - if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) && - !(ctx->flags & BLOCK_FLAG_DATA_ONLY) && - !(ret & BLOCK_ABORT)) - ret |= (*ctx->func)(ctx->fs, dind_block, - BLOCK_COUNT_DIND, ref_block, - ref_offset, ctx->priv_data); - return ret; -} - -static int block_iterate_tind(blk_t *tind_block, blk_t ref_block, - int ref_offset, struct block_context *ctx) -{ - int ret = 0, changed = 0; - int i, flags, limit, offset; - blk_t *block_nr; - - limit = ctx->fs->blocksize >> 2; - if (!(ctx->flags & (BLOCK_FLAG_DEPTH_TRAVERSE | - BLOCK_FLAG_DATA_ONLY))) - ret = (*ctx->func)(ctx->fs, tind_block, - BLOCK_COUNT_TIND, ref_block, - ref_offset, ctx->priv_data); - if (!*tind_block || (ret & BLOCK_ABORT)) { - ctx->bcount += limit*limit*limit; - return ret; - } - if (*tind_block >= ctx->fs->super->s_blocks_count || - *tind_block < ctx->fs->super->s_first_data_block) { - ctx->errcode = EXT2_ET_BAD_TIND_BLOCK; - ret |= BLOCK_ERROR; - return ret; - } - ctx->errcode = ext2fs_read_ind_block(ctx->fs, *tind_block, - ctx->tind_buf); - if (ctx->errcode) { - ret |= BLOCK_ERROR; - return ret; - } - - block_nr = (blk_t *) ctx->tind_buf; - offset = 0; - if (ctx->flags & BLOCK_FLAG_APPEND) { - for (i = 0; i < limit; i++, block_nr++) { - flags = block_iterate_dind(block_nr, - *tind_block, - offset, ctx); - changed |= flags; - if (flags & (BLOCK_ABORT | BLOCK_ERROR)) { - ret |= flags & (BLOCK_ABORT | BLOCK_ERROR); - break; - } - offset += sizeof(blk_t); - } - } else { - for (i = 0; i < limit; i++, block_nr++) { - if (*block_nr == 0) { - ctx->bcount += limit*limit; - continue; - } - flags = block_iterate_dind(block_nr, - *tind_block, - offset, ctx); - changed |= flags; - if (flags & (BLOCK_ABORT | BLOCK_ERROR)) { - ret |= flags & (BLOCK_ABORT | BLOCK_ERROR); - break; - } - offset += sizeof(blk_t); - } - } - if (changed & BLOCK_CHANGED) { - ctx->errcode = ext2fs_write_ind_block(ctx->fs, *tind_block, - ctx->tind_buf); - if (ctx->errcode) - ret |= BLOCK_ERROR | BLOCK_ABORT; - } - if ((ctx->flags & BLOCK_FLAG_DEPTH_TRAVERSE) && - !(ctx->flags & BLOCK_FLAG_DATA_ONLY) && - !(ret & BLOCK_ABORT)) - ret |= (*ctx->func)(ctx->fs, tind_block, - BLOCK_COUNT_TIND, ref_block, - ref_offset, ctx->priv_data); - - return ret; -} - -errcode_t ext2fs_block_iterate2(ext2_filsys fs, - ext2_ino_t ino, - int flags, - char *block_buf, - int (*func)(ext2_filsys fs, - blk_t *blocknr, - e2_blkcnt_t blockcnt, - blk_t ref_blk, - int ref_offset, - void *priv_data), - void *priv_data) -{ - int i; - int got_inode = 0; - int ret = 0; - blk_t blocks[EXT2_N_BLOCKS]; /* directory data blocks */ - struct ext2_inode inode; - errcode_t retval; - struct block_context ctx; - int limit; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - /* - * Check to see if we need to limit large files - */ - if (flags & BLOCK_FLAG_NO_LARGE) { - ctx.errcode = ext2fs_read_inode(fs, ino, &inode); - if (ctx.errcode) - return ctx.errcode; - got_inode = 1; - if (!LINUX_S_ISDIR(inode.i_mode) && - (inode.i_size_high != 0)) - return EXT2_ET_FILE_TOO_BIG; - } - - retval = ext2fs_get_blocks(fs, ino, blocks); - if (retval) - return retval; - - limit = fs->blocksize >> 2; - - ctx.fs = fs; - ctx.func = func; - ctx.priv_data = priv_data; - ctx.flags = flags; - ctx.bcount = 0; - if (block_buf) { - ctx.ind_buf = block_buf; - } else { - retval = ext2fs_get_mem(fs->blocksize * 3, &ctx.ind_buf); - if (retval) - return retval; - } - ctx.dind_buf = ctx.ind_buf + fs->blocksize; - ctx.tind_buf = ctx.dind_buf + fs->blocksize; - - /* - * Iterate over the HURD translator block (if present) - */ - if ((fs->super->s_creator_os == EXT2_OS_HURD) && - !(flags & BLOCK_FLAG_DATA_ONLY)) { - ctx.errcode = ext2fs_read_inode(fs, ino, &inode); - if (ctx.errcode) - goto abort_exit; - got_inode = 1; - if (inode.osd1.hurd1.h_i_translator) { - ret |= (*ctx.func)(fs, - &inode.osd1.hurd1.h_i_translator, - BLOCK_COUNT_TRANSLATOR, - 0, 0, priv_data); - if (ret & BLOCK_ABORT) - goto abort_exit; - } - } - - /* - * Iterate over normal data blocks - */ - for (i = 0; i < EXT2_NDIR_BLOCKS; i++, ctx.bcount++) { - if (blocks[i] || (flags & BLOCK_FLAG_APPEND)) { - ret |= (*ctx.func)(fs, &blocks[i], - ctx.bcount, 0, i, priv_data); - if (ret & BLOCK_ABORT) - goto abort_exit; - } - } - if (*(blocks + EXT2_IND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) { - ret |= block_iterate_ind(blocks + EXT2_IND_BLOCK, - 0, EXT2_IND_BLOCK, &ctx); - if (ret & BLOCK_ABORT) - goto abort_exit; - } else - ctx.bcount += limit; - if (*(blocks + EXT2_DIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) { - ret |= block_iterate_dind(blocks + EXT2_DIND_BLOCK, - 0, EXT2_DIND_BLOCK, &ctx); - if (ret & BLOCK_ABORT) - goto abort_exit; - } else - ctx.bcount += limit * limit; - if (*(blocks + EXT2_TIND_BLOCK) || (flags & BLOCK_FLAG_APPEND)) { - ret |= block_iterate_tind(blocks + EXT2_TIND_BLOCK, - 0, EXT2_TIND_BLOCK, &ctx); - if (ret & BLOCK_ABORT) - goto abort_exit; - } - -abort_exit: - if (ret & BLOCK_CHANGED) { - if (!got_inode) { - retval = ext2fs_read_inode(fs, ino, &inode); - if (retval) - return retval; - } - for (i=0; i < EXT2_N_BLOCKS; i++) - inode.i_block[i] = blocks[i]; - retval = ext2fs_write_inode(fs, ino, &inode); - if (retval) - return retval; - } - - if (!block_buf) - ext2fs_free_mem(&ctx.ind_buf); - - return (ret & BLOCK_ERROR) ? ctx.errcode : 0; -} - -/* - * Emulate the old ext2fs_block_iterate function! - */ - -struct xlate { - int (*func)(ext2_filsys fs, - blk_t *blocknr, - int bcount, - void *priv_data); - void *real_private; -}; - -#ifdef __TURBOC__ -# pragma argsused -#endif -static int xlate_func(ext2_filsys fs, blk_t *blocknr, e2_blkcnt_t blockcnt, - blk_t ref_block EXT2FS_ATTR((unused)), - int ref_offset EXT2FS_ATTR((unused)), - void *priv_data) -{ - struct xlate *xl = (struct xlate *) priv_data; - - return (*xl->func)(fs, blocknr, (int) blockcnt, xl->real_private); -} - -errcode_t ext2fs_block_iterate(ext2_filsys fs, - ext2_ino_t ino, - int flags, - char *block_buf, - int (*func)(ext2_filsys fs, - blk_t *blocknr, - int blockcnt, - void *priv_data), - void *priv_data) -{ - struct xlate xl; - - xl.real_private = priv_data; - xl.func = func; - - return ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_NO_LARGE | flags, - block_buf, xlate_func, &xl); -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * bmap.c --- logical to physical block mapping - * - * Copyright (C) 1997 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -extern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, - struct ext2_inode *inode, - char *block_buf, int bmap_flags, - blk_t block, blk_t *phys_blk); - -#define inode_bmap(inode, nr) ((inode)->i_block[(nr)]) - -static errcode_t block_ind_bmap(ext2_filsys fs, int flags, - blk_t ind, char *block_buf, - int *blocks_alloc, - blk_t nr, blk_t *ret_blk) -{ - errcode_t retval; - blk_t b; - - if (!ind) { - if (flags & BMAP_SET) - return EXT2_ET_SET_BMAP_NO_IND; - *ret_blk = 0; - return 0; - } - retval = io_channel_read_blk(fs->io, ind, 1, block_buf); - if (retval) - return retval; - - if (flags & BMAP_SET) { - b = *ret_blk; -#if BB_BIG_ENDIAN - if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || - (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)) - b = ext2fs_swab32(b); -#endif - ((blk_t *) block_buf)[nr] = b; - return io_channel_write_blk(fs->io, ind, 1, block_buf); - } - - b = ((blk_t *) block_buf)[nr]; - -#if BB_BIG_ENDIAN - if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || - (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) - b = ext2fs_swab32(b); -#endif - - if (!b && (flags & BMAP_ALLOC)) { - b = nr ? ((blk_t *) block_buf)[nr-1] : 0; - retval = ext2fs_alloc_block(fs, b, - block_buf + fs->blocksize, &b); - if (retval) - return retval; - -#if BB_BIG_ENDIAN - if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || - (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)) - ((blk_t *) block_buf)[nr] = ext2fs_swab32(b); - else -#endif - ((blk_t *) block_buf)[nr] = b; - - retval = io_channel_write_blk(fs->io, ind, 1, block_buf); - if (retval) - return retval; - - (*blocks_alloc)++; - } - - *ret_blk = b; - return 0; -} - -static errcode_t block_dind_bmap(ext2_filsys fs, int flags, - blk_t dind, char *block_buf, - int *blocks_alloc, - blk_t nr, blk_t *ret_blk) -{ - blk_t b; - errcode_t retval; - blk_t addr_per_block; - - addr_per_block = (blk_t) fs->blocksize >> 2; - - retval = block_ind_bmap(fs, flags & ~BMAP_SET, dind, block_buf, - blocks_alloc, nr / addr_per_block, &b); - if (retval) - return retval; - retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc, - nr % addr_per_block, ret_blk); - return retval; -} - -static errcode_t block_tind_bmap(ext2_filsys fs, int flags, - blk_t tind, char *block_buf, - int *blocks_alloc, - blk_t nr, blk_t *ret_blk) -{ - blk_t b; - errcode_t retval; - blk_t addr_per_block; - - addr_per_block = (blk_t) fs->blocksize >> 2; - - retval = block_dind_bmap(fs, flags & ~BMAP_SET, tind, block_buf, - blocks_alloc, nr / addr_per_block, &b); - if (retval) - return retval; - retval = block_ind_bmap(fs, flags, b, block_buf, blocks_alloc, - nr % addr_per_block, ret_blk); - return retval; -} - -errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode, - char *block_buf, int bmap_flags, blk_t block, - blk_t *phys_blk) -{ - struct ext2_inode inode_buf; - blk_t addr_per_block; - blk_t b; - char *buf = NULL; - errcode_t retval = 0; - int blocks_alloc = 0, inode_dirty = 0; - - if (!(bmap_flags & BMAP_SET)) - *phys_blk = 0; - - /* Read inode structure if necessary */ - if (!inode) { - retval = ext2fs_read_inode(fs, ino, &inode_buf); - if (retval) - return retval; - inode = &inode_buf; - } - addr_per_block = (blk_t) fs->blocksize >> 2; - - if (!block_buf) { - retval = ext2fs_get_mem(fs->blocksize * 2, &buf); - if (retval) - return retval; - block_buf = buf; - } - - if (block < EXT2_NDIR_BLOCKS) { - if (bmap_flags & BMAP_SET) { - b = *phys_blk; -#if BB_BIG_ENDIAN - if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || - (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) - b = ext2fs_swab32(b); -#endif - inode_bmap(inode, block) = b; - inode_dirty++; - goto done; - } - - *phys_blk = inode_bmap(inode, block); - b = block ? inode_bmap(inode, block-1) : 0; - - if ((*phys_blk == 0) && (bmap_flags & BMAP_ALLOC)) { - retval = ext2fs_alloc_block(fs, b, block_buf, &b); - if (retval) - goto done; - inode_bmap(inode, block) = b; - blocks_alloc++; - *phys_blk = b; - } - goto done; - } - - /* Indirect block */ - block -= EXT2_NDIR_BLOCKS; - if (block < addr_per_block) { - b = inode_bmap(inode, EXT2_IND_BLOCK); - if (!b) { - if (!(bmap_flags & BMAP_ALLOC)) { - if (bmap_flags & BMAP_SET) - retval = EXT2_ET_SET_BMAP_NO_IND; - goto done; - } - - b = inode_bmap(inode, EXT2_IND_BLOCK-1); - retval = ext2fs_alloc_block(fs, b, block_buf, &b); - if (retval) - goto done; - inode_bmap(inode, EXT2_IND_BLOCK) = b; - blocks_alloc++; - } - retval = block_ind_bmap(fs, bmap_flags, b, block_buf, - &blocks_alloc, block, phys_blk); - goto done; - } - - /* Doubly indirect block */ - block -= addr_per_block; - if (block < addr_per_block * addr_per_block) { - b = inode_bmap(inode, EXT2_DIND_BLOCK); - if (!b) { - if (!(bmap_flags & BMAP_ALLOC)) { - if (bmap_flags & BMAP_SET) - retval = EXT2_ET_SET_BMAP_NO_IND; - goto done; - } - - b = inode_bmap(inode, EXT2_IND_BLOCK); - retval = ext2fs_alloc_block(fs, b, block_buf, &b); - if (retval) - goto done; - inode_bmap(inode, EXT2_DIND_BLOCK) = b; - blocks_alloc++; - } - retval = block_dind_bmap(fs, bmap_flags, b, block_buf, - &blocks_alloc, block, phys_blk); - goto done; - } - - /* Triply indirect block */ - block -= addr_per_block * addr_per_block; - b = inode_bmap(inode, EXT2_TIND_BLOCK); - if (!b) { - if (!(bmap_flags & BMAP_ALLOC)) { - if (bmap_flags & BMAP_SET) - retval = EXT2_ET_SET_BMAP_NO_IND; - goto done; - } - - b = inode_bmap(inode, EXT2_DIND_BLOCK); - retval = ext2fs_alloc_block(fs, b, block_buf, &b); - if (retval) - goto done; - inode_bmap(inode, EXT2_TIND_BLOCK) = b; - blocks_alloc++; - } - retval = block_tind_bmap(fs, bmap_flags, b, block_buf, - &blocks_alloc, block, phys_blk); -done: - ext2fs_free_mem(&buf); - if ((retval == 0) && (blocks_alloc || inode_dirty)) { - inode->i_blocks += (blocks_alloc * fs->blocksize) / 512; - retval = ext2fs_write_inode(fs, ino, inode); - } - return retval; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * bmove.c --- Move blocks around to make way for a particular - * filesystem structure. - * - * Copyright (C) 1997 Theodore Ts'o. This file may be redistributed - * under the terms of the GNU Public License. - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fsP.h" - -struct process_block_struct { - ext2_ino_t ino; - struct ext2_inode * inode; - ext2fs_block_bitmap reserve; - ext2fs_block_bitmap alloc_map; - errcode_t error; - char *buf; - int add_dir; - int flags; -}; - -static int process_block(ext2_filsys fs, blk_t *block_nr, - e2_blkcnt_t blockcnt, blk_t ref_block, - int ref_offset, void *priv_data) -{ - struct process_block_struct *pb; - errcode_t retval; - int ret; - blk_t block, orig; - - pb = (struct process_block_struct *) priv_data; - block = orig = *block_nr; - ret = 0; - - /* - * Let's see if this is one which we need to relocate - */ - if (ext2fs_test_block_bitmap(pb->reserve, block)) { - do { - if (++block >= fs->super->s_blocks_count) - block = fs->super->s_first_data_block; - if (block == orig) { - pb->error = EXT2_ET_BLOCK_ALLOC_FAIL; - return BLOCK_ABORT; - } - } while (ext2fs_test_block_bitmap(pb->reserve, block) || - ext2fs_test_block_bitmap(pb->alloc_map, block)); - - retval = io_channel_read_blk(fs->io, orig, 1, pb->buf); - if (retval) { - pb->error = retval; - return BLOCK_ABORT; - } - retval = io_channel_write_blk(fs->io, block, 1, pb->buf); - if (retval) { - pb->error = retval; - return BLOCK_ABORT; - } - *block_nr = block; - ext2fs_mark_block_bitmap(pb->alloc_map, block); - ret = BLOCK_CHANGED; - if (pb->flags & EXT2_BMOVE_DEBUG) - printf("ino=%ld, blockcnt=%lld, %d->%d\n", pb->ino, - blockcnt, orig, block); - } - if (pb->add_dir) { - retval = ext2fs_add_dir_block(fs->dblist, pb->ino, - block, (int) blockcnt); - if (retval) { - pb->error = retval; - ret |= BLOCK_ABORT; - } - } - return ret; -} - -errcode_t ext2fs_move_blocks(ext2_filsys fs, - ext2fs_block_bitmap reserve, - ext2fs_block_bitmap alloc_map, - int flags) -{ - ext2_ino_t ino; - struct ext2_inode inode; - errcode_t retval; - struct process_block_struct pb; - ext2_inode_scan scan; - char *block_buf; - - retval = ext2fs_open_inode_scan(fs, 0, &scan); - if (retval) - return retval; - - pb.reserve = reserve; - pb.error = 0; - pb.alloc_map = alloc_map ? alloc_map : fs->block_map; - pb.flags = flags; - - retval = ext2fs_get_mem(fs->blocksize * 4, &block_buf); - if (retval) - return retval; - pb.buf = block_buf + fs->blocksize * 3; - - /* - * If GET_DBLIST is set in the flags field, then we should - * gather directory block information while we're doing the - * block move. - */ - if (flags & EXT2_BMOVE_GET_DBLIST) { - ext2fs_free_dblist(fs->dblist); - fs->dblist = NULL; - retval = ext2fs_init_dblist(fs, 0); - if (retval) - return retval; - } - - retval = ext2fs_get_next_inode(scan, &ino, &inode); - if (retval) - return retval; - - while (ino) { - if ((inode.i_links_count == 0) || - !ext2fs_inode_has_valid_blocks(&inode)) - goto next; - - pb.ino = ino; - pb.inode = &inode; - - pb.add_dir = (LINUX_S_ISDIR(inode.i_mode) && - flags & EXT2_BMOVE_GET_DBLIST); - - retval = ext2fs_block_iterate2(fs, ino, 0, block_buf, - process_block, &pb); - if (retval) - return retval; - if (pb.error) - return pb.error; - - next: - retval = ext2fs_get_next_inode(scan, &ino, &inode); - if (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) - goto next; - } - return 0; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * brel.h - * - * Copyright (C) 1996, 1997 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -struct ext2_block_relocate_entry { - blk_t new; - __s16 offset; - __u16 flags; - union { - blk_t block_ref; - ext2_ino_t inode_ref; - } owner; -}; - -#define RELOCATE_TYPE_REF 0x0007 -#define RELOCATE_BLOCK_REF 0x0001 -#define RELOCATE_INODE_REF 0x0002 - -typedef struct ext2_block_relocation_table *ext2_brel; - -struct ext2_block_relocation_table { - __u32 magic; - char *name; - blk_t current; - void *priv_data; - - /* - * Add a block relocation entry. - */ - errcode_t (*put)(ext2_brel brel, blk_t old, - struct ext2_block_relocate_entry *ent); - - /* - * Get a block relocation entry. - */ - errcode_t (*get)(ext2_brel brel, blk_t old, - struct ext2_block_relocate_entry *ent); - - /* - * Initialize for iterating over the block relocation entries. - */ - errcode_t (*start_iter)(ext2_brel brel); - - /* - * The iterator function for the inode relocation entries. - * Returns an inode number of 0 when out of entries. - */ - errcode_t (*next)(ext2_brel brel, blk_t *old, - struct ext2_block_relocate_entry *ent); - - /* - * Move the inode relocation table from one block number to - * another. - */ - errcode_t (*move)(ext2_brel brel, blk_t old, blk_t new); - - /* - * Remove a block relocation entry. - */ - errcode_t (*delete)(ext2_brel brel, blk_t old); - - - /* - * Free the block relocation table. - */ - errcode_t (*free)(ext2_brel brel); -}; - -errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block, - ext2_brel *brel); - -#define ext2fs_brel_put(brel, old, ent) ((brel)->put((brel), old, ent)) -#define ext2fs_brel_get(brel, old, ent) ((brel)->get((brel), old, ent)) -#define ext2fs_brel_start_iter(brel) ((brel)->start_iter((brel))) -#define ext2fs_brel_next(brel, old, ent) ((brel)->next((brel), old, ent)) -#define ext2fs_brel_move(brel, old, new) ((brel)->move((brel), old, new)) -#define ext2fs_brel_delete(brel, old) ((brel)->delete((brel), old)) -#define ext2fs_brel_free(brel) ((brel)->free((brel))) diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * brel_ma.c - * - * Copyright (C) 1996, 1997 Theodore Ts'o. - * - * TODO: rewrite to not use a direct array!!! (Fortunately this - * module isn't really used yet.) - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#if HAVE_ERRNO_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" -#include "brel.h" - -static errcode_t bma_put(ext2_brel brel, blk_t old, - struct ext2_block_relocate_entry *ent); -static errcode_t bma_get(ext2_brel brel, blk_t old, - struct ext2_block_relocate_entry *ent); -static errcode_t bma_start_iter(ext2_brel brel); -static errcode_t bma_next(ext2_brel brel, blk_t *old, - struct ext2_block_relocate_entry *ent); -static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new); -static errcode_t bma_delete(ext2_brel brel, blk_t old); -static errcode_t bma_free(ext2_brel brel); - -struct brel_ma { - __u32 magic; - blk_t max_block; - struct ext2_block_relocate_entry *entries; -}; - -errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block, - ext2_brel *new_brel) -{ - ext2_brel brel = 0; - errcode_t retval; - struct brel_ma *ma = 0; - size_t size; - - *new_brel = 0; - - /* - * Allocate memory structures - */ - retval = ext2fs_get_mem(sizeof(struct ext2_block_relocation_table), - &brel); - if (retval) - goto errout; - memset(brel, 0, sizeof(struct ext2_block_relocation_table)); - - retval = ext2fs_get_mem(strlen(name)+1, &brel->name); - if (retval) - goto errout; - strcpy(brel->name, name); - - retval = ext2fs_get_mem(sizeof(struct brel_ma), &ma); - if (retval) - goto errout; - memset(ma, 0, sizeof(struct brel_ma)); - brel->priv_data = ma; - - size = (size_t) (sizeof(struct ext2_block_relocate_entry) * - (max_block+1)); - retval = ext2fs_get_mem(size, &ma->entries); - if (retval) - goto errout; - memset(ma->entries, 0, size); - ma->max_block = max_block; - - /* - * Fill in the brel data structure - */ - brel->put = bma_put; - brel->get = bma_get; - brel->start_iter = bma_start_iter; - brel->next = bma_next; - brel->move = bma_move; - brel->delete = bma_delete; - brel->free = bma_free; - - *new_brel = brel; - return 0; - -errout: - bma_free(brel); - return retval; -} - -static errcode_t bma_put(ext2_brel brel, blk_t old, - struct ext2_block_relocate_entry *ent) -{ - struct brel_ma *ma; - - ma = brel->priv_data; - if (old > ma->max_block) - return EXT2_ET_INVALID_ARGUMENT; - ma->entries[(unsigned)old] = *ent; - return 0; -} - -static errcode_t bma_get(ext2_brel brel, blk_t old, - struct ext2_block_relocate_entry *ent) -{ - struct brel_ma *ma; - - ma = brel->priv_data; - if (old > ma->max_block) - return EXT2_ET_INVALID_ARGUMENT; - if (ma->entries[(unsigned)old].new == 0) - return ENOENT; - *ent = ma->entries[old]; - return 0; -} - -static errcode_t bma_start_iter(ext2_brel brel) -{ - brel->current = 0; - return 0; -} - -static errcode_t bma_next(ext2_brel brel, blk_t *old, - struct ext2_block_relocate_entry *ent) -{ - struct brel_ma *ma; - - ma = brel->priv_data; - while (++brel->current < ma->max_block) { - if (ma->entries[(unsigned)brel->current].new == 0) - continue; - *old = brel->current; - *ent = ma->entries[(unsigned)brel->current]; - return 0; - } - *old = 0; - return 0; -} - -static errcode_t bma_move(ext2_brel brel, blk_t old, blk_t new) -{ - struct brel_ma *ma; - - ma = brel->priv_data; - if ((old > ma->max_block) || (new > ma->max_block)) - return EXT2_ET_INVALID_ARGUMENT; - if (ma->entries[(unsigned)old].new == 0) - return ENOENT; - ma->entries[(unsigned)new] = ma->entries[old]; - ma->entries[(unsigned)old].new = 0; - return 0; -} - -static errcode_t bma_delete(ext2_brel brel, blk_t old) -{ - struct brel_ma *ma; - - ma = brel->priv_data; - if (old > ma->max_block) - return EXT2_ET_INVALID_ARGUMENT; - if (ma->entries[(unsigned)old].new == 0) - return ENOENT; - ma->entries[(unsigned)old].new = 0; - return 0; -} - -static errcode_t bma_free(ext2_brel brel) -{ - struct brel_ma *ma; - - if (!brel) - return 0; - - ma = brel->priv_data; - - if (ma) { - ext2fs_free_mem(&ma->entries); - ext2fs_free_mem(&ma); - } - ext2fs_free_mem(&brel->name); - ext2fs_free_mem(&brel); - return 0; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * check_desc.c --- Check the group descriptors of an ext2 filesystem - * - * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -/* - * This routine sanity checks the group descriptors - */ -errcode_t ext2fs_check_desc(ext2_filsys fs) -{ - dgrp_t i; - blk_t block = fs->super->s_first_data_block; - blk_t next; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - for (i = 0; i < fs->group_desc_count; i++) { - next = block + fs->super->s_blocks_per_group; - /* - * Check to make sure block bitmap for group is - * located within the group. - */ - if (fs->group_desc[i].bg_block_bitmap < block || - fs->group_desc[i].bg_block_bitmap >= next) - return EXT2_ET_GDESC_BAD_BLOCK_MAP; - /* - * Check to make sure inode bitmap for group is - * located within the group - */ - if (fs->group_desc[i].bg_inode_bitmap < block || - fs->group_desc[i].bg_inode_bitmap >= next) - return EXT2_ET_GDESC_BAD_INODE_MAP; - /* - * Check to make sure inode table for group is located - * within the group - */ - if (fs->group_desc[i].bg_inode_table < block || - ((fs->group_desc[i].bg_inode_table + - fs->inode_blocks_per_group) >= next)) - return EXT2_ET_GDESC_BAD_INODE_TABLE; - - block = next; - } - return 0; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * closefs.c --- close an ext2 filesystem - * - * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include - -#include "ext2_fs.h" -#include "ext2fsP.h" - -static int test_root(int a, int b) -{ - if (a == 0) - return 1; - while (1) { - if (a == 1) - return 1; - if (a % b) - return 0; - a = a / b; - } -} - -int ext2fs_bg_has_super(ext2_filsys fs, int group_block) -{ - if (!(fs->super->s_feature_ro_compat & - EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) - return 1; - - if (test_root(group_block, 3) || (test_root(group_block, 5)) || - test_root(group_block, 7)) - return 1; - - return 0; -} - -int ext2fs_super_and_bgd_loc(ext2_filsys fs, - dgrp_t group, - blk_t *ret_super_blk, - blk_t *ret_old_desc_blk, - blk_t *ret_new_desc_blk, - int *ret_meta_bg) -{ - blk_t group_block, super_blk = 0, old_desc_blk = 0, new_desc_blk = 0; - unsigned int meta_bg, meta_bg_size; - int numblocks, has_super; - int old_desc_blocks; - - group_block = fs->super->s_first_data_block + - (group * fs->super->s_blocks_per_group); - - if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) - old_desc_blocks = fs->super->s_first_meta_bg; - else - old_desc_blocks = - fs->desc_blocks + fs->super->s_reserved_gdt_blocks; - - if (group == fs->group_desc_count-1) { - numblocks = (fs->super->s_blocks_count - - fs->super->s_first_data_block) % - fs->super->s_blocks_per_group; - if (!numblocks) - numblocks = fs->super->s_blocks_per_group; - } else - numblocks = fs->super->s_blocks_per_group; - - has_super = ext2fs_bg_has_super(fs, group); - - if (has_super) { - super_blk = group_block; - numblocks--; - } - meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc)); - meta_bg = group / meta_bg_size; - - if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) || - (meta_bg < fs->super->s_first_meta_bg)) { - if (has_super) { - old_desc_blk = group_block + 1; - numblocks -= old_desc_blocks; - } - } else { - if (((group % meta_bg_size) == 0) || - ((group % meta_bg_size) == 1) || - ((group % meta_bg_size) == (meta_bg_size-1))) { - if (has_super) - has_super = 1; - new_desc_blk = group_block + has_super; - numblocks--; - } - } - - numblocks -= 2 + fs->inode_blocks_per_group; - - if (ret_super_blk) - *ret_super_blk = super_blk; - if (ret_old_desc_blk) - *ret_old_desc_blk = old_desc_blk; - if (ret_new_desc_blk) - *ret_new_desc_blk = new_desc_blk; - if (ret_meta_bg) - *ret_meta_bg = meta_bg; - return numblocks; -} - - -/* - * This function forces out the primary superblock. We need to only - * write out those fields which we have changed, since if the - * filesystem is mounted, it may have changed some of the other - * fields. - * - * It takes as input a superblock which has already been byte swapped - * (if necessary). - * - */ -static errcode_t write_primary_superblock(ext2_filsys fs, - struct ext2_super_block *super) -{ - __u16 *old_super, *new_super; - int check_idx, write_idx, size; - errcode_t retval; - - if (!fs->io->manager->write_byte || !fs->orig_super) { - io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET); - retval = io_channel_write_blk(fs->io, 1, -SUPERBLOCK_SIZE, - super); - io_channel_set_blksize(fs->io, fs->blocksize); - return retval; - } - - old_super = (__u16 *) fs->orig_super; - new_super = (__u16 *) super; - - for (check_idx = 0; check_idx < SUPERBLOCK_SIZE/2; check_idx++) { - if (old_super[check_idx] == new_super[check_idx]) - continue; - write_idx = check_idx; - for (check_idx++; check_idx < SUPERBLOCK_SIZE/2; check_idx++) - if (old_super[check_idx] == new_super[check_idx]) - break; - size = 2 * (check_idx - write_idx); - retval = io_channel_write_byte(fs->io, - SUPERBLOCK_OFFSET + (2 * write_idx), size, - new_super + write_idx); - if (retval) - return retval; - } - memcpy(fs->orig_super, super, SUPERBLOCK_SIZE); - return 0; -} - - -/* - * Updates the revision to EXT2_DYNAMIC_REV - */ -void ext2fs_update_dynamic_rev(ext2_filsys fs) -{ - struct ext2_super_block *sb = fs->super; - - if (sb->s_rev_level > EXT2_GOOD_OLD_REV) - return; - - sb->s_rev_level = EXT2_DYNAMIC_REV; - sb->s_first_ino = EXT2_GOOD_OLD_FIRST_INO; - sb->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE; - /* s_uuid is handled by e2fsck already */ - /* other fields should be left alone */ -} - -static errcode_t write_backup_super(ext2_filsys fs, dgrp_t group, - blk_t group_block, - struct ext2_super_block *super_shadow) -{ - dgrp_t sgrp = group; - - if (sgrp > ((1 << 16) - 1)) - sgrp = (1 << 16) - 1; -#if BB_BIG_ENDIAN - if (fs->flags & EXT2_FLAG_SWAP_BYTES) - super_shadow->s_block_group_nr = ext2fs_swab16(sgrp); - else -#endif - fs->super->s_block_group_nr = sgrp; - - return io_channel_write_blk(fs->io, group_block, -SUPERBLOCK_SIZE, - super_shadow); -} - - -errcode_t ext2fs_flush(ext2_filsys fs) -{ - dgrp_t i; - blk_t group_block; - errcode_t retval; - unsigned long fs_state; - struct ext2_super_block *super_shadow = NULL; - struct ext2_group_desc *group_shadow = NULL; - char *group_ptr; - int old_desc_blocks; -#if BB_BIG_ENDIAN - dgrp_t j; - struct ext2_group_desc *s, *t; -#endif - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - fs_state = fs->super->s_state; - - fs->super->s_wtime = time(NULL); - fs->super->s_block_group_nr = 0; -#if BB_BIG_ENDIAN - if (fs->flags & EXT2_FLAG_SWAP_BYTES) { - retval = EXT2_ET_NO_MEMORY; - retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow); - if (retval) - goto errout; - retval = ext2fs_get_mem((size_t)(fs->blocksize * - fs->desc_blocks), - &group_shadow); - if (retval) - goto errout; - memset(group_shadow, 0, (size_t) fs->blocksize * - fs->desc_blocks); - - /* swap the group descriptors */ - for (j=0, s=fs->group_desc, t=group_shadow; - j < fs->group_desc_count; j++, t++, s++) { - *t = *s; - ext2fs_swap_group_desc(t); - } - } else { - super_shadow = fs->super; - group_shadow = fs->group_desc; - } -#else - super_shadow = fs->super; - group_shadow = fs->group_desc; -#endif - - /* - * If this is an external journal device, don't write out the - * block group descriptors or any of the backup superblocks - */ - if (fs->super->s_feature_incompat & - EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) - goto write_primary_superblock_only; - - /* - * Set the state of the FS to be non-valid. (The state has - * already been backed up earlier, and will be restored after - * we write out the backup superblocks.) - */ - fs->super->s_state &= ~EXT2_VALID_FS; -#if BB_BIG_ENDIAN - if (fs->flags & EXT2_FLAG_SWAP_BYTES) { - *super_shadow = *fs->super; - ext2fs_swap_super(super_shadow); - } -#endif - - /* - * Write out the master group descriptors, and the backup - * superblocks and group descriptors. - */ - group_block = fs->super->s_first_data_block; - group_ptr = (char *) group_shadow; - if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) - old_desc_blocks = fs->super->s_first_meta_bg; - else - old_desc_blocks = fs->desc_blocks; - - for (i = 0; i < fs->group_desc_count; i++) { - blk_t super_blk, old_desc_blk, new_desc_blk; - int meta_bg; - - ext2fs_super_and_bgd_loc(fs, i, &super_blk, &old_desc_blk, - &new_desc_blk, &meta_bg); - - if (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) &&i && super_blk) { - retval = write_backup_super(fs, i, super_blk, - super_shadow); - if (retval) - goto errout; - } - if (fs->flags & EXT2_FLAG_SUPER_ONLY) - continue; - if ((old_desc_blk) && - (!(fs->flags & EXT2_FLAG_MASTER_SB_ONLY) || (i == 0))) { - retval = io_channel_write_blk(fs->io, - old_desc_blk, old_desc_blocks, group_ptr); - if (retval) - goto errout; - } - if (new_desc_blk) { - retval = io_channel_write_blk(fs->io, new_desc_blk, - 1, group_ptr + (meta_bg*fs->blocksize)); - if (retval) - goto errout; - } - } - fs->super->s_block_group_nr = 0; - fs->super->s_state = fs_state; -#if BB_BIG_ENDIAN - if (fs->flags & EXT2_FLAG_SWAP_BYTES) { - *super_shadow = *fs->super; - ext2fs_swap_super(super_shadow); - } -#endif - - /* - * If the write_bitmaps() function is present, call it to - * flush the bitmaps. This is done this way so that a simple - * program that doesn't mess with the bitmaps doesn't need to - * drag in the bitmaps.c code. - */ - if (fs->write_bitmaps) { - retval = fs->write_bitmaps(fs); - if (retval) - goto errout; - } - -write_primary_superblock_only: - /* - * Write out master superblock. This has to be done - * separately, since it is located at a fixed location - * (SUPERBLOCK_OFFSET). We flush all other pending changes - * out to disk first, just to avoid a race condition with an - * insy-tinsy window.... - */ - retval = io_channel_flush(fs->io); - retval = write_primary_superblock(fs, super_shadow); - if (retval) - goto errout; - - fs->flags &= ~EXT2_FLAG_DIRTY; - - retval = io_channel_flush(fs->io); -errout: - fs->super->s_state = fs_state; - if (fs->flags & EXT2_FLAG_SWAP_BYTES) { - if (super_shadow) - ext2fs_free_mem(&super_shadow); - if (group_shadow) - ext2fs_free_mem(&group_shadow); - } - return retval; -} - -errcode_t ext2fs_close(ext2_filsys fs) -{ - errcode_t retval; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - if (fs->flags & EXT2_FLAG_DIRTY) { - retval = ext2fs_flush(fs); - if (retval) - return retval; - } - if (fs->write_bitmaps) { - retval = fs->write_bitmaps(fs); - if (retval) - return retval; - } - ext2fs_free(fs); - return 0; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * cmp_bitmaps.c --- routines to compare inode and block bitmaps. - * - * Copyright (C) 1995 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1, - ext2fs_block_bitmap bm2) -{ - blk_t i; - - EXT2_CHECK_MAGIC(bm1, EXT2_ET_MAGIC_BLOCK_BITMAP); - EXT2_CHECK_MAGIC(bm2, EXT2_ET_MAGIC_BLOCK_BITMAP); - - if ((bm1->start != bm2->start) || - (bm1->end != bm2->end) || - (memcmp(bm1->bitmap, bm2->bitmap, - (size_t) (bm1->end - bm1->start)/8))) - return EXT2_ET_NEQ_BLOCK_BITMAP; - - for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++) - if (ext2fs_fast_test_block_bitmap(bm1, i) != - ext2fs_fast_test_block_bitmap(bm2, i)) - return EXT2_ET_NEQ_BLOCK_BITMAP; - - return 0; -} - -errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1, - ext2fs_inode_bitmap bm2) -{ - ext2_ino_t i; - - EXT2_CHECK_MAGIC(bm1, EXT2_ET_MAGIC_INODE_BITMAP); - EXT2_CHECK_MAGIC(bm2, EXT2_ET_MAGIC_INODE_BITMAP); - - if ((bm1->start != bm2->start) || - (bm1->end != bm2->end) || - (memcmp(bm1->bitmap, bm2->bitmap, - (size_t) (bm1->end - bm1->start)/8))) - return EXT2_ET_NEQ_INODE_BITMAP; - - for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++) - if (ext2fs_fast_test_inode_bitmap(bm1, i) != - ext2fs_fast_test_inode_bitmap(bm2, i)) - return EXT2_ET_NEQ_INODE_BITMAP; - - return 0; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * dblist.c -- directory block list functions - * - * Copyright 1997 by Theodore Ts'o - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - * - */ - -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include - -#include "ext2_fs.h" -#include "ext2fsP.h" - -static int dir_block_cmp(const void *a, const void *b); - -/* - * Returns the number of directories in the filesystem as reported by - * the group descriptors. Of course, the group descriptors could be - * wrong! - */ -errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs) -{ - dgrp_t i; - ext2_ino_t num_dirs, max_dirs; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - num_dirs = 0; - max_dirs = fs->super->s_inodes_per_group; - for (i = 0; i < fs->group_desc_count; i++) { - if (fs->group_desc[i].bg_used_dirs_count > max_dirs) - num_dirs += max_dirs / 8; - else - num_dirs += fs->group_desc[i].bg_used_dirs_count; - } - if (num_dirs > fs->super->s_inodes_count) - num_dirs = fs->super->s_inodes_count; - - *ret_num_dirs = num_dirs; - - return 0; -} - -/* - * helper function for making a new directory block list (for - * initialize and copy). - */ -static errcode_t make_dblist(ext2_filsys fs, ext2_ino_t size, ext2_ino_t count, - struct ext2_db_entry *list, - ext2_dblist *ret_dblist) -{ - ext2_dblist dblist; - errcode_t retval; - size_t len; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - if ((ret_dblist == 0) && fs->dblist && - (fs->dblist->magic == EXT2_ET_MAGIC_DBLIST)) - return 0; - - retval = ext2fs_get_mem(sizeof(struct ext2_struct_dblist), &dblist); - if (retval) - return retval; - memset(dblist, 0, sizeof(struct ext2_struct_dblist)); - - dblist->magic = EXT2_ET_MAGIC_DBLIST; - dblist->fs = fs; - if (size) - dblist->size = size; - else { - retval = ext2fs_get_num_dirs(fs, &dblist->size); - if (retval) - goto cleanup; - dblist->size = (dblist->size * 2) + 12; - } - len = (size_t) sizeof(struct ext2_db_entry) * dblist->size; - dblist->count = count; - retval = ext2fs_get_mem(len, &dblist->list); - if (retval) - goto cleanup; - - if (list) - memcpy(dblist->list, list, len); - else - memset(dblist->list, 0, len); - if (ret_dblist) - *ret_dblist = dblist; - else - fs->dblist = dblist; - return 0; -cleanup: - ext2fs_free_mem(&dblist); - return retval; -} - -/* - * Initialize a directory block list - */ -errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist) -{ - ext2_dblist dblist; - errcode_t retval; - - retval = make_dblist(fs, 0, 0, 0, &dblist); - if (retval) - return retval; - - dblist->sorted = 1; - if (ret_dblist) - *ret_dblist = dblist; - else - fs->dblist = dblist; - - return 0; -} - -/* - * Copy a directory block list - */ -errcode_t ext2fs_copy_dblist(ext2_dblist src, ext2_dblist *dest) -{ - ext2_dblist dblist; - errcode_t retval; - - retval = make_dblist(src->fs, src->size, src->count, src->list, - &dblist); - if (retval) - return retval; - dblist->sorted = src->sorted; - *dest = dblist; - return 0; -} - -/* - * Close a directory block list - * - * (moved to closefs.c) - */ - - -/* - * Add a directory block to the directory block list - */ -errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk, - int blockcnt) -{ - struct ext2_db_entry *new_entry; - errcode_t retval; - unsigned long old_size; - - EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); - - if (dblist->count >= dblist->size) { - old_size = dblist->size * sizeof(struct ext2_db_entry); - dblist->size += 100; - retval = ext2fs_resize_mem(old_size, (size_t) dblist->size * - sizeof(struct ext2_db_entry), - &dblist->list); - if (retval) { - dblist->size -= 100; - return retval; - } - } - new_entry = dblist->list + ( (int) dblist->count++); - new_entry->blk = blk; - new_entry->ino = ino; - new_entry->blockcnt = blockcnt; - - dblist->sorted = 0; - - return 0; -} - -/* - * Change the directory block to the directory block list - */ -errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino, blk_t blk, - int blockcnt) -{ - dgrp_t i; - - EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); - - for (i=0; i < dblist->count; i++) { - if ((dblist->list[i].ino != ino) || - (dblist->list[i].blockcnt != blockcnt)) - continue; - dblist->list[i].blk = blk; - dblist->sorted = 0; - return 0; - } - return EXT2_ET_DB_NOT_FOUND; -} - -void ext2fs_dblist_sort(ext2_dblist dblist, - int (*sortfunc)(const void *, - const void *)) -{ - if (!sortfunc) - sortfunc = dir_block_cmp; - qsort(dblist->list, (size_t) dblist->count, - sizeof(struct ext2_db_entry), sortfunc); - dblist->sorted = 1; -} - -/* - * This function iterates over the directory block list - */ -errcode_t ext2fs_dblist_iterate(ext2_dblist dblist, - int (*func)(ext2_filsys fs, - struct ext2_db_entry *db_info, - void *priv_data), - void *priv_data) -{ - ext2_ino_t i; - int ret; - - EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); - - if (!dblist->sorted) - ext2fs_dblist_sort(dblist, 0); - for (i=0; i < dblist->count; i++) { - ret = (*func)(dblist->fs, &dblist->list[(int)i], priv_data); - if (ret & DBLIST_ABORT) - return 0; - } - return 0; -} - -static int dir_block_cmp(const void *a, const void *b) -{ - const struct ext2_db_entry *db_a = - (const struct ext2_db_entry *) a; - const struct ext2_db_entry *db_b = - (const struct ext2_db_entry *) b; - - if (db_a->blk != db_b->blk) - return (int) (db_a->blk - db_b->blk); - - if (db_a->ino != db_b->ino) - return (int) (db_a->ino - db_b->ino); - - return (int) (db_a->blockcnt - db_b->blockcnt); -} - -int ext2fs_dblist_count(ext2_dblist dblist) -{ - return (int) dblist->count; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * dblist_dir.c --- iterate by directory entry - * - * Copyright 1997 by Theodore Ts'o - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - * - */ - -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include - -#include "ext2_fs.h" -#include "ext2fsP.h" - -static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry *db_info, - void *priv_data); - -errcode_t ext2fs_dblist_dir_iterate(ext2_dblist dblist, - int flags, - char *block_buf, - int (*func)(ext2_ino_t dir, - int entry, - struct ext2_dir_entry *dirent, - int offset, - int blocksize, - char *buf, - void *priv_data), - void *priv_data) -{ - errcode_t retval; - struct dir_context ctx; - - EXT2_CHECK_MAGIC(dblist, EXT2_ET_MAGIC_DBLIST); - - ctx.dir = 0; - ctx.flags = flags; - if (block_buf) - ctx.buf = block_buf; - else { - retval = ext2fs_get_mem(dblist->fs->blocksize, &ctx.buf); - if (retval) - return retval; - } - ctx.func = func; - ctx.priv_data = priv_data; - ctx.errcode = 0; - - retval = ext2fs_dblist_iterate(dblist, db_dir_proc, &ctx); - - if (!block_buf) - ext2fs_free_mem(&ctx.buf); - if (retval) - return retval; - return ctx.errcode; -} - -static int db_dir_proc(ext2_filsys fs, struct ext2_db_entry *db_info, - void *priv_data) -{ - struct dir_context *ctx; - - ctx = (struct dir_context *) priv_data; - ctx->dir = db_info->ino; - - return ext2fs_process_dir_block(fs, &db_info->blk, - db_info->blockcnt, 0, 0, priv_data); -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * dir_iterate.c --- ext2fs directory iteration operations - * - * Copyright (C) 1993, 1994, 1994, 1995, 1996, 1997 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#if HAVE_ERRNO_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fsP.h" - -/* - * This function checks to see whether or not a potential deleted - * directory entry looks valid. What we do is check the deleted entry - * and each successive entry to make sure that they all look valid and - * that the last deleted entry ends at the beginning of the next - * undeleted entry. Returns 1 if the deleted entry looks valid, zero - * if not valid. - */ -static int ext2fs_validate_entry(char *buf, int offset, int final_offset) -{ - struct ext2_dir_entry *dirent; - - while (offset < final_offset) { - dirent = (struct ext2_dir_entry *)(buf + offset); - offset += dirent->rec_len; - if ((dirent->rec_len < 8) || - ((dirent->rec_len % 4) != 0) || - (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) - return 0; - } - return (offset == final_offset); -} - -errcode_t ext2fs_dir_iterate2(ext2_filsys fs, - ext2_ino_t dir, - int flags, - char *block_buf, - int (*func)(ext2_ino_t dir, - int entry, - struct ext2_dir_entry *dirent, - int offset, - int blocksize, - char *buf, - void *priv_data), - void *priv_data) -{ - struct dir_context ctx; - errcode_t retval; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - retval = ext2fs_check_directory(fs, dir); - if (retval) - return retval; - - ctx.dir = dir; - ctx.flags = flags; - if (block_buf) - ctx.buf = block_buf; - else { - retval = ext2fs_get_mem(fs->blocksize, &ctx.buf); - if (retval) - return retval; - } - ctx.func = func; - ctx.priv_data = priv_data; - ctx.errcode = 0; - retval = ext2fs_block_iterate2(fs, dir, 0, 0, - ext2fs_process_dir_block, &ctx); - if (!block_buf) - ext2fs_free_mem(&ctx.buf); - if (retval) - return retval; - return ctx.errcode; -} - -struct xlate { - int (*func)(struct ext2_dir_entry *dirent, - int offset, - int blocksize, - char *buf, - void *priv_data); - void *real_private; -}; - -static int xlate_func(ext2_ino_t dir EXT2FS_ATTR((unused)), - int entry EXT2FS_ATTR((unused)), - struct ext2_dir_entry *dirent, int offset, - int blocksize, char *buf, void *priv_data) -{ - struct xlate *xl = (struct xlate *) priv_data; - - return (*xl->func)(dirent, offset, blocksize, buf, xl->real_private); -} - -extern errcode_t ext2fs_dir_iterate(ext2_filsys fs, - ext2_ino_t dir, - int flags, - char *block_buf, - int (*func)(struct ext2_dir_entry *dirent, - int offset, - int blocksize, - char *buf, - void *priv_data), - void *priv_data) -{ - struct xlate xl; - - xl.real_private = priv_data; - xl.func = func; - - return ext2fs_dir_iterate2(fs, dir, flags, block_buf, - xlate_func, &xl); -} - - -/* - * Helper function which is private to this module. Used by - * ext2fs_dir_iterate() and ext2fs_dblist_dir_iterate() - */ -int ext2fs_process_dir_block(ext2_filsys fs, - blk_t *blocknr, - e2_blkcnt_t blockcnt, - blk_t ref_block EXT2FS_ATTR((unused)), - int ref_offset EXT2FS_ATTR((unused)), - void *priv_data) -{ - struct dir_context *ctx = (struct dir_context *) priv_data; - unsigned int offset = 0; - unsigned int next_real_entry = 0; - int ret = 0; - int changed = 0; - int do_abort = 0; - int entry, size; - struct ext2_dir_entry *dirent; - - if (blockcnt < 0) - return 0; - - entry = blockcnt ? DIRENT_OTHER_FILE : DIRENT_DOT_FILE; - - ctx->errcode = ext2fs_read_dir_block(fs, *blocknr, ctx->buf); - if (ctx->errcode) - return BLOCK_ABORT; - - while (offset < fs->blocksize) { - dirent = (struct ext2_dir_entry *) (ctx->buf + offset); - if (((offset + dirent->rec_len) > fs->blocksize) || - (dirent->rec_len < 8) || - ((dirent->rec_len % 4) != 0) || - (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) { - ctx->errcode = EXT2_ET_DIR_CORRUPTED; - return BLOCK_ABORT; - } - if (!dirent->inode && - !(ctx->flags & DIRENT_FLAG_INCLUDE_EMPTY)) - goto next; - - ret = (ctx->func)(ctx->dir, - (next_real_entry > offset) ? - DIRENT_DELETED_FILE : entry, - dirent, offset, - fs->blocksize, ctx->buf, - ctx->priv_data); - if (entry < DIRENT_OTHER_FILE) - entry++; - - if (ret & DIRENT_CHANGED) - changed++; - if (ret & DIRENT_ABORT) { - do_abort++; - break; - } -next: - if (next_real_entry == offset) - next_real_entry += dirent->rec_len; - - if (ctx->flags & DIRENT_FLAG_INCLUDE_REMOVED) { - size = ((dirent->name_len & 0xFF) + 11) & ~3; - - if (dirent->rec_len != size) { - unsigned int final_offset; - - final_offset = offset + dirent->rec_len; - offset += size; - while (offset < final_offset && - !ext2fs_validate_entry(ctx->buf, - offset, - final_offset)) - offset += 4; - continue; - } - } - offset += dirent->rec_len; - } - - if (changed) { - ctx->errcode = ext2fs_write_dir_block(fs, *blocknr, ctx->buf); - if (ctx->errcode) - return BLOCK_ABORT; - } - if (do_abort) - return BLOCK_ABORT; - return 0; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * dirblock.c --- directory block routines. - * - * Copyright (C) 1995, 1996 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include - -#include "ext2_fs.h" -#include "ext2fs.h" - -errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block, - void *buf, int flags EXT2FS_ATTR((unused))) -{ - errcode_t retval; - char *p, *end; - struct ext2_dir_entry *dirent; - unsigned int name_len, rec_len; -#if BB_BIG_ENDIAN - unsigned int do_swap; -#endif - - retval = io_channel_read_blk(fs->io, block, 1, buf); - if (retval) - return retval; -#if BB_BIG_ENDIAN - do_swap = (fs->flags & (EXT2_FLAG_SWAP_BYTES| - EXT2_FLAG_SWAP_BYTES_READ)) != 0; -#endif - p = (char *) buf; - end = (char *) buf + fs->blocksize; - while (p < end-8) { - dirent = (struct ext2_dir_entry *) p; -#if BB_BIG_ENDIAN - if (do_swap) { - dirent->inode = ext2fs_swab32(dirent->inode); - dirent->rec_len = ext2fs_swab16(dirent->rec_len); - dirent->name_len = ext2fs_swab16(dirent->name_len); - } -#endif - name_len = dirent->name_len; -#ifdef WORDS_BIGENDIAN - if (flags & EXT2_DIRBLOCK_V2_STRUCT) - dirent->name_len = ext2fs_swab16(dirent->name_len); -#endif - rec_len = dirent->rec_len; - if ((rec_len < 8) || (rec_len % 4)) { - rec_len = 8; - retval = EXT2_ET_DIR_CORRUPTED; - } - if (((name_len & 0xFF) + 8) > dirent->rec_len) - retval = EXT2_ET_DIR_CORRUPTED; - p += rec_len; - } - return retval; -} - -errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block, - void *buf) -{ - return ext2fs_read_dir_block2(fs, block, buf, 0); -} - - -errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block, - void *inbuf, int flags EXT2FS_ATTR((unused))) -{ -#if BB_BIG_ENDIAN - int do_swap = 0; - errcode_t retval; - char *p, *end; - char *buf = NULL; - struct ext2_dir_entry *dirent; - - if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || - (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)) - do_swap = 1; - -#ifndef WORDS_BIGENDIAN - if (!do_swap) - return io_channel_write_blk(fs->io, block, 1, (char *) inbuf); -#endif - - retval = ext2fs_get_mem(fs->blocksize, &buf); - if (retval) - return retval; - memcpy(buf, inbuf, fs->blocksize); - p = buf; - end = buf + fs->blocksize; - while (p < end) { - dirent = (struct ext2_dir_entry *) p; - if ((dirent->rec_len < 8) || - (dirent->rec_len % 4)) { - ext2fs_free_mem(&buf); - return EXT2_ET_DIR_CORRUPTED; - } - p += dirent->rec_len; - if (do_swap) { - dirent->inode = ext2fs_swab32(dirent->inode); - dirent->rec_len = ext2fs_swab16(dirent->rec_len); - dirent->name_len = ext2fs_swab16(dirent->name_len); - } -#ifdef WORDS_BIGENDIAN - if (flags & EXT2_DIRBLOCK_V2_STRUCT) - dirent->name_len = ext2fs_swab16(dirent->name_len); -#endif - } - retval = io_channel_write_blk(fs->io, block, 1, buf); - ext2fs_free_mem(&buf); - return retval; -#else - return io_channel_write_blk(fs->io, block, 1, (char *) inbuf); -#endif -} - - -errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block, - void *inbuf) -{ - return ext2fs_write_dir_block2(fs, block, inbuf, 0); -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * dirhash.c -- Calculate the hash of a directory entry - * - * Copyright (c) 2001 Daniel Phillips - * - * Copyright (c) 2002 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include - -#include "ext2_fs.h" -#include "ext2fs.h" - -/* - * Keyed 32-bit hash function using TEA in a Davis-Meyer function - * H0 = Key - * Hi = E Mi(Hi-1) + Hi-1 - * - * (see Applied Cryptography, 2nd edition, p448). - * - * Jeremy Fitzhardinge 1998 - * - * This code is made available under the terms of the GPL - */ -#define DELTA 0x9E3779B9 - -static void TEA_transform(__u32 buf[4], __u32 const in[]) -{ - __u32 sum = 0; - __u32 b0 = buf[0], b1 = buf[1]; - __u32 a = in[0], b = in[1], c = in[2], d = in[3]; - int n = 16; - - do { - sum += DELTA; - b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b); - b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d); - } while (--n); - - buf[0] += b0; - buf[1] += b1; -} - -/* F, G and H are basic MD4 functions: selection, majority, parity */ -#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) -#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z))) -#define H(x, y, z) ((x) ^ (y) ^ (z)) - -/* - * The generic round function. The application is so specific that - * we don't bother protecting all the arguments with parens, as is generally - * good macro practice, in favor of extra legibility. - * Rotation is separate from addition to prevent recomputation - */ -#define ROUND(f, a, b, c, d, x, s) \ - (a += f(b, c, d) + x, a = (a << s) | (a >> (32-s))) -#define K1 0 -#define K2 013240474631UL -#define K3 015666365641UL - -/* - * Basic cut-down MD4 transform. Returns only 32 bits of result. - */ -static void halfMD4Transform (__u32 buf[4], __u32 const in[]) -{ - __u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; - - /* Round 1 */ - ROUND(F, a, b, c, d, in[0] + K1, 3); - ROUND(F, d, a, b, c, in[1] + K1, 7); - ROUND(F, c, d, a, b, in[2] + K1, 11); - ROUND(F, b, c, d, a, in[3] + K1, 19); - ROUND(F, a, b, c, d, in[4] + K1, 3); - ROUND(F, d, a, b, c, in[5] + K1, 7); - ROUND(F, c, d, a, b, in[6] + K1, 11); - ROUND(F, b, c, d, a, in[7] + K1, 19); - - /* Round 2 */ - ROUND(G, a, b, c, d, in[1] + K2, 3); - ROUND(G, d, a, b, c, in[3] + K2, 5); - ROUND(G, c, d, a, b, in[5] + K2, 9); - ROUND(G, b, c, d, a, in[7] + K2, 13); - ROUND(G, a, b, c, d, in[0] + K2, 3); - ROUND(G, d, a, b, c, in[2] + K2, 5); - ROUND(G, c, d, a, b, in[4] + K2, 9); - ROUND(G, b, c, d, a, in[6] + K2, 13); - - /* Round 3 */ - ROUND(H, a, b, c, d, in[3] + K3, 3); - ROUND(H, d, a, b, c, in[7] + K3, 9); - ROUND(H, c, d, a, b, in[2] + K3, 11); - ROUND(H, b, c, d, a, in[6] + K3, 15); - ROUND(H, a, b, c, d, in[1] + K3, 3); - ROUND(H, d, a, b, c, in[5] + K3, 9); - ROUND(H, c, d, a, b, in[0] + K3, 11); - ROUND(H, b, c, d, a, in[4] + K3, 15); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} - -#undef ROUND -#undef F -#undef G -#undef H -#undef K1 -#undef K2 -#undef K3 - -/* The old legacy hash */ -static ext2_dirhash_t dx_hack_hash (const char *name, int len) -{ - __u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9; - while (len--) { - __u32 hash = hash1 + (hash0 ^ (*name++ * 7152373)); - - if (hash & 0x80000000) hash -= 0x7fffffff; - hash1 = hash0; - hash0 = hash; - } - return (hash0 << 1); -} - -static void str2hashbuf(const char *msg, int len, __u32 *buf, int num) -{ - __u32 pad, val; - int i; - - pad = (__u32)len | ((__u32)len << 8); - pad |= pad << 16; - - val = pad; - if (len > num*4) - len = num * 4; - for (i=0; i < len; i++) { - if ((i % 4) == 0) - val = pad; - val = msg[i] + (val << 8); - if ((i % 4) == 3) { - *buf++ = val; - val = pad; - num--; - } - } - if (--num >= 0) - *buf++ = val; - while (--num >= 0) - *buf++ = pad; -} - -/* - * Returns the hash of a filename. If len is 0 and name is NULL, then - * this function can be used to test whether or not a hash version is - * supported. - * - * The seed is an 4 longword (32 bits) "secret" which can be used to - * uniquify a hash. If the seed is all zero's, then some default seed - * may be used. - * - * A particular hash version specifies whether or not the seed is - * represented, and whether or not the returned hash is 32 bits or 64 - * bits. 32 bit hashes will return 0 for the minor hash. - */ -errcode_t ext2fs_dirhash(int version, const char *name, int len, - const __u32 *seed, - ext2_dirhash_t *ret_hash, - ext2_dirhash_t *ret_minor_hash) -{ - __u32 hash; - __u32 minor_hash = 0; - const char *p; - int i; - __u32 in[8], buf[4]; - - /* Initialize the default seed for the hash checksum functions */ - buf[0] = 0x67452301; - buf[1] = 0xefcdab89; - buf[2] = 0x98badcfe; - buf[3] = 0x10325476; - - /* Check to see if the seed is all zero's */ - if (seed) { - for (i=0; i < 4; i++) { - if (seed[i]) - break; - } - if (i < 4) - memcpy(buf, seed, sizeof(buf)); - } - - switch (version) { - case EXT2_HASH_LEGACY: - hash = dx_hack_hash(name, len); - break; - case EXT2_HASH_HALF_MD4: - p = name; - while (len > 0) { - str2hashbuf(p, len, in, 8); - halfMD4Transform(buf, in); - len -= 32; - p += 32; - } - minor_hash = buf[2]; - hash = buf[1]; - break; - case EXT2_HASH_TEA: - p = name; - while (len > 0) { - str2hashbuf(p, len, in, 4); - TEA_transform(buf, in); - len -= 16; - p += 16; - } - hash = buf[0]; - minor_hash = buf[1]; - break; - default: - *ret_hash = 0; - return EXT2_ET_DIRHASH_UNSUPP; - } - *ret_hash = hash & ~1; - if (ret_minor_hash) - *ret_minor_hash = minor_hash; - return 0; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * dupfs.c --- duplicate a ext2 filesystem handle - * - * Copyright (C) 1997, 1998, 2001, 2003, 2005 by Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include - -#include "ext2_fs.h" -#include "ext2fsP.h" - -errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest) -{ - ext2_filsys fs; - errcode_t retval; - - EXT2_CHECK_MAGIC(src, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs); - if (retval) - return retval; - - *fs = *src; - fs->device_name = 0; - fs->super = 0; - fs->orig_super = 0; - fs->group_desc = 0; - fs->inode_map = 0; - fs->block_map = 0; - fs->badblocks = 0; - fs->dblist = 0; - - io_channel_bumpcount(fs->io); - if (fs->icache) - fs->icache->refcount++; - - retval = ext2fs_get_mem(strlen(src->device_name)+1, &fs->device_name); - if (retval) - goto errout; - strcpy(fs->device_name, src->device_name); - - retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->super); - if (retval) - goto errout; - memcpy(fs->super, src->super, SUPERBLOCK_SIZE); - - retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super); - if (retval) - goto errout; - memcpy(fs->orig_super, src->orig_super, SUPERBLOCK_SIZE); - - retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize, - &fs->group_desc); - if (retval) - goto errout; - memcpy(fs->group_desc, src->group_desc, - (size_t) fs->desc_blocks * fs->blocksize); - - if (src->inode_map) { - retval = ext2fs_copy_bitmap(src->inode_map, &fs->inode_map); - if (retval) - goto errout; - } - if (src->block_map) { - retval = ext2fs_copy_bitmap(src->block_map, &fs->block_map); - if (retval) - goto errout; - } - if (src->badblocks) { - retval = ext2fs_badblocks_copy(src->badblocks, &fs->badblocks); - if (retval) - goto errout; - } - if (src->dblist) { - retval = ext2fs_copy_dblist(src->dblist, &fs->dblist); - if (retval) - goto errout; - } - *dest = fs; - return 0; -errout: - ext2fs_free(fs); - return retval; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * e2image.h --- header file describing the ext2 image format - * - * Copyright (C) 2000 Theodore Ts'o. - * - * Note: this uses the POSIX IO interfaces, unlike most of the other - * functions in this library. So sue me. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - - -struct ext2_image_hdr { - __u32 magic_number; /* This must be EXT2_ET_MAGIC_E2IMAGE */ - char magic_descriptor[16]; /* "Ext2 Image 1.0", w/ null padding */ - char fs_hostname[64];/* Hostname of machine of image */ - char fs_netaddr[32]; /* Network address */ - __u32 fs_netaddr_type;/* 0 = IPV4, 1 = IPV6, etc. */ - __u32 fs_device; /* Device number of image */ - char fs_device_name[64]; /* Device name */ - char fs_uuid[16]; /* UUID of filesystem */ - __u32 fs_blocksize; /* Block size of the filesystem */ - __u32 fs_reserved[8]; - - __u32 image_device; /* Device number of image file */ - __u32 image_inode; /* Inode number of image file */ - __u32 image_time; /* Time of image creation */ - __u32 image_reserved[8]; - - __u32 offset_super; /* Byte offset of the sb and descriptors */ - __u32 offset_inode; /* Byte offset of the inode table */ - __u32 offset_inodemap; /* Byte offset of the inode bitmaps */ - __u32 offset_blockmap; /* Byte offset of the inode bitmaps */ - __u32 offset_reserved[8]; -}; diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * expand.c --- expand an ext2fs directory - * - * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -struct expand_dir_struct { - int done; - int newblocks; - errcode_t err; -}; - -static int expand_dir_proc(ext2_filsys fs, - blk_t *blocknr, - e2_blkcnt_t blockcnt, - blk_t ref_block EXT2FS_ATTR((unused)), - int ref_offset EXT2FS_ATTR((unused)), - void *priv_data) -{ - struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data; - blk_t new_blk; - static blk_t last_blk = 0; - char *block; - errcode_t retval; - - if (*blocknr) { - last_blk = *blocknr; - return 0; - } - retval = ext2fs_new_block(fs, last_blk, 0, &new_blk); - if (retval) { - es->err = retval; - return BLOCK_ABORT; - } - if (blockcnt > 0) { - retval = ext2fs_new_dir_block(fs, 0, 0, &block); - if (retval) { - es->err = retval; - return BLOCK_ABORT; - } - es->done = 1; - retval = ext2fs_write_dir_block(fs, new_blk, block); - } else { - retval = ext2fs_get_mem(fs->blocksize, &block); - if (retval) { - es->err = retval; - return BLOCK_ABORT; - } - memset(block, 0, fs->blocksize); - retval = io_channel_write_blk(fs->io, new_blk, 1, block); - } - if (retval) { - es->err = retval; - return BLOCK_ABORT; - } - ext2fs_free_mem(&block); - *blocknr = new_blk; - ext2fs_block_alloc_stats(fs, new_blk, +1); - es->newblocks++; - - if (es->done) - return (BLOCK_CHANGED | BLOCK_ABORT); - else - return BLOCK_CHANGED; -} - -errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir) -{ - errcode_t retval; - struct expand_dir_struct es; - struct ext2_inode inode; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - if (!(fs->flags & EXT2_FLAG_RW)) - return EXT2_ET_RO_FILSYS; - - if (!fs->block_map) - return EXT2_ET_NO_BLOCK_BITMAP; - - retval = ext2fs_check_directory(fs, dir); - if (retval) - return retval; - - es.done = 0; - es.err = 0; - es.newblocks = 0; - - retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND, - 0, expand_dir_proc, &es); - - if (es.err) - return es.err; - if (!es.done) - return EXT2_ET_EXPAND_DIR_ERR; - - /* - * Update the size and block count fields in the inode. - */ - retval = ext2fs_read_inode(fs, dir, &inode); - if (retval) - return retval; - - inode.i_size += fs->blocksize; - inode.i_blocks += (fs->blocksize / 512) * es.newblocks; - - retval = ext2fs_write_inode(fs, dir, &inode); - if (retval) - return retval; - - return 0; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * ext2_err.h: - * This file is automatically generated; please do not edit it. - */ - -#define EXT2_ET_BASE (2133571328L) -#define EXT2_ET_MAGIC_EXT2FS_FILSYS (2133571329L) -#define EXT2_ET_MAGIC_BADBLOCKS_LIST (2133571330L) -#define EXT2_ET_MAGIC_BADBLOCKS_ITERATE (2133571331L) -#define EXT2_ET_MAGIC_INODE_SCAN (2133571332L) -#define EXT2_ET_MAGIC_IO_CHANNEL (2133571333L) -#define EXT2_ET_MAGIC_UNIX_IO_CHANNEL (2133571334L) -#define EXT2_ET_MAGIC_IO_MANAGER (2133571335L) -#define EXT2_ET_MAGIC_BLOCK_BITMAP (2133571336L) -#define EXT2_ET_MAGIC_INODE_BITMAP (2133571337L) -#define EXT2_ET_MAGIC_GENERIC_BITMAP (2133571338L) -#define EXT2_ET_MAGIC_TEST_IO_CHANNEL (2133571339L) -#define EXT2_ET_MAGIC_DBLIST (2133571340L) -#define EXT2_ET_MAGIC_ICOUNT (2133571341L) -#define EXT2_ET_MAGIC_PQ_IO_CHANNEL (2133571342L) -#define EXT2_ET_MAGIC_EXT2_FILE (2133571343L) -#define EXT2_ET_MAGIC_E2IMAGE (2133571344L) -#define EXT2_ET_MAGIC_INODE_IO_CHANNEL (2133571345L) -#define EXT2_ET_MAGIC_RESERVED_9 (2133571346L) -#define EXT2_ET_BAD_MAGIC (2133571347L) -#define EXT2_ET_REV_TOO_HIGH (2133571348L) -#define EXT2_ET_RO_FILSYS (2133571349L) -#define EXT2_ET_GDESC_READ (2133571350L) -#define EXT2_ET_GDESC_WRITE (2133571351L) -#define EXT2_ET_GDESC_BAD_BLOCK_MAP (2133571352L) -#define EXT2_ET_GDESC_BAD_INODE_MAP (2133571353L) -#define EXT2_ET_GDESC_BAD_INODE_TABLE (2133571354L) -#define EXT2_ET_INODE_BITMAP_WRITE (2133571355L) -#define EXT2_ET_INODE_BITMAP_READ (2133571356L) -#define EXT2_ET_BLOCK_BITMAP_WRITE (2133571357L) -#define EXT2_ET_BLOCK_BITMAP_READ (2133571358L) -#define EXT2_ET_INODE_TABLE_WRITE (2133571359L) -#define EXT2_ET_INODE_TABLE_READ (2133571360L) -#define EXT2_ET_NEXT_INODE_READ (2133571361L) -#define EXT2_ET_UNEXPECTED_BLOCK_SIZE (2133571362L) -#define EXT2_ET_DIR_CORRUPTED (2133571363L) -#define EXT2_ET_SHORT_READ (2133571364L) -#define EXT2_ET_SHORT_WRITE (2133571365L) -#define EXT2_ET_DIR_NO_SPACE (2133571366L) -#define EXT2_ET_NO_INODE_BITMAP (2133571367L) -#define EXT2_ET_NO_BLOCK_BITMAP (2133571368L) -#define EXT2_ET_BAD_INODE_NUM (2133571369L) -#define EXT2_ET_BAD_BLOCK_NUM (2133571370L) -#define EXT2_ET_EXPAND_DIR_ERR (2133571371L) -#define EXT2_ET_TOOSMALL (2133571372L) -#define EXT2_ET_BAD_BLOCK_MARK (2133571373L) -#define EXT2_ET_BAD_BLOCK_UNMARK (2133571374L) -#define EXT2_ET_BAD_BLOCK_TEST (2133571375L) -#define EXT2_ET_BAD_INODE_MARK (2133571376L) -#define EXT2_ET_BAD_INODE_UNMARK (2133571377L) -#define EXT2_ET_BAD_INODE_TEST (2133571378L) -#define EXT2_ET_FUDGE_BLOCK_BITMAP_END (2133571379L) -#define EXT2_ET_FUDGE_INODE_BITMAP_END (2133571380L) -#define EXT2_ET_BAD_IND_BLOCK (2133571381L) -#define EXT2_ET_BAD_DIND_BLOCK (2133571382L) -#define EXT2_ET_BAD_TIND_BLOCK (2133571383L) -#define EXT2_ET_NEQ_BLOCK_BITMAP (2133571384L) -#define EXT2_ET_NEQ_INODE_BITMAP (2133571385L) -#define EXT2_ET_BAD_DEVICE_NAME (2133571386L) -#define EXT2_ET_MISSING_INODE_TABLE (2133571387L) -#define EXT2_ET_CORRUPT_SUPERBLOCK (2133571388L) -#define EXT2_ET_BAD_GENERIC_MARK (2133571389L) -#define EXT2_ET_BAD_GENERIC_UNMARK (2133571390L) -#define EXT2_ET_BAD_GENERIC_TEST (2133571391L) -#define EXT2_ET_SYMLINK_LOOP (2133571392L) -#define EXT2_ET_CALLBACK_NOTHANDLED (2133571393L) -#define EXT2_ET_BAD_BLOCK_IN_INODE_TABLE (2133571394L) -#define EXT2_ET_UNSUPP_FEATURE (2133571395L) -#define EXT2_ET_RO_UNSUPP_FEATURE (2133571396L) -#define EXT2_ET_LLSEEK_FAILED (2133571397L) -#define EXT2_ET_NO_MEMORY (2133571398L) -#define EXT2_ET_INVALID_ARGUMENT (2133571399L) -#define EXT2_ET_BLOCK_ALLOC_FAIL (2133571400L) -#define EXT2_ET_INODE_ALLOC_FAIL (2133571401L) -#define EXT2_ET_NO_DIRECTORY (2133571402L) -#define EXT2_ET_TOO_MANY_REFS (2133571403L) -#define EXT2_ET_FILE_NOT_FOUND (2133571404L) -#define EXT2_ET_FILE_RO (2133571405L) -#define EXT2_ET_DB_NOT_FOUND (2133571406L) -#define EXT2_ET_DIR_EXISTS (2133571407L) -#define EXT2_ET_UNIMPLEMENTED (2133571408L) -#define EXT2_ET_CANCEL_REQUESTED (2133571409L) -#define EXT2_ET_FILE_TOO_BIG (2133571410L) -#define EXT2_ET_JOURNAL_NOT_BLOCK (2133571411L) -#define EXT2_ET_NO_JOURNAL_SB (2133571412L) -#define EXT2_ET_JOURNAL_TOO_SMALL (2133571413L) -#define EXT2_ET_JOURNAL_UNSUPP_VERSION (2133571414L) -#define EXT2_ET_LOAD_EXT_JOURNAL (2133571415L) -#define EXT2_ET_NO_JOURNAL (2133571416L) -#define EXT2_ET_DIRHASH_UNSUPP (2133571417L) -#define EXT2_ET_BAD_EA_BLOCK_NUM (2133571418L) -#define EXT2_ET_TOO_MANY_INODES (2133571419L) -#define EXT2_ET_NOT_IMAGE_FILE (2133571420L) -#define EXT2_ET_RES_GDT_BLOCKS (2133571421L) -#define EXT2_ET_RESIZE_INODE_CORRUPT (2133571422L) -#define EXT2_ET_SET_BMAP_NO_IND (2133571423L) - -#if 0 -extern const struct error_table et_ext2_error_table; -extern void initialize_ext2_error_table(void); - -/* For compatibility with Heimdal */ -extern void initialize_ext2_error_table_r(struct et_list **list); - -#define ERROR_TABLE_BASE_ext2 (2133571328L) - -/* for compatibility with older versions... */ -#define init_ext2_err_tbl initialize_ext2_error_table -#define ext2_err_base ERROR_TABLE_BASE_ext2 -#endif diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - File: linux/ext2_ext_attr.h - - On-disk format of extended attributes for the ext2 filesystem. - - (C) 2000 Andreas Gruenbacher, -*/ - -/* Magic value in attribute blocks */ -#define EXT2_EXT_ATTR_MAGIC_v1 0xEA010000 -#define EXT2_EXT_ATTR_MAGIC 0xEA020000 - -/* Maximum number of references to one attribute block */ -#define EXT2_EXT_ATTR_REFCOUNT_MAX 1024 - -struct ext2_ext_attr_header { - __u32 h_magic; /* magic number for identification */ - __u32 h_refcount; /* reference count */ - __u32 h_blocks; /* number of disk blocks used */ - __u32 h_hash; /* hash value of all attributes */ - __u32 h_reserved[4]; /* zero right now */ -}; - -struct ext2_ext_attr_entry { - __u8 e_name_len; /* length of name */ - __u8 e_name_index; /* attribute name index */ - __u16 e_value_offs; /* offset in disk block of value */ - __u32 e_value_block; /* disk block attribute is stored on (n/i) */ - __u32 e_value_size; /* size of attribute value */ - __u32 e_hash; /* hash value of name and value */ -}; - -#define EXT2_EXT_ATTR_PAD_BITS 2 -#define EXT2_EXT_ATTR_PAD (1<e_name_len)) ) -#define EXT2_EXT_ATTR_SIZE(size) \ - (((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND) -#define EXT2_EXT_IS_LAST_ENTRY(entry) (*((__u32 *)(entry)) == 0UL) -#define EXT2_EXT_ATTR_NAME(entry) \ - (((char *) (entry)) + sizeof(struct ext2_ext_attr_entry)) -#define EXT2_XATTR_LEN(name_len) \ - (((name_len) + EXT2_EXT_ATTR_ROUND + \ - sizeof(struct ext2_xattr_entry)) & ~EXT2_EXT_ATTR_ROUND) -#define EXT2_XATTR_SIZE(size) \ - (((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND) diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * linux/include/linux/ext2_fs.h - * - * Copyright (C) 1992, 1993, 1994, 1995 - * Remy Card (card@masi.ibp.fr) - * Laboratoire MASI - Institut Blaise Pascal - * Universite Pierre et Marie Curie (Paris VI) - * - * from - * - * linux/include/linux/minix_fs.h - * - * Copyright (C) 1991, 1992 Linus Torvalds - */ -#ifndef LINUX_EXT2_FS_H -#define LINUX_EXT2_FS_H 1 - -#include "ext2_types.h" /* Changed from linux/types.h */ - -/* - * Special inode numbers - */ -#define EXT2_BAD_INO 1 /* Bad blocks inode */ -#define EXT2_ROOT_INO 2 /* Root inode */ -#define EXT2_ACL_IDX_INO 3 /* ACL inode */ -#define EXT2_ACL_DATA_INO 4 /* ACL inode */ -#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */ -#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */ -#define EXT2_RESIZE_INO 7 /* Reserved group descriptors inode */ -#define EXT2_JOURNAL_INO 8 /* Journal inode */ - -/* First non-reserved inode for old ext2 filesystems */ -#define EXT2_GOOD_OLD_FIRST_INO 11 - -/* - * The second extended file system magic number - */ -#define EXT2_SUPER_MAGIC 0xEF53 - -/* Assume that user mode programs are passing in an ext2fs superblock, not - * a kernel struct super_block. This will allow us to call the feature-test - * macros from user land. */ -#define EXT2_SB(sb) (sb) - -/* - * Maximal count of links to a file - */ -#define EXT2_LINK_MAX 32000 - -/* - * Macro-instructions used to manage several block sizes - */ -#define EXT2_MIN_BLOCK_LOG_SIZE 10 /* 1024 */ -#define EXT2_MAX_BLOCK_LOG_SIZE 16 /* 65536 */ -#define EXT2_MIN_BLOCK_SIZE (1 << EXT2_MIN_BLOCK_LOG_SIZE) -#define EXT2_MAX_BLOCK_SIZE (1 << EXT2_MAX_BLOCK_LOG_SIZE) -#define EXT2_BLOCK_SIZE(s) (EXT2_MIN_BLOCK_SIZE << (s)->s_log_block_size) -#define EXT2_BLOCK_SIZE_BITS(s) ((s)->s_log_block_size + 10) -#define EXT2_INODE_SIZE(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \ - EXT2_GOOD_OLD_INODE_SIZE : (s)->s_inode_size) -#define EXT2_FIRST_INO(s) (((s)->s_rev_level == EXT2_GOOD_OLD_REV) ? \ - EXT2_GOOD_OLD_FIRST_INO : (s)->s_first_ino) -#define EXT2_ADDR_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof(__u32)) - -/* - * Macro-instructions used to manage fragments - */ -#define EXT2_MIN_FRAG_SIZE EXT2_MIN_BLOCK_SIZE -#define EXT2_MAX_FRAG_SIZE EXT2_MAX_BLOCK_SIZE -#define EXT2_MIN_FRAG_LOG_SIZE EXT2_MIN_BLOCK_LOG_SIZE -# define EXT2_FRAG_SIZE(s) (EXT2_MIN_FRAG_SIZE << (s)->s_log_frag_size) -# define EXT2_FRAGS_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / EXT2_FRAG_SIZE(s)) - -/* - * ACL structures - */ -struct ext2_acl_header /* Header of Access Control Lists */ -{ - __u32 aclh_size; - __u32 aclh_file_count; - __u32 aclh_acle_count; - __u32 aclh_first_acle; -}; - -struct ext2_acl_entry /* Access Control List Entry */ -{ - __u32 acle_size; - __u16 acle_perms; /* Access permissions */ - __u16 acle_type; /* Type of entry */ - __u16 acle_tag; /* User or group identity */ - __u16 acle_pad1; - __u32 acle_next; /* Pointer on next entry for the */ - /* same inode or on next free entry */ -}; - -/* - * Structure of a blocks group descriptor - */ -struct ext2_group_desc -{ - __u32 bg_block_bitmap; /* Blocks bitmap block */ - __u32 bg_inode_bitmap; /* Inodes bitmap block */ - __u32 bg_inode_table; /* Inodes table block */ - __u16 bg_free_blocks_count; /* Free blocks count */ - __u16 bg_free_inodes_count; /* Free inodes count */ - __u16 bg_used_dirs_count; /* Directories count */ - __u16 bg_pad; - __u32 bg_reserved[3]; -}; - -/* - * Data structures used by the directory indexing feature - * - * Note: all of the multibyte integer fields are little endian. - */ - -/* - * Note: dx_root_info is laid out so that if it should somehow get - * overlaid by a dirent the two low bits of the hash version will be - * zero. Therefore, the hash version mod 4 should never be 0. - * Sincerely, the paranoia department. - */ -struct ext2_dx_root_info { - __u32 reserved_zero; - __u8 hash_version; /* 0 now, 1 at release */ - __u8 info_length; /* 8 */ - __u8 indirect_levels; - __u8 unused_flags; -}; - -#define EXT2_HASH_LEGACY 0 -#define EXT2_HASH_HALF_MD4 1 -#define EXT2_HASH_TEA 2 - -#define EXT2_HASH_FLAG_INCOMPAT 0x1 - -struct ext2_dx_entry { - __u32 hash; - __u32 block; -}; - -struct ext2_dx_countlimit { - __u16 limit; - __u16 count; -}; - - -/* - * Macro-instructions used to manage group descriptors - */ -#define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->s_blocks_per_group) -#define EXT2_INODES_PER_GROUP(s) (EXT2_SB(s)->s_inodes_per_group) -#define EXT2_INODES_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s)/EXT2_INODE_SIZE(s)) -/* limits imposed by 16-bit value gd_free_{blocks,inode}_count */ -#define EXT2_MAX_BLOCKS_PER_GROUP(s) ((1 << 16) - 8) -#define EXT2_MAX_INODES_PER_GROUP(s) ((1 << 16) - EXT2_INODES_PER_BLOCK(s)) -#define EXT2_DESC_PER_BLOCK(s) (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc)) - -/* - * Constants relative to the data blocks - */ -#define EXT2_NDIR_BLOCKS 12 -#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS -#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1) -#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1) -#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1) - -/* - * Inode flags - */ -#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */ -#define EXT2_UNRM_FL 0x00000002 /* Undelete */ -#define EXT2_COMPR_FL 0x00000004 /* Compress file */ -#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */ -#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */ -#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */ -#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */ -#define EXT2_NOATIME_FL 0x00000080 /* do not update atime */ -/* Reserved for compression usage... */ -#define EXT2_DIRTY_FL 0x00000100 -#define EXT2_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */ -#define EXT2_NOCOMPR_FL 0x00000400 /* Access raw compressed data */ -#define EXT2_ECOMPR_FL 0x00000800 /* Compression error */ -/* End compression flags --- maybe not all used */ -#define EXT2_BTREE_FL 0x00001000 /* btree format dir */ -#define EXT2_INDEX_FL 0x00001000 /* hash-indexed directory */ -#define EXT2_IMAGIC_FL 0x00002000 -#define EXT3_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */ -#define EXT2_NOTAIL_FL 0x00008000 /* file tail should not be merged */ -#define EXT2_DIRSYNC_FL 0x00010000 /* Synchronous directory modifications */ -#define EXT2_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/ -#define EXT3_EXTENTS_FL 0x00080000 /* Inode uses extents */ -#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */ - -#define EXT2_FL_USER_VISIBLE 0x0003DFFF /* User visible flags */ -#define EXT2_FL_USER_MODIFIABLE 0x000080FF /* User modifiable flags */ - -/* - * ioctl commands - */ -#define EXT2_IOC_GETFLAGS _IOR('f', 1, long) -#define EXT2_IOC_SETFLAGS _IOW('f', 2, long) -#define EXT2_IOC_GETVERSION _IOR('v', 1, long) -#define EXT2_IOC_SETVERSION _IOW('v', 2, long) - -/* - * Structure of an inode on the disk - */ -struct ext2_inode { - __u16 i_mode; /* File mode */ - __u16 i_uid; /* Low 16 bits of Owner Uid */ - __u32 i_size; /* Size in bytes */ - __u32 i_atime; /* Access time */ - __u32 i_ctime; /* Creation time */ - __u32 i_mtime; /* Modification time */ - __u32 i_dtime; /* Deletion Time */ - __u16 i_gid; /* Low 16 bits of Group Id */ - __u16 i_links_count; /* Links count */ - __u32 i_blocks; /* Blocks count */ - __u32 i_flags; /* File flags */ - union { - struct { - __u32 l_i_reserved1; - } linux1; - struct { - __u32 h_i_translator; - } hurd1; - struct { - __u32 m_i_reserved1; - } masix1; - } osd1; /* OS dependent 1 */ - __u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ - __u32 i_generation; /* File version (for NFS) */ - __u32 i_file_acl; /* File ACL */ - __u32 i_dir_acl; /* Directory ACL */ - __u32 i_faddr; /* Fragment address */ - union { - struct { - __u8 l_i_frag; /* Fragment number */ - __u8 l_i_fsize; /* Fragment size */ - __u16 i_pad1; - __u16 l_i_uid_high; /* these 2 fields */ - __u16 l_i_gid_high; /* were reserved2[0] */ - __u32 l_i_reserved2; - } linux2; - struct { - __u8 h_i_frag; /* Fragment number */ - __u8 h_i_fsize; /* Fragment size */ - __u16 h_i_mode_high; - __u16 h_i_uid_high; - __u16 h_i_gid_high; - __u32 h_i_author; - } hurd2; - struct { - __u8 m_i_frag; /* Fragment number */ - __u8 m_i_fsize; /* Fragment size */ - __u16 m_pad1; - __u32 m_i_reserved2[2]; - } masix2; - } osd2; /* OS dependent 2 */ -}; - -/* - * Permanent part of an large inode on the disk - */ -struct ext2_inode_large { - __u16 i_mode; /* File mode */ - __u16 i_uid; /* Low 16 bits of Owner Uid */ - __u32 i_size; /* Size in bytes */ - __u32 i_atime; /* Access time */ - __u32 i_ctime; /* Creation time */ - __u32 i_mtime; /* Modification time */ - __u32 i_dtime; /* Deletion Time */ - __u16 i_gid; /* Low 16 bits of Group Id */ - __u16 i_links_count; /* Links count */ - __u32 i_blocks; /* Blocks count */ - __u32 i_flags; /* File flags */ - union { - struct { - __u32 l_i_reserved1; - } linux1; - struct { - __u32 h_i_translator; - } hurd1; - struct { - __u32 m_i_reserved1; - } masix1; - } osd1; /* OS dependent 1 */ - __u32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ - __u32 i_generation; /* File version (for NFS) */ - __u32 i_file_acl; /* File ACL */ - __u32 i_dir_acl; /* Directory ACL */ - __u32 i_faddr; /* Fragment address */ - union { - struct { - __u8 l_i_frag; /* Fragment number */ - __u8 l_i_fsize; /* Fragment size */ - __u16 i_pad1; - __u16 l_i_uid_high; /* these 2 fields */ - __u16 l_i_gid_high; /* were reserved2[0] */ - __u32 l_i_reserved2; - } linux2; - struct { - __u8 h_i_frag; /* Fragment number */ - __u8 h_i_fsize; /* Fragment size */ - __u16 h_i_mode_high; - __u16 h_i_uid_high; - __u16 h_i_gid_high; - __u32 h_i_author; - } hurd2; - struct { - __u8 m_i_frag; /* Fragment number */ - __u8 m_i_fsize; /* Fragment size */ - __u16 m_pad1; - __u32 m_i_reserved2[2]; - } masix2; - } osd2; /* OS dependent 2 */ - __u16 i_extra_isize; - __u16 i_pad1; -}; - -#define i_size_high i_dir_acl - -/* - * File system states - */ -#define EXT2_VALID_FS 0x0001 /* Unmounted cleanly */ -#define EXT2_ERROR_FS 0x0002 /* Errors detected */ - -/* - * Mount flags - */ -#define EXT2_MOUNT_CHECK 0x0001 /* Do mount-time checks */ -#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */ -#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */ -#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */ -#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */ -#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */ -#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */ -#define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */ - -#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt -#define set_opt(o, opt) o |= EXT2_MOUNT_##opt -#define test_opt(sb, opt) (EXT2_SB(sb)->s_mount_opt & \ - EXT2_MOUNT_##opt) -/* - * Maximal mount counts between two filesystem checks - */ -#define EXT2_DFL_MAX_MNT_COUNT 20 /* Allow 20 mounts */ -#define EXT2_DFL_CHECKINTERVAL 0 /* Don't use interval check */ - -/* - * Behaviour when detecting errors - */ -#define EXT2_ERRORS_CONTINUE 1 /* Continue execution */ -#define EXT2_ERRORS_RO 2 /* Remount fs read-only */ -#define EXT2_ERRORS_PANIC 3 /* Panic */ -#define EXT2_ERRORS_DEFAULT EXT2_ERRORS_CONTINUE - -/* - * Structure of the super block - */ -struct ext2_super_block { - __u32 s_inodes_count; /* Inodes count */ - __u32 s_blocks_count; /* Blocks count */ - __u32 s_r_blocks_count; /* Reserved blocks count */ - __u32 s_free_blocks_count; /* Free blocks count */ - __u32 s_free_inodes_count; /* Free inodes count */ - __u32 s_first_data_block; /* First Data Block */ - __u32 s_log_block_size; /* Block size */ - __s32 s_log_frag_size; /* Fragment size */ - __u32 s_blocks_per_group; /* # Blocks per group */ - __u32 s_frags_per_group; /* # Fragments per group */ - __u32 s_inodes_per_group; /* # Inodes per group */ - __u32 s_mtime; /* Mount time */ - __u32 s_wtime; /* Write time */ - __u16 s_mnt_count; /* Mount count */ - __s16 s_max_mnt_count; /* Maximal mount count */ - __u16 s_magic; /* Magic signature */ - __u16 s_state; /* File system state */ - __u16 s_errors; /* Behaviour when detecting errors */ - __u16 s_minor_rev_level; /* minor revision level */ - __u32 s_lastcheck; /* time of last check */ - __u32 s_checkinterval; /* max. time between checks */ - __u32 s_creator_os; /* OS */ - __u32 s_rev_level; /* Revision level */ - __u16 s_def_resuid; /* Default uid for reserved blocks */ - __u16 s_def_resgid; /* Default gid for reserved blocks */ - /* - * These fields are for EXT2_DYNAMIC_REV superblocks only. - * - * Note: the difference between the compatible feature set and - * the incompatible feature set is that if there is a bit set - * in the incompatible feature set that the kernel doesn't - * know about, it should refuse to mount the filesystem. - * - * e2fsck's requirements are more strict; if it doesn't know - * about a feature in either the compatible or incompatible - * feature set, it must abort and not try to meddle with - * things it doesn't understand... - */ - __u32 s_first_ino; /* First non-reserved inode */ - __u16 s_inode_size; /* size of inode structure */ - __u16 s_block_group_nr; /* block group # of this superblock */ - __u32 s_feature_compat; /* compatible feature set */ - __u32 s_feature_incompat; /* incompatible feature set */ - __u32 s_feature_ro_compat; /* readonly-compatible feature set */ - __u8 s_uuid[16]; /* 128-bit uuid for volume */ - char s_volume_name[16]; /* volume name */ - char s_last_mounted[64]; /* directory where last mounted */ - __u32 s_algorithm_usage_bitmap; /* For compression */ - /* - * Performance hints. Directory preallocation should only - * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on. - */ - __u8 s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ - __u8 s_prealloc_dir_blocks; /* Nr to preallocate for dirs */ - __u16 s_reserved_gdt_blocks; /* Per group table for online growth */ - /* - * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set. - */ - __u8 s_journal_uuid[16]; /* uuid of journal superblock */ - __u32 s_journal_inum; /* inode number of journal file */ - __u32 s_journal_dev; /* device number of journal file */ - __u32 s_last_orphan; /* start of list of inodes to delete */ - __u32 s_hash_seed[4]; /* HTREE hash seed */ - __u8 s_def_hash_version; /* Default hash version to use */ - __u8 s_jnl_backup_type; /* Default type of journal backup */ - __u16 s_reserved_word_pad; - __u32 s_default_mount_opts; - __u32 s_first_meta_bg; /* First metablock group */ - __u32 s_mkfs_time; /* When the filesystem was created */ - __u32 s_jnl_blocks[17]; /* Backup of the journal inode */ - __u32 s_reserved[172]; /* Padding to the end of the block */ -}; - -/* - * Codes for operating systems - */ -#define EXT2_OS_LINUX 0 -#define EXT2_OS_HURD 1 -#define EXT2_OS_MASIX 2 -#define EXT2_OS_FREEBSD 3 -#define EXT2_OS_LITES 4 - -/* - * Revision levels - */ -#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */ -#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */ - -#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV -#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV - -#define EXT2_GOOD_OLD_INODE_SIZE 128 - -/* - * Journal inode backup types - */ -#define EXT3_JNL_BACKUP_BLOCKS 1 - -/* - * Feature set definitions - */ - -#define EXT2_HAS_COMPAT_FEATURE(sb,mask) \ - ( EXT2_SB(sb)->s_feature_compat & (mask) ) -#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask) \ - ( EXT2_SB(sb)->s_feature_ro_compat & (mask) ) -#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask) \ - ( EXT2_SB(sb)->s_feature_incompat & (mask) ) - -#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001 -#define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002 -#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004 -#define EXT2_FEATURE_COMPAT_EXT_ATTR 0x0008 -#define EXT2_FEATURE_COMPAT_RESIZE_INO 0x0010 -#define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020 - -#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 -#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 -/* #define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 not used */ - -#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001 -#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 -#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 /* Needs recovery */ -#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 /* Journal device */ -#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 -#define EXT3_FEATURE_INCOMPAT_EXTENTS 0x0040 - - -#define EXT2_FEATURE_COMPAT_SUPP 0 -#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE) -#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ - EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ - EXT2_FEATURE_RO_COMPAT_BTREE_DIR) - -/* - * Default values for user and/or group using reserved blocks - */ -#define EXT2_DEF_RESUID 0 -#define EXT2_DEF_RESGID 0 - -/* - * Default mount options - */ -#define EXT2_DEFM_DEBUG 0x0001 -#define EXT2_DEFM_BSDGROUPS 0x0002 -#define EXT2_DEFM_XATTR_USER 0x0004 -#define EXT2_DEFM_ACL 0x0008 -#define EXT2_DEFM_UID16 0x0010 -#define EXT3_DEFM_JMODE 0x0060 -#define EXT3_DEFM_JMODE_DATA 0x0020 -#define EXT3_DEFM_JMODE_ORDERED 0x0040 -#define EXT3_DEFM_JMODE_WBACK 0x0060 - -/* - * Structure of a directory entry - */ -#define EXT2_NAME_LEN 255 - -struct ext2_dir_entry { - __u32 inode; /* Inode number */ - __u16 rec_len; /* Directory entry length */ - __u16 name_len; /* Name length */ - char name[EXT2_NAME_LEN]; /* File name */ -}; - -/* - * The new version of the directory entry. Since EXT2 structures are - * stored in intel byte order, and the name_len field could never be - * bigger than 255 chars, it's safe to reclaim the extra byte for the - * file_type field. - */ -struct ext2_dir_entry_2 { - __u32 inode; /* Inode number */ - __u16 rec_len; /* Directory entry length */ - __u8 name_len; /* Name length */ - __u8 file_type; - char name[EXT2_NAME_LEN]; /* File name */ -}; - -/* - * Ext2 directory file types. Only the low 3 bits are used. The - * other bits are reserved for now. - */ -#define EXT2_FT_UNKNOWN 0 -#define EXT2_FT_REG_FILE 1 -#define EXT2_FT_DIR 2 -#define EXT2_FT_CHRDEV 3 -#define EXT2_FT_BLKDEV 4 -#define EXT2_FT_FIFO 5 -#define EXT2_FT_SOCK 6 -#define EXT2_FT_SYMLINK 7 - -#define EXT2_FT_MAX 8 - -/* - * EXT2_DIR_PAD defines the directory entries boundaries - * - * NOTE: It must be a multiple of 4 - */ -#define EXT2_DIR_PAD 4 -#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1) -#define EXT2_DIR_REC_LEN(name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \ - ~EXT2_DIR_ROUND) - -#endif diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * io.h --- the I/O manager abstraction - * - * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ -#ifndef EXT2FS_EXT2_IO_H -#define EXT2FS_EXT2_IO_H 1 - -/* - * ext2_loff_t is defined here since unix_io.c needs it. - */ -#if defined(__GNUC__) || defined(HAS_LONG_LONG) -typedef long long ext2_loff_t; -#else -typedef long ext2_loff_t; -#endif - -/* llseek.c */ -/* ext2_loff_t ext2fs_llseek (int, ext2_loff_t, int); */ -#ifdef CONFIG_LFS -# define ext2fs_llseek lseek64 -#else -# define ext2fs_llseek lseek -#endif - -typedef struct struct_io_manager *io_manager; -typedef struct struct_io_channel *io_channel; - -#define CHANNEL_FLAGS_WRITETHROUGH 0x01 - -struct struct_io_channel { - errcode_t magic; - io_manager manager; - char *name; - int block_size; - errcode_t (*read_error)(io_channel channel, - unsigned long block, - int count, - void *data, - size_t size, - int actual_bytes_read, - errcode_t error); - errcode_t (*write_error)(io_channel channel, - unsigned long block, - int count, - const void *data, - size_t size, - int actual_bytes_written, - errcode_t error); - int refcount; - int flags; - int reserved[14]; - void *private_data; - void *app_data; -}; - -struct struct_io_manager { - errcode_t magic; - const char *name; - errcode_t (*open)(const char *name, int flags, io_channel *channel); - errcode_t (*close)(io_channel channel); - errcode_t (*set_blksize)(io_channel channel, int blksize); - errcode_t (*read_blk)(io_channel channel, unsigned long block, - int count, void *data); - errcode_t (*write_blk)(io_channel channel, unsigned long block, - int count, const void *data); - errcode_t (*flush)(io_channel channel); - errcode_t (*write_byte)(io_channel channel, unsigned long offset, - int count, const void *data); - errcode_t (*set_option)(io_channel channel, const char *option, - const char *arg); - int reserved[14]; -}; - -#define IO_FLAG_RW 1 - -/* - * Convenience functions.... - */ -#define io_channel_close(c) ((c)->manager->close((c))) -#define io_channel_set_blksize(c,s) ((c)->manager->set_blksize((c),s)) -#define io_channel_read_blk(c,b,n,d) ((c)->manager->read_blk((c),b,n,d)) -#define io_channel_write_blk(c,b,n,d) ((c)->manager->write_blk((c),b,n,d)) -#define io_channel_flush(c) ((c)->manager->flush((c))) -#define io_channel_bumpcount(c) ((c)->refcount++) - -/* io_manager.c */ -extern errcode_t io_channel_set_options(io_channel channel, - const char *options); -extern errcode_t io_channel_write_byte(io_channel channel, - unsigned long offset, - int count, const void *data); - -/* unix_io.c */ -extern io_manager unix_io_manager; - -/* test_io.c */ -extern io_manager test_io_manager, test_io_backing_manager; -extern void (*test_io_cb_read_blk) - (unsigned long block, int count, errcode_t err); -extern void (*test_io_cb_write_blk) - (unsigned long block, int count, errcode_t err); -extern void (*test_io_cb_set_blksize) - (int blksize, errcode_t err); - -#endif diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -#include 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 @@ -/* vi: set sw=4 ts=4: */ -/* - * ext2fs.h --- ext2fs - * - * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ -#ifndef EXT2FS_EXT2FS_H -#define EXT2FS_EXT2FS_H 1 - - -#define EXT2FS_ATTR(x) - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Where the master copy of the superblock is located, and how big - * superblocks are supposed to be. We define SUPERBLOCK_SIZE because - * the size of the superblock structure is not necessarily trustworthy - * (some versions have the padding set up so that the superblock is - * 1032 bytes long). - */ -#define SUPERBLOCK_OFFSET 1024 -#define SUPERBLOCK_SIZE 1024 - -/* - * The last ext2fs revision level that this version of the library is - * able to support. - */ -#define EXT2_LIB_CURRENT_REV EXT2_DYNAMIC_REV - -#ifdef HAVE_SYS_TYPES_H -#include -#endif - -#include -#include - -#include "ext2_types.h" -#include "ext2_fs.h" - -typedef __u32 ext2_ino_t; -typedef __u32 blk_t; -typedef __u32 dgrp_t; -typedef __u32 ext2_off_t; -typedef __s64 e2_blkcnt_t; -typedef __u32 ext2_dirhash_t; - -#include "ext2_io.h" -#include "ext2_err.h" - -typedef struct struct_ext2_filsys *ext2_filsys; - -struct ext2fs_struct_generic_bitmap { - errcode_t magic; - ext2_filsys fs; - __u32 start, end; - __u32 real_end; - char * description; - char * bitmap; - errcode_t base_error_code; - __u32 reserved[7]; -}; - -#define EXT2FS_MARK_ERROR 0 -#define EXT2FS_UNMARK_ERROR 1 -#define EXT2FS_TEST_ERROR 2 - -typedef struct ext2fs_struct_generic_bitmap *ext2fs_generic_bitmap; -typedef struct ext2fs_struct_generic_bitmap *ext2fs_inode_bitmap; -typedef struct ext2fs_struct_generic_bitmap *ext2fs_block_bitmap; - -#define EXT2_FIRST_INODE(s) EXT2_FIRST_INO(s) - -/* - * badblocks list definitions - */ - -typedef struct ext2_struct_u32_list *ext2_badblocks_list; -typedef struct ext2_struct_u32_iterate *ext2_badblocks_iterate; - -typedef struct ext2_struct_u32_list *ext2_u32_list; -typedef struct ext2_struct_u32_iterate *ext2_u32_iterate; - -/* old */ -typedef struct ext2_struct_u32_list *badblocks_list; -typedef struct ext2_struct_u32_iterate *badblocks_iterate; - -#define BADBLOCKS_FLAG_DIRTY 1 - -/* - * ext2_dblist structure and abstractions (see dblist.c) - */ -struct ext2_db_entry { - ext2_ino_t ino; - blk_t blk; - int blockcnt; -}; - -typedef struct ext2_struct_dblist *ext2_dblist; - -#define DBLIST_ABORT 1 - -/* - * ext2_fileio definitions - */ - -#define EXT2_FILE_WRITE 0x0001 -#define EXT2_FILE_CREATE 0x0002 - -#define EXT2_FILE_MASK 0x00FF - -#define EXT2_FILE_BUF_DIRTY 0x4000 -#define EXT2_FILE_BUF_VALID 0x2000 - -typedef struct ext2_file *ext2_file_t; - -#define EXT2_SEEK_SET 0 -#define EXT2_SEEK_CUR 1 -#define EXT2_SEEK_END 2 - -/* - * Flags for the ext2_filsys structure and for ext2fs_open() - */ -#define EXT2_FLAG_RW 0x01 -#define EXT2_FLAG_CHANGED 0x02 -#define EXT2_FLAG_DIRTY 0x04 -#define EXT2_FLAG_VALID 0x08 -#define EXT2_FLAG_IB_DIRTY 0x10 -#define EXT2_FLAG_BB_DIRTY 0x20 -#define EXT2_FLAG_SWAP_BYTES 0x40 -#define EXT2_FLAG_SWAP_BYTES_READ 0x80 -#define EXT2_FLAG_SWAP_BYTES_WRITE 0x100 -#define EXT2_FLAG_MASTER_SB_ONLY 0x200 -#define EXT2_FLAG_FORCE 0x400 -#define EXT2_FLAG_SUPER_ONLY 0x800 -#define EXT2_FLAG_JOURNAL_DEV_OK 0x1000 -#define EXT2_FLAG_IMAGE_FILE 0x2000 - -/* - * Special flag in the ext2 inode i_flag field that means that this is - * a new inode. (So that ext2_write_inode() can clear extra fields.) - */ -#define EXT2_NEW_INODE_FL 0x80000000 - -/* - * Flags for mkjournal - * - * EXT2_MKJOURNAL_V1_SUPER Make a (deprecated) V1 journal superblock - */ -#define EXT2_MKJOURNAL_V1_SUPER 0x0000001 - -struct struct_ext2_filsys { - errcode_t magic; - io_channel io; - int flags; - char * device_name; - struct ext2_super_block * super; - unsigned int blocksize; - int fragsize; - dgrp_t group_desc_count; - unsigned long desc_blocks; - struct ext2_group_desc * group_desc; - int inode_blocks_per_group; - ext2fs_inode_bitmap inode_map; - ext2fs_block_bitmap block_map; - errcode_t (*get_blocks)(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks); - errcode_t (*check_directory)(ext2_filsys fs, ext2_ino_t ino); - errcode_t (*write_bitmaps)(ext2_filsys fs); - errcode_t (*read_inode)(ext2_filsys fs, ext2_ino_t ino, - struct ext2_inode *inode); - errcode_t (*write_inode)(ext2_filsys fs, ext2_ino_t ino, - struct ext2_inode *inode); - ext2_badblocks_list badblocks; - ext2_dblist dblist; - __u32 stride; /* for mke2fs */ - struct ext2_super_block * orig_super; - struct ext2_image_hdr * image_header; - __u32 umask; - /* - * Reserved for future expansion - */ - __u32 reserved[8]; - - /* - * Reserved for the use of the calling application. - */ - void * priv_data; - - /* - * Inode cache - */ - struct ext2_inode_cache *icache; - io_channel image_io; -}; - -#include "bitops.h" - -/* - * Return flags for the block iterator functions - */ -#define BLOCK_CHANGED 1 -#define BLOCK_ABORT 2 -#define BLOCK_ERROR 4 - -/* - * Block interate flags - * - * BLOCK_FLAG_APPEND, or BLOCK_FLAG_HOLE, indicates that the interator - * function should be called on blocks where the block number is zero. - * This is used by ext2fs_expand_dir() to be able to add a new block - * to an inode. It can also be used for programs that want to be able - * to deal with files that contain "holes". - * - * BLOCK_FLAG_TRAVERSE indicates that the iterator function for the - * indirect, doubly indirect, etc. blocks should be called after all - * of the blocks containined in the indirect blocks are processed. - * This is useful if you are going to be deallocating blocks from an - * inode. - * - * BLOCK_FLAG_DATA_ONLY indicates that the iterator function should be - * called for data blocks only. - * - * BLOCK_FLAG_NO_LARGE is for internal use only. It informs - * ext2fs_block_iterate2 that large files won't be accepted. - */ -#define BLOCK_FLAG_APPEND 1 -#define BLOCK_FLAG_HOLE 1 -#define BLOCK_FLAG_DEPTH_TRAVERSE 2 -#define BLOCK_FLAG_DATA_ONLY 4 - -#define BLOCK_FLAG_NO_LARGE 0x1000 - -/* - * Magic "block count" return values for the block iterator function. - */ -#define BLOCK_COUNT_IND (-1) -#define BLOCK_COUNT_DIND (-2) -#define BLOCK_COUNT_TIND (-3) -#define BLOCK_COUNT_TRANSLATOR (-4) - -#if 0 -/* - * Flags for ext2fs_move_blocks - */ -#define EXT2_BMOVE_GET_DBLIST 0x0001 -#define EXT2_BMOVE_DEBUG 0x0002 -#endif - -/* - * Flags for directory block reading and writing functions - */ -#define EXT2_DIRBLOCK_V2_STRUCT 0x0001 - -/* - * Return flags for the directory iterator functions - */ -#define DIRENT_CHANGED 1 -#define DIRENT_ABORT 2 -#define DIRENT_ERROR 3 - -/* - * Directory iterator flags - */ - -#define DIRENT_FLAG_INCLUDE_EMPTY 1 -#define DIRENT_FLAG_INCLUDE_REMOVED 2 - -#define DIRENT_DOT_FILE 1 -#define DIRENT_DOT_DOT_FILE 2 -#define DIRENT_OTHER_FILE 3 -#define DIRENT_DELETED_FILE 4 - -/* - * Inode scan definitions - */ -typedef struct ext2_struct_inode_scan *ext2_inode_scan; - -/* - * ext2fs_scan flags - */ -#define EXT2_SF_CHK_BADBLOCKS 0x0001 -#define EXT2_SF_BAD_INODE_BLK 0x0002 -#define EXT2_SF_BAD_EXTRA_BYTES 0x0004 -#define EXT2_SF_SKIP_MISSING_ITABLE 0x0008 - -/* - * ext2fs_check_if_mounted flags - */ -#define EXT2_MF_MOUNTED 1 -#define EXT2_MF_ISROOT 2 -#define EXT2_MF_READONLY 4 -#define EXT2_MF_SWAP 8 -#define EXT2_MF_BUSY 16 - -/* - * Ext2/linux mode flags. We define them here so that we don't need - * to depend on the OS's sys/stat.h, since we may be compiling on a - * non-Linux system. - */ -#define LINUX_S_IFMT 00170000 -#define LINUX_S_IFSOCK 0140000 -#define LINUX_S_IFLNK 0120000 -#define LINUX_S_IFREG 0100000 -#define LINUX_S_IFBLK 0060000 -#define LINUX_S_IFDIR 0040000 -#define LINUX_S_IFCHR 0020000 -#define LINUX_S_IFIFO 0010000 -#define LINUX_S_ISUID 0004000 -#define LINUX_S_ISGID 0002000 -#define LINUX_S_ISVTX 0001000 - -#define LINUX_S_IRWXU 00700 -#define LINUX_S_IRUSR 00400 -#define LINUX_S_IWUSR 00200 -#define LINUX_S_IXUSR 00100 - -#define LINUX_S_IRWXG 00070 -#define LINUX_S_IRGRP 00040 -#define LINUX_S_IWGRP 00020 -#define LINUX_S_IXGRP 00010 - -#define LINUX_S_IRWXO 00007 -#define LINUX_S_IROTH 00004 -#define LINUX_S_IWOTH 00002 -#define LINUX_S_IXOTH 00001 - -#define LINUX_S_ISLNK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFLNK) -#define LINUX_S_ISREG(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFREG) -#define LINUX_S_ISDIR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFDIR) -#define LINUX_S_ISCHR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFCHR) -#define LINUX_S_ISBLK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFBLK) -#define LINUX_S_ISFIFO(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFIFO) -#define LINUX_S_ISSOCK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFSOCK) - -/* - * ext2 size of an inode - */ -#define EXT2_I_SIZE(i) ((i)->i_size | ((__u64) (i)->i_size_high << 32)) - -/* - * ext2_icount_t abstraction - */ -#define EXT2_ICOUNT_OPT_INCREMENT 0x01 - -typedef struct ext2_icount *ext2_icount_t; - -/* - * Flags for ext2fs_bmap - */ -#define BMAP_ALLOC 0x0001 -#define BMAP_SET 0x0002 - -/* - * Flags for imager.c functions - */ -#define IMAGER_FLAG_INODEMAP 1 -#define IMAGER_FLAG_SPARSEWRITE 2 - -/* - * For checking structure magic numbers... - */ - -#define EXT2_CHECK_MAGIC(struct, code) \ - if ((struct)->magic != (code)) return (code) - - -/* - * For ext2 compression support - */ -#define EXT2FS_COMPRESSED_BLKADDR ((blk_t) 0xffffffff) -#define HOLE_BLKADDR(_b) ((_b) == 0 || (_b) == EXT2FS_COMPRESSED_BLKADDR) - -/* - * Features supported by this version of the library - */ -#define EXT2_LIB_FEATURE_COMPAT_SUPP (EXT2_FEATURE_COMPAT_DIR_PREALLOC|\ - EXT2_FEATURE_COMPAT_IMAGIC_INODES|\ - EXT3_FEATURE_COMPAT_HAS_JOURNAL|\ - EXT2_FEATURE_COMPAT_RESIZE_INO|\ - EXT2_FEATURE_COMPAT_DIR_INDEX|\ - EXT2_FEATURE_COMPAT_EXT_ATTR) - -/* This #ifdef is temporary until compression is fully supported */ -#ifdef ENABLE_COMPRESSION -#ifndef I_KNOW_THAT_COMPRESSION_IS_EXPERIMENTAL -/* If the below warning bugs you, then have - `CPPFLAGS=-DI_KNOW_THAT_COMPRESSION_IS_EXPERIMENTAL' in your - environment at configure time. */ - #warning "Compression support is experimental" -#endif -#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\ - EXT2_FEATURE_INCOMPAT_COMPRESSION|\ - EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\ - EXT2_FEATURE_INCOMPAT_META_BG|\ - EXT3_FEATURE_INCOMPAT_RECOVER) -#else -#define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\ - EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|\ - EXT2_FEATURE_INCOMPAT_META_BG|\ - EXT3_FEATURE_INCOMPAT_RECOVER) -#endif -#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\ - EXT2_FEATURE_RO_COMPAT_LARGE_FILE) -/* - * function prototypes - */ - -/* alloc.c */ -extern errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir, int mode, - ext2fs_inode_bitmap map, ext2_ino_t *ret); -extern errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal, - ext2fs_block_bitmap map, blk_t *ret); -extern errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start, - blk_t finish, int num, - ext2fs_block_bitmap map, - blk_t *ret); -extern errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal, - char *block_buf, blk_t *ret); - -/* alloc_sb.c */ -extern int ext2fs_reserve_super_and_bgd(ext2_filsys fs, - dgrp_t group, - ext2fs_block_bitmap bmap); - -/* alloc_stats.c */ -void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse); -void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino, - int inuse, int isdir); -void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse); - -/* alloc_tables.c */ -extern errcode_t ext2fs_allocate_tables(ext2_filsys fs); -extern errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group, - ext2fs_block_bitmap bmap); - -/* badblocks.c */ -extern errcode_t ext2fs_u32_list_create(ext2_u32_list *ret, int size); -extern errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk); -extern int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk); -extern int ext2fs_u32_list_test(ext2_u32_list bb, blk_t blk); -extern errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb, - ext2_u32_iterate *ret); -extern int ext2fs_u32_list_iterate(ext2_u32_iterate iter, blk_t *blk); -extern void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter); -extern errcode_t ext2fs_u32_copy(ext2_u32_list src, ext2_u32_list *dest); -extern int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2); - -extern errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, - int size); -extern errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, - blk_t blk); -extern int ext2fs_badblocks_list_test(ext2_badblocks_list bb, - blk_t blk); -extern int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk); -extern void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk); -extern errcode_t - ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb, - ext2_badblocks_iterate *ret); -extern int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, - blk_t *blk); -extern void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter); -extern errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src, - ext2_badblocks_list *dest); -extern int ext2fs_badblocks_equal(ext2_badblocks_list bb1, - ext2_badblocks_list bb2); -extern int ext2fs_u32_list_count(ext2_u32_list bb); - -/* bb_compat */ -extern errcode_t badblocks_list_create(badblocks_list *ret, int size); -extern errcode_t badblocks_list_add(badblocks_list bb, blk_t blk); -extern int badblocks_list_test(badblocks_list bb, blk_t blk); -extern errcode_t badblocks_list_iterate_begin(badblocks_list bb, - badblocks_iterate *ret); -extern int badblocks_list_iterate(badblocks_iterate iter, blk_t *blk); -extern void badblocks_list_iterate_end(badblocks_iterate iter); -extern void badblocks_list_free(badblocks_list bb); - -/* bb_inode.c */ -extern errcode_t ext2fs_update_bb_inode(ext2_filsys fs, - ext2_badblocks_list bb_list); - -/* bitmaps.c */ -extern errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs); -extern errcode_t ext2fs_write_block_bitmap (ext2_filsys fs); -extern errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs); -extern errcode_t ext2fs_read_block_bitmap(ext2_filsys fs); -extern errcode_t ext2fs_allocate_generic_bitmap(__u32 start, - __u32 end, - __u32 real_end, - const char *descr, - ext2fs_generic_bitmap *ret); -extern errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs, - const char *descr, - ext2fs_block_bitmap *ret); -extern errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs, - const char *descr, - ext2fs_inode_bitmap *ret); -extern errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap, - ext2_ino_t end, ext2_ino_t *oend); -extern errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap, - blk_t end, blk_t *oend); -extern void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap); -extern void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap); -extern errcode_t ext2fs_read_bitmaps(ext2_filsys fs); -extern errcode_t ext2fs_write_bitmaps(ext2_filsys fs); - -/* block.c */ -extern errcode_t ext2fs_block_iterate(ext2_filsys fs, - ext2_ino_t ino, - int flags, - char *block_buf, - int (*func)(ext2_filsys fs, - blk_t *blocknr, - int blockcnt, - void *priv_data), - void *priv_data); -errcode_t ext2fs_block_iterate2(ext2_filsys fs, - ext2_ino_t ino, - int flags, - char *block_buf, - int (*func)(ext2_filsys fs, - blk_t *blocknr, - e2_blkcnt_t blockcnt, - blk_t ref_blk, - int ref_offset, - void *priv_data), - void *priv_data); - -/* bmap.c */ -extern errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, - struct ext2_inode *inode, - char *block_buf, int bmap_flags, - blk_t block, blk_t *phys_blk); - - -#if 0 -/* bmove.c */ -extern errcode_t ext2fs_move_blocks(ext2_filsys fs, - ext2fs_block_bitmap reserve, - ext2fs_block_bitmap alloc_map, - int flags); -#endif - -/* check_desc.c */ -extern errcode_t ext2fs_check_desc(ext2_filsys fs); - -/* closefs.c */ -extern errcode_t ext2fs_close(ext2_filsys fs); -extern errcode_t ext2fs_flush(ext2_filsys fs); -extern int ext2fs_bg_has_super(ext2_filsys fs, int group_block); -extern int ext2fs_super_and_bgd_loc(ext2_filsys fs, - dgrp_t group, - blk_t *ret_super_blk, - blk_t *ret_old_desc_blk, - blk_t *ret_new_desc_blk, - int *ret_meta_bg); -extern void ext2fs_update_dynamic_rev(ext2_filsys fs); - -/* cmp_bitmaps.c */ -extern errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1, - ext2fs_block_bitmap bm2); -extern errcode_t ext2fs_compare_inode_bitmap(ext2fs_inode_bitmap bm1, - ext2fs_inode_bitmap bm2); - -/* dblist.c */ - -extern errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs); -extern errcode_t ext2fs_init_dblist(ext2_filsys fs, ext2_dblist *ret_dblist); -extern errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino, - blk_t blk, int blockcnt); -extern void ext2fs_dblist_sort(ext2_dblist dblist, - int (*sortfunc)(const void *, - const void *)); -extern errcode_t ext2fs_dblist_iterate(ext2_dblist dblist, - int (*func)(ext2_filsys fs, struct ext2_db_entry *db_info, - void *priv_data), - void *priv_data); -extern errcode_t ext2fs_set_dir_block(ext2_dblist dblist, ext2_ino_t ino, - blk_t blk, int blockcnt); -extern errcode_t ext2fs_copy_dblist(ext2_dblist src, - ext2_dblist *dest); -extern int ext2fs_dblist_count(ext2_dblist dblist); - -/* dblist_dir.c */ -extern errcode_t - ext2fs_dblist_dir_iterate(ext2_dblist dblist, - int flags, - char *block_buf, - int (*func)(ext2_ino_t dir, - int entry, - struct ext2_dir_entry *dirent, - int offset, - int blocksize, - char *buf, - void *priv_data), - void *priv_data); - -/* dirblock.c */ -extern errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block, - void *buf); -extern errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block, - void *buf, int flags); -extern errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block, - void *buf); -extern errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block, - void *buf, int flags); - -/* dirhash.c */ -extern errcode_t ext2fs_dirhash(int version, const char *name, int len, - const __u32 *seed, - ext2_dirhash_t *ret_hash, - ext2_dirhash_t *ret_minor_hash); - - -/* dir_iterate.c */ -extern errcode_t ext2fs_dir_iterate(ext2_filsys fs, - ext2_ino_t dir, - int flags, - char *block_buf, - int (*func)(struct ext2_dir_entry *dirent, - int offset, - int blocksize, - char *buf, - void *priv_data), - void *priv_data); -extern errcode_t ext2fs_dir_iterate2(ext2_filsys fs, - ext2_ino_t dir, - int flags, - char *block_buf, - int (*func)(ext2_ino_t dir, - int entry, - struct ext2_dir_entry *dirent, - int offset, - int blocksize, - char *buf, - void *priv_data), - void *priv_data); - -/* dupfs.c */ -extern errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest); - -/* expanddir.c */ -extern errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir); - -/* ext_attr.c */ -extern errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf); -extern errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, - void *buf); -extern errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk, - char *block_buf, - int adjust, __u32 *newcount); - -/* fileio.c */ -extern errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino, - struct ext2_inode *inode, - int flags, ext2_file_t *ret); -extern errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino, - int flags, ext2_file_t *ret); -extern ext2_filsys ext2fs_file_get_fs(ext2_file_t file); -extern errcode_t ext2fs_file_close(ext2_file_t file); -extern errcode_t ext2fs_file_flush(ext2_file_t file); -extern errcode_t ext2fs_file_read(ext2_file_t file, void *buf, - unsigned int wanted, unsigned int *got); -extern errcode_t ext2fs_file_write(ext2_file_t file, const void *buf, - unsigned int nbytes, unsigned int *written); -extern errcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset, - int whence, __u64 *ret_pos); -extern errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset, - int whence, ext2_off_t *ret_pos); -errcode_t ext2fs_file_get_lsize(ext2_file_t file, __u64 *ret_size); -extern ext2_off_t ext2fs_file_get_size(ext2_file_t file); -extern errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size); - -/* finddev.c */ -extern char *ext2fs_find_block_device(dev_t device); - -/* flushb.c */ -extern errcode_t ext2fs_sync_device(int fd, int flushb); - -/* freefs.c */ -extern void ext2fs_free(ext2_filsys fs); -extern void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap); -extern void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap); -extern void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap); -extern void ext2fs_free_dblist(ext2_dblist dblist); -extern void ext2fs_badblocks_list_free(ext2_badblocks_list bb); -extern void ext2fs_u32_list_free(ext2_u32_list bb); - -/* getsize.c */ -extern errcode_t ext2fs_get_device_size(const char *file, int blocksize, - blk_t *retblocks); - -/* getsectsize.c */ -errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize); - -/* imager.c */ -extern errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags); -extern errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd, int flags); -extern errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, int flags); -extern errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd, int flags); -extern errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags); -extern errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags); - -/* ind_block.c */ -errcode_t ext2fs_read_ind_block(ext2_filsys fs, blk_t blk, void *buf); -errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf); - -/* initialize.c */ -extern errcode_t ext2fs_initialize(const char *name, int flags, - struct ext2_super_block *param, - io_manager manager, ext2_filsys *ret_fs); - -/* icount.c */ -extern void ext2fs_free_icount(ext2_icount_t icount); -extern errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, - unsigned int size, - ext2_icount_t hint, ext2_icount_t *ret); -extern errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, - unsigned int size, - ext2_icount_t *ret); -extern errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino, - __u16 *ret); -extern errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino, - __u16 *ret); -extern errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino, - __u16 *ret); -extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino, - __u16 count); -extern ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount); -errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *); - -/* inode.c */ -extern errcode_t ext2fs_flush_icache(ext2_filsys fs); -extern errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan, - ext2_ino_t *ino, - struct ext2_inode *inode, - int bufsize); -extern errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks, - ext2_inode_scan *ret_scan); -extern void ext2fs_close_inode_scan(ext2_inode_scan scan); -extern errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino, - struct ext2_inode *inode); -extern errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan, - int group); -extern void ext2fs_set_inode_callback - (ext2_inode_scan scan, - errcode_t (*done_group)(ext2_filsys fs, - dgrp_t group, - void * priv_data), - void *done_group_data); -extern int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags, - int clear_flags); -extern errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino, - struct ext2_inode * inode, - int bufsize); -extern errcode_t ext2fs_read_inode (ext2_filsys fs, ext2_ino_t ino, - struct ext2_inode * inode); -extern errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino, - struct ext2_inode * inode, - int bufsize); -extern errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino, - struct ext2_inode * inode); -extern errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino, - struct ext2_inode * inode); -extern errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks); -extern errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino); - -/* inode_io.c */ -extern io_manager inode_io_manager; -extern errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino, - char **name); -extern errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino, - struct ext2_inode *inode, - char **name); - -/* ismounted.c */ -extern errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags); -extern errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags, - char *mtpt, int mtlen); - -/* namei.c */ -extern errcode_t ext2fs_lookup(ext2_filsys fs, ext2_ino_t dir, const char *name, - int namelen, char *buf, ext2_ino_t *inode); -extern errcode_t ext2fs_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, - const char *name, ext2_ino_t *inode); -errcode_t ext2fs_namei_follow(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, - const char *name, ext2_ino_t *inode); -extern errcode_t ext2fs_follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, - ext2_ino_t inode, ext2_ino_t *res_inode); - -/* native.c */ -int ext2fs_native_flag(void); - -/* newdir.c */ -extern errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino, - ext2_ino_t parent_ino, char **block); - -/* mkdir.c */ -extern errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum, - const char *name); - -/* mkjournal.c */ -extern errcode_t ext2fs_create_journal_superblock(ext2_filsys fs, - __u32 size, int flags, - char **ret_jsb); -extern errcode_t ext2fs_add_journal_device(ext2_filsys fs, - ext2_filsys journal_dev); -extern errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size, - int flags); - -/* openfs.c */ -extern errcode_t ext2fs_open(const char *name, int flags, int superblock, - unsigned int block_size, io_manager manager, - ext2_filsys *ret_fs); -extern errcode_t ext2fs_open2(const char *name, const char *io_options, - int flags, int superblock, - unsigned int block_size, io_manager manager, - ext2_filsys *ret_fs); -extern blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, - dgrp_t i); -errcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io); -errcode_t ext2fs_set_data_io(ext2_filsys fs, io_channel new_io); -errcode_t ext2fs_rewrite_to_io(ext2_filsys fs, io_channel new_io); - -/* get_pathname.c */ -extern errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino, - char **name); - -/* link.c */ -errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name, - ext2_ino_t ino, int flags); -errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir, const char *name, - ext2_ino_t ino, int flags); - -/* read_bb.c */ -extern errcode_t ext2fs_read_bb_inode(ext2_filsys fs, - ext2_badblocks_list *bb_list); - -/* read_bb_file.c */ -extern errcode_t ext2fs_read_bb_FILE2(ext2_filsys fs, FILE *f, - ext2_badblocks_list *bb_list, - void *priv_data, - void (*invalid)(ext2_filsys fs, - blk_t blk, - char *badstr, - void *priv_data)); -extern errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f, - ext2_badblocks_list *bb_list, - void (*invalid)(ext2_filsys fs, - blk_t blk)); - -/* res_gdt.c */ -extern errcode_t ext2fs_create_resize_inode(ext2_filsys fs); - -/* rs_bitmap.c */ -extern errcode_t ext2fs_resize_generic_bitmap(__u32 new_end, - __u32 new_real_end, - ext2fs_generic_bitmap bmap); -extern errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end, - ext2fs_inode_bitmap bmap); -extern errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end, - ext2fs_block_bitmap bmap); -extern errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src, - ext2fs_generic_bitmap *dest); - -/* swapfs.c */ -extern void ext2fs_swap_ext_attr(char *to, char *from, int bufsize, - int has_header); -extern void ext2fs_swap_super(struct ext2_super_block * super); -extern void ext2fs_swap_group_desc(struct ext2_group_desc *gdp); -extern void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t, - struct ext2_inode_large *f, int hostorder, - int bufsize); -extern void ext2fs_swap_inode(ext2_filsys fs,struct ext2_inode *t, - struct ext2_inode *f, int hostorder); - -/* valid_blk.c */ -extern int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode); - -/* version.c */ -extern int ext2fs_parse_version_string(const char *ver_string); -extern int ext2fs_get_library_version(const char **ver_string, - const char **date_string); - -/* write_bb_file.c */ -extern errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list, - unsigned int flags, - FILE *f); - - -/* inline functions */ -extern errcode_t ext2fs_get_mem(unsigned long size, void *ptr); -extern errcode_t ext2fs_free_mem(void *ptr); -extern errcode_t ext2fs_resize_mem(unsigned long old_size, - unsigned long size, void *ptr); -extern void ext2fs_mark_super_dirty(ext2_filsys fs); -extern void ext2fs_mark_changed(ext2_filsys fs); -extern int ext2fs_test_changed(ext2_filsys fs); -extern void ext2fs_mark_valid(ext2_filsys fs); -extern void ext2fs_unmark_valid(ext2_filsys fs); -extern int ext2fs_test_valid(ext2_filsys fs); -extern void ext2fs_mark_ib_dirty(ext2_filsys fs); -extern void ext2fs_mark_bb_dirty(ext2_filsys fs); -extern int ext2fs_test_ib_dirty(ext2_filsys fs); -extern int ext2fs_test_bb_dirty(ext2_filsys fs); -extern int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk); -extern int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino); -extern blk_t ext2fs_inode_data_blocks(ext2_filsys fs, - struct ext2_inode *inode); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * ext2fsP.h --- private header file for ext2 library - * - * Copyright (C) 1997 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include "ext2fs.h" - -/* - * Badblocks list - */ -struct ext2_struct_u32_list { - int magic; - int num; - int size; - __u32 *list; - int badblocks_flags; -}; - -struct ext2_struct_u32_iterate { - int magic; - ext2_u32_list bb; - int ptr; -}; - - -/* - * Directory block iterator definition - */ -struct ext2_struct_dblist { - int magic; - ext2_filsys fs; - ext2_ino_t size; - ext2_ino_t count; - int sorted; - struct ext2_db_entry * list; -}; - -/* - * For directory iterators - */ -struct dir_context { - ext2_ino_t dir; - int flags; - char *buf; - int (*func)(ext2_ino_t dir, - int entry, - struct ext2_dir_entry *dirent, - int offset, - int blocksize, - char *buf, - void *priv_data); - void *priv_data; - errcode_t errcode; -}; - -/* - * Inode cache structure - */ -struct ext2_inode_cache { - void * buffer; - blk_t buffer_blk; - int cache_last; - int cache_size; - int refcount; - struct ext2_inode_cache_ent *cache; -}; - -struct ext2_inode_cache_ent { - ext2_ino_t ino; - struct ext2_inode inode; -}; - -/* Function prototypes */ - -extern int ext2fs_process_dir_block(ext2_filsys fs, - blk_t *blocknr, - e2_blkcnt_t blockcnt, - blk_t ref_block, - int ref_offset, - void *priv_data); diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * ext2fs.h --- ext2fs - * - * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include "ext2fs.h" -#include "bitops.h" -#include - -/* - * Allocate memory - */ -errcode_t ext2fs_get_mem(unsigned long size, void *ptr) -{ - void **pp = (void **)ptr; - - *pp = malloc(size); - if (!*pp) - return EXT2_ET_NO_MEMORY; - return 0; -} - -/* - * Free memory - */ -errcode_t ext2fs_free_mem(void *ptr) -{ - void **pp = (void **)ptr; - - free(*pp); - *pp = 0; - return 0; -} - -/* - * Resize memory - */ -errcode_t ext2fs_resize_mem(unsigned long EXT2FS_ATTR((unused)) old_size, - unsigned long size, void *ptr) -{ - void *p; - - /* Use "memcpy" for pointer assignments here to avoid problems - * with C99 strict type aliasing rules. */ - memcpy(&p, ptr, sizeof (p)); - p = xrealloc(p, size); - memcpy(ptr, &p, sizeof (p)); - return 0; -} - -/* - * Mark a filesystem superblock as dirty - */ -void ext2fs_mark_super_dirty(ext2_filsys fs) -{ - fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_CHANGED; -} - -/* - * Mark a filesystem as changed - */ -void ext2fs_mark_changed(ext2_filsys fs) -{ - fs->flags |= EXT2_FLAG_CHANGED; -} - -/* - * Check to see if a filesystem has changed - */ -int ext2fs_test_changed(ext2_filsys fs) -{ - return (fs->flags & EXT2_FLAG_CHANGED); -} - -/* - * Mark a filesystem as valid - */ -void ext2fs_mark_valid(ext2_filsys fs) -{ - fs->flags |= EXT2_FLAG_VALID; -} - -/* - * Mark a filesystem as NOT valid - */ -void ext2fs_unmark_valid(ext2_filsys fs) -{ - fs->flags &= ~EXT2_FLAG_VALID; -} - -/* - * Check to see if a filesystem is valid - */ -int ext2fs_test_valid(ext2_filsys fs) -{ - return (fs->flags & EXT2_FLAG_VALID); -} - -/* - * Mark the inode bitmap as dirty - */ -void ext2fs_mark_ib_dirty(ext2_filsys fs) -{ - fs->flags |= EXT2_FLAG_IB_DIRTY | EXT2_FLAG_CHANGED; -} - -/* - * Mark the block bitmap as dirty - */ -void ext2fs_mark_bb_dirty(ext2_filsys fs) -{ - fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_CHANGED; -} - -/* - * Check to see if a filesystem's inode bitmap is dirty - */ -int ext2fs_test_ib_dirty(ext2_filsys fs) -{ - return (fs->flags & EXT2_FLAG_IB_DIRTY); -} - -/* - * Check to see if a filesystem's block bitmap is dirty - */ -int ext2fs_test_bb_dirty(ext2_filsys fs) -{ - return (fs->flags & EXT2_FLAG_BB_DIRTY); -} - -/* - * Return the group # of a block - */ -int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk) -{ - return (blk - fs->super->s_first_data_block) / - fs->super->s_blocks_per_group; -} - -/* - * Return the group # of an inode number - */ -int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino) -{ - return (ino - 1) / fs->super->s_inodes_per_group; -} - -blk_t ext2fs_inode_data_blocks(ext2_filsys fs, - struct ext2_inode *inode) -{ - return inode->i_blocks - - (inode->i_file_acl ? fs->blocksize >> 9 : 0); -} - - - - - - - - - -__u16 ext2fs_swab16(__u16 val) -{ - return (val >> 8) | (val << 8); -} - -__u32 ext2fs_swab32(__u32 val) -{ - return ((val>>24) | ((val>>8)&0xFF00) | - ((val<<8)&0xFF0000) | (val<<24)); -} - -int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap, - blk_t bitno); - -int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap, - blk_t bitno) -{ - if ((bitno < bitmap->start) || (bitno > bitmap->end)) { - ext2fs_warn_bitmap2(bitmap, EXT2FS_TEST_ERROR, bitno); - return 0; - } - return ext2fs_test_bit(bitno - bitmap->start, bitmap->bitmap); -} - -int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, - blk_t block) -{ - return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) - bitmap, - block); -} - -int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap, - blk_t block) -{ - return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, - block); -} - -int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, - blk_t block) -{ - return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap, - block); -} - -int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, - ext2_ino_t inode) -{ - return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, - inode); -} - -int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap, - ext2_ino_t inode) -{ - return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, - inode); -} - -int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, - ext2_ino_t inode) -{ - return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap, - inode); -} - -void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap, - blk_t block) -{ - ext2fs_set_bit(block - bitmap->start, bitmap->bitmap); -} - -void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap, - blk_t block) -{ - ext2fs_clear_bit(block - bitmap->start, bitmap->bitmap); -} - -int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap, - blk_t block) -{ - return ext2fs_test_bit(block - bitmap->start, bitmap->bitmap); -} - -void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, - ext2_ino_t inode) -{ - ext2fs_set_bit(inode - bitmap->start, bitmap->bitmap); -} - -void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap, - ext2_ino_t inode) -{ - ext2fs_clear_bit(inode - bitmap->start, bitmap->bitmap); -} - -int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap, - ext2_ino_t inode) -{ - return ext2fs_test_bit(inode - bitmap->start, bitmap->bitmap); -} - -blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap) -{ - return bitmap->start; -} - -ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap) -{ - return bitmap->start; -} - -blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap) -{ - return bitmap->end; -} - -ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap) -{ - return bitmap->end; -} - -int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap, - blk_t block, int num) -{ - int i; - - if ((block < bitmap->start) || (block+num-1 > bitmap->end)) { - ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_TEST, - block, bitmap->description); - return 0; - } - for (i=0; i < num; i++) { - if (ext2fs_fast_test_block_bitmap(bitmap, block+i)) - return 0; - } - return 1; -} - -int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap, - blk_t block, int num) -{ - int i; - - for (i=0; i < num; i++) { - if (ext2fs_fast_test_block_bitmap(bitmap, block+i)) - return 0; - } - return 1; -} - -void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap, - blk_t block, int num) -{ - int i; - - if ((block < bitmap->start) || (block+num-1 > bitmap->end)) { - ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_MARK, block, - bitmap->description); - return; - } - for (i=0; i < num; i++) - ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap); -} - -void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap, - blk_t block, int num) -{ - int i; - - for (i=0; i < num; i++) - ext2fs_set_bit(block + i - bitmap->start, bitmap->bitmap); -} - -void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap, - blk_t block, int num) -{ - int i; - - if ((block < bitmap->start) || (block+num-1 > bitmap->end)) { - ext2fs_warn_bitmap(EXT2_ET_BAD_BLOCK_UNMARK, block, - bitmap->description); - return; - } - for (i=0; i < num; i++) - ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap); -} - -void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap, - blk_t block, int num) -{ - int i; - for (i=0; i < num; i++) - ext2fs_clear_bit(block + i - bitmap->start, bitmap->bitmap); -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * ext_attr.c --- extended attribute blocks - * - * Copyright (C) 2001 Andreas Gruenbacher, - * - * Copyright (C) 2002 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#include -#include - -#include "ext2_fs.h" -#include "ext2_ext_attr.h" -#include "ext2fs.h" - -errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf) -{ - errcode_t retval; - - retval = io_channel_read_blk(fs->io, block, 1, buf); - if (retval) - return retval; -#if BB_BIG_ENDIAN - if ((fs->flags & (EXT2_FLAG_SWAP_BYTES| - EXT2_FLAG_SWAP_BYTES_READ)) != 0) - ext2fs_swap_ext_attr(buf, buf, fs->blocksize, 1); -#endif - return 0; -} - -errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *inbuf) -{ - errcode_t retval; - char *write_buf; - char *buf = NULL; - - if (BB_BIG_ENDIAN && ((fs->flags & EXT2_FLAG_SWAP_BYTES) || - (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))) { - retval = ext2fs_get_mem(fs->blocksize, &buf); - if (retval) - return retval; - write_buf = buf; - ext2fs_swap_ext_attr(buf, inbuf, fs->blocksize, 1); - } else - write_buf = (char *) inbuf; - retval = io_channel_write_blk(fs->io, block, 1, write_buf); - if (buf) - ext2fs_free_mem(&buf); - if (!retval) - ext2fs_mark_changed(fs); - return retval; -} - -/* - * This function adjusts the reference count of the EA block. - */ -errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk, - char *block_buf, int adjust, - __u32 *newcount) -{ - errcode_t retval; - struct ext2_ext_attr_header *header; - char *buf = NULL; - - if ((blk >= fs->super->s_blocks_count) || - (blk < fs->super->s_first_data_block)) - return EXT2_ET_BAD_EA_BLOCK_NUM; - - if (!block_buf) { - retval = ext2fs_get_mem(fs->blocksize, &buf); - if (retval) - return retval; - block_buf = buf; - } - - retval = ext2fs_read_ext_attr(fs, blk, block_buf); - if (retval) - goto errout; - - header = (struct ext2_ext_attr_header *) block_buf; - header->h_refcount += adjust; - if (newcount) - *newcount = header->h_refcount; - - retval = ext2fs_write_ext_attr(fs, blk, block_buf); - if (retval) - goto errout; - -errout: - if (buf) - ext2fs_free_mem(&buf); - return retval; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * fileio.c --- Simple file I/O routines - * - * Copyright (C) 1997 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -struct ext2_file { - errcode_t magic; - ext2_filsys fs; - ext2_ino_t ino; - struct ext2_inode inode; - int flags; - __u64 pos; - blk_t blockno; - blk_t physblock; - char *buf; -}; - -#define BMAP_BUFFER (file->buf + fs->blocksize) - -errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino, - struct ext2_inode *inode, - int flags, ext2_file_t *ret) -{ - ext2_file_t file; - errcode_t retval; - - /* - * Don't let caller create or open a file for writing if the - * filesystem is read-only. - */ - if ((flags & (EXT2_FILE_WRITE | EXT2_FILE_CREATE)) && - !(fs->flags & EXT2_FLAG_RW)) - return EXT2_ET_RO_FILSYS; - - retval = ext2fs_get_mem(sizeof(struct ext2_file), &file); - if (retval) - return retval; - - memset(file, 0, sizeof(struct ext2_file)); - file->magic = EXT2_ET_MAGIC_EXT2_FILE; - file->fs = fs; - file->ino = ino; - file->flags = flags & EXT2_FILE_MASK; - - if (inode) { - memcpy(&file->inode, inode, sizeof(struct ext2_inode)); - } else { - retval = ext2fs_read_inode(fs, ino, &file->inode); - if (retval) - goto fail; - } - - retval = ext2fs_get_mem(fs->blocksize * 3, &file->buf); - if (retval) - goto fail; - - *ret = file; - return 0; - -fail: - ext2fs_free_mem(&file->buf); - ext2fs_free_mem(&file); - return retval; -} - -errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino, - int flags, ext2_file_t *ret) -{ - return ext2fs_file_open2(fs, ino, NULL, flags, ret); -} - -/* - * This function returns the filesystem handle of a file from the structure - */ -ext2_filsys ext2fs_file_get_fs(ext2_file_t file) -{ - if (file->magic != EXT2_ET_MAGIC_EXT2_FILE) - return 0; - return file->fs; -} - -/* - * This function flushes the dirty block buffer out to disk if - * necessary. - */ -errcode_t ext2fs_file_flush(ext2_file_t file) -{ - errcode_t retval; - ext2_filsys fs; - - EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); - fs = file->fs; - - if (!(file->flags & EXT2_FILE_BUF_VALID) || - !(file->flags & EXT2_FILE_BUF_DIRTY)) - return 0; - - /* - * OK, the physical block hasn't been allocated yet. - * Allocate it. - */ - if (!file->physblock) { - retval = ext2fs_bmap(fs, file->ino, &file->inode, - BMAP_BUFFER, file->ino ? BMAP_ALLOC : 0, - file->blockno, &file->physblock); - if (retval) - return retval; - } - - retval = io_channel_write_blk(fs->io, file->physblock, - 1, file->buf); - if (retval) - return retval; - - file->flags &= ~EXT2_FILE_BUF_DIRTY; - - return retval; -} - -/* - * This function synchronizes the file's block buffer and the current - * file position, possibly invalidating block buffer if necessary - */ -static errcode_t sync_buffer_position(ext2_file_t file) -{ - blk_t b; - errcode_t retval; - - b = file->pos / file->fs->blocksize; - if (b != file->blockno) { - retval = ext2fs_file_flush(file); - if (retval) - return retval; - file->flags &= ~EXT2_FILE_BUF_VALID; - } - file->blockno = b; - return 0; -} - -/* - * This function loads the file's block buffer with valid data from - * the disk as necessary. - * - * If dontfill is true, then skip initializing the buffer since we're - * going to be replacing its entire contents anyway. If set, then the - * function basically only sets file->physblock and EXT2_FILE_BUF_VALID - */ -#define DONTFILL 1 -static errcode_t load_buffer(ext2_file_t file, int dontfill) -{ - ext2_filsys fs = file->fs; - errcode_t retval; - - if (!(file->flags & EXT2_FILE_BUF_VALID)) { - retval = ext2fs_bmap(fs, file->ino, &file->inode, - BMAP_BUFFER, 0, file->blockno, - &file->physblock); - if (retval) - return retval; - if (!dontfill) { - if (file->physblock) { - retval = io_channel_read_blk(fs->io, - file->physblock, - 1, file->buf); - if (retval) - return retval; - } else - memset(file->buf, 0, fs->blocksize); - } - file->flags |= EXT2_FILE_BUF_VALID; - } - return 0; -} - - -errcode_t ext2fs_file_close(ext2_file_t file) -{ - errcode_t retval; - - EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); - - retval = ext2fs_file_flush(file); - - ext2fs_free_mem(&file->buf); - ext2fs_free_mem(&file); - - return retval; -} - - -errcode_t ext2fs_file_read(ext2_file_t file, void *buf, - unsigned int wanted, unsigned int *got) -{ - ext2_filsys fs; - errcode_t retval = 0; - unsigned int start, c, count = 0; - __u64 left; - char *ptr = (char *) buf; - - EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); - fs = file->fs; - - while ((file->pos < EXT2_I_SIZE(&file->inode)) && (wanted > 0)) { - retval = sync_buffer_position(file); - if (retval) - goto fail; - retval = load_buffer(file, 0); - if (retval) - goto fail; - - start = file->pos % fs->blocksize; - c = fs->blocksize - start; - if (c > wanted) - c = wanted; - left = EXT2_I_SIZE(&file->inode) - file->pos; - if (c > left) - c = left; - - memcpy(ptr, file->buf+start, c); - file->pos += c; - ptr += c; - count += c; - wanted -= c; - } - -fail: - if (got) - *got = count; - return retval; -} - - -errcode_t ext2fs_file_write(ext2_file_t file, const void *buf, - unsigned int nbytes, unsigned int *written) -{ - ext2_filsys fs; - errcode_t retval = 0; - unsigned int start, c, count = 0; - const char *ptr = (const char *) buf; - - EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); - fs = file->fs; - - if (!(file->flags & EXT2_FILE_WRITE)) - return EXT2_ET_FILE_RO; - - while (nbytes > 0) { - retval = sync_buffer_position(file); - if (retval) - goto fail; - - start = file->pos % fs->blocksize; - c = fs->blocksize - start; - if (c > nbytes) - c = nbytes; - - /* - * We only need to do a read-modify-update cycle if - * we're doing a partial write. - */ - retval = load_buffer(file, (c == fs->blocksize)); - if (retval) - goto fail; - - file->flags |= EXT2_FILE_BUF_DIRTY; - memcpy(file->buf+start, ptr, c); - file->pos += c; - ptr += c; - count += c; - nbytes -= c; - } - -fail: - if (written) - *written = count; - return retval; -} - -errcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset, - int whence, __u64 *ret_pos) -{ - EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); - - if (whence == EXT2_SEEK_SET) - file->pos = offset; - else if (whence == EXT2_SEEK_CUR) - file->pos += offset; - else if (whence == EXT2_SEEK_END) - file->pos = EXT2_I_SIZE(&file->inode) + offset; - else - return EXT2_ET_INVALID_ARGUMENT; - - if (ret_pos) - *ret_pos = file->pos; - - return 0; -} - -errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset, - int whence, ext2_off_t *ret_pos) -{ - __u64 loffset, ret_loffset; - errcode_t retval; - - loffset = offset; - retval = ext2fs_file_llseek(file, loffset, whence, &ret_loffset); - if (ret_pos) - *ret_pos = (ext2_off_t) ret_loffset; - return retval; -} - - -/* - * This function returns the size of the file, according to the inode - */ -errcode_t ext2fs_file_get_lsize(ext2_file_t file, __u64 *ret_size) -{ - if (file->magic != EXT2_ET_MAGIC_EXT2_FILE) - return EXT2_ET_MAGIC_EXT2_FILE; - *ret_size = EXT2_I_SIZE(&file->inode); - return 0; -} - -/* - * This function returns the size of the file, according to the inode - */ -ext2_off_t ext2fs_file_get_size(ext2_file_t file) -{ - __u64 size; - - if (ext2fs_file_get_lsize(file, &size)) - return 0; - if ((size >> 32) != 0) - return 0; - return size; -} - -/* - * This function sets the size of the file, truncating it if necessary - * - * XXX still need to call truncate - */ -errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size) -{ - errcode_t retval; - EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE); - - file->inode.i_size = size; - file->inode.i_size_high = 0; - if (file->ino) { - retval = ext2fs_write_inode(file->fs, file->ino, &file->inode); - if (retval) - return retval; - } - - /* - * XXX truncate inode if necessary - */ - - return 0; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * finddev.c -- this routine attempts to find a particular device in - * /dev - * - * Copyright (C) 2000 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#ifdef HAVE_UNISTD_H -#include -#endif -#include -#include -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_SYS_STAT_H -#include -#endif -#include -#ifdef HAVE_ERRNO_H -#include -#endif -#ifdef HAVE_SYS_MKDEV_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -struct dir_list { - char *name; - struct dir_list *next; -}; - -/* - * This function adds an entry to the directory list - */ -static void add_to_dirlist(const char *name, struct dir_list **list) -{ - struct dir_list *dp; - - dp = xmalloc(sizeof(struct dir_list)); - dp->name = xmalloc(strlen(name)+1); - strcpy(dp->name, name); - dp->next = *list; - *list = dp; -} - -/* - * This function frees a directory list - */ -static void free_dirlist(struct dir_list **list) -{ - struct dir_list *dp, *next; - - for (dp = *list; dp; dp = next) { - next = dp->next; - free(dp->name); - free(dp); - } - *list = 0; -} - -static int scan_dir(char *dir_name, dev_t device, struct dir_list **list, - char **ret_path) -{ - DIR *dir; - struct dirent *dp; - char path[1024], *cp; - int dirlen; - struct stat st; - - dirlen = strlen(dir_name); - if ((dir = opendir(dir_name)) == NULL) - return errno; - dp = readdir(dir); - while (dp) { - if (dirlen + strlen(dp->d_name) + 2 >= sizeof(path)) - goto skip_to_next; - if (dp->d_name[0] == '.' && - ((dp->d_name[1] == 0) || - ((dp->d_name[1] == '.') && (dp->d_name[2] == 0)))) - goto skip_to_next; - sprintf(path, "%s/%s", dir_name, dp->d_name); - if (stat(path, &st) < 0) - goto skip_to_next; - if (S_ISDIR(st.st_mode)) - add_to_dirlist(path, list); - if (S_ISBLK(st.st_mode) && st.st_rdev == device) { - cp = xmalloc(strlen(path)+1); - strcpy(cp, path); - *ret_path = cp; - goto success; - } - skip_to_next: - dp = readdir(dir); - } -success: - closedir(dir); - return 0; -} - -/* - * This function finds the pathname to a block device with a given - * device number. It returns a pointer to allocated memory to the - * pathname on success, and NULL on failure. - */ -char *ext2fs_find_block_device(dev_t device) -{ - struct dir_list *list = NULL, *new_list = NULL; - struct dir_list *current; - char *ret_path = NULL; - - /* - * Add the starting directories to search... - */ - add_to_dirlist("/devices", &list); - add_to_dirlist("/devfs", &list); - add_to_dirlist("/dev", &list); - - while (list) { - current = list; - list = list->next; -#ifdef DEBUG - printf("Scanning directory %s\n", current->name); -#endif - scan_dir(current->name, device, &new_list, &ret_path); - free(current->name); - free(current); - if (ret_path) - break; - /* - * If we're done checking at this level, descend to - * the next level of subdirectories. (breadth-first) - */ - if (list == 0) { - list = new_list; - new_list = 0; - } - } - free_dirlist(&list); - free_dirlist(&new_list); - return ret_path; -} - - -#ifdef DEBUG -int main(int argc, char** argv) -{ - char *devname, *tmp; - int major, minor; - dev_t device; - const char *errmsg = "Cannot parse %s: %s\n"; - - if ((argc != 2) && (argc != 3)) { - fprintf(stderr, "Usage: %s device_number\n", argv[0]); - fprintf(stderr, "\t: %s major minor\n", argv[0]); - exit(1); - } - if (argc == 2) { - device = strtoul(argv[1], &tmp, 0); - if (*tmp) { - fprintf(stderr, errmsg, "device number", argv[1]); - exit(1); - } - } else { - major = strtoul(argv[1], &tmp, 0); - if (*tmp) { - fprintf(stderr, errmsg, "major number", argv[1]); - exit(1); - } - minor = strtoul(argv[2], &tmp, 0); - if (*tmp) { - fprintf(stderr, errmsg, "minor number", argv[2]); - exit(1); - } - device = makedev(major, minor); - printf("Looking for device 0x%04x (%d:%d)\n", device, - major, minor); - } - devname = ext2fs_find_block_device(device); - if (devname) { - printf("Found device! %s\n", devname); - free(devname); - } else { - printf("Cannot find device.\n"); - } - return 0; -} - -#endif diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * flushb.c --- Hides system-dependent information for both syncing a - * device to disk and to flush any buffers from disk cache. - * - * Copyright (C) 2000 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#if HAVE_ERRNO_H -#include -#endif -#if HAVE_UNISTD_H -#include -#endif -#if HAVE_SYS_IOCTL_H -#include -#endif -#if HAVE_SYS_MOUNT_H -#include -#include /* This may define BLKFLSBUF */ -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -/* - * For Linux, define BLKFLSBUF and FDFLUSH if necessary, since - * not all portable header file does so for us. This really should be - * fixed in the glibc header files. (Recent glibcs appear to define - * BLKFLSBUF in sys/mount.h, but FDFLUSH still doesn't seem to be - * defined anywhere portable.) Until then.... - */ -#ifdef __linux__ -#ifndef BLKFLSBUF -#define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */ -#endif -#ifndef FDFLUSH -#define FDFLUSH _IO(2,0x4b) /* flush floppy disk */ -#endif -#endif - -/* - * This function will sync a device/file, and optionally attempt to - * flush the buffer cache. The latter is basically only useful for - * system benchmarks and for torturing systems in burn-in tests. :) - */ -errcode_t ext2fs_sync_device(int fd, int flushb) -{ - /* - * We always sync the device in case we're running on old - * kernels for which we can lose data if we don't. (There - * still is a race condition for those kernels, but this - * reduces it greatly.) - */ - if (fsync (fd) == -1) - return errno; - - if (flushb) { - -#ifdef BLKFLSBUF - if (ioctl (fd, BLKFLSBUF, 0) == 0) - return 0; -#else -#ifdef __GNUC__ -# warning BLKFLSBUF not defined -#endif /* __GNUC__ */ -#endif -#ifdef FDFLUSH - ioctl (fd, FDFLUSH, 0); /* In case this is a floppy */ -#else -#ifdef __GNUC__ -# warning FDFLUSH not defined -#endif /* __GNUC__ */ -#endif - } - return 0; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * freefs.c --- free an ext2 filesystem - * - * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#if HAVE_UNISTD_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fsP.h" - -static void ext2fs_free_inode_cache(struct ext2_inode_cache *icache); - -void ext2fs_free(ext2_filsys fs) -{ - if (!fs || (fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS)) - return; - if (fs->image_io != fs->io) { - if (fs->image_io) - io_channel_close(fs->image_io); - } - if (fs->io) { - io_channel_close(fs->io); - } - ext2fs_free_mem(&fs->device_name); - ext2fs_free_mem(&fs->super); - ext2fs_free_mem(&fs->orig_super); - ext2fs_free_mem(&fs->group_desc); - ext2fs_free_block_bitmap(fs->block_map); - ext2fs_free_inode_bitmap(fs->inode_map); - - ext2fs_badblocks_list_free(fs->badblocks); - fs->badblocks = 0; - - ext2fs_free_dblist(fs->dblist); - - if (fs->icache) - ext2fs_free_inode_cache(fs->icache); - - fs->magic = 0; - - ext2fs_free_mem(&fs); -} - -void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap) -{ - if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_GENERIC_BITMAP)) - return; - - bitmap->magic = 0; - ext2fs_free_mem(&bitmap->description); - ext2fs_free_mem(&bitmap->bitmap); - ext2fs_free_mem(&bitmap); -} - -void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap) -{ - if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_INODE_BITMAP)) - return; - - bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP; - ext2fs_free_generic_bitmap(bitmap); -} - -void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap) -{ - if (!bitmap || (bitmap->magic != EXT2_ET_MAGIC_BLOCK_BITMAP)) - return; - - bitmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP; - ext2fs_free_generic_bitmap(bitmap); -} - -/* - * Free the inode cache structure - */ -static void ext2fs_free_inode_cache(struct ext2_inode_cache *icache) -{ - if (--icache->refcount) - return; - ext2fs_free_mem(&icache->buffer); - ext2fs_free_mem(&icache->cache); - icache->buffer_blk = 0; - ext2fs_free_mem(&icache); -} - -/* - * This procedure frees a badblocks list. - */ -void ext2fs_u32_list_free(ext2_u32_list bb) -{ - if (!bb || bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST) - return; - - ext2fs_free_mem(&bb->list); - ext2fs_free_mem(&bb); -} - -void ext2fs_badblocks_list_free(ext2_badblocks_list bb) -{ - ext2fs_u32_list_free((ext2_u32_list) bb); -} - - -/* - * Free a directory block list - */ -void ext2fs_free_dblist(ext2_dblist dblist) -{ - if (!dblist || (dblist->magic != EXT2_ET_MAGIC_DBLIST)) - return; - - ext2fs_free_mem(&dblist->list); - if (dblist->fs && dblist->fs->dblist == dblist) - dblist->fs->dblist = 0; - dblist->magic = 0; - ext2fs_free_mem(&dblist); -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * gen_bitmap.c --- Generic bitmap routines that used to be inlined. - * - * Copyright (C) 2001 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap, - __u32 bitno) -{ - if ((bitno < bitmap->start) || (bitno > bitmap->end)) { - ext2fs_warn_bitmap2(bitmap, EXT2FS_MARK_ERROR, bitno); - return 0; - } - return ext2fs_set_bit(bitno - bitmap->start, bitmap->bitmap); -} - -int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap, - blk_t bitno) -{ - if ((bitno < bitmap->start) || (bitno > bitmap->end)) { - ext2fs_warn_bitmap2(bitmap, EXT2FS_UNMARK_ERROR, bitno); - return 0; - } - return ext2fs_clear_bit(bitno - bitmap->start, bitmap->bitmap); -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * get_pathname.c --- do directry/inode -> name translation - * - * Copyright (C) 1993, 1994, 1995 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - * - * ext2fs_get_pathname(fs, dir, ino, name) - * - * This function translates takes two inode numbers into a - * string, placing the result in . is the containing - * directory inode, and is the inode number itself. If - * is zero, then ext2fs_get_pathname will return pathname - * of the directory . - * - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -struct get_pathname_struct { - ext2_ino_t search_ino; - ext2_ino_t parent; - char *name; - errcode_t errcode; -}; - -#ifdef __TURBOC__ -# pragma argsused -#endif -static int get_pathname_proc(struct ext2_dir_entry *dirent, - int offset EXT2FS_ATTR((unused)), - int blocksize EXT2FS_ATTR((unused)), - char *buf EXT2FS_ATTR((unused)), - void *priv_data) -{ - struct get_pathname_struct *gp; - errcode_t retval; - - gp = (struct get_pathname_struct *) priv_data; - - if (((dirent->name_len & 0xFF) == 2) && - !strncmp(dirent->name, "..", 2)) - gp->parent = dirent->inode; - if (dirent->inode == gp->search_ino) { - retval = ext2fs_get_mem((dirent->name_len & 0xFF) + 1, - &gp->name); - if (retval) { - gp->errcode = retval; - return DIRENT_ABORT; - } - strncpy(gp->name, dirent->name, (dirent->name_len & 0xFF)); - gp->name[dirent->name_len & 0xFF] = '\0'; - return DIRENT_ABORT; - } - return 0; -} - -static errcode_t ext2fs_get_pathname_int(ext2_filsys fs, ext2_ino_t dir, - ext2_ino_t ino, int maxdepth, - char *buf, char **name) -{ - struct get_pathname_struct gp; - char *parent_name, *ret; - errcode_t retval; - - if (dir == ino) { - retval = ext2fs_get_mem(2, name); - if (retval) - return retval; - strcpy(*name, (dir == EXT2_ROOT_INO) ? "/" : "."); - return 0; - } - - if (!dir || (maxdepth < 0)) { - retval = ext2fs_get_mem(4, name); - if (retval) - return retval; - strcpy(*name, "..."); - return 0; - } - - gp.search_ino = ino; - gp.parent = 0; - gp.name = 0; - gp.errcode = 0; - - retval = ext2fs_dir_iterate(fs, dir, 0, buf, get_pathname_proc, &gp); - if (retval) - goto cleanup; - if (gp.errcode) { - retval = gp.errcode; - goto cleanup; - } - - retval = ext2fs_get_pathname_int(fs, gp.parent, dir, maxdepth-1, - buf, &parent_name); - if (retval) - goto cleanup; - if (!ino) { - *name = parent_name; - return 0; - } - - if (gp.name) - retval = ext2fs_get_mem(strlen(parent_name)+strlen(gp.name)+2, - &ret); - else - retval = ext2fs_get_mem(strlen(parent_name)+5, &ret); - if (retval) - goto cleanup; - - ret[0] = 0; - if (parent_name[1]) - strcat(ret, parent_name); - strcat(ret, "/"); - if (gp.name) - strcat(ret, gp.name); - else - strcat(ret, "???"); - *name = ret; - ext2fs_free_mem(&parent_name); - retval = 0; - -cleanup: - ext2fs_free_mem(&gp.name); - return retval; -} - -errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino, - char **name) -{ - char *buf; - errcode_t retval; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - retval = ext2fs_get_mem(fs->blocksize, &buf); - if (retval) - return retval; - if (dir == ino) - ino = 0; - retval = ext2fs_get_pathname_int(fs, dir, ino, 32, buf, name); - ext2fs_free_mem(&buf); - return retval; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * getsectsize.c --- get the sector size of a device. - * - * Copyright (C) 1995, 1995 Theodore Ts'o. - * Copyright (C) 2003 VMware, Inc. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#if HAVE_UNISTD_H -#include -#endif -#if HAVE_ERRNO_H -#include -#endif -#include -#ifdef HAVE_LINUX_FD_H -#include -#include -#endif - -#if defined(__linux__) && defined(_IO) && !defined(BLKSSZGET) -#define BLKSSZGET _IO(0x12,104)/* get block device sector size */ -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -/* - * Returns the number of blocks in a partition - */ -errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize) -{ - int fd; - -#ifdef CONFIG_LFS - fd = open64(file, O_RDONLY); -#else - fd = open(file, O_RDONLY); -#endif - if (fd < 0) - return errno; - -#ifdef BLKSSZGET - if (ioctl(fd, BLKSSZGET, sectsize) >= 0) { - close(fd); - return 0; - } -#endif - *sectsize = 0; - close(fd); - return 0; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * getsize.c --- get the size of a partition. - * - * Copyright (C) 1995, 1995 Theodore Ts'o. - * Copyright (C) 2003 VMware, Inc. - * - * Windows version of ext2fs_get_device_size by Chris Li, VMware. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#if HAVE_UNISTD_H -#include -#endif -#if HAVE_ERRNO_H -#include -#endif -#include -#ifdef HAVE_SYS_IOCTL_H -#include -#endif -#ifdef HAVE_LINUX_FD_H -#include -#endif -#ifdef HAVE_SYS_DISKLABEL_H -#include -#endif -#ifdef HAVE_SYS_DISK_H -#ifdef HAVE_SYS_QUEUE_H -#include /* for LIST_HEAD */ -#endif -#include -#endif -#ifdef __linux__ -#include -#endif - -#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE) -#define BLKGETSIZE _IO(0x12,96) /* return device size */ -#endif - -#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64) -#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */ -#endif - -#ifdef APPLE_DARWIN -#define BLKGETSIZE DKIOCGETBLOCKCOUNT32 -#endif /* APPLE_DARWIN */ - -#include "ext2_fs.h" -#include "ext2fs.h" - -#if defined(__CYGWIN__) || defined(WIN32) -#include -#include - -#if (_WIN32_WINNT >= 0x0500) -#define HAVE_GET_FILE_SIZE_EX 1 -#endif - -errcode_t ext2fs_get_device_size(const char *file, int blocksize, - blk_t *retblocks) -{ - HANDLE dev; - PARTITION_INFORMATION pi; - DISK_GEOMETRY gi; - DWORD retbytes; -#ifdef HAVE_GET_FILE_SIZE_EX - LARGE_INTEGER filesize; -#else - DWORD filesize; -#endif /* HAVE_GET_FILE_SIZE_EX */ - - dev = CreateFile(file, GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE , - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - - if (dev == INVALID_HANDLE_VALUE) - return EBADF; - if (DeviceIoControl(dev, IOCTL_DISK_GET_PARTITION_INFO, - &pi, sizeof(PARTITION_INFORMATION), - &pi, sizeof(PARTITION_INFORMATION), - &retbytes, NULL)) { - - *retblocks = pi.PartitionLength.QuadPart / blocksize; - - } else if (DeviceIoControl(dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, - &gi, sizeof(DISK_GEOMETRY), - &gi, sizeof(DISK_GEOMETRY), - &retbytes, NULL)) { - - *retblocks = gi.BytesPerSector * - gi.SectorsPerTrack * - gi.TracksPerCylinder * - gi.Cylinders.QuadPart / blocksize; - -#ifdef HAVE_GET_FILE_SIZE_EX - } else if (GetFileSizeEx(dev, &filesize)) { - *retblocks = filesize.QuadPart / blocksize; - } -#else - } else { - filesize = GetFileSize(dev, NULL); - if (INVALID_FILE_SIZE != filesize) { - *retblocks = filesize / blocksize; - } - } -#endif /* HAVE_GET_FILE_SIZE_EX */ - - CloseHandle(dev); - return 0; -} - -#else - -static int valid_offset (int fd, ext2_loff_t offset) -{ - char ch; - - if (ext2fs_llseek (fd, offset, 0) < 0) - return 0; - if (read (fd, &ch, 1) < 1) - return 0; - return 1; -} - -/* - * Returns the number of blocks in a partition - */ -errcode_t ext2fs_get_device_size(const char *file, int blocksize, - blk_t *retblocks) -{ - int fd; - int valid_blkgetsize64 = 1; -#ifdef __linux__ - struct utsname ut; -#endif - unsigned long long size64; - unsigned long size; - ext2_loff_t high, low; -#ifdef FDGETPRM - struct floppy_struct this_floppy; -#endif -#ifdef HAVE_SYS_DISKLABEL_H - int part; - struct disklabel lab; - struct partition *pp; - char ch; -#endif /* HAVE_SYS_DISKLABEL_H */ - -#ifdef CONFIG_LFS - fd = open64(file, O_RDONLY); -#else - fd = open(file, O_RDONLY); -#endif - if (fd < 0) - return errno; - -#ifdef DKIOCGETBLOCKCOUNT /* For Apple Darwin */ - if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) { - if ((sizeof(*retblocks) < sizeof(unsigned long long)) - && ((size64 / (blocksize / 512)) > 0xFFFFFFFF)) - return EFBIG; - close(fd); - *retblocks = size64 / (blocksize / 512); - return 0; - } -#endif - -#ifdef BLKGETSIZE64 -#ifdef __linux__ - uname(&ut); - if ((ut.release[0] == '2') && (ut.release[1] == '.') && - (ut.release[2] < '6') && (ut.release[3] == '.')) - valid_blkgetsize64 = 0; -#endif - if (valid_blkgetsize64 && - ioctl(fd, BLKGETSIZE64, &size64) >= 0) { - if ((sizeof(*retblocks) < sizeof(unsigned long long)) - && ((size64 / blocksize) > 0xFFFFFFFF)) - return EFBIG; - close(fd); - *retblocks = size64 / blocksize; - return 0; - } -#endif - -#ifdef BLKGETSIZE - if (ioctl(fd, BLKGETSIZE, &size) >= 0) { - close(fd); - *retblocks = size / (blocksize / 512); - return 0; - } -#endif - -#ifdef FDGETPRM - if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) { - close(fd); - *retblocks = this_floppy.size / (blocksize / 512); - return 0; - } -#endif - -#ifdef HAVE_SYS_DISKLABEL_H -#if defined(DIOCGMEDIASIZE) - { - off_t ms; - u_int bs; - if (ioctl(fd, DIOCGMEDIASIZE, &ms) >= 0) { - *retblocks = ms / blocksize; - return 0; - } - } -#elif defined(DIOCGDINFO) - /* old disklabel interface */ - part = strlen(file) - 1; - if (part >= 0) { - ch = file[part]; - if (isdigit(ch)) - part = 0; - else if (ch >= 'a' && ch <= 'h') - part = ch - 'a'; - else - part = -1; - } - if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) { - pp = &lab.d_partitions[part]; - if (pp->p_size) { - close(fd); - *retblocks = pp->p_size / (blocksize / 512); - return 0; - } - } -#endif /* defined(DIOCG*) */ -#endif /* HAVE_SYS_DISKLABEL_H */ - - /* - * OK, we couldn't figure it out by using a specialized ioctl, - * which is generally the best way. So do binary search to - * find the size of the partition. - */ - low = 0; - for (high = 1024; valid_offset (fd, high); high *= 2) - low = high; - while (low < high - 1) - { - const ext2_loff_t mid = (low + high) / 2; - - if (valid_offset (fd, mid)) - low = mid; - else - high = mid; - } - valid_offset (fd, 0); - close(fd); - size64 = low + 1; - if ((sizeof(*retblocks) < sizeof(unsigned long long)) - && ((size64 / blocksize) > 0xFFFFFFFF)) - return EFBIG; - *retblocks = size64 / blocksize; - return 0; -} - -#endif /* WIN32 */ - -#ifdef DEBUG -int main(int argc, char **argv) -{ - blk_t blocks; - int retval; - - if (argc < 2) { - fprintf(stderr, "Usage: %s device\n", argv[0]); - exit(1); - } - - retval = ext2fs_get_device_size(argv[1], 1024, &blocks); - if (retval) { - com_err(argv[0], retval, - "while calling ext2fs_get_device_size"); - exit(1); - } - printf("Device %s has %d 1k blocks.\n", argv[1], blocks); - exit(0); -} -#endif diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * icount.c --- an efficient inode count abstraction - * - * Copyright (C) 1997 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#if HAVE_UNISTD_H -#include -#endif -#include -#include - -#include "ext2_fs.h" -#include "ext2fs.h" - -/* - * The data storage strategy used by icount relies on the observation - * that most inode counts are either zero (for non-allocated inodes), - * one (for most files), and only a few that are two or more - * (directories and files that are linked to more than one directory). - * - * Also, e2fsck tends to load the icount data sequentially. - * - * So, we use an inode bitmap to indicate which inodes have a count of - * one, and then use a sorted list to store the counts for inodes - * which are greater than one. - * - * We also use an optional bitmap to indicate which inodes are already - * in the sorted list, to speed up the use of this abstraction by - * e2fsck's pass 2. Pass 2 increments inode counts as it finds them, - * so this extra bitmap avoids searching the sorted list to see if a - * particular inode is on the sorted list already. - */ - -struct ext2_icount_el { - ext2_ino_t ino; - __u16 count; -}; - -struct ext2_icount { - errcode_t magic; - ext2fs_inode_bitmap single; - ext2fs_inode_bitmap multiple; - ext2_ino_t count; - ext2_ino_t size; - ext2_ino_t num_inodes; - ext2_ino_t cursor; - struct ext2_icount_el *list; -}; - -void ext2fs_free_icount(ext2_icount_t icount) -{ - if (!icount) - return; - - icount->magic = 0; - ext2fs_free_mem(&icount->list); - ext2fs_free_inode_bitmap(icount->single); - ext2fs_free_inode_bitmap(icount->multiple); - ext2fs_free_mem(&icount); -} - -errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, unsigned int size, - ext2_icount_t hint, ext2_icount_t *ret) -{ - ext2_icount_t icount; - errcode_t retval; - size_t bytes; - ext2_ino_t i; - - if (hint) { - EXT2_CHECK_MAGIC(hint, EXT2_ET_MAGIC_ICOUNT); - if (hint->size > size) - size = (size_t) hint->size; - } - - retval = ext2fs_get_mem(sizeof(struct ext2_icount), &icount); - if (retval) - return retval; - memset(icount, 0, sizeof(struct ext2_icount)); - - retval = ext2fs_allocate_inode_bitmap(fs, 0, - &icount->single); - if (retval) - goto errout; - - if (flags & EXT2_ICOUNT_OPT_INCREMENT) { - retval = ext2fs_allocate_inode_bitmap(fs, 0, - &icount->multiple); - if (retval) - goto errout; - } else - icount->multiple = 0; - - if (size) { - icount->size = size; - } else { - /* - * Figure out how many special case inode counts we will - * have. We know we will need one for each directory; - * we also need to reserve some extra room for file links - */ - retval = ext2fs_get_num_dirs(fs, &icount->size); - if (retval) - goto errout; - icount->size += fs->super->s_inodes_count / 50; - } - - bytes = (size_t) (icount->size * sizeof(struct ext2_icount_el)); - retval = ext2fs_get_mem(bytes, &icount->list); - if (retval) - goto errout; - memset(icount->list, 0, bytes); - - icount->magic = EXT2_ET_MAGIC_ICOUNT; - icount->count = 0; - icount->cursor = 0; - icount->num_inodes = fs->super->s_inodes_count; - - /* - * Populate the sorted list with those entries which were - * found in the hint icount (since those are ones which will - * likely need to be in the sorted list this time around). - */ - if (hint) { - for (i=0; i < hint->count; i++) - icount->list[i].ino = hint->list[i].ino; - icount->count = hint->count; - } - - *ret = icount; - return 0; - -errout: - ext2fs_free_icount(icount); - return retval; -} - -errcode_t ext2fs_create_icount(ext2_filsys fs, int flags, - unsigned int size, - ext2_icount_t *ret) -{ - return ext2fs_create_icount2(fs, flags, size, 0, ret); -} - -/* - * insert_icount_el() --- Insert a new entry into the sorted list at a - * specified position. - */ -static struct ext2_icount_el *insert_icount_el(ext2_icount_t icount, - ext2_ino_t ino, int pos) -{ - struct ext2_icount_el *el; - errcode_t retval; - ext2_ino_t new_size = 0; - int num; - - if (icount->count >= icount->size) { - if (icount->count) { - new_size = icount->list[(unsigned)icount->count-1].ino; - new_size = (ext2_ino_t) (icount->count * - ((float) icount->num_inodes / new_size)); - } - if (new_size < (icount->size + 100)) - new_size = icount->size + 100; - retval = ext2fs_resize_mem((size_t) icount->size * - sizeof(struct ext2_icount_el), - (size_t) new_size * - sizeof(struct ext2_icount_el), - &icount->list); - if (retval) - return 0; - icount->size = new_size; - } - num = (int) icount->count - pos; - if (num < 0) - return 0; /* should never happen */ - if (num) { - memmove(&icount->list[pos+1], &icount->list[pos], - sizeof(struct ext2_icount_el) * num); - } - icount->count++; - el = &icount->list[pos]; - el->count = 0; - el->ino = ino; - return el; -} - -/* - * get_icount_el() --- given an inode number, try to find icount - * information in the sorted list. If the create flag is set, - * and we can't find an entry, create one in the sorted list. - */ -static struct ext2_icount_el *get_icount_el(ext2_icount_t icount, - ext2_ino_t ino, int create) -{ - float range; - int low, high, mid; - ext2_ino_t lowval, highval; - - if (!icount || !icount->list) - return 0; - - if (create && ((icount->count == 0) || - (ino > icount->list[(unsigned)icount->count-1].ino))) { - return insert_icount_el(icount, ino, (unsigned) icount->count); - } - if (icount->count == 0) - return 0; - - if (icount->cursor >= icount->count) - icount->cursor = 0; - if (ino == icount->list[icount->cursor].ino) - return &icount->list[icount->cursor++]; - low = 0; - high = (int) icount->count-1; - while (low <= high) { - if (low == high) - mid = low; - else { - /* Interpolate for efficiency */ - lowval = icount->list[low].ino; - highval = icount->list[high].ino; - - if (ino < lowval) - range = 0; - else if (ino > highval) - range = 1; - else - range = ((float) (ino - lowval)) / - (highval - lowval); - mid = low + ((int) (range * (high-low))); - } - if (ino == icount->list[mid].ino) { - icount->cursor = mid+1; - return &icount->list[mid]; - } - if (ino < icount->list[mid].ino) - high = mid-1; - else - low = mid+1; - } - /* - * If we need to create a new entry, it should be right at - * low (where high will be left at low-1). - */ - if (create) - return insert_icount_el(icount, ino, low); - return 0; -} - -errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *out) -{ - errcode_t ret = 0; - unsigned int i; - const char *bad = "bad icount"; - - EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); - - if (icount->count > icount->size) { - fprintf(out, "%s: count > size\n", bad); - return EXT2_ET_INVALID_ARGUMENT; - } - for (i=1; i < icount->count; i++) { - if (icount->list[i-1].ino >= icount->list[i].ino) { - fprintf(out, "%s: list[%d].ino=%u, list[%d].ino=%u\n", - bad, i-1, icount->list[i-1].ino, - i, icount->list[i].ino); - ret = EXT2_ET_INVALID_ARGUMENT; - } - } - return ret; -} - -errcode_t ext2fs_icount_fetch(ext2_icount_t icount, ext2_ino_t ino, __u16 *ret) -{ - struct ext2_icount_el *el; - - EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); - - if (!ino || (ino > icount->num_inodes)) - return EXT2_ET_INVALID_ARGUMENT; - - if (ext2fs_test_inode_bitmap(icount->single, ino)) { - *ret = 1; - return 0; - } - if (icount->multiple && - !ext2fs_test_inode_bitmap(icount->multiple, ino)) { - *ret = 0; - return 0; - } - el = get_icount_el(icount, ino, 0); - if (!el) { - *ret = 0; - return 0; - } - *ret = el->count; - return 0; -} - -errcode_t ext2fs_icount_increment(ext2_icount_t icount, ext2_ino_t ino, - __u16 *ret) -{ - struct ext2_icount_el *el; - - EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); - - if (!ino || (ino > icount->num_inodes)) - return EXT2_ET_INVALID_ARGUMENT; - - if (ext2fs_test_inode_bitmap(icount->single, ino)) { - /* - * If the existing count is 1, then we know there is - * no entry in the list. - */ - el = get_icount_el(icount, ino, 1); - if (!el) - return EXT2_ET_NO_MEMORY; - ext2fs_unmark_inode_bitmap(icount->single, ino); - el->count = 2; - } else if (icount->multiple) { - /* - * The count is either zero or greater than 1; if the - * inode is set in icount->multiple, then there should - * be an entry in the list, so find it using - * get_icount_el(). - */ - if (ext2fs_test_inode_bitmap(icount->multiple, ino)) { - el = get_icount_el(icount, ino, 1); - if (!el) - return EXT2_ET_NO_MEMORY; - el->count++; - } else { - /* - * The count was zero; mark the single bitmap - * and return. - */ - zero_count: - ext2fs_mark_inode_bitmap(icount->single, ino); - if (ret) - *ret = 1; - return 0; - } - } else { - /* - * The count is either zero or greater than 1; try to - * find an entry in the list to determine which. - */ - el = get_icount_el(icount, ino, 0); - if (!el) { - /* No entry means the count was zero */ - goto zero_count; - } - el = get_icount_el(icount, ino, 1); - if (!el) - return EXT2_ET_NO_MEMORY; - el->count++; - } - if (icount->multiple) - ext2fs_mark_inode_bitmap(icount->multiple, ino); - if (ret) - *ret = el->count; - return 0; -} - -errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino, - __u16 *ret) -{ - struct ext2_icount_el *el; - - if (!ino || (ino > icount->num_inodes)) - return EXT2_ET_INVALID_ARGUMENT; - - EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); - - if (ext2fs_test_inode_bitmap(icount->single, ino)) { - ext2fs_unmark_inode_bitmap(icount->single, ino); - if (icount->multiple) - ext2fs_unmark_inode_bitmap(icount->multiple, ino); - else { - el = get_icount_el(icount, ino, 0); - if (el) - el->count = 0; - } - if (ret) - *ret = 0; - return 0; - } - - if (icount->multiple && - !ext2fs_test_inode_bitmap(icount->multiple, ino)) - return EXT2_ET_INVALID_ARGUMENT; - - el = get_icount_el(icount, ino, 0); - if (!el || el->count == 0) - return EXT2_ET_INVALID_ARGUMENT; - - el->count--; - if (el->count == 1) - ext2fs_mark_inode_bitmap(icount->single, ino); - if ((el->count == 0) && icount->multiple) - ext2fs_unmark_inode_bitmap(icount->multiple, ino); - - if (ret) - *ret = el->count; - return 0; -} - -errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino, - __u16 count) -{ - struct ext2_icount_el *el; - - if (!ino || (ino > icount->num_inodes)) - return EXT2_ET_INVALID_ARGUMENT; - - EXT2_CHECK_MAGIC(icount, EXT2_ET_MAGIC_ICOUNT); - - if (count == 1) { - ext2fs_mark_inode_bitmap(icount->single, ino); - if (icount->multiple) - ext2fs_unmark_inode_bitmap(icount->multiple, ino); - return 0; - } - if (count == 0) { - ext2fs_unmark_inode_bitmap(icount->single, ino); - if (icount->multiple) { - /* - * If the icount->multiple bitmap is enabled, - * we can just clear both bitmaps and we're done - */ - ext2fs_unmark_inode_bitmap(icount->multiple, ino); - } else { - el = get_icount_el(icount, ino, 0); - if (el) - el->count = 0; - } - return 0; - } - - /* - * Get the icount element - */ - el = get_icount_el(icount, ino, 1); - if (!el) - return EXT2_ET_NO_MEMORY; - el->count = count; - ext2fs_unmark_inode_bitmap(icount->single, ino); - if (icount->multiple) - ext2fs_mark_inode_bitmap(icount->multiple, ino); - return 0; -} - -ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount) -{ - if (!icount || icount->magic != EXT2_ET_MAGIC_ICOUNT) - return 0; - - return icount->size; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * image.c --- writes out the critical parts of the filesystem as a - * flat file. - * - * Copyright (C) 2000 Theodore Ts'o. - * - * Note: this uses the POSIX IO interfaces, unlike most of the other - * functions in this library. So sue me. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#if HAVE_ERRNO_H -#include -#endif -#include -#include -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -#ifndef HAVE_TYPE_SSIZE_T -typedef int ssize_t; -#endif - -/* - * This function returns 1 if the specified block is all zeros - */ -static int check_zero_block(char *buf, int blocksize) -{ - char *cp = buf; - int left = blocksize; - - while (left > 0) { - if (*cp++) - return 0; - left--; - } - return 1; -} - -/* - * Write the inode table out as a single block. - */ -#define BUF_BLOCKS 32 - -errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags) -{ - unsigned int group, left, c, d; - char *buf, *cp; - blk_t blk; - ssize_t actual; - errcode_t retval; - - buf = xmalloc(fs->blocksize * BUF_BLOCKS); - - for (group = 0; group < fs->group_desc_count; group++) { - blk = fs->group_desc[(unsigned)group].bg_inode_table; - if (!blk) - return EXT2_ET_MISSING_INODE_TABLE; - left = fs->inode_blocks_per_group; - while (left) { - c = BUF_BLOCKS; - if (c > left) - c = left; - retval = io_channel_read_blk(fs->io, blk, c, buf); - if (retval) - goto errout; - cp = buf; - while (c) { - if (!(flags & IMAGER_FLAG_SPARSEWRITE)) { - d = c; - goto skip_sparse; - } - /* Skip zero blocks */ - if (check_zero_block(cp, fs->blocksize)) { - c--; - blk++; - left--; - cp += fs->blocksize; - lseek(fd, fs->blocksize, SEEK_CUR); - continue; - } - /* Find non-zero blocks */ - for (d=1; d < c; d++) { - if (check_zero_block(cp + d*fs->blocksize, fs->blocksize)) - break; - } - skip_sparse: - actual = write(fd, cp, fs->blocksize * d); - if (actual == -1) { - retval = errno; - goto errout; - } - if (actual != (ssize_t) (fs->blocksize * d)) { - retval = EXT2_ET_SHORT_WRITE; - goto errout; - } - blk += d; - left -= d; - cp += fs->blocksize * d; - c -= d; - } - } - } - retval = 0; - -errout: - free(buf); - return retval; -} - -/* - * Read in the inode table and stuff it into place - */ -errcode_t ext2fs_image_inode_read(ext2_filsys fs, int fd, - int flags EXT2FS_ATTR((unused))) -{ - unsigned int group, c, left; - char *buf; - blk_t blk; - ssize_t actual; - errcode_t retval; - - buf = xmalloc(fs->blocksize * BUF_BLOCKS); - - for (group = 0; group < fs->group_desc_count; group++) { - blk = fs->group_desc[(unsigned)group].bg_inode_table; - if (!blk) { - retval = EXT2_ET_MISSING_INODE_TABLE; - goto errout; - } - left = fs->inode_blocks_per_group; - while (left) { - c = BUF_BLOCKS; - if (c > left) - c = left; - actual = read(fd, buf, fs->blocksize * c); - if (actual == -1) { - retval = errno; - goto errout; - } - if (actual != (ssize_t) (fs->blocksize * c)) { - retval = EXT2_ET_SHORT_READ; - goto errout; - } - retval = io_channel_write_blk(fs->io, blk, c, buf); - if (retval) - goto errout; - - blk += c; - left -= c; - } - } - retval = ext2fs_flush_icache(fs); - -errout: - free(buf); - return retval; -} - -/* - * Write out superblock and group descriptors - */ -errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, - int flags EXT2FS_ATTR((unused))) -{ - char *buf, *cp; - ssize_t actual; - errcode_t retval; - - buf = xmalloc(fs->blocksize); - - /* - * Write out the superblock - */ - memset(buf, 0, fs->blocksize); - memcpy(buf, fs->super, SUPERBLOCK_SIZE); - actual = write(fd, buf, fs->blocksize); - if (actual == -1) { - retval = errno; - goto errout; - } - if (actual != (ssize_t) fs->blocksize) { - retval = EXT2_ET_SHORT_WRITE; - goto errout; - } - - /* - * Now write out the block group descriptors - */ - cp = (char *) fs->group_desc; - actual = write(fd, cp, fs->blocksize * fs->desc_blocks); - if (actual == -1) { - retval = errno; - goto errout; - } - if (actual != (ssize_t) (fs->blocksize * fs->desc_blocks)) { - retval = EXT2_ET_SHORT_WRITE; - goto errout; - } - - retval = 0; - -errout: - free(buf); - return retval; -} - -/* - * Read the superblock and group descriptors and overwrite them. - */ -errcode_t ext2fs_image_super_read(ext2_filsys fs, int fd, - int flags EXT2FS_ATTR((unused))) -{ - char *buf; - ssize_t actual, size; - errcode_t retval; - - size = fs->blocksize * (fs->group_desc_count + 1); - buf = xmalloc(size); - - /* - * Read it all in. - */ - actual = read(fd, buf, size); - if (actual == -1) { - retval = errno; - goto errout; - } - if (actual != size) { - retval = EXT2_ET_SHORT_READ; - goto errout; - } - - /* - * Now copy in the superblock and group descriptors - */ - memcpy(fs->super, buf, SUPERBLOCK_SIZE); - - memcpy(fs->group_desc, buf + fs->blocksize, - fs->blocksize * fs->group_desc_count); - - retval = 0; - -errout: - free(buf); - return retval; -} - -/* - * Write the block/inode bitmaps. - */ -errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags) -{ - char *ptr; - int c, size; - char zero_buf[1024]; - ssize_t actual; - errcode_t retval; - - if (flags & IMAGER_FLAG_INODEMAP) { - if (!fs->inode_map) { - retval = ext2fs_read_inode_bitmap(fs); - if (retval) - return retval; - } - ptr = fs->inode_map->bitmap; - size = (EXT2_INODES_PER_GROUP(fs->super) / 8); - } else { - if (!fs->block_map) { - retval = ext2fs_read_block_bitmap(fs); - if (retval) - return retval; - } - ptr = fs->block_map->bitmap; - size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8; - } - size = size * fs->group_desc_count; - - actual = write(fd, ptr, size); - if (actual == -1) { - retval = errno; - goto errout; - } - if (actual != size) { - retval = EXT2_ET_SHORT_WRITE; - goto errout; - } - size = size % fs->blocksize; - memset(zero_buf, 0, sizeof(zero_buf)); - if (size) { - size = fs->blocksize - size; - while (size) { - c = size; - if (c > (int) sizeof(zero_buf)) - c = sizeof(zero_buf); - actual = write(fd, zero_buf, c); - if (actual == -1) { - retval = errno; - goto errout; - } - if (actual != c) { - retval = EXT2_ET_SHORT_WRITE; - goto errout; - } - size -= c; - } - } - retval = 0; -errout: - return retval; -} - - -/* - * Read the block/inode bitmaps. - */ -errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags) -{ - char *ptr, *buf = NULL; - int size; - ssize_t actual; - errcode_t retval; - - if (flags & IMAGER_FLAG_INODEMAP) { - if (!fs->inode_map) { - retval = ext2fs_read_inode_bitmap(fs); - if (retval) - return retval; - } - ptr = fs->inode_map->bitmap; - size = (EXT2_INODES_PER_GROUP(fs->super) / 8); - } else { - if (!fs->block_map) { - retval = ext2fs_read_block_bitmap(fs); - if (retval) - return retval; - } - ptr = fs->block_map->bitmap; - size = EXT2_BLOCKS_PER_GROUP(fs->super) / 8; - } - size = size * fs->group_desc_count; - - buf = xmalloc(size); - - actual = read(fd, buf, size); - if (actual == -1) { - retval = errno; - goto errout; - } - if (actual != size) { - retval = EXT2_ET_SHORT_WRITE; - goto errout; - } - memcpy(ptr, buf, size); - - retval = 0; -errout: - free(buf); - return retval; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * ind_block.c --- indirect block I/O routines - * - * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - * 2001, 2002, 2003, 2004, 2005 by Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -errcode_t ext2fs_read_ind_block(ext2_filsys fs, blk_t blk, void *buf) -{ - errcode_t retval; -#if BB_BIG_ENDIAN - blk_t *block_nr; - int i; - int limit = fs->blocksize >> 2; -#endif - - if ((fs->flags & EXT2_FLAG_IMAGE_FILE) && - (fs->io != fs->image_io)) - memset(buf, 0, fs->blocksize); - else { - retval = io_channel_read_blk(fs->io, blk, 1, buf); - if (retval) - return retval; - } -#if BB_BIG_ENDIAN - if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_READ)) { - block_nr = (blk_t *) buf; - for (i = 0; i < limit; i++, block_nr++) - *block_nr = ext2fs_swab32(*block_nr); - } -#endif - return 0; -} - -errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf) -{ -#if BB_BIG_ENDIAN - blk_t *block_nr; - int i; - int limit = fs->blocksize >> 2; -#endif - - if (fs->flags & EXT2_FLAG_IMAGE_FILE) - return 0; - -#if BB_BIG_ENDIAN - if (fs->flags & (EXT2_FLAG_SWAP_BYTES | EXT2_FLAG_SWAP_BYTES_WRITE)) { - block_nr = (blk_t *) buf; - for (i = 0; i < limit; i++, block_nr++) - *block_nr = ext2fs_swab32(*block_nr); - } -#endif - return io_channel_write_blk(fs->io, blk, 1, buf); -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * initialize.c --- initialize a filesystem handle given superblock - * parameters. Used by mke2fs when initializing a filesystem. - * - * Copyright (C) 1994, 1995, 1996 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -#if defined(__linux__) && defined(EXT2_OS_LINUX) -#define CREATOR_OS EXT2_OS_LINUX -#else -#if defined(__GNU__) && defined(EXT2_OS_HURD) -#define CREATOR_OS EXT2_OS_HURD -#else -#if defined(__FreeBSD__) && defined(EXT2_OS_FREEBSD) -#define CREATOR_OS EXT2_OS_FREEBSD -#else -#if defined(LITES) && defined(EXT2_OS_LITES) -#define CREATOR_OS EXT2_OS_LITES -#else -#define CREATOR_OS EXT2_OS_LINUX /* by default */ -#endif /* defined(LITES) && defined(EXT2_OS_LITES) */ -#endif /* defined(__FreeBSD__) && defined(EXT2_OS_FREEBSD) */ -#endif /* defined(__GNU__) && defined(EXT2_OS_HURD) */ -#endif /* defined(__linux__) && defined(EXT2_OS_LINUX) */ - -/* - * Note we override the kernel include file's idea of what the default - * check interval (never) should be. It's a good idea to check at - * least *occasionally*, specially since servers will never rarely get - * to reboot, since Linux is so robust these days. :-) - * - * 180 days (six months) seems like a good value. - */ -#ifdef EXT2_DFL_CHECKINTERVAL -#undef EXT2_DFL_CHECKINTERVAL -#endif -#define EXT2_DFL_CHECKINTERVAL (86400L * 180L) - -/* - * Calculate the number of GDT blocks to reserve for online filesystem growth. - * The absolute maximum number of GDT blocks we can reserve is determined by - * the number of block pointers that can fit into a single block. - */ -static int calc_reserved_gdt_blocks(ext2_filsys fs) -{ - struct ext2_super_block *sb = fs->super; - unsigned long bpg = sb->s_blocks_per_group; - unsigned int gdpb = fs->blocksize / sizeof(struct ext2_group_desc); - unsigned long max_blocks = 0xffffffff; - unsigned long rsv_groups; - int rsv_gdb; - - /* We set it at 1024x the current filesystem size, or - * the upper block count limit (2^32), whichever is lower. - */ - if (sb->s_blocks_count < max_blocks / 1024) - max_blocks = sb->s_blocks_count * 1024; - rsv_groups = (max_blocks - sb->s_first_data_block + bpg - 1) / bpg; - rsv_gdb = (rsv_groups + gdpb - 1) / gdpb - fs->desc_blocks; - if (rsv_gdb > EXT2_ADDR_PER_BLOCK(sb)) - rsv_gdb = EXT2_ADDR_PER_BLOCK(sb); -#ifdef RES_GDT_DEBUG - printf("max_blocks %lu, rsv_groups = %lu, rsv_gdb = %u\n", - max_blocks, rsv_groups, rsv_gdb); -#endif - - return rsv_gdb; -} - -errcode_t ext2fs_initialize(const char *name, int flags, - struct ext2_super_block *param, - io_manager manager, ext2_filsys *ret_fs) -{ - ext2_filsys fs; - errcode_t retval; - struct ext2_super_block *super; - int frags_per_block; - unsigned int rem; - unsigned int overhead = 0; - blk_t group_block; - unsigned int ipg; - dgrp_t i; - blk_t numblocks; - int rsv_gdt; - char *buf; - - if (!param || !param->s_blocks_count) - return EXT2_ET_INVALID_ARGUMENT; - - retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs); - if (retval) - return retval; - - memset(fs, 0, sizeof(struct struct_ext2_filsys)); - fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS; - fs->flags = flags | EXT2_FLAG_RW; - fs->umask = 022; -#ifdef WORDS_BIGENDIAN - fs->flags |= EXT2_FLAG_SWAP_BYTES; -#endif - retval = manager->open(name, IO_FLAG_RW, &fs->io); - if (retval) - goto cleanup; - fs->image_io = fs->io; - fs->io->app_data = fs; - retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name); - if (retval) - goto cleanup; - - strcpy(fs->device_name, name); - retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super); - if (retval) - goto cleanup; - fs->super = super; - - memset(super, 0, SUPERBLOCK_SIZE); - -#define set_field(field, default) (super->field = param->field ? \ - param->field : (default)) - - super->s_magic = EXT2_SUPER_MAGIC; - super->s_state = EXT2_VALID_FS; - - set_field(s_log_block_size, 0); /* default blocksize: 1024 bytes */ - set_field(s_log_frag_size, 0); /* default fragsize: 1024 bytes */ - set_field(s_first_data_block, super->s_log_block_size ? 0 : 1); - set_field(s_max_mnt_count, EXT2_DFL_MAX_MNT_COUNT); - set_field(s_errors, EXT2_ERRORS_DEFAULT); - set_field(s_feature_compat, 0); - set_field(s_feature_incompat, 0); - set_field(s_feature_ro_compat, 0); - set_field(s_first_meta_bg, 0); - if (super->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) { - retval = EXT2_ET_UNSUPP_FEATURE; - goto cleanup; - } - if (super->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) { - retval = EXT2_ET_RO_UNSUPP_FEATURE; - goto cleanup; - } - - set_field(s_rev_level, EXT2_GOOD_OLD_REV); - if (super->s_rev_level >= EXT2_DYNAMIC_REV) { - set_field(s_first_ino, EXT2_GOOD_OLD_FIRST_INO); - set_field(s_inode_size, EXT2_GOOD_OLD_INODE_SIZE); - } - - set_field(s_checkinterval, EXT2_DFL_CHECKINTERVAL); - super->s_mkfs_time = super->s_lastcheck = time(NULL); - - super->s_creator_os = CREATOR_OS; - - fs->blocksize = EXT2_BLOCK_SIZE(super); - fs->fragsize = EXT2_FRAG_SIZE(super); - frags_per_block = fs->blocksize / fs->fragsize; - - /* default: (fs->blocksize*8) blocks/group, up to 2^16 (GDT limit) */ - set_field(s_blocks_per_group, fs->blocksize * 8); - if (super->s_blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(super)) - super->s_blocks_per_group = EXT2_MAX_BLOCKS_PER_GROUP(super); - super->s_frags_per_group = super->s_blocks_per_group * frags_per_block; - - super->s_blocks_count = param->s_blocks_count; - super->s_r_blocks_count = param->s_r_blocks_count; - if (super->s_r_blocks_count >= param->s_blocks_count) { - retval = EXT2_ET_INVALID_ARGUMENT; - goto cleanup; - } - - /* - * If we're creating an external journal device, we don't need - * to bother with the rest. - */ - if (super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) { - fs->group_desc_count = 0; - ext2fs_mark_super_dirty(fs); - *ret_fs = fs; - return 0; - } - -retry: - fs->group_desc_count = (super->s_blocks_count - - super->s_first_data_block + - EXT2_BLOCKS_PER_GROUP(super) - 1) - / EXT2_BLOCKS_PER_GROUP(super); - if (fs->group_desc_count == 0) { - retval = EXT2_ET_TOOSMALL; - goto cleanup; - } - fs->desc_blocks = (fs->group_desc_count + - EXT2_DESC_PER_BLOCK(super) - 1) - / EXT2_DESC_PER_BLOCK(super); - - i = fs->blocksize >= 4096 ? 1 : 4096 / fs->blocksize; - set_field(s_inodes_count, super->s_blocks_count / i); - - /* - * Make sure we have at least EXT2_FIRST_INO + 1 inodes, so - * that we have enough inodes for the filesystem(!) - */ - if (super->s_inodes_count < EXT2_FIRST_INODE(super)+1) - super->s_inodes_count = EXT2_FIRST_INODE(super)+1; - - /* - * There should be at least as many inodes as the user - * requested. Figure out how many inodes per group that - * should be. But make sure that we don't allocate more than - * one bitmap's worth of inodes each group. - */ - ipg = (super->s_inodes_count + fs->group_desc_count - 1) / - fs->group_desc_count; - if (ipg > fs->blocksize * 8) { - if (super->s_blocks_per_group >= 256) { - /* Try again with slightly different parameters */ - super->s_blocks_per_group -= 8; - super->s_blocks_count = param->s_blocks_count; - super->s_frags_per_group = super->s_blocks_per_group * - frags_per_block; - goto retry; - } else - return EXT2_ET_TOO_MANY_INODES; - } - - if (ipg > (unsigned) EXT2_MAX_INODES_PER_GROUP(super)) - ipg = EXT2_MAX_INODES_PER_GROUP(super); - - super->s_inodes_per_group = ipg; - if (super->s_inodes_count > ipg * fs->group_desc_count) - super->s_inodes_count = ipg * fs->group_desc_count; - - /* - * Make sure the number of inodes per group completely fills - * the inode table blocks in the descriptor. If not, add some - * additional inodes/group. Waste not, want not... - */ - fs->inode_blocks_per_group = (((super->s_inodes_per_group * - EXT2_INODE_SIZE(super)) + - EXT2_BLOCK_SIZE(super) - 1) / - EXT2_BLOCK_SIZE(super)); - super->s_inodes_per_group = ((fs->inode_blocks_per_group * - EXT2_BLOCK_SIZE(super)) / - EXT2_INODE_SIZE(super)); - /* - * Finally, make sure the number of inodes per group is a - * multiple of 8. This is needed to simplify the bitmap - * splicing code. - */ - super->s_inodes_per_group &= ~7; - fs->inode_blocks_per_group = (((super->s_inodes_per_group * - EXT2_INODE_SIZE(super)) + - EXT2_BLOCK_SIZE(super) - 1) / - EXT2_BLOCK_SIZE(super)); - - /* - * adjust inode count to reflect the adjusted inodes_per_group - */ - super->s_inodes_count = super->s_inodes_per_group * - fs->group_desc_count; - super->s_free_inodes_count = super->s_inodes_count; - - /* - * check the number of reserved group descriptor table blocks - */ - if (super->s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INO) - rsv_gdt = calc_reserved_gdt_blocks(fs); - else - rsv_gdt = 0; - set_field(s_reserved_gdt_blocks, rsv_gdt); - if (super->s_reserved_gdt_blocks > EXT2_ADDR_PER_BLOCK(super)) { - retval = EXT2_ET_RES_GDT_BLOCKS; - goto cleanup; - } - - /* - * Overhead is the number of bookkeeping blocks per group. It - * includes the superblock backup, the group descriptor - * backups, the inode bitmap, the block bitmap, and the inode - * table. - */ - - overhead = (int) (2 + fs->inode_blocks_per_group); - - if (ext2fs_bg_has_super(fs, fs->group_desc_count - 1)) - overhead += 1 + fs->desc_blocks + super->s_reserved_gdt_blocks; - - /* This can only happen if the user requested too many inodes */ - if (overhead > super->s_blocks_per_group) - return EXT2_ET_TOO_MANY_INODES; - - /* - * See if the last group is big enough to support the - * necessary data structures. If not, we need to get rid of - * it. - */ - rem = ((super->s_blocks_count - super->s_first_data_block) % - super->s_blocks_per_group); - if ((fs->group_desc_count == 1) && rem && (rem < overhead)) - return EXT2_ET_TOOSMALL; - if (rem && (rem < overhead+50)) { - super->s_blocks_count -= rem; - goto retry; - } - - /* - * At this point we know how big the filesystem will be. So - * we can do any and all allocations that depend on the block - * count. - */ - - retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf); - if (retval) - goto cleanup; - - sprintf(buf, "block bitmap for %s", fs->device_name); - retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map); - if (retval) - goto cleanup; - - sprintf(buf, "inode bitmap for %s", fs->device_name); - retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map); - if (retval) - goto cleanup; - - ext2fs_free_mem(&buf); - - retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize, - &fs->group_desc); - if (retval) - goto cleanup; - - memset(fs->group_desc, 0, (size_t) fs->desc_blocks * fs->blocksize); - - /* - * Reserve the superblock and group descriptors for each - * group, and fill in the correct group statistics for group. - * Note that although the block bitmap, inode bitmap, and - * inode table have not been allocated (and in fact won't be - * by this routine), they are accounted for nevertheless. - */ - group_block = super->s_first_data_block; - super->s_free_blocks_count = 0; - for (i = 0; i < fs->group_desc_count; i++) { - numblocks = ext2fs_reserve_super_and_bgd(fs, i, fs->block_map); - - super->s_free_blocks_count += numblocks; - fs->group_desc[i].bg_free_blocks_count = numblocks; - fs->group_desc[i].bg_free_inodes_count = - fs->super->s_inodes_per_group; - fs->group_desc[i].bg_used_dirs_count = 0; - - group_block += super->s_blocks_per_group; - } - - ext2fs_mark_super_dirty(fs); - ext2fs_mark_bb_dirty(fs); - ext2fs_mark_ib_dirty(fs); - - io_channel_set_blksize(fs->io, fs->blocksize); - - *ret_fs = fs; - return 0; -cleanup: - ext2fs_free(fs); - return retval; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * inline.c --- Includes the inlined functions defined in the header - * files as standalone functions, in case the application program - * is compiled with inlining turned off. - * - * Copyright (C) 1993, 1994 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" -#define INCLUDE_INLINE_FUNCS -#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 @@ -/* vi: set sw=4 ts=4: */ -/* - * inode.c --- utility routines to read and write inodes - * - * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#if HAVE_ERRNO_H -#include -#endif -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fsP.h" -#include "e2image.h" - -struct ext2_struct_inode_scan { - errcode_t magic; - ext2_filsys fs; - ext2_ino_t current_inode; - blk_t current_block; - dgrp_t current_group; - ext2_ino_t inodes_left; - blk_t blocks_left; - dgrp_t groups_left; - blk_t inode_buffer_blocks; - char * inode_buffer; - int inode_size; - char * ptr; - int bytes_left; - char *temp_buffer; - errcode_t (*done_group)(ext2_filsys fs, - dgrp_t group, - void * priv_data); - void * done_group_data; - int bad_block_ptr; - int scan_flags; - int reserved[6]; -}; - -/* - * This routine flushes the icache, if it exists. - */ -errcode_t ext2fs_flush_icache(ext2_filsys fs) -{ - int i; - - if (!fs->icache) - return 0; - - for (i=0; i < fs->icache->cache_size; i++) - fs->icache->cache[i].ino = 0; - - fs->icache->buffer_blk = 0; - return 0; -} - -static errcode_t create_icache(ext2_filsys fs) -{ - errcode_t retval; - - if (fs->icache) - return 0; - retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache), &fs->icache); - if (retval) - return retval; - - memset(fs->icache, 0, sizeof(struct ext2_inode_cache)); - retval = ext2fs_get_mem(fs->blocksize, &fs->icache->buffer); - if (retval) { - ext2fs_free_mem(&fs->icache); - return retval; - } - fs->icache->buffer_blk = 0; - fs->icache->cache_last = -1; - fs->icache->cache_size = 4; - fs->icache->refcount = 1; - retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache_ent) - * fs->icache->cache_size, - &fs->icache->cache); - if (retval) { - ext2fs_free_mem(&fs->icache->buffer); - ext2fs_free_mem(&fs->icache); - return retval; - } - ext2fs_flush_icache(fs); - return 0; -} - -errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks, - ext2_inode_scan *ret_scan) -{ - ext2_inode_scan scan; - errcode_t retval; - errcode_t (*save_get_blocks)(ext2_filsys f, ext2_ino_t ino, blk_t *blocks); - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - /* - * If fs->badblocks isn't set, then set it --- since the inode - * scanning functions require it. - */ - if (fs->badblocks == 0) { - /* - * Temporarly save fs->get_blocks and set it to zero, - * for compatibility with old e2fsck's. - */ - save_get_blocks = fs->get_blocks; - fs->get_blocks = 0; - retval = ext2fs_read_bb_inode(fs, &fs->badblocks); - if (retval) { - ext2fs_badblocks_list_free(fs->badblocks); - fs->badblocks = 0; - } - fs->get_blocks = save_get_blocks; - } - - retval = ext2fs_get_mem(sizeof(struct ext2_struct_inode_scan), &scan); - if (retval) - return retval; - memset(scan, 0, sizeof(struct ext2_struct_inode_scan)); - - scan->magic = EXT2_ET_MAGIC_INODE_SCAN; - scan->fs = fs; - scan->inode_size = EXT2_INODE_SIZE(fs->super); - scan->bytes_left = 0; - scan->current_group = 0; - scan->groups_left = fs->group_desc_count - 1; - scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks : 8; - scan->current_block = scan->fs-> - group_desc[scan->current_group].bg_inode_table; - scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super); - scan->blocks_left = scan->fs->inode_blocks_per_group; - retval = ext2fs_get_mem((size_t) (scan->inode_buffer_blocks * - fs->blocksize), - &scan->inode_buffer); - scan->done_group = 0; - scan->done_group_data = 0; - scan->bad_block_ptr = 0; - if (retval) { - ext2fs_free_mem(&scan); - return retval; - } - retval = ext2fs_get_mem(scan->inode_size, &scan->temp_buffer); - if (retval) { - ext2fs_free_mem(&scan->inode_buffer); - ext2fs_free_mem(&scan); - return retval; - } - if (scan->fs->badblocks && scan->fs->badblocks->num) - scan->scan_flags |= EXT2_SF_CHK_BADBLOCKS; - *ret_scan = scan; - return 0; -} - -void ext2fs_close_inode_scan(ext2_inode_scan scan) -{ - if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN)) - return; - - ext2fs_free_mem(&scan->inode_buffer); - scan->inode_buffer = NULL; - ext2fs_free_mem(&scan->temp_buffer); - scan->temp_buffer = NULL; - ext2fs_free_mem(&scan); -} - -void ext2fs_set_inode_callback(ext2_inode_scan scan, - errcode_t (*done_group)(ext2_filsys fs, - dgrp_t group, - void * priv_data), - void *done_group_data) -{ - if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN)) - return; - - scan->done_group = done_group; - scan->done_group_data = done_group_data; -} - -int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags, - int clear_flags) -{ - int old_flags; - - if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN)) - return 0; - - old_flags = scan->scan_flags; - scan->scan_flags &= ~clear_flags; - scan->scan_flags |= set_flags; - return old_flags; -} - -/* - * This function is called by ext2fs_get_next_inode when it needs to - * get ready to read in a new blockgroup. - */ -static errcode_t get_next_blockgroup(ext2_inode_scan scan) -{ - scan->current_group++; - scan->groups_left--; - - scan->current_block = scan->fs-> - group_desc[scan->current_group].bg_inode_table; - - scan->current_inode = scan->current_group * - EXT2_INODES_PER_GROUP(scan->fs->super); - - scan->bytes_left = 0; - scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super); - scan->blocks_left = scan->fs->inode_blocks_per_group; - return 0; -} - -errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan, - int group) -{ - scan->current_group = group - 1; - scan->groups_left = scan->fs->group_desc_count - group; - return get_next_blockgroup(scan); -} - -/* - * This function is called by get_next_blocks() to check for bad - * blocks in the inode table. - * - * This function assumes that badblocks_list->list is sorted in - * increasing order. - */ -static errcode_t check_for_inode_bad_blocks(ext2_inode_scan scan, - blk_t *num_blocks) -{ - blk_t blk = scan->current_block; - badblocks_list bb = scan->fs->badblocks; - - /* - * If the inode table is missing, then obviously there are no - * bad blocks. :-) - */ - if (blk == 0) - return 0; - - /* - * If the current block is greater than the bad block listed - * in the bad block list, then advance the pointer until this - * is no longer the case. If we run out of bad blocks, then - * we don't need to do any more checking! - */ - while (blk > bb->list[scan->bad_block_ptr]) { - if (++scan->bad_block_ptr >= bb->num) { - scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS; - return 0; - } - } - - /* - * If the current block is equal to the bad block listed in - * the bad block list, then handle that one block specially. - * (We could try to handle runs of bad blocks, but that - * only increases CPU efficiency by a small amount, at the - * expense of a huge expense of code complexity, and for an - * uncommon case at that.) - */ - if (blk == bb->list[scan->bad_block_ptr]) { - scan->scan_flags |= EXT2_SF_BAD_INODE_BLK; - *num_blocks = 1; - if (++scan->bad_block_ptr >= bb->num) - scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS; - return 0; - } - - /* - * If there is a bad block in the range that we're about to - * read in, adjust the number of blocks to read so that we we - * don't read in the bad block. (Then the next block to read - * will be the bad block, which is handled in the above case.) - */ - if ((blk + *num_blocks) > bb->list[scan->bad_block_ptr]) - *num_blocks = (int) (bb->list[scan->bad_block_ptr] - blk); - - return 0; -} - -/* - * This function is called by ext2fs_get_next_inode when it needs to - * read in more blocks from the current blockgroup's inode table. - */ -static errcode_t get_next_blocks(ext2_inode_scan scan) -{ - blk_t num_blocks; - errcode_t retval; - - /* - * Figure out how many blocks to read; we read at most - * inode_buffer_blocks, and perhaps less if there aren't that - * many blocks left to read. - */ - num_blocks = scan->inode_buffer_blocks; - if (num_blocks > scan->blocks_left) - num_blocks = scan->blocks_left; - - /* - * If the past block "read" was a bad block, then mark the - * left-over extra bytes as also being bad. - */ - if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) { - if (scan->bytes_left) - scan->scan_flags |= EXT2_SF_BAD_EXTRA_BYTES; - scan->scan_flags &= ~EXT2_SF_BAD_INODE_BLK; - } - - /* - * Do inode bad block processing, if necessary. - */ - if (scan->scan_flags & EXT2_SF_CHK_BADBLOCKS) { - retval = check_for_inode_bad_blocks(scan, &num_blocks); - if (retval) - return retval; - } - - if ((scan->scan_flags & EXT2_SF_BAD_INODE_BLK) || - (scan->current_block == 0)) { - memset(scan->inode_buffer, 0, - (size_t) num_blocks * scan->fs->blocksize); - } else { - retval = io_channel_read_blk(scan->fs->io, - scan->current_block, - (int) num_blocks, - scan->inode_buffer); - if (retval) - return EXT2_ET_NEXT_INODE_READ; - } - scan->ptr = scan->inode_buffer; - scan->bytes_left = num_blocks * scan->fs->blocksize; - - scan->blocks_left -= num_blocks; - if (scan->current_block) - scan->current_block += num_blocks; - return 0; -} - -errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan, ext2_ino_t *ino, - struct ext2_inode *inode, int bufsize) -{ - errcode_t retval; - int extra_bytes = 0; - - EXT2_CHECK_MAGIC(scan, EXT2_ET_MAGIC_INODE_SCAN); - - /* - * Do we need to start reading a new block group? - */ - if (scan->inodes_left <= 0) { - force_new_group: - if (scan->done_group) { - retval = (scan->done_group) - (scan->fs, scan->current_group, - scan->done_group_data); - if (retval) - return retval; - } - if (scan->groups_left <= 0) { - *ino = 0; - return 0; - } - retval = get_next_blockgroup(scan); - if (retval) - return retval; - } - /* - * This is done outside the above if statement so that the - * check can be done for block group #0. - */ - if (scan->current_block == 0) { - if (scan->scan_flags & EXT2_SF_SKIP_MISSING_ITABLE) { - goto force_new_group; - } else - return EXT2_ET_MISSING_INODE_TABLE; - } - - - /* - * Have we run out of space in the inode buffer? If so, we - * need to read in more blocks. - */ - if (scan->bytes_left < scan->inode_size) { - memcpy(scan->temp_buffer, scan->ptr, scan->bytes_left); - extra_bytes = scan->bytes_left; - - retval = get_next_blocks(scan); - if (retval) - return retval; -#if 0 - /* - * XXX test Need check for used inode somehow. - * (Note: this is hard.) - */ - if (is_empty_scan(scan)) - goto force_new_group; -#endif - } - - retval = 0; - if (extra_bytes) { - memcpy(scan->temp_buffer+extra_bytes, scan->ptr, - scan->inode_size - extra_bytes); - scan->ptr += scan->inode_size - extra_bytes; - scan->bytes_left -= scan->inode_size - extra_bytes; - -#if BB_BIG_ENDIAN - if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) || - (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) - ext2fs_swap_inode_full(scan->fs, - (struct ext2_inode_large *) inode, - (struct ext2_inode_large *) scan->temp_buffer, - 0, bufsize); - else -#endif - *inode = *((struct ext2_inode *) scan->temp_buffer); - if (scan->scan_flags & EXT2_SF_BAD_EXTRA_BYTES) - retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE; - scan->scan_flags &= ~EXT2_SF_BAD_EXTRA_BYTES; - } else { -#if BB_BIG_ENDIAN - if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) || - (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) - ext2fs_swap_inode_full(scan->fs, - (struct ext2_inode_large *) inode, - (struct ext2_inode_large *) scan->ptr, - 0, bufsize); - else -#endif - memcpy(inode, scan->ptr, bufsize); - scan->ptr += scan->inode_size; - scan->bytes_left -= scan->inode_size; - if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) - retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE; - } - - scan->inodes_left--; - scan->current_inode++; - *ino = scan->current_inode; - return retval; -} - -errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino, - struct ext2_inode *inode) -{ - return ext2fs_get_next_inode_full(scan, ino, inode, - sizeof(struct ext2_inode)); -} - -/* - * Functions to read and write a single inode. - */ -errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino, - struct ext2_inode * inode, int bufsize) -{ - unsigned long group, block, block_nr, offset; - char *ptr; - errcode_t retval; - int clen, i, inodes_per_block, length; - io_channel io; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - /* Check to see if user has an override function */ - if (fs->read_inode) { - retval = (fs->read_inode)(fs, ino, inode); - if (retval != EXT2_ET_CALLBACK_NOTHANDLED) - return retval; - } - /* Create inode cache if not present */ - if (!fs->icache) { - retval = create_icache(fs); - if (retval) - return retval; - } - /* Check to see if it's in the inode cache */ - if (bufsize == sizeof(struct ext2_inode)) { - /* only old good inode can be retrieve from the cache */ - for (i=0; i < fs->icache->cache_size; i++) { - if (fs->icache->cache[i].ino == ino) { - *inode = fs->icache->cache[i].inode; - return 0; - } - } - } - if ((ino == 0) || (ino > fs->super->s_inodes_count)) - return EXT2_ET_BAD_INODE_NUM; - if (fs->flags & EXT2_FLAG_IMAGE_FILE) { - inodes_per_block = fs->blocksize / EXT2_INODE_SIZE(fs->super); - block_nr = fs->image_header->offset_inode / fs->blocksize; - block_nr += (ino - 1) / inodes_per_block; - offset = ((ino - 1) % inodes_per_block) * - EXT2_INODE_SIZE(fs->super); - io = fs->image_io; - } else { - group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super); - offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) * - EXT2_INODE_SIZE(fs->super); - block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super); - if (!fs->group_desc[(unsigned)group].bg_inode_table) - return EXT2_ET_MISSING_INODE_TABLE; - block_nr = fs->group_desc[(unsigned)group].bg_inode_table + - block; - io = fs->io; - } - offset &= (EXT2_BLOCK_SIZE(fs->super) - 1); - - length = EXT2_INODE_SIZE(fs->super); - if (bufsize < length) - length = bufsize; - - ptr = (char *) inode; - while (length) { - clen = length; - if ((offset + length) > fs->blocksize) - clen = fs->blocksize - offset; - - if (block_nr != fs->icache->buffer_blk) { - retval = io_channel_read_blk(io, block_nr, 1, - fs->icache->buffer); - if (retval) - return retval; - fs->icache->buffer_blk = block_nr; - } - - memcpy(ptr, ((char *) fs->icache->buffer) + (unsigned) offset, - clen); - - offset = 0; - length -= clen; - ptr += clen; - block_nr++; - } - -#if BB_BIG_ENDIAN - if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || - (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) - ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) inode, - (struct ext2_inode_large *) inode, - 0, length); -#endif - - /* Update the inode cache */ - fs->icache->cache_last = (fs->icache->cache_last + 1) % - fs->icache->cache_size; - fs->icache->cache[fs->icache->cache_last].ino = ino; - fs->icache->cache[fs->icache->cache_last].inode = *inode; - - return 0; -} - -errcode_t ext2fs_read_inode(ext2_filsys fs, ext2_ino_t ino, - struct ext2_inode * inode) -{ - return ext2fs_read_inode_full(fs, ino, inode, - sizeof(struct ext2_inode)); -} - -errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino, - struct ext2_inode * inode, int bufsize) -{ - unsigned long group, block, block_nr, offset; - errcode_t retval = 0; - struct ext2_inode_large temp_inode, *w_inode; - char *ptr; - int clen, i, length; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - /* Check to see if user provided an override function */ - if (fs->write_inode) { - retval = (fs->write_inode)(fs, ino, inode); - if (retval != EXT2_ET_CALLBACK_NOTHANDLED) - return retval; - } - - /* Check to see if the inode cache needs to be updated */ - if (fs->icache) { - for (i=0; i < fs->icache->cache_size; i++) { - if (fs->icache->cache[i].ino == ino) { - fs->icache->cache[i].inode = *inode; - break; - } - } - } else { - retval = create_icache(fs); - if (retval) - return retval; - } - - if (!(fs->flags & EXT2_FLAG_RW)) - return EXT2_ET_RO_FILSYS; - - if ((ino == 0) || (ino > fs->super->s_inodes_count)) - return EXT2_ET_BAD_INODE_NUM; - - length = bufsize; - if (length < EXT2_INODE_SIZE(fs->super)) - length = EXT2_INODE_SIZE(fs->super); - - if (length > (int) sizeof(struct ext2_inode_large)) { - w_inode = xmalloc(length); - } else - w_inode = &temp_inode; - memset(w_inode, 0, length); - -#if BB_BIG_ENDIAN - if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || - (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)) - ext2fs_swap_inode_full(fs, w_inode, - (struct ext2_inode_large *) inode, - 1, bufsize); - else -#endif - memcpy(w_inode, inode, bufsize); - - group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super); - offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) * - EXT2_INODE_SIZE(fs->super); - block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super); - if (!fs->group_desc[(unsigned) group].bg_inode_table) - return EXT2_ET_MISSING_INODE_TABLE; - block_nr = fs->group_desc[(unsigned) group].bg_inode_table + block; - - offset &= (EXT2_BLOCK_SIZE(fs->super) - 1); - - length = EXT2_INODE_SIZE(fs->super); - if (length > bufsize) - length = bufsize; - - ptr = (char *) w_inode; - - while (length) { - clen = length; - if ((offset + length) > fs->blocksize) - clen = fs->blocksize - offset; - - if (fs->icache->buffer_blk != block_nr) { - retval = io_channel_read_blk(fs->io, block_nr, 1, - fs->icache->buffer); - if (retval) - goto errout; - fs->icache->buffer_blk = block_nr; - } - - - memcpy((char *) fs->icache->buffer + (unsigned) offset, - ptr, clen); - - retval = io_channel_write_blk(fs->io, block_nr, 1, - fs->icache->buffer); - if (retval) - goto errout; - - offset = 0; - ptr += clen; - length -= clen; - block_nr++; - } - - fs->flags |= EXT2_FLAG_CHANGED; -errout: - if (w_inode && w_inode != &temp_inode) - free(w_inode); - return retval; -} - -errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino, - struct ext2_inode *inode) -{ - return ext2fs_write_inode_full(fs, ino, inode, - sizeof(struct ext2_inode)); -} - -/* - * This function should be called when writing a new inode. It makes - * sure that extra part of large inodes is initialized properly. - */ -errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino, - struct ext2_inode *inode) -{ - struct ext2_inode *buf; - int size = EXT2_INODE_SIZE(fs->super); - struct ext2_inode_large *large_inode; - - if (size == sizeof(struct ext2_inode)) - return ext2fs_write_inode_full(fs, ino, inode, - sizeof(struct ext2_inode)); - - buf = xmalloc(size); - - memset(buf, 0, size); - *buf = *inode; - - large_inode = (struct ext2_inode_large *) buf; - large_inode->i_extra_isize = sizeof(struct ext2_inode_large) - - EXT2_GOOD_OLD_INODE_SIZE; - - return ext2fs_write_inode_full(fs, ino, buf, size); -} - - -errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks) -{ - struct ext2_inode inode; - int i; - errcode_t retval; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - if (ino > fs->super->s_inodes_count) - return EXT2_ET_BAD_INODE_NUM; - - if (fs->get_blocks) { - if (!(*fs->get_blocks)(fs, ino, blocks)) - return 0; - } - retval = ext2fs_read_inode(fs, ino, &inode); - if (retval) - return retval; - for (i=0; i < EXT2_N_BLOCKS; i++) - blocks[i] = inode.i_block[i]; - return 0; -} - -errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino) -{ - struct ext2_inode inode; - errcode_t retval; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - if (ino > fs->super->s_inodes_count) - return EXT2_ET_BAD_INODE_NUM; - - if (fs->check_directory) { - retval = (fs->check_directory)(fs, ino); - if (retval != EXT2_ET_CALLBACK_NOTHANDLED) - return retval; - } - retval = ext2fs_read_inode(fs, ino, &inode); - if (retval) - return retval; - if (!LINUX_S_ISDIR(inode.i_mode)) - return EXT2_ET_NO_DIRECTORY; - return 0; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * inode_io.c --- This is allows an inode in an ext2 filesystem image - * to be accessed via the I/O manager interface. - * - * Copyright (C) 2002 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#if HAVE_ERRNO_H -#include -#endif -#include - -#include "ext2_fs.h" -#include "ext2fs.h" - -/* - * For checking structure magic numbers... - */ - -#define EXT2_CHECK_MAGIC(struct, code) \ - if ((struct)->magic != (code)) return (code) - -struct inode_private_data { - int magic; - char name[32]; - ext2_file_t file; - ext2_filsys fs; - ext2_ino_t ino; - struct ext2_inode inode; - int flags; - struct inode_private_data *next; -}; - -#define CHANNEL_HAS_INODE 0x8000 - -static struct inode_private_data *top_intern; -static int ino_unique = 0; - -static errcode_t inode_open(const char *name, int flags, io_channel *channel); -static errcode_t inode_close(io_channel channel); -static errcode_t inode_set_blksize(io_channel channel, int blksize); -static errcode_t inode_read_blk(io_channel channel, unsigned long block, - int count, void *data); -static errcode_t inode_write_blk(io_channel channel, unsigned long block, - int count, const void *data); -static errcode_t inode_flush(io_channel channel); -static errcode_t inode_write_byte(io_channel channel, unsigned long offset, - int size, const void *data); - -static struct struct_io_manager struct_inode_manager = { - EXT2_ET_MAGIC_IO_MANAGER, - "Inode I/O Manager", - inode_open, - inode_close, - inode_set_blksize, - inode_read_blk, - inode_write_blk, - inode_flush, - inode_write_byte -}; - -io_manager inode_io_manager = &struct_inode_manager; - -errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino, - struct ext2_inode *inode, - char **name) -{ - struct inode_private_data *data; - errcode_t retval; - - if ((retval = ext2fs_get_mem(sizeof(struct inode_private_data), - &data))) - return retval; - data->magic = EXT2_ET_MAGIC_INODE_IO_CHANNEL; - sprintf(data->name, "%u:%d", ino, ino_unique++); - data->file = 0; - data->fs = fs; - data->ino = ino; - data->flags = 0; - if (inode) { - memcpy(&data->inode, inode, sizeof(struct ext2_inode)); - data->flags |= CHANNEL_HAS_INODE; - } - data->next = top_intern; - top_intern = data; - *name = data->name; - return 0; -} - -errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino, - char **name) -{ - return ext2fs_inode_io_intern2(fs, ino, NULL, name); -} - - -static errcode_t inode_open(const char *name, int flags, io_channel *channel) -{ - io_channel io = NULL; - struct inode_private_data *prev, *data = NULL; - errcode_t retval; - int open_flags; - - if (name == 0) - return EXT2_ET_BAD_DEVICE_NAME; - - for (data = top_intern, prev = NULL; data; - prev = data, data = data->next) - if (strcmp(name, data->name) == 0) - break; - if (!data) - return ENOENT; - if (prev) - prev->next = data->next; - else - top_intern = data->next; - - retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io); - if (retval) - goto cleanup; - memset(io, 0, sizeof(struct struct_io_channel)); - - io->magic = EXT2_ET_MAGIC_IO_CHANNEL; - io->manager = inode_io_manager; - retval = ext2fs_get_mem(strlen(name)+1, &io->name); - if (retval) - goto cleanup; - - strcpy(io->name, name); - io->private_data = data; - io->block_size = 1024; - io->read_error = 0; - io->write_error = 0; - io->refcount = 1; - - open_flags = (flags & IO_FLAG_RW) ? EXT2_FILE_WRITE : 0; - retval = ext2fs_file_open2(data->fs, data->ino, - (data->flags & CHANNEL_HAS_INODE) ? - &data->inode : 0, open_flags, - &data->file); - if (retval) - goto cleanup; - - *channel = io; - return 0; - -cleanup: - if (data) { - ext2fs_free_mem(&data); - } - if (io) - ext2fs_free_mem(&io); - return retval; -} - -static errcode_t inode_close(io_channel channel) -{ - struct inode_private_data *data; - errcode_t retval = 0; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - data = (struct inode_private_data *) channel->private_data; - EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL); - - if (--channel->refcount > 0) - return 0; - - retval = ext2fs_file_close(data->file); - - ext2fs_free_mem(&channel->private_data); - if (channel->name) - ext2fs_free_mem(&channel->name); - ext2fs_free_mem(&channel); - return retval; -} - -static errcode_t inode_set_blksize(io_channel channel, int blksize) -{ - struct inode_private_data *data; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - data = (struct inode_private_data *) channel->private_data; - EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL); - - channel->block_size = blksize; - return 0; -} - - -static errcode_t inode_read_blk(io_channel channel, unsigned long block, - int count, void *buf) -{ - struct inode_private_data *data; - errcode_t retval; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - data = (struct inode_private_data *) channel->private_data; - EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL); - - if ((retval = ext2fs_file_lseek(data->file, - block * channel->block_size, - EXT2_SEEK_SET, 0))) - return retval; - - count = (count < 0) ? -count : (count * channel->block_size); - - return ext2fs_file_read(data->file, buf, count, 0); -} - -static errcode_t inode_write_blk(io_channel channel, unsigned long block, - int count, const void *buf) -{ - struct inode_private_data *data; - errcode_t retval; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - data = (struct inode_private_data *) channel->private_data; - EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL); - - if ((retval = ext2fs_file_lseek(data->file, - block * channel->block_size, - EXT2_SEEK_SET, 0))) - return retval; - - count = (count < 0) ? -count : (count * channel->block_size); - - return ext2fs_file_write(data->file, buf, count, 0); -} - -static errcode_t inode_write_byte(io_channel channel, unsigned long offset, - int size, const void *buf) -{ - struct inode_private_data *data; - errcode_t retval = 0; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - data = (struct inode_private_data *) channel->private_data; - EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL); - - if ((retval = ext2fs_file_lseek(data->file, offset, - EXT2_SEEK_SET, 0))) - return retval; - - return ext2fs_file_write(data->file, buf, size, 0); -} - -/* - * Flush data buffers to disk. - */ -static errcode_t inode_flush(io_channel channel) -{ - struct inode_private_data *data; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - data = (struct inode_private_data *) channel->private_data; - EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL); - - return ext2fs_file_flush(data->file); -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * io_manager.c --- the I/O manager abstraction - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -errcode_t io_channel_set_options(io_channel channel, const char *opts) -{ - errcode_t retval = 0; - char *next, *ptr, *options, *arg; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - - if (!opts) - return 0; - - if (!channel->manager->set_option) - return EXT2_ET_INVALID_ARGUMENT; - - options = malloc(strlen(opts)+1); - if (!options) - return EXT2_ET_NO_MEMORY; - strcpy(options, opts); - ptr = options; - - while (ptr && *ptr) { - next = strchr(ptr, '&'); - if (next) - *next++ = 0; - - arg = strchr(ptr, '='); - if (arg) - *arg++ = 0; - - retval = (channel->manager->set_option)(channel, ptr, arg); - if (retval) - break; - ptr = next; - } - free(options); - return retval; -} - -errcode_t io_channel_write_byte(io_channel channel, unsigned long offset, - int count, const void *data) -{ - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - - if (channel->manager->write_byte) - return channel->manager->write_byte(channel, offset, - count, data); - - return EXT2_ET_UNIMPLEMENTED; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * irel.h - * - * Copyright (C) 1996, 1997 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -struct ext2_inode_reference { - blk_t block; - __u16 offset; -}; - -struct ext2_inode_relocate_entry { - ext2_ino_t new; - ext2_ino_t orig; - __u16 flags; - __u16 max_refs; -}; - -typedef struct ext2_inode_relocation_table *ext2_irel; - -struct ext2_inode_relocation_table { - __u32 magic; - char *name; - ext2_ino_t current; - void *priv_data; - - /* - * Add an inode relocation entry. - */ - errcode_t (*put)(ext2_irel irel, ext2_ino_t old, - struct ext2_inode_relocate_entry *ent); - /* - * Get an inode relocation entry. - */ - errcode_t (*get)(ext2_irel irel, ext2_ino_t old, - struct ext2_inode_relocate_entry *ent); - - /* - * Get an inode relocation entry by its original inode number - */ - errcode_t (*get_by_orig)(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old, - struct ext2_inode_relocate_entry *ent); - - /* - * Initialize for iterating over the inode relocation entries. - */ - errcode_t (*start_iter)(ext2_irel irel); - - /* - * The iterator function for the inode relocation entries. - * Returns an inode number of 0 when out of entries. - */ - errcode_t (*next)(ext2_irel irel, ext2_ino_t *old, - struct ext2_inode_relocate_entry *ent); - - /* - * Add an inode reference (i.e., note the fact that a - * particular block/offset contains a reference to an inode) - */ - errcode_t (*add_ref)(ext2_irel irel, ext2_ino_t ino, - struct ext2_inode_reference *ref); - - /* - * Initialize for iterating over the inode references for a - * particular inode. - */ - errcode_t (*start_iter_ref)(ext2_irel irel, ext2_ino_t ino); - - /* - * The iterator function for the inode references for an - * inode. The references for only one inode can be interator - * over at a time, as the iterator state is stored in ext2_irel. - */ - errcode_t (*next_ref)(ext2_irel irel, - struct ext2_inode_reference *ref); - - /* - * Move the inode relocation table from one inode number to - * another. Note that the inode references also must move. - */ - errcode_t (*move)(ext2_irel irel, ext2_ino_t old, ext2_ino_t new); - - /* - * Remove an inode relocation entry, along with all of the - * inode references. - */ - errcode_t (*delete)(ext2_irel irel, ext2_ino_t old); - - /* - * Free the inode relocation table. - */ - errcode_t (*free)(ext2_irel irel); -}; - -errcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode, - ext2_irel *irel); - -#define ext2fs_irel_put(irel, old, ent) ((irel)->put((irel), old, ent)) -#define ext2fs_irel_get(irel, old, ent) ((irel)->get((irel), old, ent)) -#define ext2fs_irel_get_by_orig(irel, orig, old, ent) \ - ((irel)->get_by_orig((irel), orig, old, ent)) -#define ext2fs_irel_start_iter(irel) ((irel)->start_iter((irel))) -#define ext2fs_irel_next(irel, old, ent) ((irel)->next((irel), old, ent)) -#define ext2fs_irel_add_ref(irel, ino, ref) ((irel)->add_ref((irel), ino, ref)) -#define ext2fs_irel_start_iter_ref(irel, ino) ((irel)->start_iter_ref((irel), ino)) -#define ext2fs_irel_next_ref(irel, ref) ((irel)->next_ref((irel), ref)) -#define ext2fs_irel_move(irel, old, new) ((irel)->move((irel), old, new)) -#define ext2fs_irel_delete(irel, old) ((irel)->delete((irel), old)) -#define ext2fs_irel_free(irel) ((irel)->free((irel))) diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * irel_ma.c - * - * Copyright (C) 1996, 1997 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#if HAVE_ERRNO_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" -#include "irel.h" - -static errcode_t ima_put(ext2_irel irel, ext2_ino_t old, - struct ext2_inode_relocate_entry *ent); -static errcode_t ima_get(ext2_irel irel, ext2_ino_t old, - struct ext2_inode_relocate_entry *ent); -static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old, - struct ext2_inode_relocate_entry *ent); -static errcode_t ima_start_iter(ext2_irel irel); -static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old, - struct ext2_inode_relocate_entry *ent); -static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino, - struct ext2_inode_reference *ref); -static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino); -static errcode_t ima_next_ref(ext2_irel irel, struct ext2_inode_reference *ref); -static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new); -static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old); -static errcode_t ima_free(ext2_irel irel); - -/* - * This data structure stores the array of inode references; there is - * a structure for each inode. - */ -struct inode_reference_entry { - __u16 num; - struct ext2_inode_reference *refs; -}; - -struct irel_ma { - __u32 magic; - ext2_ino_t max_inode; - ext2_ino_t ref_current; - int ref_iter; - ext2_ino_t *orig_map; - struct ext2_inode_relocate_entry *entries; - struct inode_reference_entry *ref_entries; -}; - -errcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode, - ext2_irel *new_irel) -{ - ext2_irel irel = 0; - errcode_t retval; - struct irel_ma *ma = 0; - size_t size; - - *new_irel = 0; - - /* - * Allocate memory structures - */ - retval = ext2fs_get_mem(sizeof(struct ext2_inode_relocation_table), - &irel); - if (retval) - goto errout; - memset(irel, 0, sizeof(struct ext2_inode_relocation_table)); - - retval = ext2fs_get_mem(strlen(name)+1, &irel->name); - if (retval) - goto errout; - strcpy(irel->name, name); - - retval = ext2fs_get_mem(sizeof(struct irel_ma), &ma); - if (retval) - goto errout; - memset(ma, 0, sizeof(struct irel_ma)); - irel->priv_data = ma; - - size = (size_t) (sizeof(ext2_ino_t) * (max_inode+1)); - retval = ext2fs_get_mem(size, &ma->orig_map); - if (retval) - goto errout; - memset(ma->orig_map, 0, size); - - size = (size_t) (sizeof(struct ext2_inode_relocate_entry) * - (max_inode+1)); - retval = ext2fs_get_mem(size, &ma->entries); - if (retval) - goto errout; - memset(ma->entries, 0, size); - - size = (size_t) (sizeof(struct inode_reference_entry) * - (max_inode+1)); - retval = ext2fs_get_mem(size, &ma->ref_entries); - if (retval) - goto errout; - memset(ma->ref_entries, 0, size); - ma->max_inode = max_inode; - - /* - * Fill in the irel data structure - */ - irel->put = ima_put; - irel->get = ima_get; - irel->get_by_orig = ima_get_by_orig; - irel->start_iter = ima_start_iter; - irel->next = ima_next; - irel->add_ref = ima_add_ref; - irel->start_iter_ref = ima_start_iter_ref; - irel->next_ref = ima_next_ref; - irel->move = ima_move; - irel->delete = ima_delete; - irel->free = ima_free; - - *new_irel = irel; - return 0; - -errout: - ima_free(irel); - return retval; -} - -static errcode_t ima_put(ext2_irel irel, ext2_ino_t old, - struct ext2_inode_relocate_entry *ent) -{ - struct inode_reference_entry *ref_ent; - struct irel_ma *ma; - errcode_t retval; - size_t size, old_size; - - ma = irel->priv_data; - if (old > ma->max_inode) - return EXT2_ET_INVALID_ARGUMENT; - - /* - * Force the orig field to the correct value; the application - * program shouldn't be messing with this field. - */ - if (ma->entries[(unsigned) old].new == 0) - ent->orig = old; - else - ent->orig = ma->entries[(unsigned) old].orig; - - /* - * If max_refs has changed, reallocate the refs array - */ - ref_ent = ma->ref_entries + (unsigned) old; - if (ref_ent->refs && ent->max_refs != - ma->entries[(unsigned) old].max_refs) { - size = (sizeof(struct ext2_inode_reference) * ent->max_refs); - old_size = (sizeof(struct ext2_inode_reference) * - ma->entries[(unsigned) old].max_refs); - retval = ext2fs_resize_mem(old_size, size, &ref_ent->refs); - if (retval) - return retval; - } - - ma->entries[(unsigned) old] = *ent; - ma->orig_map[(unsigned) ent->orig] = old; - return 0; -} - -static errcode_t ima_get(ext2_irel irel, ext2_ino_t old, - struct ext2_inode_relocate_entry *ent) -{ - struct irel_ma *ma; - - ma = irel->priv_data; - if (old > ma->max_inode) - return EXT2_ET_INVALID_ARGUMENT; - if (ma->entries[(unsigned) old].new == 0) - return ENOENT; - *ent = ma->entries[(unsigned) old]; - return 0; -} - -static errcode_t ima_get_by_orig(ext2_irel irel, ext2_ino_t orig, ext2_ino_t *old, - struct ext2_inode_relocate_entry *ent) -{ - struct irel_ma *ma; - ext2_ino_t ino; - - ma = irel->priv_data; - if (orig > ma->max_inode) - return EXT2_ET_INVALID_ARGUMENT; - ino = ma->orig_map[(unsigned) orig]; - if (ino == 0) - return ENOENT; - *old = ino; - *ent = ma->entries[(unsigned) ino]; - return 0; -} - -static errcode_t ima_start_iter(ext2_irel irel) -{ - irel->current = 0; - return 0; -} - -static errcode_t ima_next(ext2_irel irel, ext2_ino_t *old, - struct ext2_inode_relocate_entry *ent) -{ - struct irel_ma *ma; - - ma = irel->priv_data; - while (++irel->current < ma->max_inode) { - if (ma->entries[(unsigned) irel->current].new == 0) - continue; - *old = irel->current; - *ent = ma->entries[(unsigned) irel->current]; - return 0; - } - *old = 0; - return 0; -} - -static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino, - struct ext2_inode_reference *ref) -{ - struct irel_ma *ma; - size_t size; - struct inode_reference_entry *ref_ent; - struct ext2_inode_relocate_entry *ent; - errcode_t retval; - - ma = irel->priv_data; - if (ino > ma->max_inode) - return EXT2_ET_INVALID_ARGUMENT; - - ref_ent = ma->ref_entries + (unsigned) ino; - ent = ma->entries + (unsigned) ino; - - /* - * If the inode reference array doesn't exist, create it. - */ - if (ref_ent->refs == 0) { - size = (size_t) ((sizeof(struct ext2_inode_reference) * - ent->max_refs)); - retval = ext2fs_get_mem(size, &ref_ent->refs); - if (retval) - return retval; - memset(ref_ent->refs, 0, size); - ref_ent->num = 0; - } - - if (ref_ent->num >= ent->max_refs) - return EXT2_ET_TOO_MANY_REFS; - - ref_ent->refs[(unsigned) ref_ent->num++] = *ref; - return 0; -} - -static errcode_t ima_start_iter_ref(ext2_irel irel, ext2_ino_t ino) -{ - struct irel_ma *ma; - - ma = irel->priv_data; - if (ino > ma->max_inode) - return EXT2_ET_INVALID_ARGUMENT; - if (ma->entries[(unsigned) ino].new == 0) - return ENOENT; - ma->ref_current = ino; - ma->ref_iter = 0; - return 0; -} - -static errcode_t ima_next_ref(ext2_irel irel, - struct ext2_inode_reference *ref) -{ - struct irel_ma *ma; - struct inode_reference_entry *ref_ent; - - ma = irel->priv_data; - - ref_ent = ma->ref_entries + ma->ref_current; - - if ((ref_ent->refs == NULL) || - (ma->ref_iter >= ref_ent->num)) { - ref->block = 0; - ref->offset = 0; - return 0; - } - *ref = ref_ent->refs[ma->ref_iter++]; - return 0; -} - - -static errcode_t ima_move(ext2_irel irel, ext2_ino_t old, ext2_ino_t new) -{ - struct irel_ma *ma; - - ma = irel->priv_data; - if ((old > ma->max_inode) || (new > ma->max_inode)) - return EXT2_ET_INVALID_ARGUMENT; - if (ma->entries[(unsigned) old].new == 0) - return ENOENT; - - ma->entries[(unsigned) new] = ma->entries[(unsigned) old]; - ext2fs_free_mem(&ma->ref_entries[(unsigned) new].refs); - ma->ref_entries[(unsigned) new] = ma->ref_entries[(unsigned) old]; - - ma->entries[(unsigned) old].new = 0; - ma->ref_entries[(unsigned) old].num = 0; - ma->ref_entries[(unsigned) old].refs = 0; - - ma->orig_map[ma->entries[new].orig] = new; - return 0; -} - -static errcode_t ima_delete(ext2_irel irel, ext2_ino_t old) -{ - struct irel_ma *ma; - - ma = irel->priv_data; - if (old > ma->max_inode) - return EXT2_ET_INVALID_ARGUMENT; - if (ma->entries[(unsigned) old].new == 0) - return ENOENT; - - ma->entries[old].new = 0; - ext2fs_free_mem(&ma->ref_entries[(unsigned) old].refs); - ma->orig_map[ma->entries[(unsigned) old].orig] = 0; - - ma->ref_entries[(unsigned) old].num = 0; - ma->ref_entries[(unsigned) old].refs = 0; - return 0; -} - -static errcode_t ima_free(ext2_irel irel) -{ - struct irel_ma *ma; - ext2_ino_t ino; - - if (!irel) - return 0; - - ma = irel->priv_data; - - if (ma) { - ext2fs_free_mem(&ma->orig_map); - ext2fs_free_mem(&ma->entries); - if (ma->ref_entries) { - for (ino = 0; ino <= ma->max_inode; ino++) { - ext2fs_free_mem(&ma->ref_entries[(unsigned) ino].refs); - } - ext2fs_free_mem(&ma->ref_entries); - } - ext2fs_free_mem(&ma); - } - ext2fs_free_mem(&irel->name); - ext2fs_free_mem(&irel); - return 0; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * ismounted.c --- Check to see if the filesystem was mounted - * - * Copyright (C) 1995,1996,1997,1998,1999,2000 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#if HAVE_UNISTD_H -#include -#endif -#if HAVE_ERRNO_H -#include -#endif -#include -#ifdef HAVE_LINUX_FD_H -#include -#endif -#ifdef HAVE_MNTENT_H -#include -#endif -#ifdef HAVE_GETMNTINFO -#include -#include -#include -#endif /* HAVE_GETMNTINFO */ -#include -#include - -#include "ext2_fs.h" -#include "ext2fs.h" - -#ifdef HAVE_MNTENT_H -/* - * Helper function which checks a file in /etc/mtab format to see if a - * filesystem is mounted. Returns an error if the file doesn't exist - * or can't be opened. - */ -static errcode_t check_mntent_file(const char *mtab_file, const char *file, - int *mount_flags, char *mtpt, int mtlen) -{ - struct mntent *mnt; - struct stat st_buf; - errcode_t retval = 0; - dev_t file_dev=0, file_rdev=0; - ino_t file_ino=0; - FILE *f; - int fd; - - *mount_flags = 0; - if ((f = setmntent (mtab_file, "r")) == NULL) - return errno; - if (stat(file, &st_buf) == 0) { - if (S_ISBLK(st_buf.st_mode)) { -#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */ - file_rdev = st_buf.st_rdev; -#endif /* __GNU__ */ - } else { - file_dev = st_buf.st_dev; - file_ino = st_buf.st_ino; - } - } - while ((mnt = getmntent (f)) != NULL) { - if (strcmp(file, mnt->mnt_fsname) == 0) - break; - if (stat(mnt->mnt_fsname, &st_buf) == 0) { - if (S_ISBLK(st_buf.st_mode)) { -#ifndef __GNU__ - if (file_rdev && (file_rdev == st_buf.st_rdev)) - break; -#endif /* __GNU__ */ - } else { - if (file_dev && ((file_dev == st_buf.st_dev) && - (file_ino == st_buf.st_ino))) - break; - } - } - } - - if (mnt == 0) { -#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */ - /* - * Do an extra check to see if this is the root device. We - * can't trust /etc/mtab, and /proc/mounts will only list - * /dev/root for the root filesystem. Argh. Instead we - * check if the given device has the same major/minor number - * as the device that the root directory is on. - */ - if (file_rdev && stat("/", &st_buf) == 0) { - if (st_buf.st_dev == file_rdev) { - *mount_flags = EXT2_MF_MOUNTED; - if (mtpt) - strncpy(mtpt, "/", mtlen); - goto is_root; - } - } -#endif /* __GNU__ */ - goto errout; - } -#ifndef __GNU__ /* The GNU hurd is deficient; what else is new? */ - /* Validate the entry in case /etc/mtab is out of date */ - /* - * We need to be paranoid, because some broken distributions - * (read: Slackware) don't initialize /etc/mtab before checking - * all of the non-root filesystems on the disk. - */ - if (stat(mnt->mnt_dir, &st_buf) < 0) { - retval = errno; - if (retval == ENOENT) { -#ifdef DEBUG - printf("Bogus entry in %s! (%s does not exist)\n", - mtab_file, mnt->mnt_dir); -#endif /* DEBUG */ - retval = 0; - } - goto errout; - } - if (file_rdev && (st_buf.st_dev != file_rdev)) { -#ifdef DEBUG - printf("Bogus entry in %s! (%s not mounted on %s)\n", - mtab_file, file, mnt->mnt_dir); -#endif /* DEBUG */ - goto errout; - } -#endif /* __GNU__ */ - *mount_flags = EXT2_MF_MOUNTED; - -#ifdef MNTOPT_RO - /* Check to see if the ro option is set */ - if (hasmntopt(mnt, MNTOPT_RO)) - *mount_flags |= EXT2_MF_READONLY; -#endif - - if (mtpt) - strncpy(mtpt, mnt->mnt_dir, mtlen); - /* - * Check to see if we're referring to the root filesystem. - * If so, do a manual check to see if we can open /etc/mtab - * read/write, since if the root is mounted read/only, the - * contents of /etc/mtab may not be accurate. - */ - if (LONE_CHAR(mnt->mnt_dir, '/')) { -is_root: -#define TEST_FILE "/.ismount-test-file" - *mount_flags |= EXT2_MF_ISROOT; - fd = open(TEST_FILE, O_RDWR|O_CREAT); - if (fd < 0) { - if (errno == EROFS) - *mount_flags |= EXT2_MF_READONLY; - } else - close(fd); - (void) unlink(TEST_FILE); - } - retval = 0; -errout: - endmntent (f); - return retval; -} - -static errcode_t check_mntent(const char *file, int *mount_flags, - char *mtpt, int mtlen) -{ - errcode_t retval; - -#ifdef DEBUG - retval = check_mntent_file("/tmp/mtab", file, mount_flags, - mtpt, mtlen); - if (retval == 0) - return 0; -#endif /* DEBUG */ -#ifdef __linux__ - retval = check_mntent_file("/proc/mounts", file, mount_flags, - mtpt, mtlen); - if (retval == 0 && (*mount_flags != 0)) - return 0; -#endif /* __linux__ */ -#if defined(MOUNTED) || defined(_PATH_MOUNTED) -#ifndef MOUNTED -#define MOUNTED _PATH_MOUNTED -#endif /* MOUNTED */ - retval = check_mntent_file(MOUNTED, file, mount_flags, mtpt, mtlen); - return retval; -#else - *mount_flags = 0; - return 0; -#endif /* defined(MOUNTED) || defined(_PATH_MOUNTED) */ -} - -#else -#if defined(HAVE_GETMNTINFO) - -static errcode_t check_getmntinfo(const char *file, int *mount_flags, - char *mtpt, int mtlen) -{ - struct statfs *mp; - int len, n; - const char *s1; - char *s2; - - n = getmntinfo(&mp, MNT_NOWAIT); - if (n == 0) - return errno; - - len = sizeof(_PATH_DEV) - 1; - s1 = file; - if (strncmp(_PATH_DEV, s1, len) == 0) - s1 += len; - - *mount_flags = 0; - while (--n >= 0) { - s2 = mp->f_mntfromname; - if (strncmp(_PATH_DEV, s2, len) == 0) { - s2 += len - 1; - *s2 = 'r'; - } - if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0) { - *mount_flags = EXT2_MF_MOUNTED; - break; - } - ++mp; - } - if (mtpt) - strncpy(mtpt, mp->f_mntonname, mtlen); - return 0; -} -#endif /* HAVE_GETMNTINFO */ -#endif /* HAVE_MNTENT_H */ - -/* - * Check to see if we're dealing with the swap device. - */ -static int is_swap_device(const char *file) -{ - FILE *f; - char buf[1024], *cp; - dev_t file_dev; - struct stat st_buf; - int ret = 0; - - file_dev = 0; -#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */ - if ((stat(file, &st_buf) == 0) && - S_ISBLK(st_buf.st_mode)) - file_dev = st_buf.st_rdev; -#endif /* __GNU__ */ - - if (!(f = fopen_for_read("/proc/swaps"))) - return 0; - /* Skip the first line */ - fgets(buf, sizeof(buf), f); - while (!feof(f)) { - if (!fgets(buf, sizeof(buf), f)) - break; - if ((cp = strchr(buf, ' ')) != NULL) - *cp = 0; - if ((cp = strchr(buf, '\t')) != NULL) - *cp = 0; - if (strcmp(buf, file) == 0) { - ret++; - break; - } -#ifndef __GNU__ - if (file_dev && (stat(buf, &st_buf) == 0) && - S_ISBLK(st_buf.st_mode) && - file_dev == st_buf.st_rdev) { - ret++; - break; - } -#endif /* __GNU__ */ - } - fclose(f); - return ret; -} - - -/* - * ext2fs_check_mount_point() returns 1 if the device is mounted, 0 - * otherwise. If mtpt is non-NULL, the directory where the device is - * mounted is copied to where mtpt is pointing, up to mtlen - * characters. - */ -#ifdef __TURBOC__ -# pragma argsused -#endif -errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags, - char *mtpt, int mtlen) -{ - if (is_swap_device(device)) { - *mount_flags = EXT2_MF_MOUNTED | EXT2_MF_SWAP; - strncpy(mtpt, "", mtlen); - return 0; - } -#ifdef HAVE_MNTENT_H - return check_mntent(device, mount_flags, mtpt, mtlen); -#else -#ifdef HAVE_GETMNTINFO - return check_getmntinfo(device, mount_flags, mtpt, mtlen); -#else -#ifdef __GNUC__ - #warning "Can't use getmntent or getmntinfo to check for mounted filesystems!" -#endif - *mount_flags = 0; - return 0; -#endif /* HAVE_GETMNTINFO */ -#endif /* HAVE_MNTENT_H */ -} - -/* - * ext2fs_check_if_mounted() sets the mount_flags EXT2_MF_MOUNTED, - * EXT2_MF_READONLY, and EXT2_MF_ROOT - * - */ -errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags) -{ - return ext2fs_check_mount_point(file, mount_flags, NULL, 0); -} - -#ifdef DEBUG -int main(int argc, char **argv) -{ - int retval, mount_flags; - char mntpt[80]; - - if (argc < 2) { - fprintf(stderr, "Usage: %s device\n", argv[0]); - exit(1); - } - - mntpt[0] = 0; - retval = ext2fs_check_mount_point(argv[1], &mount_flags, - mntpt, sizeof(mntpt)); - if (retval) { - com_err(argv[0], retval, - "while calling ext2fs_check_if_mounted"); - exit(1); - } - printf("Device %s reports flags %02x\n", argv[1], mount_flags); - if (mount_flags & EXT2_MF_BUSY) - printf("\t%s is apparently in use.\n", argv[1]); - if (mount_flags & EXT2_MF_MOUNTED) - printf("\t%s is mounted.\n", argv[1]); - if (mount_flags & EXT2_MF_SWAP) - printf("\t%s is a swap device.\n", argv[1]); - if (mount_flags & EXT2_MF_READONLY) - printf("\t%s is read-only.\n", argv[1]); - if (mount_flags & EXT2_MF_ISROOT) - printf("\t%s is the root filesystem.\n", argv[1]); - if (mntpt[0]) - printf("\t%s is mounted on %s.\n", argv[1], mntpt); - exit(0); -} -#endif /* DEBUG */ diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * jfs_dat.h --- stripped down header file which only contains the JFS - * on-disk data structures - */ - -#define JFS_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */ - -/* - * On-disk structures - */ - -/* - * Descriptor block types: - */ - -#define JFS_DESCRIPTOR_BLOCK 1 -#define JFS_COMMIT_BLOCK 2 -#define JFS_SUPERBLOCK 3 - -/* - * Standard header for all descriptor blocks: - */ -typedef struct journal_header_s -{ - __u32 h_magic; - __u32 h_blocktype; - __u32 h_sequence; -} journal_header_t; - - -/* - * The block tag: used to describe a single buffer in the journal - */ -typedef struct journal_block_tag_s -{ - __u32 t_blocknr; /* The on-disk block number */ - __u32 t_flags; /* See below */ -} journal_block_tag_t; - -/* Definitions for the journal tag flags word: */ -#define JFS_FLAG_ESCAPE 1 /* on-disk block is escaped */ -#define JFS_FLAG_SAME_UUID 2 /* block has same uuid as previous */ -#define JFS_FLAG_DELETED 4 /* block deleted by this transaction */ -#define JFS_FLAG_LAST_TAG 8 /* last tag in this descriptor block */ - - -/* - * The journal superblock - */ -typedef struct journal_superblock_s -{ - journal_header_t s_header; - - /* Static information describing the journal */ - __u32 s_blocksize; /* journal device blocksize */ - __u32 s_maxlen; /* total blocks in journal file */ - __u32 s_first; /* first block of log information */ - - /* Dynamic information describing the current state of the log */ - __u32 s_sequence; /* first commit ID expected in log */ - __u32 s_start; /* blocknr of start of log */ -} journal_superblock_t; diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * linux/include/linux/jbd.h - * - * Written by Stephen C. Tweedie - * - * Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved - * - * This file is part of the Linux kernel and is made available under - * the terms of the GNU General Public License, version 2, or at your - * option, any later version, incorporated herein by reference. - * - * Definitions for transaction data structures for the buffer cache - * filesystem journaling support. - */ -#ifndef LINUX_JBD_H -#define LINUX_JBD_H 1 - -#include -#include -#include "ext2fs.h" - -/* - * Standard header for all descriptor blocks: - */ - -typedef struct journal_header_s -{ - __u32 h_magic; - __u32 h_blocktype; - __u32 h_sequence; -} journal_header_t; - -/* - * This is the global e2fsck structure. - */ -typedef struct e2fsck_struct *e2fsck_t; - - -struct inode { - e2fsck_t i_ctx; - ext2_ino_t i_ino; - struct ext2_inode i_ext2; -}; - - -/* - * The journal superblock. All fields are in big-endian byte order. - */ -typedef struct journal_superblock_s -{ -/* 0x0000 */ - journal_header_t s_header; - -/* 0x000C */ - /* Static information describing the journal */ - __u32 s_blocksize; /* journal device blocksize */ - __u32 s_maxlen; /* total blocks in journal file */ - __u32 s_first; /* first block of log information */ - -/* 0x0018 */ - /* Dynamic information describing the current state of the log */ - __u32 s_sequence; /* first commit ID expected in log */ - __u32 s_start; /* blocknr of start of log */ - -/* 0x0020 */ - /* Error value, as set by journal_abort(). */ - __s32 s_errno; - -/* 0x0024 */ - /* Remaining fields are only valid in a version-2 superblock */ - __u32 s_feature_compat; /* compatible feature set */ - __u32 s_feature_incompat; /* incompatible feature set */ - __u32 s_feature_ro_compat; /* readonly-compatible feature set */ -/* 0x0030 */ - __u8 s_uuid[16]; /* 128-bit uuid for journal */ - -/* 0x0040 */ - __u32 s_nr_users; /* Nr of filesystems sharing log */ - - __u32 s_dynsuper; /* Blocknr of dynamic superblock copy*/ - -/* 0x0048 */ - __u32 s_max_transaction; /* Limit of journal blocks per trans.*/ - __u32 s_max_trans_data; /* Limit of data blocks per trans. */ - -/* 0x0050 */ - __u32 s_padding[44]; - -/* 0x0100 */ - __u8 s_users[16*48]; /* ids of all fs'es sharing the log */ -/* 0x0400 */ -} journal_superblock_t; - - -extern int journal_blocks_per_page(struct inode *inode); -extern int jbd_blocks_per_page(struct inode *inode); - -#define JFS_MIN_JOURNAL_BLOCKS 1024 - - -/* - * Internal structures used by the logging mechanism: - */ - -#define JFS_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */ - -/* - * Descriptor block types: - */ - -#define JFS_DESCRIPTOR_BLOCK 1 -#define JFS_COMMIT_BLOCK 2 -#define JFS_SUPERBLOCK_V1 3 -#define JFS_SUPERBLOCK_V2 4 -#define JFS_REVOKE_BLOCK 5 - -/* - * The block tag: used to describe a single buffer in the journal - */ -typedef struct journal_block_tag_s -{ - __u32 t_blocknr; /* The on-disk block number */ - __u32 t_flags; /* See below */ -} journal_block_tag_t; - -/* - * The revoke descriptor: used on disk to describe a series of blocks to - * be revoked from the log - */ -typedef struct journal_revoke_header_s -{ - journal_header_t r_header; - int r_count; /* Count of bytes used in the block */ -} journal_revoke_header_t; - - -/* Definitions for the journal tag flags word: */ -#define JFS_FLAG_ESCAPE 1 /* on-disk block is escaped */ -#define JFS_FLAG_SAME_UUID 2 /* block has same uuid as previous */ -#define JFS_FLAG_DELETED 4 /* block deleted by this transaction */ -#define JFS_FLAG_LAST_TAG 8 /* last tag in this descriptor block */ - - - - -#define JFS_HAS_COMPAT_FEATURE(j,mask) \ - ((j)->j_format_version >= 2 && \ - ((j)->j_superblock->s_feature_compat & cpu_to_be32((mask)))) -#define JFS_HAS_RO_COMPAT_FEATURE(j,mask) \ - ((j)->j_format_version >= 2 && \ - ((j)->j_superblock->s_feature_ro_compat & cpu_to_be32((mask)))) -#define JFS_HAS_INCOMPAT_FEATURE(j,mask) \ - ((j)->j_format_version >= 2 && \ - ((j)->j_superblock->s_feature_incompat & cpu_to_be32((mask)))) - -#define JFS_FEATURE_INCOMPAT_REVOKE 0x00000001 - -/* Features known to this kernel version: */ -#define JFS_KNOWN_COMPAT_FEATURES 0 -#define JFS_KNOWN_ROCOMPAT_FEATURES 0 -#define JFS_KNOWN_INCOMPAT_FEATURES JFS_FEATURE_INCOMPAT_REVOKE - -/* Comparison functions for transaction IDs: perform comparisons using - * modulo arithmetic so that they work over sequence number wraps. */ - - -/* - * Definitions which augment the buffer_head layer - */ - -/* journaling buffer types */ -#define BJ_None 0 /* Not journaled */ -#define BJ_SyncData 1 /* Normal data: flush before commit */ -#define BJ_AsyncData 2 /* writepage data: wait on it before commit */ -#define BJ_Metadata 3 /* Normal journaled metadata */ -#define BJ_Forget 4 /* Buffer superceded by this transaction */ -#define BJ_IO 5 /* Buffer is for temporary IO use */ -#define BJ_Shadow 6 /* Buffer contents being shadowed to the log */ -#define BJ_LogCtl 7 /* Buffer contains log descriptors */ -#define BJ_Reserved 8 /* Buffer is reserved for access by journal */ -#define BJ_Types 9 - - -struct kdev_s { - e2fsck_t k_ctx; - int k_dev; -}; - -typedef struct kdev_s *kdev_t; -typedef unsigned int tid_t; - -struct journal_s -{ - unsigned long j_flags; - int j_errno; - struct buffer_head * j_sb_buffer; - struct journal_superblock_s *j_superblock; - int j_format_version; - unsigned long j_head; - unsigned long j_tail; - unsigned long j_free; - unsigned long j_first, j_last; - kdev_t j_dev; - kdev_t j_fs_dev; - int j_blocksize; - unsigned int j_blk_offset; - unsigned int j_maxlen; - struct inode * j_inode; - tid_t j_tail_sequence; - tid_t j_transaction_sequence; - __u8 j_uuid[16]; - struct jbd_revoke_table_s *j_revoke; -}; - -typedef struct journal_s journal_t; - -extern int journal_recover (journal_t *journal); -extern int journal_skip_recovery (journal_t *); - -/* Primary revoke support */ -extern int journal_init_revoke(journal_t *, int); -extern void journal_destroy_revoke_caches(void); -extern int journal_init_revoke_caches(void); - -/* Recovery revoke support */ -extern int journal_set_revoke(journal_t *, unsigned long, tid_t); -extern int journal_test_revoke(journal_t *, unsigned long, tid_t); -extern void journal_clear_revoke(journal_t *); -extern void journal_brelse_array(struct buffer_head *b[], int n); - -extern void journal_destroy_revoke(journal_t *); - - -#endif diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -#ifndef LINUX_LIST_H -#define LINUX_LIST_H 1 - -/* - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ - -struct list_head { - struct list_head *next, *prev; -}; - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = { &name, &name } - -#define INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -} while (0) - -#if (!defined(__GNUC__) && !defined(__WATCOMC__)) -#define __inline__ -#endif - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static __inline__ void __list_add(struct list_head * new, - struct list_head * prev, - struct list_head * next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -/* - * Insert a new entry after the specified head.. - */ -static __inline__ void list_add(struct list_head *new, struct list_head *head) -{ - __list_add(new, head, head->next); -} - -/* - * Insert a new entry at the tail - */ -static __inline__ void list_add_tail(struct list_head *new, struct list_head *head) -{ - __list_add(new, head->prev, head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static __inline__ void __list_del(struct list_head * prev, - struct list_head * next) -{ - next->prev = prev; - prev->next = next; -} - -static __inline__ void list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); -} - -static __inline__ int list_empty(struct list_head *head) -{ - return head->next == head; -} - -/* - * Splice in "list" into "head" - */ -static __inline__ void list_splice(struct list_head *list, struct list_head *head) -{ - struct list_head *first = list->next; - - if (first != list) { - struct list_head *last = list->prev; - struct list_head *at = head->next; - - first->prev = head; - head->next = first; - - last->next = at; - at->prev = last; - } -} - -#define list_entry(ptr, type, member) \ - ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) - -#define list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) - -#endif diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * link.c --- create links in a ext2fs directory - * - * Copyright (C) 1993, 1994 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -struct link_struct { - const char *name; - int namelen; - ext2_ino_t inode; - int flags; - int done; - struct ext2_super_block *sb; -}; - -static int link_proc(struct ext2_dir_entry *dirent, - int offset, - int blocksize, - char *buf, - void *priv_data) -{ - struct link_struct *ls = (struct link_struct *) priv_data; - struct ext2_dir_entry *next; - int rec_len, min_rec_len; - int ret = 0; - - rec_len = EXT2_DIR_REC_LEN(ls->namelen); - - /* - * See if the following directory entry (if any) is unused; - * if so, absorb it into this one. - */ - next = (struct ext2_dir_entry *) (buf + offset + dirent->rec_len); - if ((offset + dirent->rec_len < blocksize - 8) && - (next->inode == 0) && - (offset + dirent->rec_len + next->rec_len <= blocksize)) { - dirent->rec_len += next->rec_len; - ret = DIRENT_CHANGED; - } - - /* - * If the directory entry is used, see if we can split the - * directory entry to make room for the new name. If so, - * truncate it and return. - */ - if (dirent->inode) { - min_rec_len = EXT2_DIR_REC_LEN(dirent->name_len & 0xFF); - if (dirent->rec_len < (min_rec_len + rec_len)) - return ret; - rec_len = dirent->rec_len - min_rec_len; - dirent->rec_len = min_rec_len; - next = (struct ext2_dir_entry *) (buf + offset + - dirent->rec_len); - next->inode = 0; - next->name_len = 0; - next->rec_len = rec_len; - return DIRENT_CHANGED; - } - - /* - * If we get this far, then the directory entry is not used. - * See if we can fit the request entry in. If so, do it. - */ - if (dirent->rec_len < rec_len) - return ret; - dirent->inode = ls->inode; - dirent->name_len = ls->namelen; - strncpy(dirent->name, ls->name, ls->namelen); - if (ls->sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE) - dirent->name_len |= (ls->flags & 0x7) << 8; - - ls->done++; - return DIRENT_ABORT|DIRENT_CHANGED; -} - -/* - * Note: the low 3 bits of the flags field are used as the directory - * entry filetype. - */ -#ifdef __TURBOC__ -# pragma argsused -#endif -errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name, - ext2_ino_t ino, int flags) -{ - errcode_t retval; - struct link_struct ls; - struct ext2_inode inode; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - if (!(fs->flags & EXT2_FLAG_RW)) - return EXT2_ET_RO_FILSYS; - - ls.name = name; - ls.namelen = name ? strlen(name) : 0; - ls.inode = ino; - ls.flags = flags; - ls.done = 0; - ls.sb = fs->super; - - retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY, - 0, link_proc, &ls); - if (retval) - return retval; - - if (!ls.done) - return EXT2_ET_DIR_NO_SPACE; - - if ((retval = ext2fs_read_inode(fs, dir, &inode)) != 0) - return retval; - - if (inode.i_flags & EXT2_INDEX_FL) { - inode.i_flags &= ~EXT2_INDEX_FL; - if ((retval = ext2fs_write_inode(fs, dir, &inode)) != 0) - return retval; - } - - return 0; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * lookup.c --- ext2fs directory lookup operations - * - * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -struct lookup_struct { - const char *name; - int len; - ext2_ino_t *inode; - int found; -}; - -#ifdef __TURBOC__ -# pragma argsused -#endif -static int lookup_proc(struct ext2_dir_entry *dirent, - int offset EXT2FS_ATTR((unused)), - int blocksize EXT2FS_ATTR((unused)), - char *buf EXT2FS_ATTR((unused)), - void *priv_data) -{ - struct lookup_struct *ls = (struct lookup_struct *) priv_data; - - if (ls->len != (dirent->name_len & 0xFF)) - return 0; - if (strncmp(ls->name, dirent->name, (dirent->name_len & 0xFF))) - return 0; - *ls->inode = dirent->inode; - ls->found++; - return DIRENT_ABORT; -} - - -errcode_t ext2fs_lookup(ext2_filsys fs, ext2_ino_t dir, const char *name, - int namelen, char *buf, ext2_ino_t *inode) -{ - errcode_t retval; - struct lookup_struct ls; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - ls.name = name; - ls.len = namelen; - ls.inode = inode; - ls.found = 0; - - retval = ext2fs_dir_iterate(fs, dir, 0, buf, lookup_proc, &ls); - if (retval) - return retval; - - return (ls.found) ? 0 : EXT2_ET_FILE_NOT_FOUND; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * mkdir.c --- make a directory in the filesystem - * - * Copyright (C) 1994, 1995 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -#ifndef EXT2_FT_DIR -#define EXT2_FT_DIR 2 -#endif - -errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum, - const char *name) -{ - errcode_t retval; - struct ext2_inode parent_inode, inode; - ext2_ino_t ino = inum; - ext2_ino_t scratch_ino; - blk_t blk; - char *block = NULL; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - /* - * Allocate an inode, if necessary - */ - if (!ino) { - retval = ext2fs_new_inode(fs, parent, LINUX_S_IFDIR | 0755, - 0, &ino); - if (retval) - goto cleanup; - } - - /* - * Allocate a data block for the directory - */ - retval = ext2fs_new_block(fs, 0, 0, &blk); - if (retval) - goto cleanup; - - /* - * Create a scratch template for the directory - */ - retval = ext2fs_new_dir_block(fs, ino, parent, &block); - if (retval) - goto cleanup; - - /* - * Get the parent's inode, if necessary - */ - if (parent != ino) { - retval = ext2fs_read_inode(fs, parent, &parent_inode); - if (retval) - goto cleanup; - } else - memset(&parent_inode, 0, sizeof(parent_inode)); - - /* - * Create the inode structure.... - */ - memset(&inode, 0, sizeof(struct ext2_inode)); - inode.i_mode = LINUX_S_IFDIR | (0777 & ~fs->umask); - inode.i_uid = inode.i_gid = 0; - inode.i_blocks = fs->blocksize / 512; - inode.i_block[0] = blk; - inode.i_links_count = 2; - inode.i_ctime = inode.i_atime = inode.i_mtime = time(NULL); - inode.i_size = fs->blocksize; - - /* - * Write out the inode and inode data block - */ - retval = ext2fs_write_dir_block(fs, blk, block); - if (retval) - goto cleanup; - retval = ext2fs_write_new_inode(fs, ino, &inode); - if (retval) - goto cleanup; - - /* - * Link the directory into the filesystem hierarchy - */ - if (name) { - retval = ext2fs_lookup(fs, parent, name, strlen(name), 0, - &scratch_ino); - if (!retval) { - retval = EXT2_ET_DIR_EXISTS; - name = 0; - goto cleanup; - } - if (retval != EXT2_ET_FILE_NOT_FOUND) - goto cleanup; - retval = ext2fs_link(fs, parent, name, ino, EXT2_FT_DIR); - if (retval) - goto cleanup; - } - - /* - * Update parent inode's counts - */ - if (parent != ino) { - parent_inode.i_links_count++; - retval = ext2fs_write_inode(fs, parent, &parent_inode); - if (retval) - goto cleanup; - } - - /* - * Update accounting.... - */ - ext2fs_block_alloc_stats(fs, blk, +1); - ext2fs_inode_alloc_stats2(fs, ino, +1, 1); - -cleanup: - ext2fs_free_mem(&block); - return retval; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * mkjournal.c --- make a journal for a filesystem - * - * Copyright (C) 2000 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#if HAVE_ERRNO_H -#include -#endif -#include -#include -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif -#if HAVE_SYS_IOCTL_H -#include -#endif -#if HAVE_NETINET_IN_H -#include -#endif - -#include "ext2_fs.h" -#include "../e2p/e2p.h" -#include "../e2fsck.h" -#include "ext2fs.h" -#include "kernel-jbd.h" - -/* - * This function automatically sets up the journal superblock and - * returns it as an allocated block. - */ -errcode_t ext2fs_create_journal_superblock(ext2_filsys fs, - __u32 size, int flags, - char **ret_jsb) -{ - errcode_t retval; - journal_superblock_t *jsb; - - if (size < 1024) - return EXT2_ET_JOURNAL_TOO_SMALL; - - if ((retval = ext2fs_get_mem(fs->blocksize, &jsb))) - return retval; - - memset (jsb, 0, fs->blocksize); - - jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER); - if (flags & EXT2_MKJOURNAL_V1_SUPER) - jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V1); - else - jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2); - jsb->s_blocksize = htonl(fs->blocksize); - jsb->s_maxlen = htonl(size); - jsb->s_nr_users = htonl(1); - jsb->s_first = htonl(1); - jsb->s_sequence = htonl(1); - memcpy(jsb->s_uuid, fs->super->s_uuid, sizeof(fs->super->s_uuid)); - /* - * If we're creating an external journal device, we need to - * adjust these fields. - */ - if (fs->super->s_feature_incompat & - EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) { - jsb->s_nr_users = 0; - if (fs->blocksize == 1024) - jsb->s_first = htonl(3); - else - jsb->s_first = htonl(2); - } - - *ret_jsb = (char *) jsb; - return 0; -} - -/* - * This function writes a journal using POSIX routines. It is used - * for creating external journals and creating journals on live - * filesystems. - */ -static errcode_t write_journal_file(ext2_filsys fs, char *filename, - blk_t size, int flags) -{ - errcode_t retval; - char *buf = NULL; - int fd, ret_size; - blk_t i; - - if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf))) - return retval; - - /* Open the device or journal file */ - if ((fd = open(filename, O_WRONLY)) < 0) { - retval = errno; - goto errout; - } - - /* Write the superblock out */ - retval = EXT2_ET_SHORT_WRITE; - ret_size = write(fd, buf, fs->blocksize); - if (ret_size < 0) { - retval = errno; - goto errout; - } - if (ret_size != (int) fs->blocksize) - goto errout; - memset(buf, 0, fs->blocksize); - - for (i = 1; i < size; i++) { - ret_size = write(fd, buf, fs->blocksize); - if (ret_size < 0) { - retval = errno; - goto errout; - } - if (ret_size != (int) fs->blocksize) - goto errout; - } - close(fd); - - retval = 0; -errout: - ext2fs_free_mem(&buf); - return retval; -} - -/* - * Helper function for creating the journal using direct I/O routines - */ -struct mkjournal_struct { - int num_blocks; - int newblocks; - char *buf; - errcode_t err; -}; - -static int mkjournal_proc(ext2_filsys fs, - blk_t *blocknr, - e2_blkcnt_t blockcnt, - blk_t ref_block EXT2FS_ATTR((unused)), - int ref_offset EXT2FS_ATTR((unused)), - void *priv_data) -{ - struct mkjournal_struct *es = (struct mkjournal_struct *) priv_data; - blk_t new_blk; - static blk_t last_blk = 0; - errcode_t retval; - - if (*blocknr) { - last_blk = *blocknr; - return 0; - } - retval = ext2fs_new_block(fs, last_blk, 0, &new_blk); - if (retval) { - es->err = retval; - return BLOCK_ABORT; - } - if (blockcnt > 0) - es->num_blocks--; - - es->newblocks++; - retval = io_channel_write_blk(fs->io, new_blk, 1, es->buf); - - if (blockcnt == 0) - memset(es->buf, 0, fs->blocksize); - - if (retval) { - es->err = retval; - return BLOCK_ABORT; - } - *blocknr = new_blk; - last_blk = new_blk; - ext2fs_block_alloc_stats(fs, new_blk, +1); - - if (es->num_blocks == 0) - return (BLOCK_CHANGED | BLOCK_ABORT); - else - return BLOCK_CHANGED; -} - -/* - * This function creates a journal using direct I/O routines. - */ -static errcode_t write_journal_inode(ext2_filsys fs, ext2_ino_t journal_ino, - blk_t size, int flags) -{ - char *buf; - errcode_t retval; - struct ext2_inode inode; - struct mkjournal_struct es; - - if ((retval = ext2fs_create_journal_superblock(fs, size, flags, &buf))) - return retval; - - if ((retval = ext2fs_read_bitmaps(fs))) - return retval; - - if ((retval = ext2fs_read_inode(fs, journal_ino, &inode))) - return retval; - - if (inode.i_blocks > 0) - return EEXIST; - - es.num_blocks = size; - es.newblocks = 0; - es.buf = buf; - es.err = 0; - - retval = ext2fs_block_iterate2(fs, journal_ino, BLOCK_FLAG_APPEND, - 0, mkjournal_proc, &es); - if (es.err) { - retval = es.err; - goto errout; - } - - if ((retval = ext2fs_read_inode(fs, journal_ino, &inode))) - goto errout; - - inode.i_size += fs->blocksize * size; - inode.i_blocks += (fs->blocksize / 512) * es.newblocks; - inode.i_mtime = inode.i_ctime = time(NULL); - inode.i_links_count = 1; - inode.i_mode = LINUX_S_IFREG | 0600; - - if ((retval = ext2fs_write_inode(fs, journal_ino, &inode))) - goto errout; - retval = 0; - - memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4); - fs->super->s_jnl_blocks[16] = inode.i_size; - fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS; - ext2fs_mark_super_dirty(fs); - -errout: - ext2fs_free_mem(&buf); - return retval; -} - -/* - * This function adds a journal device to a filesystem - */ -errcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev) -{ - struct stat st; - errcode_t retval; - char buf[1024]; - journal_superblock_t *jsb; - int start; - __u32 i, nr_users; - - /* Make sure the device exists and is a block device */ - if (stat(journal_dev->device_name, &st) < 0) - return errno; - - if (!S_ISBLK(st.st_mode)) - return EXT2_ET_JOURNAL_NOT_BLOCK; /* Must be a block device */ - - /* Get the journal superblock */ - start = 1; - if (journal_dev->blocksize == 1024) - start++; - if ((retval = io_channel_read_blk(journal_dev->io, start, -1024, buf))) - return retval; - - jsb = (journal_superblock_t *) buf; - if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) || - (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2))) - return EXT2_ET_NO_JOURNAL_SB; - - if (ntohl(jsb->s_blocksize) != (unsigned long) fs->blocksize) - return EXT2_ET_UNEXPECTED_BLOCK_SIZE; - - /* Check and see if this filesystem has already been added */ - nr_users = ntohl(jsb->s_nr_users); - for (i=0; i < nr_users; i++) { - if (memcmp(fs->super->s_uuid, - &jsb->s_users[i*16], 16) == 0) - break; - } - if (i >= nr_users) { - memcpy(&jsb->s_users[nr_users*16], - fs->super->s_uuid, 16); - jsb->s_nr_users = htonl(nr_users+1); - } - - /* Writeback the journal superblock */ - if ((retval = io_channel_write_blk(journal_dev->io, start, -1024, buf))) - return retval; - - fs->super->s_journal_inum = 0; - fs->super->s_journal_dev = st.st_rdev; - memcpy(fs->super->s_journal_uuid, jsb->s_uuid, - sizeof(fs->super->s_journal_uuid)); - fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL; - ext2fs_mark_super_dirty(fs); - return 0; -} - -/* - * This function adds a journal inode to a filesystem, using either - * POSIX routines if the filesystem is mounted, or using direct I/O - * functions if it is not. - */ -errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size, int flags) -{ - errcode_t retval; - ext2_ino_t journal_ino; - struct stat st; - char jfile[1024]; - int fd, mount_flags, f; - - retval = ext2fs_check_mount_point(fs->device_name, &mount_flags, - jfile, sizeof(jfile)-10); - if (retval) - return retval; - - if (mount_flags & EXT2_MF_MOUNTED) { - strcat(jfile, "/.journal"); - - /* - * If .../.journal already exists, make sure any - * immutable or append-only flags are cleared. - */ -#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP) - (void) chflags (jfile, 0); -#else -#if HAVE_EXT2_IOCTLS - fd = open(jfile, O_RDONLY); - if (fd >= 0) { - f = 0; - ioctl(fd, EXT2_IOC_SETFLAGS, &f); - close(fd); - } -#endif -#endif - - /* Create the journal file */ - if ((fd = open(jfile, O_CREAT|O_WRONLY, 0600)) < 0) - return errno; - - if ((retval = write_journal_file(fs, jfile, size, flags))) - goto errout; - - /* Get inode number of the journal file */ - if (fstat(fd, &st) < 0) - goto errout; - -#if defined(HAVE_CHFLAGS) && defined(UF_NODUMP) - retval = fchflags (fd, UF_NODUMP|UF_IMMUTABLE); -#else -#if HAVE_EXT2_IOCTLS - f = EXT2_NODUMP_FL | EXT2_IMMUTABLE_FL; - retval = ioctl(fd, EXT2_IOC_SETFLAGS, &f); -#endif -#endif - if (retval) - goto errout; - - close(fd); - journal_ino = st.st_ino; - } else { - journal_ino = EXT2_JOURNAL_INO; - if ((retval = write_journal_inode(fs, journal_ino, - size, flags))) - return retval; - } - - fs->super->s_journal_inum = journal_ino; - fs->super->s_journal_dev = 0; - memset(fs->super->s_journal_uuid, 0, - sizeof(fs->super->s_journal_uuid)); - fs->super->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL; - - ext2fs_mark_super_dirty(fs); - return 0; -errout: - close(fd); - return retval; -} - -#ifdef DEBUG -main(int argc, char **argv) -{ - errcode_t retval; - char *device_name; - ext2_filsys fs; - - if (argc < 2) { - fprintf(stderr, "Usage: %s filesystem\n", argv[0]); - exit(1); - } - device_name = argv[1]; - - retval = ext2fs_open (device_name, EXT2_FLAG_RW, 0, 0, - unix_io_manager, &fs); - if (retval) { - com_err(argv[0], retval, "while opening %s", device_name); - exit(1); - } - - retval = ext2fs_add_journal_inode(fs, 1024); - if (retval) { - com_err(argv[0], retval, "while adding journal to %s", - device_name); - exit(1); - } - retval = ext2fs_flush(fs); - if (retval) { - printf("Warning, had trouble writing out superblocks.\n"); - } - ext2fs_close(fs); - exit(0); -} -#endif diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * namei.c --- ext2fs directory lookup operations - * - * Copyright (C) 1993, 1994, 1994, 1995 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif - -/* #define NAMEI_DEBUG */ - -#include "ext2_fs.h" -#include "ext2fs.h" - -static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base, - const char *pathname, size_t pathlen, int follow, - int link_count, char *buf, ext2_ino_t *res_inode); - -static errcode_t follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir, - ext2_ino_t inode, int link_count, - char *buf, ext2_ino_t *res_inode) -{ - char *pathname; - char *buffer = NULL; - errcode_t retval; - struct ext2_inode ei; - -#ifdef NAMEI_DEBUG - printf("follow_link: root=%lu, dir=%lu, inode=%lu, lc=%d\n", - root, dir, inode, link_count); - -#endif - retval = ext2fs_read_inode (fs, inode, &ei); - if (retval) return retval; - if (!LINUX_S_ISLNK (ei.i_mode)) { - *res_inode = inode; - return 0; - } - if (link_count++ > 5) { - return EXT2_ET_SYMLINK_LOOP; - } - if (ext2fs_inode_data_blocks(fs, &ei)) { - retval = ext2fs_get_mem(fs->blocksize, &buffer); - if (retval) - return retval; - retval = io_channel_read_blk(fs->io, ei.i_block[0], 1, buffer); - if (retval) { - ext2fs_free_mem(&buffer); - return retval; - } - pathname = buffer; - } else - pathname = (char *)&(ei.i_block[0]); - retval = open_namei(fs, root, dir, pathname, ei.i_size, 1, - link_count, buf, res_inode); - ext2fs_free_mem(&buffer); - return retval; -} - -/* - * This routine interprets a pathname in the context of the current - * directory and the root directory, and returns the inode of the - * containing directory, and a pointer to the filename of the file - * (pointing into the pathname) and the length of the filename. - */ -static errcode_t dir_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir, - const char *pathname, int pathlen, - int link_count, char *buf, - const char **name, int *namelen, - ext2_ino_t *res_inode) -{ - char c; - const char *thisname; - int len; - ext2_ino_t inode; - errcode_t retval; - - if ((c = *pathname) == '/') { - dir = root; - pathname++; - pathlen--; - } - while (1) { - thisname = pathname; - for (len=0; --pathlen >= 0;len++) { - c = *(pathname++); - if (c == '/') - break; - } - if (pathlen < 0) - break; - retval = ext2fs_lookup (fs, dir, thisname, len, buf, &inode); - if (retval) return retval; - retval = follow_link (fs, root, dir, inode, - link_count, buf, &dir); - if (retval) return retval; - } - *name = thisname; - *namelen = len; - *res_inode = dir; - return 0; -} - -static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base, - const char *pathname, size_t pathlen, int follow, - int link_count, char *buf, ext2_ino_t *res_inode) -{ - const char *basename; - int namelen; - ext2_ino_t dir, inode; - errcode_t retval; - -#ifdef NAMEI_DEBUG - printf("open_namei: root=%lu, dir=%lu, path=%*s, lc=%d\n", - root, base, pathlen, pathname, link_count); -#endif - retval = dir_namei(fs, root, base, pathname, pathlen, - link_count, buf, &basename, &namelen, &dir); - if (retval) return retval; - if (!namelen) { /* special case: '/usr/' etc */ - *res_inode=dir; - return 0; - } - retval = ext2fs_lookup (fs, dir, basename, namelen, buf, &inode); - if (retval) - return retval; - if (follow) { - retval = follow_link(fs, root, dir, inode, link_count, - buf, &inode); - if (retval) - return retval; - } -#ifdef NAMEI_DEBUG - printf("open_namei: (link_count=%d) returns %lu\n", - link_count, inode); -#endif - *res_inode = inode; - return 0; -} - -errcode_t ext2fs_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, - const char *name, ext2_ino_t *inode) -{ - char *buf; - errcode_t retval; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - retval = ext2fs_get_mem(fs->blocksize, &buf); - if (retval) - return retval; - - retval = open_namei(fs, root, cwd, name, strlen(name), 0, 0, - buf, inode); - - ext2fs_free_mem(&buf); - return retval; -} - -errcode_t ext2fs_namei_follow(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, - const char *name, ext2_ino_t *inode) -{ - char *buf; - errcode_t retval; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - retval = ext2fs_get_mem(fs->blocksize, &buf); - if (retval) - return retval; - - retval = open_namei(fs, root, cwd, name, strlen(name), 1, 0, - buf, inode); - - ext2fs_free_mem(&buf); - return retval; -} - -errcode_t ext2fs_follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t cwd, - ext2_ino_t inode, ext2_ino_t *res_inode) -{ - char *buf; - errcode_t retval; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - retval = ext2fs_get_mem(fs->blocksize, &buf); - if (retval) - return retval; - - retval = follow_link(fs, root, cwd, inode, 0, buf, res_inode); - - ext2fs_free_mem(&buf); - return retval; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * newdir.c --- create a new directory block - * - * Copyright (C) 1994, 1995 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -#ifndef EXT2_FT_DIR -#define EXT2_FT_DIR 2 -#endif - -/* - * Create new directory block - */ -errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino, - ext2_ino_t parent_ino, char **block) -{ - struct ext2_dir_entry *dir = NULL; - errcode_t retval; - char *buf; - int rec_len; - int filetype = 0; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - retval = ext2fs_get_mem(fs->blocksize, &buf); - if (retval) - return retval; - memset(buf, 0, fs->blocksize); - dir = (struct ext2_dir_entry *) buf; - dir->rec_len = fs->blocksize; - - if (dir_ino) { - if (fs->super->s_feature_incompat & - EXT2_FEATURE_INCOMPAT_FILETYPE) - filetype = EXT2_FT_DIR << 8; - /* - * Set up entry for '.' - */ - dir->inode = dir_ino; - dir->name_len = 1 | filetype; - dir->name[0] = '.'; - rec_len = dir->rec_len - EXT2_DIR_REC_LEN(1); - dir->rec_len = EXT2_DIR_REC_LEN(1); - - /* - * Set up entry for '..' - */ - dir = (struct ext2_dir_entry *) (buf + dir->rec_len); - dir->rec_len = rec_len; - dir->inode = parent_ino; - dir->name_len = 2 | filetype; - dir->name[0] = '.'; - dir->name[1] = '.'; - } - *block = buf; - return 0; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * openfs.c --- open an ext2 filesystem - * - * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" - - -#include "ext2fs.h" -#include "e2image.h" - -blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, dgrp_t i) -{ - int bg; - int has_super = 0; - int ret_blk; - - if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) || - (i < fs->super->s_first_meta_bg)) - return (group_block + i + 1); - - bg = (fs->blocksize / sizeof (struct ext2_group_desc)) * i; - if (ext2fs_bg_has_super(fs, bg)) - has_super = 1; - ret_blk = (fs->super->s_first_data_block + has_super + - (bg * fs->super->s_blocks_per_group)); - /* - * If group_block is not the normal value, we're trying to use - * the backup group descriptors and superblock --- so use the - * alternate location of the second block group in the - * metablock group. Ideally we should be testing each bg - * descriptor block individually for correctness, but we don't - * have the infrastructure in place to do that. - */ - if (group_block != fs->super->s_first_data_block && - ((ret_blk + fs->super->s_blocks_per_group) < - fs->super->s_blocks_count)) - ret_blk += fs->super->s_blocks_per_group; - return ret_blk; -} - -errcode_t ext2fs_open(const char *name, int flags, int superblock, - unsigned int block_size, io_manager manager, - ext2_filsys *ret_fs) -{ - return ext2fs_open2(name, 0, flags, superblock, block_size, - manager, ret_fs); -} - -/* - * Note: if superblock is non-zero, block-size must also be non-zero. - * Superblock and block_size can be zero to use the default size. - * - * Valid flags for ext2fs_open() - * - * EXT2_FLAG_RW - Open the filesystem for read/write. - * EXT2_FLAG_FORCE - Open the filesystem even if some of the - * features aren't supported. - * EXT2_FLAG_JOURNAL_DEV_OK - Open an ext3 journal device - */ -errcode_t ext2fs_open2(const char *name, const char *io_options, - int flags, int superblock, - unsigned int block_size, io_manager manager, - ext2_filsys *ret_fs) -{ - ext2_filsys fs; - errcode_t retval; - unsigned long i; - int groups_per_block, blocks_per_group; - blk_t group_block, blk; - char *dest, *cp; -#if BB_BIG_ENDIAN - int j; - struct ext2_group_desc *gdp; -#endif - - EXT2_CHECK_MAGIC(manager, EXT2_ET_MAGIC_IO_MANAGER); - - retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs); - if (retval) - return retval; - - memset(fs, 0, sizeof(struct struct_ext2_filsys)); - fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS; - fs->flags = flags; - fs->umask = 022; - retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name); - if (retval) - goto cleanup; - strcpy(fs->device_name, name); - cp = strchr(fs->device_name, '?'); - if (!io_options && cp) { - *cp++ = 0; - io_options = cp; - } - - retval = manager->open(fs->device_name, - (flags & EXT2_FLAG_RW) ? IO_FLAG_RW : 0, - &fs->io); - if (retval) - goto cleanup; - if (io_options && - (retval = io_channel_set_options(fs->io, io_options))) - goto cleanup; - fs->image_io = fs->io; - fs->io->app_data = fs; - retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->super); - if (retval) - goto cleanup; - if (flags & EXT2_FLAG_IMAGE_FILE) { - retval = ext2fs_get_mem(sizeof(struct ext2_image_hdr), - &fs->image_header); - if (retval) - goto cleanup; - retval = io_channel_read_blk(fs->io, 0, - -(int)sizeof(struct ext2_image_hdr), - fs->image_header); - if (retval) - goto cleanup; - if (fs->image_header->magic_number != EXT2_ET_MAGIC_E2IMAGE) - return EXT2_ET_MAGIC_E2IMAGE; - superblock = 1; - block_size = fs->image_header->fs_blocksize; - } - - /* - * If the user specifies a specific block # for the - * superblock, then he/she must also specify the block size! - * Otherwise, read the master superblock located at offset - * SUPERBLOCK_OFFSET from the start of the partition. - * - * Note: we only save a backup copy of the superblock if we - * are reading the superblock from the primary superblock location. - */ - if (superblock) { - if (!block_size) { - retval = EXT2_ET_INVALID_ARGUMENT; - goto cleanup; - } - io_channel_set_blksize(fs->io, block_size); - group_block = superblock; - fs->orig_super = 0; - } else { - io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET); - superblock = 1; - group_block = 0; - retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super); - if (retval) - goto cleanup; - } - retval = io_channel_read_blk(fs->io, superblock, -SUPERBLOCK_SIZE, - fs->super); - if (retval) - goto cleanup; - if (fs->orig_super) - memcpy(fs->orig_super, fs->super, SUPERBLOCK_SIZE); - -#if BB_BIG_ENDIAN - if ((fs->super->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC)) || - (fs->flags & EXT2_FLAG_SWAP_BYTES)) { - fs->flags |= EXT2_FLAG_SWAP_BYTES; - - ext2fs_swap_super(fs->super); - } -#endif - - if (fs->super->s_magic != EXT2_SUPER_MAGIC) { - retval = EXT2_ET_BAD_MAGIC; - goto cleanup; - } - if (fs->super->s_rev_level > EXT2_LIB_CURRENT_REV) { - retval = EXT2_ET_REV_TOO_HIGH; - goto cleanup; - } - - /* - * Check for feature set incompatibility - */ - if (!(flags & EXT2_FLAG_FORCE)) { - if (fs->super->s_feature_incompat & - ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) { - retval = EXT2_ET_UNSUPP_FEATURE; - goto cleanup; - } - if ((flags & EXT2_FLAG_RW) && - (fs->super->s_feature_ro_compat & - ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP)) { - retval = EXT2_ET_RO_UNSUPP_FEATURE; - goto cleanup; - } - if (!(flags & EXT2_FLAG_JOURNAL_DEV_OK) && - (fs->super->s_feature_incompat & - EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) { - retval = EXT2_ET_UNSUPP_FEATURE; - goto cleanup; - } - } - - fs->blocksize = EXT2_BLOCK_SIZE(fs->super); - if (fs->blocksize == 0) { - retval = EXT2_ET_CORRUPT_SUPERBLOCK; - goto cleanup; - } - fs->fragsize = EXT2_FRAG_SIZE(fs->super); - fs->inode_blocks_per_group = ((fs->super->s_inodes_per_group * - EXT2_INODE_SIZE(fs->super) + - EXT2_BLOCK_SIZE(fs->super) - 1) / - EXT2_BLOCK_SIZE(fs->super)); - if (block_size) { - if (block_size != fs->blocksize) { - retval = EXT2_ET_UNEXPECTED_BLOCK_SIZE; - goto cleanup; - } - } - /* - * Set the blocksize to the filesystem's blocksize. - */ - io_channel_set_blksize(fs->io, fs->blocksize); - - /* - * If this is an external journal device, don't try to read - * the group descriptors, because they're not there. - */ - if (fs->super->s_feature_incompat & - EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) { - fs->group_desc_count = 0; - *ret_fs = fs; - return 0; - } - - /* - * Read group descriptors - */ - blocks_per_group = EXT2_BLOCKS_PER_GROUP(fs->super); - if (blocks_per_group == 0 || - blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(fs->super) || - fs->inode_blocks_per_group > EXT2_MAX_INODES_PER_GROUP(fs->super)) { - retval = EXT2_ET_CORRUPT_SUPERBLOCK; - goto cleanup; - } - fs->group_desc_count = (fs->super->s_blocks_count - - fs->super->s_first_data_block + - blocks_per_group - 1) / blocks_per_group; - fs->desc_blocks = (fs->group_desc_count + - EXT2_DESC_PER_BLOCK(fs->super) - 1) - / EXT2_DESC_PER_BLOCK(fs->super); - retval = ext2fs_get_mem(fs->desc_blocks * fs->blocksize, - &fs->group_desc); - if (retval) - goto cleanup; - if (!group_block) - group_block = fs->super->s_first_data_block; - dest = (char *) fs->group_desc; - groups_per_block = fs->blocksize / sizeof(struct ext2_group_desc); - for (i = 0; i < fs->desc_blocks; i++) { - blk = ext2fs_descriptor_block_loc(fs, group_block, i); - retval = io_channel_read_blk(fs->io, blk, 1, dest); - if (retval) - goto cleanup; -#if BB_BIG_ENDIAN - if (fs->flags & EXT2_FLAG_SWAP_BYTES) { - gdp = (struct ext2_group_desc *) dest; - for (j=0; j < groups_per_block; j++) - ext2fs_swap_group_desc(gdp++); - } -#endif - dest += fs->blocksize; - } - - *ret_fs = fs; - return 0; -cleanup: - ext2fs_free(fs); - return retval; -} - -/* - * Set/get the filesystem data I/O channel. - * - * These functions are only valid if EXT2_FLAG_IMAGE_FILE is true. - */ -errcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io) -{ - if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0) - return EXT2_ET_NOT_IMAGE_FILE; - if (old_io) { - *old_io = (fs->image_io == fs->io) ? 0 : fs->io; - } - return 0; -} - -errcode_t ext2fs_set_data_io(ext2_filsys fs, io_channel new_io) -{ - if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0) - return EXT2_ET_NOT_IMAGE_FILE; - fs->io = new_io ? new_io : fs->image_io; - return 0; -} - -errcode_t ext2fs_rewrite_to_io(ext2_filsys fs, io_channel new_io) -{ - if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0) - return EXT2_ET_NOT_IMAGE_FILE; - fs->io = fs->image_io = new_io; - fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_RW | - EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY; - fs->flags &= ~EXT2_FLAG_IMAGE_FILE; - return 0; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * read_bb --- read the bad blocks inode - * - * Copyright (C) 1994 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -struct read_bb_record { - ext2_badblocks_list bb_list; - errcode_t err; -}; - -/* - * Helper function for ext2fs_read_bb_inode() - */ -#ifdef __TURBOC__ -# pragma argsused -#endif -static int mark_bad_block(ext2_filsys fs, blk_t *block_nr, - e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), - blk_t ref_block EXT2FS_ATTR((unused)), - int ref_offset EXT2FS_ATTR((unused)), - void *priv_data) -{ - struct read_bb_record *rb = (struct read_bb_record *) priv_data; - - if (blockcnt < 0) - return 0; - - if ((*block_nr < fs->super->s_first_data_block) || - (*block_nr >= fs->super->s_blocks_count)) - return 0; /* Ignore illegal blocks */ - - rb->err = ext2fs_badblocks_list_add(rb->bb_list, *block_nr); - if (rb->err) - return BLOCK_ABORT; - return 0; -} - -/* - * Reads the current bad blocks from the bad blocks inode. - */ -errcode_t ext2fs_read_bb_inode(ext2_filsys fs, ext2_badblocks_list *bb_list) -{ - errcode_t retval; - struct read_bb_record rb; - struct ext2_inode inode; - blk_t numblocks; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - if (!*bb_list) { - retval = ext2fs_read_inode(fs, EXT2_BAD_INO, &inode); - if (retval) - return retval; - if (inode.i_blocks < 500) - numblocks = (inode.i_blocks / - (fs->blocksize / 512)) + 20; - else - numblocks = 500; - retval = ext2fs_badblocks_list_create(bb_list, numblocks); - if (retval) - return retval; - } - - rb.bb_list = *bb_list; - rb.err = 0; - retval = ext2fs_block_iterate2(fs, EXT2_BAD_INO, 0, 0, - mark_bad_block, &rb); - if (retval) - return retval; - - return rb.err; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * read_bb_file.c --- read a list of bad blocks from a FILE * - * - * Copyright (C) 1994, 1995, 2000 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -/* - * Reads a list of bad blocks from a FILE * - */ -errcode_t ext2fs_read_bb_FILE2(ext2_filsys fs, FILE *f, - ext2_badblocks_list *bb_list, - void *priv_data, - void (*invalid)(ext2_filsys fs, - blk_t blk, - char *badstr, - void *priv_data)) -{ - errcode_t retval; - blk_t blockno; - int count; - char buf[128]; - - if (fs) - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - if (!*bb_list) { - retval = ext2fs_badblocks_list_create(bb_list, 10); - if (retval) - return retval; - } - - while (!feof (f)) { - if (fgets(buf, sizeof(buf), f) == NULL) - break; - count = sscanf(buf, "%u", &blockno); - if (count <= 0) - continue; - if (fs && - ((blockno < fs->super->s_first_data_block) || - (blockno >= fs->super->s_blocks_count))) { - if (invalid) - (invalid)(fs, blockno, buf, priv_data); - continue; - } - retval = ext2fs_badblocks_list_add(*bb_list, blockno); - if (retval) - return retval; - } - return 0; -} - -static void call_compat_invalid(ext2_filsys fs, blk_t blk, - char *badstr EXT2FS_ATTR((unused)), - void *priv_data) -{ - void (*invalid)(ext2_filsys, blk_t); - - invalid = (void (*)(ext2_filsys, blk_t)) priv_data; - if (invalid) - invalid(fs, blk); -} - - -/* - * Reads a list of bad blocks from a FILE * - */ -errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f, - ext2_badblocks_list *bb_list, - void (*invalid)(ext2_filsys fs, blk_t blk)) -{ - return ext2fs_read_bb_FILE2(fs, f, bb_list, (void *) invalid, - call_compat_invalid); -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * res_gdt.c --- reserve blocks for growing the group descriptor table - * during online resizing. - * - * Copyright (C) 2002 Andreas Dilger - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#include -#include "ext2_fs.h" -#include "ext2fs.h" - -/* - * Iterate through the groups which hold BACKUP superblock/GDT copies in an - * ext3 filesystem. The counters should be initialized to 1, 5, and 7 before - * calling this for the first time. In a sparse filesystem it will be the - * sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ... - * For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ... - */ -static unsigned int list_backups(ext2_filsys fs, unsigned int *three, - unsigned int *five, unsigned int *seven) -{ - unsigned int *min = three; - int mult = 3; - unsigned int ret; - - if (!(fs->super->s_feature_ro_compat & - EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) { - ret = *min; - *min += 1; - return ret; - } - - if (*five < *min) { - min = five; - mult = 5; - } - if (*seven < *min) { - min = seven; - mult = 7; - } - - ret = *min; - *min *= mult; - - return ret; -} - -/* - * This code assumes that the reserved blocks have already been marked in-use - * during ext2fs_initialize(), so that they are not allocated for other - * uses before we can add them to the resize inode (which has to come - * after the creation of the inode table). - */ -errcode_t ext2fs_create_resize_inode(ext2_filsys fs) -{ - errcode_t retval, retval2; - struct ext2_super_block *sb; - struct ext2_inode inode; - __u32 *dindir_buf, *gdt_buf; - int rsv_add; - unsigned long long apb, inode_size; - blk_t dindir_blk, rsv_off, gdt_off, gdt_blk; - int dindir_dirty = 0, inode_dirty = 0; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - sb = fs->super; - - retval = ext2fs_get_mem(2 * fs->blocksize, (void *)&dindir_buf); - if (retval) - goto out_free; - gdt_buf = (__u32 *)((char *)dindir_buf + fs->blocksize); - - retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode); - if (retval) - goto out_free; - - /* Maximum possible file size (we donly use the dindirect blocks) */ - apb = EXT2_ADDR_PER_BLOCK(sb); - rsv_add = fs->blocksize / 512; - if ((dindir_blk = inode.i_block[EXT2_DIND_BLOCK])) { -#ifdef RES_GDT_DEBUG - printf("reading GDT dindir %u\n", dindir_blk); -#endif - retval = ext2fs_read_ind_block(fs, dindir_blk, dindir_buf); - if (retval) - goto out_inode; - } else { - blk_t goal = 3 + sb->s_reserved_gdt_blocks + - fs->desc_blocks + fs->inode_blocks_per_group; - - retval = ext2fs_alloc_block(fs, goal, 0, &dindir_blk); - if (retval) - goto out_free; - inode.i_mode = LINUX_S_IFREG | 0600; - inode.i_links_count = 1; - inode.i_block[EXT2_DIND_BLOCK] = dindir_blk; - inode.i_blocks = rsv_add; - memset(dindir_buf, 0, fs->blocksize); -#ifdef RES_GDT_DEBUG - printf("allocated GDT dindir %u\n", dindir_blk); -#endif - dindir_dirty = inode_dirty = 1; - inode_size = apb*apb + apb + EXT2_NDIR_BLOCKS; - inode_size *= fs->blocksize; - inode.i_size = inode_size & 0xFFFFFFFF; - inode.i_size_high = (inode_size >> 32) & 0xFFFFFFFF; - if (inode.i_size_high) { - sb->s_feature_ro_compat |= - EXT2_FEATURE_RO_COMPAT_LARGE_FILE; - } - inode.i_ctime = time(NULL); - } - - for (rsv_off = 0, gdt_off = fs->desc_blocks, - gdt_blk = sb->s_first_data_block + 1 + fs->desc_blocks; - rsv_off < sb->s_reserved_gdt_blocks; - rsv_off++, gdt_off++, gdt_blk++) { - unsigned int three = 1, five = 5, seven = 7; - unsigned int grp, last = 0; - int gdt_dirty = 0; - - gdt_off %= apb; - if (!dindir_buf[gdt_off]) { - /* FIXME XXX XXX - blk_t new_blk; - - retval = ext2fs_new_block(fs, gdt_blk, 0, &new_blk); - if (retval) - goto out_free; - if (new_blk != gdt_blk) { - // XXX free block - retval = -1; // XXX - } - */ - gdt_dirty = dindir_dirty = inode_dirty = 1; - memset(gdt_buf, 0, fs->blocksize); - dindir_buf[gdt_off] = gdt_blk; - inode.i_blocks += rsv_add; -#ifdef RES_GDT_DEBUG - printf("added primary GDT block %u at %u[%u]\n", - gdt_blk, dindir_blk, gdt_off); -#endif - } else if (dindir_buf[gdt_off] == gdt_blk) { -#ifdef RES_GDT_DEBUG - printf("reading primary GDT block %u\n", gdt_blk); -#endif - retval = ext2fs_read_ind_block(fs, gdt_blk, gdt_buf); - if (retval) - goto out_dindir; - } else { -#ifdef RES_GDT_DEBUG - printf("bad primary GDT %u != %u at %u[%u]\n", - dindir_buf[gdt_off], gdt_blk,dindir_blk,gdt_off); -#endif - retval = EXT2_ET_RESIZE_INODE_CORRUPT; - goto out_dindir; - } - - while ((grp = list_backups(fs, &three, &five, &seven)) < - fs->group_desc_count) { - blk_t expect = gdt_blk + grp * sb->s_blocks_per_group; - - if (!gdt_buf[last]) { -#ifdef RES_GDT_DEBUG - printf("added backup GDT %u grp %u@%u[%u]\n", - expect, grp, gdt_blk, last); -#endif - gdt_buf[last] = expect; - inode.i_blocks += rsv_add; - gdt_dirty = inode_dirty = 1; - } else if (gdt_buf[last] != expect) { -#ifdef RES_GDT_DEBUG - printf("bad backup GDT %u != %u at %u[%u]\n", - gdt_buf[last], expect, gdt_blk, last); -#endif - retval = EXT2_ET_RESIZE_INODE_CORRUPT; - goto out_dindir; - } - last++; - } - if (gdt_dirty) { -#ifdef RES_GDT_DEBUG - printf("writing primary GDT block %u\n", gdt_blk); -#endif - retval = ext2fs_write_ind_block(fs, gdt_blk, gdt_buf); - if (retval) - goto out_dindir; - } - } - -out_dindir: - if (dindir_dirty) { - retval2 = ext2fs_write_ind_block(fs, dindir_blk, dindir_buf); - if (!retval) - retval = retval2; - } -out_inode: -#ifdef RES_GDT_DEBUG - printf("inode.i_blocks = %u, i_size = %u\n", inode.i_blocks, - inode.i_size); -#endif - if (inode_dirty) { - inode.i_atime = inode.i_mtime = time(NULL); - retval2 = ext2fs_write_inode(fs, EXT2_RESIZE_INO, &inode); - if (!retval) - retval = retval2; - } -out_free: - ext2fs_free_mem((void *)&dindir_buf); - return retval; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * rs_bitmap.c --- routine for changing the size of a bitmap - * - * Copyright (C) 1996, 1997 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#ifdef HAVE_SYS_STAT_H -#include -#endif -#ifdef HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -errcode_t ext2fs_resize_generic_bitmap(__u32 new_end, __u32 new_real_end, - ext2fs_generic_bitmap bmap) -{ - errcode_t retval; - size_t size, new_size; - __u32 bitno; - - if (!bmap) - return EXT2_ET_INVALID_ARGUMENT; - - EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_GENERIC_BITMAP); - - /* - * If we're expanding the bitmap, make sure all of the new - * parts of the bitmap are zero. - */ - if (new_end > bmap->end) { - bitno = bmap->real_end; - if (bitno > new_end) - bitno = new_end; - for (; bitno > bmap->end; bitno--) - ext2fs_clear_bit(bitno - bmap->start, bmap->bitmap); - } - if (new_real_end == bmap->real_end) { - bmap->end = new_end; - return 0; - } - - size = ((bmap->real_end - bmap->start) / 8) + 1; - new_size = ((new_real_end - bmap->start) / 8) + 1; - - if (size != new_size) { - retval = ext2fs_resize_mem(size, new_size, &bmap->bitmap); - if (retval) - return retval; - } - if (new_size > size) - memset(bmap->bitmap + size, 0, new_size - size); - - bmap->end = new_end; - bmap->real_end = new_real_end; - return 0; -} - -errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end, - ext2fs_inode_bitmap bmap) -{ - errcode_t retval; - - if (!bmap) - return EXT2_ET_INVALID_ARGUMENT; - - EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_INODE_BITMAP); - - bmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP; - retval = ext2fs_resize_generic_bitmap(new_end, new_real_end, - bmap); - bmap->magic = EXT2_ET_MAGIC_INODE_BITMAP; - return retval; -} - -errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end, - ext2fs_block_bitmap bmap) -{ - errcode_t retval; - - if (!bmap) - return EXT2_ET_INVALID_ARGUMENT; - - EXT2_CHECK_MAGIC(bmap, EXT2_ET_MAGIC_BLOCK_BITMAP); - - bmap->magic = EXT2_ET_MAGIC_GENERIC_BITMAP; - retval = ext2fs_resize_generic_bitmap(new_end, new_real_end, - bmap); - bmap->magic = EXT2_ET_MAGIC_BLOCK_BITMAP; - return retval; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * rw_bitmaps.c --- routines to read and write the inode and block bitmaps. - * - * Copyright (C) 1993, 1994, 1994, 1996 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#ifdef HAVE_SYS_STAT_H -#include -#endif -#ifdef HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" -#include "e2image.h" - -#if defined(__powerpc__) && BB_BIG_ENDIAN -/* - * On the PowerPC, the big-endian variant of the ext2 filesystem - * has its bitmaps stored as 32-bit words with bit 0 as the LSB - * of each word. Thus a bitmap with only bit 0 set would be, as - * a string of bytes, 00 00 00 01 00 ... - * To cope with this, we byte-reverse each word of a bitmap if - * we have a big-endian filesystem, that is, if we are *not* - * byte-swapping other word-sized numbers. - */ -#define EXT2_BIG_ENDIAN_BITMAPS -#endif - -#ifdef EXT2_BIG_ENDIAN_BITMAPS -static void ext2fs_swap_bitmap(ext2_filsys fs, char *bitmap, int nbytes) -{ - __u32 *p = (__u32 *) bitmap; - int n; - - for (n = nbytes / sizeof(__u32); n > 0; --n, ++p) - *p = ext2fs_swab32(*p); -} -#endif - -errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs) -{ - dgrp_t i; - size_t nbytes; - errcode_t retval; - char * inode_bitmap = fs->inode_map->bitmap; - char * bitmap_block = NULL; - blk_t blk; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - if (!(fs->flags & EXT2_FLAG_RW)) - return EXT2_ET_RO_FILSYS; - if (!inode_bitmap) - return 0; - nbytes = (size_t) ((EXT2_INODES_PER_GROUP(fs->super)+7) / 8); - - retval = ext2fs_get_mem(fs->blocksize, &bitmap_block); - if (retval) - return retval; - memset(bitmap_block, 0xff, fs->blocksize); - for (i = 0; i < fs->group_desc_count; i++) { - memcpy(bitmap_block, inode_bitmap, nbytes); - blk = fs->group_desc[i].bg_inode_bitmap; - if (blk) { -#ifdef EXT2_BIG_ENDIAN_BITMAPS - if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) || - (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))) - ext2fs_swap_bitmap(fs, bitmap_block, nbytes); -#endif - retval = io_channel_write_blk(fs->io, blk, 1, - bitmap_block); - if (retval) - return EXT2_ET_INODE_BITMAP_WRITE; - } - inode_bitmap += nbytes; - } - fs->flags &= ~EXT2_FLAG_IB_DIRTY; - ext2fs_free_mem(&bitmap_block); - return 0; -} - -errcode_t ext2fs_write_block_bitmap (ext2_filsys fs) -{ - dgrp_t i; - unsigned int j; - int nbytes; - unsigned int nbits; - errcode_t retval; - char * block_bitmap = fs->block_map->bitmap; - char * bitmap_block = NULL; - blk_t blk; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - if (!(fs->flags & EXT2_FLAG_RW)) - return EXT2_ET_RO_FILSYS; - if (!block_bitmap) - return 0; - nbytes = EXT2_BLOCKS_PER_GROUP(fs->super) / 8; - retval = ext2fs_get_mem(fs->blocksize, &bitmap_block); - if (retval) - return retval; - memset(bitmap_block, 0xff, fs->blocksize); - for (i = 0; i < fs->group_desc_count; i++) { - memcpy(bitmap_block, block_bitmap, nbytes); - if (i == fs->group_desc_count - 1) { - /* Force bitmap padding for the last group */ - nbits = ((fs->super->s_blocks_count - - fs->super->s_first_data_block) - % EXT2_BLOCKS_PER_GROUP(fs->super)); - if (nbits) - for (j = nbits; j < fs->blocksize * 8; j++) - ext2fs_set_bit(j, bitmap_block); - } - blk = fs->group_desc[i].bg_block_bitmap; - if (blk) { -#ifdef EXT2_BIG_ENDIAN_BITMAPS - if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) || - (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))) - ext2fs_swap_bitmap(fs, bitmap_block, nbytes); -#endif - retval = io_channel_write_blk(fs->io, blk, 1, - bitmap_block); - if (retval) - return EXT2_ET_BLOCK_BITMAP_WRITE; - } - block_bitmap += nbytes; - } - fs->flags &= ~EXT2_FLAG_BB_DIRTY; - ext2fs_free_mem(&bitmap_block); - return 0; -} - -static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) -{ - dgrp_t i; - char *block_bitmap = NULL, *inode_bitmap = NULL; - char *buf; - errcode_t retval; - int block_nbytes = (int) EXT2_BLOCKS_PER_GROUP(fs->super) / 8; - int inode_nbytes = (int) EXT2_INODES_PER_GROUP(fs->super) / 8; - blk_t blk; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - fs->write_bitmaps = ext2fs_write_bitmaps; - - retval = ext2fs_get_mem(strlen(fs->device_name) + 80, &buf); - if (retval) - return retval; - if (do_block) { - ext2fs_free_block_bitmap(fs->block_map); - sprintf(buf, "block bitmap for %s", fs->device_name); - retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map); - if (retval) - goto cleanup; - block_bitmap = fs->block_map->bitmap; - } - if (do_inode) { - ext2fs_free_inode_bitmap(fs->inode_map); - sprintf(buf, "inode bitmap for %s", fs->device_name); - retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map); - if (retval) - goto cleanup; - inode_bitmap = fs->inode_map->bitmap; - } - ext2fs_free_mem(&buf); - - if (fs->flags & EXT2_FLAG_IMAGE_FILE) { - if (inode_bitmap) { - blk = (fs->image_header->offset_inodemap / - fs->blocksize); - retval = io_channel_read_blk(fs->image_io, blk, - -(inode_nbytes * fs->group_desc_count), - inode_bitmap); - if (retval) - goto cleanup; - } - if (block_bitmap) { - blk = (fs->image_header->offset_blockmap / - fs->blocksize); - retval = io_channel_read_blk(fs->image_io, blk, - -(block_nbytes * fs->group_desc_count), - block_bitmap); - if (retval) - goto cleanup; - } - return 0; - } - - for (i = 0; i < fs->group_desc_count; i++) { - if (block_bitmap) { - blk = fs->group_desc[i].bg_block_bitmap; - if (blk) { - retval = io_channel_read_blk(fs->io, blk, - -block_nbytes, block_bitmap); - if (retval) { - retval = EXT2_ET_BLOCK_BITMAP_READ; - goto cleanup; - } -#ifdef EXT2_BIG_ENDIAN_BITMAPS - if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) || - (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))) - ext2fs_swap_bitmap(fs, block_bitmap, block_nbytes); -#endif - } else - memset(block_bitmap, 0, block_nbytes); - block_bitmap += block_nbytes; - } - if (inode_bitmap) { - blk = fs->group_desc[i].bg_inode_bitmap; - if (blk) { - retval = io_channel_read_blk(fs->io, blk, - -inode_nbytes, inode_bitmap); - if (retval) { - retval = EXT2_ET_INODE_BITMAP_READ; - goto cleanup; - } -#ifdef EXT2_BIG_ENDIAN_BITMAPS - if (!((fs->flags & EXT2_FLAG_SWAP_BYTES) || - (fs->flags & EXT2_FLAG_SWAP_BYTES_READ))) - ext2fs_swap_bitmap(fs, inode_bitmap, inode_nbytes); -#endif - } else - memset(inode_bitmap, 0, inode_nbytes); - inode_bitmap += inode_nbytes; - } - } - return 0; - -cleanup: - if (do_block) { - ext2fs_free_mem(&fs->block_map); - } - if (do_inode) { - ext2fs_free_mem(&fs->inode_map); - } - ext2fs_free_mem(&buf); - return retval; -} - -errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs) -{ - return read_bitmaps(fs, 1, 0); -} - -errcode_t ext2fs_read_block_bitmap(ext2_filsys fs) -{ - return read_bitmaps(fs, 0, 1); -} - -errcode_t ext2fs_read_bitmaps(ext2_filsys fs) -{ - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - if (fs->inode_map && fs->block_map) - return 0; - - return read_bitmaps(fs, !fs->inode_map, !fs->block_map); -} - -errcode_t ext2fs_write_bitmaps(ext2_filsys fs) -{ - errcode_t retval; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - if (fs->block_map && ext2fs_test_bb_dirty(fs)) { - retval = ext2fs_write_block_bitmap(fs); - if (retval) - return retval; - } - if (fs->inode_map && ext2fs_test_ib_dirty(fs)) { - retval = ext2fs_write_inode_bitmap(fs); - if (retval) - return retval; - } - return 0; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * sparse.c --- find the groups in an ext2 filesystem with metadata backups - * - * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. - * Copyright (C) 2002 Andreas Dilger. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include - -#include "ext2_fs.h" -#include "ext2fsP.h" - -static int test_root(int a, int b) -{ - if (a == 0) - return 1; - while (1) { - if (a == 1) - return 1; - if (a % b) - return 0; - a = a / b; - } -} - -int ext2fs_bg_has_super(ext2_filsys fs, int group_block) -{ - if (!(fs->super->s_feature_ro_compat & - EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) - return 1; - - if (test_root(group_block, 3) || (test_root(group_block, 5)) || - test_root(group_block, 7)) - return 1; - - return 0; -} - -/* - * Iterate through the groups which hold BACKUP superblock/GDT copies in an - * ext3 filesystem. The counters should be initialized to 1, 5, and 7 before - * calling this for the first time. In a sparse filesystem it will be the - * sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ... - * For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ... - */ -unsigned int ext2fs_list_backups(ext2_filsys fs, unsigned int *three, - unsigned int *five, unsigned int *seven) -{ - unsigned int *min = three; - int mult = 3; - unsigned int ret; - - if (!(fs->super->s_feature_ro_compat & - EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) { - ret = *min; - *min += 1; - return ret; - } - - if (*five < *min) { - min = five; - mult = 5; - } - if (*seven < *min) { - min = seven; - mult = 7; - } - - ret = *min; - *min *= mult; - - return ret; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * swapfs.c --- swap ext2 filesystem data structures - * - * Copyright (C) 1995, 1996, 2002 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#include -#include - -#include "ext2_fs.h" -#include "ext2fs.h" -#include "ext2_ext_attr.h" - -#if BB_BIG_ENDIAN -void ext2fs_swap_super(struct ext2_super_block * sb) -{ - int i; - sb->s_inodes_count = ext2fs_swab32(sb->s_inodes_count); - sb->s_blocks_count = ext2fs_swab32(sb->s_blocks_count); - sb->s_r_blocks_count = ext2fs_swab32(sb->s_r_blocks_count); - sb->s_free_blocks_count = ext2fs_swab32(sb->s_free_blocks_count); - sb->s_free_inodes_count = ext2fs_swab32(sb->s_free_inodes_count); - sb->s_first_data_block = ext2fs_swab32(sb->s_first_data_block); - sb->s_log_block_size = ext2fs_swab32(sb->s_log_block_size); - sb->s_log_frag_size = ext2fs_swab32(sb->s_log_frag_size); - sb->s_blocks_per_group = ext2fs_swab32(sb->s_blocks_per_group); - sb->s_frags_per_group = ext2fs_swab32(sb->s_frags_per_group); - sb->s_inodes_per_group = ext2fs_swab32(sb->s_inodes_per_group); - sb->s_mtime = ext2fs_swab32(sb->s_mtime); - sb->s_wtime = ext2fs_swab32(sb->s_wtime); - sb->s_mnt_count = ext2fs_swab16(sb->s_mnt_count); - sb->s_max_mnt_count = ext2fs_swab16(sb->s_max_mnt_count); - sb->s_magic = ext2fs_swab16(sb->s_magic); - sb->s_state = ext2fs_swab16(sb->s_state); - sb->s_errors = ext2fs_swab16(sb->s_errors); - sb->s_minor_rev_level = ext2fs_swab16(sb->s_minor_rev_level); - sb->s_lastcheck = ext2fs_swab32(sb->s_lastcheck); - sb->s_checkinterval = ext2fs_swab32(sb->s_checkinterval); - sb->s_creator_os = ext2fs_swab32(sb->s_creator_os); - sb->s_rev_level = ext2fs_swab32(sb->s_rev_level); - sb->s_def_resuid = ext2fs_swab16(sb->s_def_resuid); - sb->s_def_resgid = ext2fs_swab16(sb->s_def_resgid); - sb->s_first_ino = ext2fs_swab32(sb->s_first_ino); - sb->s_inode_size = ext2fs_swab16(sb->s_inode_size); - sb->s_block_group_nr = ext2fs_swab16(sb->s_block_group_nr); - sb->s_feature_compat = ext2fs_swab32(sb->s_feature_compat); - sb->s_feature_incompat = ext2fs_swab32(sb->s_feature_incompat); - sb->s_feature_ro_compat = ext2fs_swab32(sb->s_feature_ro_compat); - sb->s_algorithm_usage_bitmap = ext2fs_swab32(sb->s_algorithm_usage_bitmap); - sb->s_reserved_gdt_blocks = ext2fs_swab16(sb->s_reserved_gdt_blocks); - sb->s_journal_inum = ext2fs_swab32(sb->s_journal_inum); - sb->s_journal_dev = ext2fs_swab32(sb->s_journal_dev); - sb->s_last_orphan = ext2fs_swab32(sb->s_last_orphan); - sb->s_default_mount_opts = ext2fs_swab32(sb->s_default_mount_opts); - sb->s_first_meta_bg = ext2fs_swab32(sb->s_first_meta_bg); - sb->s_mkfs_time = ext2fs_swab32(sb->s_mkfs_time); - for (i=0; i < 4; i++) - sb->s_hash_seed[i] = ext2fs_swab32(sb->s_hash_seed[i]); - for (i=0; i < 17; i++) - sb->s_jnl_blocks[i] = ext2fs_swab32(sb->s_jnl_blocks[i]); -} - -void ext2fs_swap_group_desc(struct ext2_group_desc *gdp) -{ - gdp->bg_block_bitmap = ext2fs_swab32(gdp->bg_block_bitmap); - gdp->bg_inode_bitmap = ext2fs_swab32(gdp->bg_inode_bitmap); - gdp->bg_inode_table = ext2fs_swab32(gdp->bg_inode_table); - gdp->bg_free_blocks_count = ext2fs_swab16(gdp->bg_free_blocks_count); - gdp->bg_free_inodes_count = ext2fs_swab16(gdp->bg_free_inodes_count); - gdp->bg_used_dirs_count = ext2fs_swab16(gdp->bg_used_dirs_count); -} - -void ext2fs_swap_ext_attr(char *to, char *from, int bufsize, int has_header) -{ - struct ext2_ext_attr_header *from_header = - (struct ext2_ext_attr_header *)from; - struct ext2_ext_attr_header *to_header = - (struct ext2_ext_attr_header *)to; - struct ext2_ext_attr_entry *from_entry, *to_entry; - char *from_end = (char *)from_header + bufsize; - int n; - - if (to_header != from_header) - memcpy(to_header, from_header, bufsize); - - from_entry = (struct ext2_ext_attr_entry *)from_header; - to_entry = (struct ext2_ext_attr_entry *)to_header; - - if (has_header) { - to_header->h_magic = ext2fs_swab32(from_header->h_magic); - to_header->h_blocks = ext2fs_swab32(from_header->h_blocks); - to_header->h_refcount = ext2fs_swab32(from_header->h_refcount); - for (n=0; n<4; n++) - to_header->h_reserved[n] = - ext2fs_swab32(from_header->h_reserved[n]); - from_entry = (struct ext2_ext_attr_entry *)(from_header+1); - to_entry = (struct ext2_ext_attr_entry *)(to_header+1); - } - - while ((char *)from_entry < from_end && *(__u32 *)from_entry) { - to_entry->e_value_offs = - ext2fs_swab16(from_entry->e_value_offs); - to_entry->e_value_block = - ext2fs_swab32(from_entry->e_value_block); - to_entry->e_value_size = - ext2fs_swab32(from_entry->e_value_size); - from_entry = EXT2_EXT_ATTR_NEXT(from_entry); - to_entry = EXT2_EXT_ATTR_NEXT(to_entry); - } -} - -void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t, - struct ext2_inode_large *f, int hostorder, - int bufsize) -{ - unsigned i; - int islnk = 0; - __u32 *eaf, *eat; - - if (hostorder && LINUX_S_ISLNK(f->i_mode)) - islnk = 1; - t->i_mode = ext2fs_swab16(f->i_mode); - if (!hostorder && LINUX_S_ISLNK(t->i_mode)) - islnk = 1; - t->i_uid = ext2fs_swab16(f->i_uid); - t->i_size = ext2fs_swab32(f->i_size); - t->i_atime = ext2fs_swab32(f->i_atime); - t->i_ctime = ext2fs_swab32(f->i_ctime); - t->i_mtime = ext2fs_swab32(f->i_mtime); - t->i_dtime = ext2fs_swab32(f->i_dtime); - t->i_gid = ext2fs_swab16(f->i_gid); - t->i_links_count = ext2fs_swab16(f->i_links_count); - t->i_blocks = ext2fs_swab32(f->i_blocks); - t->i_flags = ext2fs_swab32(f->i_flags); - t->i_file_acl = ext2fs_swab32(f->i_file_acl); - t->i_dir_acl = ext2fs_swab32(f->i_dir_acl); - if (!islnk || ext2fs_inode_data_blocks(fs, (struct ext2_inode *)t)) { - for (i = 0; i < EXT2_N_BLOCKS; i++) - t->i_block[i] = ext2fs_swab32(f->i_block[i]); - } else if (t != f) { - for (i = 0; i < EXT2_N_BLOCKS; i++) - t->i_block[i] = f->i_block[i]; - } - t->i_generation = ext2fs_swab32(f->i_generation); - t->i_faddr = ext2fs_swab32(f->i_faddr); - - switch (fs->super->s_creator_os) { - case EXT2_OS_LINUX: - t->osd1.linux1.l_i_reserved1 = - ext2fs_swab32(f->osd1.linux1.l_i_reserved1); - t->osd2.linux2.l_i_frag = f->osd2.linux2.l_i_frag; - t->osd2.linux2.l_i_fsize = f->osd2.linux2.l_i_fsize; - t->osd2.linux2.i_pad1 = ext2fs_swab16(f->osd2.linux2.i_pad1); - t->osd2.linux2.l_i_uid_high = - ext2fs_swab16 (f->osd2.linux2.l_i_uid_high); - t->osd2.linux2.l_i_gid_high = - ext2fs_swab16 (f->osd2.linux2.l_i_gid_high); - t->osd2.linux2.l_i_reserved2 = - ext2fs_swab32(f->osd2.linux2.l_i_reserved2); - break; - case EXT2_OS_HURD: - t->osd1.hurd1.h_i_translator = - ext2fs_swab32 (f->osd1.hurd1.h_i_translator); - t->osd2.hurd2.h_i_frag = f->osd2.hurd2.h_i_frag; - t->osd2.hurd2.h_i_fsize = f->osd2.hurd2.h_i_fsize; - t->osd2.hurd2.h_i_mode_high = - ext2fs_swab16 (f->osd2.hurd2.h_i_mode_high); - t->osd2.hurd2.h_i_uid_high = - ext2fs_swab16 (f->osd2.hurd2.h_i_uid_high); - t->osd2.hurd2.h_i_gid_high = - ext2fs_swab16 (f->osd2.hurd2.h_i_gid_high); - t->osd2.hurd2.h_i_author = - ext2fs_swab32 (f->osd2.hurd2.h_i_author); - break; - case EXT2_OS_MASIX: - t->osd1.masix1.m_i_reserved1 = - ext2fs_swab32(f->osd1.masix1.m_i_reserved1); - t->osd2.masix2.m_i_frag = f->osd2.masix2.m_i_frag; - t->osd2.masix2.m_i_fsize = f->osd2.masix2.m_i_fsize; - t->osd2.masix2.m_pad1 = ext2fs_swab16(f->osd2.masix2.m_pad1); - t->osd2.masix2.m_i_reserved2[0] = - ext2fs_swab32(f->osd2.masix2.m_i_reserved2[0]); - t->osd2.masix2.m_i_reserved2[1] = - ext2fs_swab32(f->osd2.masix2.m_i_reserved2[1]); - break; - } - - if (bufsize < (int) (sizeof(struct ext2_inode) + sizeof(__u16))) - return; /* no i_extra_isize field */ - - t->i_extra_isize = ext2fs_swab16(f->i_extra_isize); - if (t->i_extra_isize > EXT2_INODE_SIZE(fs->super) - - sizeof(struct ext2_inode)) { - /* this is error case: i_extra_size is too large */ - return; - } - - i = sizeof(struct ext2_inode) + t->i_extra_isize + sizeof(__u32); - if (bufsize < (int) i) - return; /* no space for EA magic */ - - eaf = (__u32 *) (((char *) f) + sizeof(struct ext2_inode) + - f->i_extra_isize); - - if (ext2fs_swab32(*eaf) != EXT2_EXT_ATTR_MAGIC) - return; /* it seems no magic here */ - - eat = (__u32 *) (((char *) t) + sizeof(struct ext2_inode) + - f->i_extra_isize); - *eat = ext2fs_swab32(*eaf); - - /* convert EA(s) */ - ext2fs_swap_ext_attr((char *) (eat + 1), (char *) (eaf + 1), - bufsize - sizeof(struct ext2_inode) - - t->i_extra_isize - sizeof(__u32), 0); -} - -void ext2fs_swap_inode(ext2_filsys fs, struct ext2_inode *t, - struct ext2_inode *f, int hostorder) -{ - ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) t, - (struct ext2_inode_large *) f, hostorder, - sizeof(struct ext2_inode)); -} - -#endif diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * test_io.c --- This is the Test I/O interface. - * - * Copyright (C) 1996 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -/* - * For checking structure magic numbers... - */ - -#define EXT2_CHECK_MAGIC(struct, code) \ - if ((struct)->magic != (code)) return (code) - -struct test_private_data { - int magic; - io_channel real; - int flags; - FILE *outfile; - unsigned long block; - int read_abort_count, write_abort_count; - void (*read_blk)(unsigned long block, int count, errcode_t err); - void (*write_blk)(unsigned long block, int count, errcode_t err); - void (*set_blksize)(int blksize, errcode_t err); - void (*write_byte)(unsigned long block, int count, errcode_t err); -}; - -static errcode_t test_open(const char *name, int flags, io_channel *channel); -static errcode_t test_close(io_channel channel); -static errcode_t test_set_blksize(io_channel channel, int blksize); -static errcode_t test_read_blk(io_channel channel, unsigned long block, - int count, void *data); -static errcode_t test_write_blk(io_channel channel, unsigned long block, - int count, const void *data); -static errcode_t test_flush(io_channel channel); -static errcode_t test_write_byte(io_channel channel, unsigned long offset, - int count, const void *buf); -static errcode_t test_set_option(io_channel channel, const char *option, - const char *arg); - -static struct struct_io_manager struct_test_manager = { - EXT2_ET_MAGIC_IO_MANAGER, - "Test I/O Manager", - test_open, - test_close, - test_set_blksize, - test_read_blk, - test_write_blk, - test_flush, - test_write_byte, - test_set_option -}; - -io_manager test_io_manager = &struct_test_manager; - -/* - * These global variable can be set by the test program as - * necessary *before* calling test_open - */ -io_manager test_io_backing_manager = 0; -void (*test_io_cb_read_blk) - (unsigned long block, int count, errcode_t err) = 0; -void (*test_io_cb_write_blk) - (unsigned long block, int count, errcode_t err) = 0; -void (*test_io_cb_set_blksize) - (int blksize, errcode_t err) = 0; -void (*test_io_cb_write_byte) - (unsigned long block, int count, errcode_t err) = 0; - -/* - * Test flags - */ -#define TEST_FLAG_READ 0x01 -#define TEST_FLAG_WRITE 0x02 -#define TEST_FLAG_SET_BLKSIZE 0x04 -#define TEST_FLAG_FLUSH 0x08 -#define TEST_FLAG_DUMP 0x10 -#define TEST_FLAG_SET_OPTION 0x20 - -static void test_dump_block(io_channel channel, - struct test_private_data *data, - unsigned long block, const void *buf) -{ - const unsigned char *cp; - FILE *f = data->outfile; - int i; - unsigned long cksum = 0; - - for (i=0, cp = buf; i < channel->block_size; i++, cp++) { - cksum += *cp; - } - fprintf(f, "Contents of block %lu, checksum %08lu:\n", block, cksum); - for (i=0, cp = buf; i < channel->block_size; i++, cp++) { - if ((i % 16) == 0) - fprintf(f, "%04x: ", i); - fprintf(f, "%02x%c", *cp, ((i % 16) == 15) ? '\n' : ' '); - } -} - -static void test_abort(io_channel channel, unsigned long block) -{ - struct test_private_data *data; - FILE *f; - - data = (struct test_private_data *) channel->private_data; - f = data->outfile; - test_flush(channel); - - fprintf(f, "Aborting due to I/O to block %lu\n", block); - fflush(f); - abort(); -} - -static errcode_t test_open(const char *name, int flags, io_channel *channel) -{ - io_channel io = NULL; - struct test_private_data *data = NULL; - errcode_t retval; - char *value; - - if (name == 0) - return EXT2_ET_BAD_DEVICE_NAME; - retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io); - if (retval) - return retval; - memset(io, 0, sizeof(struct struct_io_channel)); - io->magic = EXT2_ET_MAGIC_IO_CHANNEL; - retval = ext2fs_get_mem(sizeof(struct test_private_data), &data); - if (retval) { - retval = EXT2_ET_NO_MEMORY; - goto cleanup; - } - io->manager = test_io_manager; - retval = ext2fs_get_mem(strlen(name)+1, &io->name); - if (retval) - goto cleanup; - - strcpy(io->name, name); - io->private_data = data; - io->block_size = 1024; - io->read_error = 0; - io->write_error = 0; - io->refcount = 1; - - memset(data, 0, sizeof(struct test_private_data)); - data->magic = EXT2_ET_MAGIC_TEST_IO_CHANNEL; - if (test_io_backing_manager) { - retval = test_io_backing_manager->open(name, flags, - &data->real); - if (retval) - goto cleanup; - } else - data->real = 0; - data->read_blk = test_io_cb_read_blk; - data->write_blk = test_io_cb_write_blk; - data->set_blksize = test_io_cb_set_blksize; - data->write_byte = test_io_cb_write_byte; - - data->outfile = NULL; - if ((value = getenv("TEST_IO_LOGFILE")) != NULL) - data->outfile = fopen_for_write(value); - if (!data->outfile) - data->outfile = stderr; - - data->flags = 0; - if ((value = getenv("TEST_IO_FLAGS")) != NULL) - data->flags = strtoul(value, NULL, 0); - - data->block = 0; - if ((value = getenv("TEST_IO_BLOCK")) != NULL) - data->block = strtoul(value, NULL, 0); - - data->read_abort_count = 0; - if ((value = getenv("TEST_IO_READ_ABORT")) != NULL) - data->read_abort_count = strtoul(value, NULL, 0); - - data->write_abort_count = 0; - if ((value = getenv("TEST_IO_WRITE_ABORT")) != NULL) - data->write_abort_count = strtoul(value, NULL, 0); - - *channel = io; - return 0; - -cleanup: - ext2fs_free_mem(&io); - ext2fs_free_mem(&data); - return retval; -} - -static errcode_t test_close(io_channel channel) -{ - struct test_private_data *data; - errcode_t retval = 0; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - data = (struct test_private_data *) channel->private_data; - EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); - - if (--channel->refcount > 0) - return 0; - - if (data->real) - retval = io_channel_close(data->real); - - if (data->outfile && data->outfile != stderr) - fclose(data->outfile); - - ext2fs_free_mem(&channel->private_data); - ext2fs_free_mem(&channel->name); - ext2fs_free_mem(&channel); - return retval; -} - -static errcode_t test_set_blksize(io_channel channel, int blksize) -{ - struct test_private_data *data; - errcode_t retval = 0; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - data = (struct test_private_data *) channel->private_data; - EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); - - if (data->real) - retval = io_channel_set_blksize(data->real, blksize); - if (data->set_blksize) - data->set_blksize(blksize, retval); - if (data->flags & TEST_FLAG_SET_BLKSIZE) - fprintf(data->outfile, - "Test_io: set_blksize(%d) returned %s\n", - blksize, retval ? error_message(retval) : "OK"); - channel->block_size = blksize; - return retval; -} - - -static errcode_t test_read_blk(io_channel channel, unsigned long block, - int count, void *buf) -{ - struct test_private_data *data; - errcode_t retval = 0; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - data = (struct test_private_data *) channel->private_data; - EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); - - if (data->real) - retval = io_channel_read_blk(data->real, block, count, buf); - if (data->read_blk) - data->read_blk(block, count, retval); - if (data->flags & TEST_FLAG_READ) - fprintf(data->outfile, - "Test_io: read_blk(%lu, %d) returned %s\n", - block, count, retval ? error_message(retval) : "OK"); - if (data->block && data->block == block) { - if (data->flags & TEST_FLAG_DUMP) - test_dump_block(channel, data, block, buf); - if (--data->read_abort_count == 0) - test_abort(channel, block); - } - return retval; -} - -static errcode_t test_write_blk(io_channel channel, unsigned long block, - int count, const void *buf) -{ - struct test_private_data *data; - errcode_t retval = 0; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - data = (struct test_private_data *) channel->private_data; - EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); - - if (data->real) - retval = io_channel_write_blk(data->real, block, count, buf); - if (data->write_blk) - data->write_blk(block, count, retval); - if (data->flags & TEST_FLAG_WRITE) - fprintf(data->outfile, - "Test_io: write_blk(%lu, %d) returned %s\n", - block, count, retval ? error_message(retval) : "OK"); - if (data->block && data->block == block) { - if (data->flags & TEST_FLAG_DUMP) - test_dump_block(channel, data, block, buf); - if (--data->write_abort_count == 0) - test_abort(channel, block); - } - return retval; -} - -static errcode_t test_write_byte(io_channel channel, unsigned long offset, - int count, const void *buf) -{ - struct test_private_data *data; - errcode_t retval = 0; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - data = (struct test_private_data *) channel->private_data; - EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); - - if (data->real && data->real->manager->write_byte) - retval = io_channel_write_byte(data->real, offset, count, buf); - if (data->write_byte) - data->write_byte(offset, count, retval); - if (data->flags & TEST_FLAG_WRITE) - fprintf(data->outfile, - "Test_io: write_byte(%lu, %d) returned %s\n", - offset, count, retval ? error_message(retval) : "OK"); - return retval; -} - -/* - * Flush data buffers to disk. - */ -static errcode_t test_flush(io_channel channel) -{ - struct test_private_data *data; - errcode_t retval = 0; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - data = (struct test_private_data *) channel->private_data; - EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); - - if (data->real) - retval = io_channel_flush(data->real); - - if (data->flags & TEST_FLAG_FLUSH) - fprintf(data->outfile, "Test_io: flush() returned %s\n", - retval ? error_message(retval) : "OK"); - - return retval; -} - -static errcode_t test_set_option(io_channel channel, const char *option, - const char *arg) -{ - struct test_private_data *data; - errcode_t retval = 0; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - data = (struct test_private_data *) channel->private_data; - EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_TEST_IO_CHANNEL); - - - if (data->flags & TEST_FLAG_SET_OPTION) - fprintf(data->outfile, "Test_io: set_option(%s, %s) ", - option, arg); - if (data->real && data->real->manager->set_option) { - retval = (data->real->manager->set_option)(data->real, - option, arg); - if (data->flags & TEST_FLAG_SET_OPTION) - fprintf(data->outfile, "returned %s\n", - retval ? error_message(retval) : "OK"); - } else { - if (data->flags & TEST_FLAG_SET_OPTION) - fprintf(data->outfile, "not implemented\n"); - } - return retval; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * unix_io.c --- This is the Unix (well, really POSIX) implementation - * of the I/O manager. - * - * Implements a one-block write-through cache. - * - * Includes support for Windows NT support under Cygwin. - * - * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - * 2002 by Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif -#if HAVE_ERRNO_H -#include -#endif -#include -#include -#ifdef __linux__ -#include -#endif -#if HAVE_SYS_STAT_H -#include -#endif -#if HAVE_SYS_TYPES_H -#include -#endif -#include - -#include "ext2_fs.h" -#include "ext2fs.h" - -/* - * For checking structure magic numbers... - */ - -#define EXT2_CHECK_MAGIC(struct, code) \ - if ((struct)->magic != (code)) return (code) - -struct unix_cache { - char *buf; - unsigned long block; - int access_time; - unsigned dirty:1; - unsigned in_use:1; -}; - -#define CACHE_SIZE 8 -#define WRITE_DIRECT_SIZE 4 /* Must be smaller than CACHE_SIZE */ -#define READ_DIRECT_SIZE 4 /* Should be smaller than CACHE_SIZE */ - -struct unix_private_data { - int magic; - int dev; - int flags; - int access_time; - ext2_loff_t offset; - struct unix_cache cache[CACHE_SIZE]; -}; - -static errcode_t unix_open(const char *name, int flags, io_channel *channel); -static errcode_t unix_close(io_channel channel); -static errcode_t unix_set_blksize(io_channel channel, int blksize); -static errcode_t unix_read_blk(io_channel channel, unsigned long block, - int count, void *data); -static errcode_t unix_write_blk(io_channel channel, unsigned long block, - int count, const void *data); -static errcode_t unix_flush(io_channel channel); -static errcode_t unix_write_byte(io_channel channel, unsigned long offset, - int size, const void *data); -static errcode_t unix_set_option(io_channel channel, const char *option, - const char *arg); - -static void reuse_cache(io_channel channel, struct unix_private_data *data, - struct unix_cache *cache, unsigned long block); - -/* __FreeBSD_kernel__ is defined by GNU/kFreeBSD - the FreeBSD kernel - * does not know buffered block devices - everything is raw. */ -#if defined(__CYGWIN__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) -#define NEED_BOUNCE_BUFFER -#else -#undef NEED_BOUNCE_BUFFER -#endif - -static struct struct_io_manager struct_unix_manager = { - EXT2_ET_MAGIC_IO_MANAGER, - "Unix I/O Manager", - unix_open, - unix_close, - unix_set_blksize, - unix_read_blk, - unix_write_blk, - unix_flush, -#ifdef NEED_BOUNCE_BUFFER - 0, -#else - unix_write_byte, -#endif - unix_set_option -}; - -io_manager unix_io_manager = &struct_unix_manager; - -/* - * Here are the raw I/O functions - */ -#ifndef NEED_BOUNCE_BUFFER -static errcode_t raw_read_blk(io_channel channel, - struct unix_private_data *data, - unsigned long block, - int count, void *buf) -{ - errcode_t retval; - ssize_t size; - ext2_loff_t location; - int actual = 0; - - size = (count < 0) ? -count : count * channel->block_size; - location = ((ext2_loff_t) block * channel->block_size) + data->offset; - if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) { - retval = errno ? errno : EXT2_ET_LLSEEK_FAILED; - goto error_out; - } - actual = read(data->dev, buf, size); - if (actual != size) { - if (actual < 0) - actual = 0; - retval = EXT2_ET_SHORT_READ; - goto error_out; - } - return 0; - -error_out: - memset((char *) buf+actual, 0, size-actual); - if (channel->read_error) - retval = (channel->read_error)(channel, block, count, buf, - size, actual, retval); - return retval; -} -#else /* NEED_BOUNCE_BUFFER */ -/* - * Windows and FreeBSD block devices only allow sector alignment IO in offset and size - */ -static errcode_t raw_read_blk(io_channel channel, - struct unix_private_data *data, - unsigned long block, - int count, void *buf) -{ - errcode_t retval; - size_t size, alignsize, fragment; - ext2_loff_t location; - int total = 0, actual; -#define BLOCKALIGN 512 - char sector[BLOCKALIGN]; - - size = (count < 0) ? -count : count * channel->block_size; - location = ((ext2_loff_t) block * channel->block_size) + data->offset; -#ifdef DEBUG - printf("count=%d, size=%d, block=%d, blk_size=%d, location=%lx\n", - count, size, block, channel->block_size, location); -#endif - if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) { - retval = errno ? errno : EXT2_ET_LLSEEK_FAILED; - goto error_out; - } - fragment = size % BLOCKALIGN; - alignsize = size - fragment; - if (alignsize) { - actual = read(data->dev, buf, alignsize); - if (actual != alignsize) - goto short_read; - } - if (fragment) { - actual = read(data->dev, sector, BLOCKALIGN); - if (actual != BLOCKALIGN) - goto short_read; - memcpy(buf+alignsize, sector, fragment); - } - return 0; - -short_read: - if (actual>0) - total += actual; - retval = EXT2_ET_SHORT_READ; - -error_out: - memset((char *) buf+total, 0, size-actual); - if (channel->read_error) - retval = (channel->read_error)(channel, block, count, buf, - size, actual, retval); - return retval; -} -#endif - -static errcode_t raw_write_blk(io_channel channel, - struct unix_private_data *data, - unsigned long block, - int count, const void *buf) -{ - ssize_t size; - ext2_loff_t location; - int actual = 0; - errcode_t retval; - - if (count == 1) - size = channel->block_size; - else { - if (count < 0) - size = -count; - else - size = count * channel->block_size; - } - - location = ((ext2_loff_t) block * channel->block_size) + data->offset; - if (ext2fs_llseek(data->dev, location, SEEK_SET) != location) { - retval = errno ? errno : EXT2_ET_LLSEEK_FAILED; - goto error_out; - } - - actual = write(data->dev, buf, size); - if (actual != size) { - retval = EXT2_ET_SHORT_WRITE; - goto error_out; - } - return 0; - -error_out: - if (channel->write_error) - retval = (channel->write_error)(channel, block, count, buf, - size, actual, retval); - return retval; -} - - -/* - * Here we implement the cache functions - */ - -/* Allocate the cache buffers */ -static errcode_t alloc_cache(io_channel channel, - struct unix_private_data *data) -{ - errcode_t retval; - struct unix_cache *cache; - int i; - - data->access_time = 0; - for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { - cache->block = 0; - cache->access_time = 0; - cache->dirty = 0; - cache->in_use = 0; - if ((retval = ext2fs_get_mem(channel->block_size, - &cache->buf))) - return retval; - } - return 0; -} - -/* Free the cache buffers */ -static void free_cache(struct unix_private_data *data) -{ - struct unix_cache *cache; - int i; - - data->access_time = 0; - for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { - cache->block = 0; - cache->access_time = 0; - cache->dirty = 0; - cache->in_use = 0; - ext2fs_free_mem(&cache->buf); - cache->buf = 0; - } -} - -#ifndef NO_IO_CACHE -/* - * Try to find a block in the cache. If the block is not found, and - * eldest is a non-zero pointer, then fill in eldest with the cache - * entry to that should be reused. - */ -static struct unix_cache *find_cached_block(struct unix_private_data *data, - unsigned long block, - struct unix_cache **eldest) -{ - struct unix_cache *cache, *unused_cache, *oldest_cache; - int i; - - unused_cache = oldest_cache = 0; - for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { - if (!cache->in_use) { - if (!unused_cache) - unused_cache = cache; - continue; - } - if (cache->block == block) { - cache->access_time = ++data->access_time; - return cache; - } - if (!oldest_cache || - (cache->access_time < oldest_cache->access_time)) - oldest_cache = cache; - } - if (eldest) - *eldest = (unused_cache) ? unused_cache : oldest_cache; - return 0; -} - -/* - * Reuse a particular cache entry for another block. - */ -static void reuse_cache(io_channel channel, struct unix_private_data *data, - struct unix_cache *cache, unsigned long block) -{ - if (cache->dirty && cache->in_use) - raw_write_blk(channel, data, cache->block, 1, cache->buf); - - cache->in_use = 1; - cache->dirty = 0; - cache->block = block; - cache->access_time = ++data->access_time; -} - -/* - * Flush all of the blocks in the cache - */ -static errcode_t flush_cached_blocks(io_channel channel, - struct unix_private_data *data, - int invalidate) - -{ - struct unix_cache *cache; - errcode_t retval, retval2; - int i; - - retval2 = 0; - for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { - if (!cache->in_use) - continue; - - if (invalidate) - cache->in_use = 0; - - if (!cache->dirty) - continue; - - retval = raw_write_blk(channel, data, - cache->block, 1, cache->buf); - if (retval) - retval2 = retval; - else - cache->dirty = 0; - } - return retval2; -} -#endif /* NO_IO_CACHE */ - -static errcode_t unix_open(const char *name, int flags, io_channel *channel) -{ - io_channel io = NULL; - struct unix_private_data *data = NULL; - errcode_t retval; - int open_flags; - struct stat st; -#ifdef __linux__ - struct utsname ut; -#endif - - if (name == 0) - return EXT2_ET_BAD_DEVICE_NAME; - retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io); - if (retval) - return retval; - memset(io, 0, sizeof(struct struct_io_channel)); - io->magic = EXT2_ET_MAGIC_IO_CHANNEL; - retval = ext2fs_get_mem(sizeof(struct unix_private_data), &data); - if (retval) - goto cleanup; - - io->manager = unix_io_manager; - retval = ext2fs_get_mem(strlen(name)+1, &io->name); - if (retval) - goto cleanup; - - strcpy(io->name, name); - io->private_data = data; - io->block_size = 1024; - io->read_error = 0; - io->write_error = 0; - io->refcount = 1; - - memset(data, 0, sizeof(struct unix_private_data)); - data->magic = EXT2_ET_MAGIC_UNIX_IO_CHANNEL; - - if ((retval = alloc_cache(io, data))) - goto cleanup; - - open_flags = (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY; -#ifdef CONFIG_LFS - data->dev = open64(io->name, open_flags); -#else - data->dev = open(io->name, open_flags); -#endif - if (data->dev < 0) { - retval = errno; - goto cleanup; - } - -#ifdef __linux__ -#undef RLIM_INFINITY -#if (defined(__alpha__) || ((defined(__sparc__) || defined(__mips__)) && (SIZEOF_LONG == 4))) -#define RLIM_INFINITY ((unsigned long)(~0UL>>1)) -#else -#define RLIM_INFINITY (~0UL) -#endif - /* - * Work around a bug in 2.4.10-2.4.18 kernels where writes to - * block devices are wrongly getting hit by the filesize - * limit. This workaround isn't perfect, since it won't work - * if glibc wasn't built against 2.2 header files. (Sigh.) - * - */ - if ((flags & IO_FLAG_RW) && - (uname(&ut) == 0) && - ((ut.release[0] == '2') && (ut.release[1] == '.') && - (ut.release[2] == '4') && (ut.release[3] == '.') && - (ut.release[4] == '1') && (ut.release[5] >= '0') && - (ut.release[5] < '8')) && - (fstat(data->dev, &st) == 0) && - (S_ISBLK(st.st_mode))) { - struct rlimit rlim; - - rlim.rlim_cur = rlim.rlim_max = (unsigned long) RLIM_INFINITY; - setrlimit(RLIMIT_FSIZE, &rlim); - getrlimit(RLIMIT_FSIZE, &rlim); - if (((unsigned long) rlim.rlim_cur) < - ((unsigned long) rlim.rlim_max)) { - rlim.rlim_cur = rlim.rlim_max; - setrlimit(RLIMIT_FSIZE, &rlim); - } - } -#endif - *channel = io; - return 0; - -cleanup: - if (data) { - free_cache(data); - ext2fs_free_mem(&data); - } - ext2fs_free_mem(&io); - return retval; -} - -static errcode_t unix_close(io_channel channel) -{ - struct unix_private_data *data; - errcode_t retval = 0; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - data = (struct unix_private_data *) channel->private_data; - EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); - - if (--channel->refcount > 0) - return 0; - -#ifndef NO_IO_CACHE - retval = flush_cached_blocks(channel, data, 0); -#endif - - if (close(data->dev) < 0) - retval = errno; - free_cache(data); - - ext2fs_free_mem(&channel->private_data); - ext2fs_free_mem(&channel->name); - ext2fs_free_mem(&channel); - return retval; -} - -static errcode_t unix_set_blksize(io_channel channel, int blksize) -{ - struct unix_private_data *data; - errcode_t retval; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - data = (struct unix_private_data *) channel->private_data; - EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); - - if (channel->block_size != blksize) { -#ifndef NO_IO_CACHE - if ((retval = flush_cached_blocks(channel, data, 0))) - return retval; -#endif - - channel->block_size = blksize; - free_cache(data); - if ((retval = alloc_cache(channel, data))) - return retval; - } - return 0; -} - - -static errcode_t unix_read_blk(io_channel channel, unsigned long block, - int count, void *buf) -{ - struct unix_private_data *data; - struct unix_cache *cache, *reuse[READ_DIRECT_SIZE]; - errcode_t retval; - char *cp; - int i, j; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - data = (struct unix_private_data *) channel->private_data; - EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); - -#ifdef NO_IO_CACHE - return raw_read_blk(channel, data, block, count, buf); -#else - /* - * If we're doing an odd-sized read or a very large read, - * flush out the cache and then do a direct read. - */ - if (count < 0 || count > WRITE_DIRECT_SIZE) { - if ((retval = flush_cached_blocks(channel, data, 0))) - return retval; - return raw_read_blk(channel, data, block, count, buf); - } - - cp = buf; - while (count > 0) { - /* If it's in the cache, use it! */ - if ((cache = find_cached_block(data, block, &reuse[0]))) { -#ifdef DEBUG - printf("Using cached block %lu\n", block); -#endif - memcpy(cp, cache->buf, channel->block_size); - count--; - block++; - cp += channel->block_size; - continue; - } - /* - * Find the number of uncached blocks so we can do a - * single read request - */ - for (i=1; i < count; i++) - if (find_cached_block(data, block+i, &reuse[i])) - break; -#ifdef DEBUG - printf("Reading %d blocks starting at %lu\n", i, block); -#endif - if ((retval = raw_read_blk(channel, data, block, i, cp))) - return retval; - - /* Save the results in the cache */ - for (j=0; j < i; j++) { - count--; - cache = reuse[j]; - reuse_cache(channel, data, cache, block++); - memcpy(cache->buf, cp, channel->block_size); - cp += channel->block_size; - } - } - return 0; -#endif /* NO_IO_CACHE */ -} - -static errcode_t unix_write_blk(io_channel channel, unsigned long block, - int count, const void *buf) -{ - struct unix_private_data *data; - struct unix_cache *cache, *reuse; - errcode_t retval = 0; - const char *cp; - int writethrough; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - data = (struct unix_private_data *) channel->private_data; - EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); - -#ifdef NO_IO_CACHE - return raw_write_blk(channel, data, block, count, buf); -#else - /* - * If we're doing an odd-sized write or a very large write, - * flush out the cache completely and then do a direct write. - */ - if (count < 0 || count > WRITE_DIRECT_SIZE) { - if ((retval = flush_cached_blocks(channel, data, 1))) - return retval; - return raw_write_blk(channel, data, block, count, buf); - } - - /* - * For a moderate-sized multi-block write, first force a write - * if we're in write-through cache mode, and then fill the - * cache with the blocks. - */ - writethrough = channel->flags & CHANNEL_FLAGS_WRITETHROUGH; - if (writethrough) - retval = raw_write_blk(channel, data, block, count, buf); - - cp = buf; - while (count > 0) { - cache = find_cached_block(data, block, &reuse); - if (!cache) { - cache = reuse; - reuse_cache(channel, data, cache, block); - } - memcpy(cache->buf, cp, channel->block_size); - cache->dirty = !writethrough; - count--; - block++; - cp += channel->block_size; - } - return retval; -#endif /* NO_IO_CACHE */ -} - -static errcode_t unix_write_byte(io_channel channel, unsigned long offset, - int size, const void *buf) -{ - struct unix_private_data *data; - errcode_t retval = 0; - ssize_t actual; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - data = (struct unix_private_data *) channel->private_data; - EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); - -#ifndef NO_IO_CACHE - /* - * Flush out the cache completely - */ - if ((retval = flush_cached_blocks(channel, data, 1))) - return retval; -#endif - - if (lseek(data->dev, offset + data->offset, SEEK_SET) < 0) - return errno; - - actual = write(data->dev, buf, size); - if (actual != size) - return EXT2_ET_SHORT_WRITE; - - return 0; -} - -/* - * Flush data buffers to disk. - */ -static errcode_t unix_flush(io_channel channel) -{ - struct unix_private_data *data; - errcode_t retval = 0; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - data = (struct unix_private_data *) channel->private_data; - EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); - -#ifndef NO_IO_CACHE - retval = flush_cached_blocks(channel, data, 0); -#endif - fsync(data->dev); - return retval; -} - -static errcode_t unix_set_option(io_channel channel, const char *option, - const char *arg) -{ - struct unix_private_data *data; - unsigned long tmp; - char *end; - - EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); - data = (struct unix_private_data *) channel->private_data; - EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); - - if (!strcmp(option, "offset")) { - if (!arg) - return EXT2_ET_INVALID_ARGUMENT; - - tmp = strtoul(arg, &end, 0); - if (*end) - return EXT2_ET_INVALID_ARGUMENT; - data->offset = tmp; - return 0; - } - return EXT2_ET_INVALID_ARGUMENT; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * unlink.c --- delete links in a ext2fs directory - * - * Copyright (C) 1993, 1994, 1997 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include -#include -#if HAVE_UNISTD_H -#include -#endif - -#include "ext2_fs.h" -#include "ext2fs.h" - -struct link_struct { - const char *name; - int namelen; - ext2_ino_t inode; - int flags; - struct ext2_dir_entry *prev; - int done; -}; - -#ifdef __TURBOC__ -# pragma argsused -#endif -static int unlink_proc(struct ext2_dir_entry *dirent, - int offset EXT2FS_ATTR((unused)), - int blocksize EXT2FS_ATTR((unused)), - char *buf EXT2FS_ATTR((unused)), - void *priv_data) -{ - struct link_struct *ls = (struct link_struct *) priv_data; - struct ext2_dir_entry *prev; - - prev = ls->prev; - ls->prev = dirent; - - if (ls->name) { - if ((dirent->name_len & 0xFF) != ls->namelen) - return 0; - if (strncmp(ls->name, dirent->name, dirent->name_len & 0xFF)) - return 0; - } - if (ls->inode) { - if (dirent->inode != ls->inode) - return 0; - } else { - if (!dirent->inode) - return 0; - } - - if (prev) - prev->rec_len += dirent->rec_len; - else - dirent->inode = 0; - ls->done++; - return DIRENT_ABORT|DIRENT_CHANGED; -} - -#ifdef __TURBOC__ - #pragma argsused -#endif -errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir, - const char *name, ext2_ino_t ino, - int flags EXT2FS_ATTR((unused))) -{ - errcode_t retval; - struct link_struct ls; - - EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); - - if (!name && !ino) - return EXT2_ET_INVALID_ARGUMENT; - - if (!(fs->flags & EXT2_FLAG_RW)) - return EXT2_ET_RO_FILSYS; - - ls.name = name; - ls.namelen = name ? strlen(name) : 0; - ls.inode = ino; - ls.flags = 0; - ls.done = 0; - ls.prev = 0; - - retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY, - 0, unlink_proc, &ls); - if (retval) - return retval; - - return (ls.done) ? 0 : EXT2_ET_DIR_NO_SPACE; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * valid_blk.c --- does the inode have valid blocks? - * - * Copyright 1997 by Theodore Ts'o - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - * - */ - -#include -#if HAVE_UNISTD_H -#include -#endif -#include -#include - -#include "ext2_fs.h" -#include "ext2fs.h" - -/* - * This function returns 1 if the inode's block entries actually - * contain block entries. - */ -int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode) -{ - /* - * Only directories, regular files, and some symbolic links - * have valid block entries. - */ - if (!LINUX_S_ISDIR(inode->i_mode) && !LINUX_S_ISREG(inode->i_mode) && - !LINUX_S_ISLNK(inode->i_mode)) - return 0; - - /* - * If the symbolic link is a "fast symlink", then the symlink - * target is stored in the block entries. - */ - if (LINUX_S_ISLNK (inode->i_mode)) { - if (inode->i_file_acl == 0) { - /* With no EA block, we can rely on i_blocks */ - if (inode->i_blocks == 0) - return 0; - } else { - /* With an EA block, life gets more tricky */ - if (inode->i_size >= EXT2_N_BLOCKS*4) - return 1; /* definitely using i_block[] */ - if (inode->i_size > 4 && inode->i_block[1] == 0) - return 1; /* definitely using i_block[] */ - return 0; /* Probably a fast symlink */ - } - } - return 1; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * version.c --- Return the version of the ext2 library - * - * Copyright (C) 1997 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#if HAVE_UNISTD_H -#include -#endif -#include -#include -#include - -#include "ext2_fs.h" -#include "ext2fs.h" - -static const char *lib_version = E2FSPROGS_VERSION; -static const char *lib_date = E2FSPROGS_DATE; - -int ext2fs_parse_version_string(const char *ver_string) -{ - const char *cp; - int version = 0; - - for (cp = ver_string; *cp; cp++) { - if (*cp == '.') - continue; - if (!isdigit(*cp)) - break; - version = (version * 10) + (*cp - '0'); - } - return version; -} - - -int ext2fs_get_library_version(const char **ver_string, - const char **date_string) -{ - if (ver_string) - *ver_string = lib_version; - if (date_string) - *date_string = lib_date; - - return ext2fs_parse_version_string(lib_version); -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * write_bb_file.c --- write a list of bad blocks to a FILE * - * - * Copyright (C) 1994, 1995 Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -#include - -#include "ext2_fs.h" -#include "ext2fs.h" - -errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list, - unsigned int flags EXT2FS_ATTR((unused)), - FILE *f) -{ - badblocks_iterate bb_iter; - blk_t blk; - errcode_t retval; - - retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter); - if (retval) - return retval; - - while (ext2fs_badblocks_list_iterate(bb_iter, &blk)) { - fprintf(f, "%d\n", blk); - } - ext2fs_badblocks_list_iterate_end(bb_iter); - return 0; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * pfsck --- A generic, parallelizing front-end for the fsck program. - * It will automatically try to run fsck programs in parallel if the - * devices are on separate spindles. It is based on the same ideas as - * the generic front end for fsck by David Engel and Fred van Kempen, - * but it has been completely rewritten from scratch to support - * parallel execution. - * - * Written by Theodore Ts'o, - * - * Miquel van Smoorenburg (miquels@drinkel.ow.org) 20-Oct-1994: - * o Changed -t fstype to behave like with mount when -A (all file - * systems) or -M (like mount) is specified. - * o fsck looks if it can find the fsck.type program to decide - * if it should ignore the fs type. This way more fsck programs - * can be added without changing this front-end. - * o -R flag skip root file system. - * - * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - * 2001, 2002, 2003, 2004, 2005 by Theodore Ts'o. - * - * Licensed under GPLv2, see file LICENSE in this source tree. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "fsck.h" -#include "blkid/blkid.h" - -#include "e2fsbb.h" - -#include "libbb.h" - -#ifndef _PATH_MNTTAB -#define _PATH_MNTTAB "/etc/fstab" -#endif - -/* - * fsck.h - */ - -#ifndef DEFAULT_FSTYPE -#define DEFAULT_FSTYPE "ext2" -#endif - -#define MAX_DEVICES 32 -#define MAX_ARGS 32 - -/* - * Internal structure for mount tabel entries. - */ - -struct fs_info { - char *device; - char *mountpt; - char *type; - char *opts; - int freq; - int passno; - int flags; - struct fs_info *next; -}; - -#define FLAG_DONE 1 -#define FLAG_PROGRESS 2 - -/* - * Structure to allow exit codes to be stored - */ -struct fsck_instance { - int pid; - int flags; - int exit_status; - time_t start_time; - char * prog; - char * type; - char * device; - char * base_device; - struct fsck_instance *next; -}; - -/* - * base_device.c - * - * Return the "base device" given a particular device; this is used to - * assure that we only fsck one partition on a particular drive at any - * one time. Otherwise, the disk heads will be seeking all over the - * place. If the base device cannot be determined, return NULL. - * - * The base_device() function returns an allocated string which must - * be freed. - * - */ - - -#ifdef CONFIG_FEATURE_DEVFS -/* - * Required for the uber-silly devfs /dev/ide/host1/bus2/target3/lun3 - * pathames. - */ -static const char *const devfs_hier[] = { - "host", "bus", "target", "lun", 0 -}; -#endif - -static char *base_device(const char *device) -{ - char *str, *cp; -#ifdef CONFIG_FEATURE_DEVFS - const char *const *hier; - const char *disk; - int len; -#endif - - cp = str = xstrdup(device); - - /* Skip over /dev/; if it's not present, give up. */ - if (strncmp(cp, "/dev/", 5) != 0) - goto errout; - cp += 5; - - /* - * For md devices, we treat them all as if they were all - * on one disk, since we don't know how to parallelize them. - */ - if (cp[0] == 'm' && cp[1] == 'd') { - *(cp+2) = 0; - return str; - } - - /* Handle DAC 960 devices */ - if (strncmp(cp, "rd/", 3) == 0) { - cp += 3; - if (cp[0] != 'c' || cp[2] != 'd' || - !isdigit(cp[1]) || !isdigit(cp[3])) - goto errout; - *(cp+4) = 0; - return str; - } - - /* Now let's handle /dev/hd* and /dev/sd* devices.... */ - if ((cp[0] == 'h' || cp[0] == 's') && (cp[1] == 'd')) { - cp += 2; - /* If there's a single number after /dev/hd, skip it */ - if (isdigit(*cp)) - cp++; - /* What follows must be an alpha char, or give up */ - if (!isalpha(*cp)) - goto errout; - *(cp + 1) = 0; - return str; - } - -#ifdef CONFIG_FEATURE_DEVFS - /* Now let's handle devfs (ugh) names */ - len = 0; - if (strncmp(cp, "ide/", 4) == 0) - len = 4; - if (strncmp(cp, "scsi/", 5) == 0) - len = 5; - if (len) { - cp += len; - /* - * Now we proceed down the expected devfs hierarchy. - * i.e., .../host1/bus2/target3/lun4/... - * If we don't find the expected token, followed by - * some number of digits at each level, abort. - */ - for (hier = devfs_hier; *hier; hier++) { - len = strlen(*hier); - if (strncmp(cp, *hier, len) != 0) - goto errout; - cp += len; - while (*cp != '/' && *cp != 0) { - if (!isdigit(*cp)) - goto errout; - cp++; - } - cp++; - } - *(cp - 1) = 0; - return str; - } - - /* Now handle devfs /dev/disc or /dev/disk names */ - disk = 0; - if (strncmp(cp, "discs/", 6) == 0) - disk = "disc"; - else if (strncmp(cp, "disks/", 6) == 0) - disk = "disk"; - if (disk) { - cp += 6; - if (strncmp(cp, disk, 4) != 0) - goto errout; - cp += 4; - while (*cp != '/' && *cp != 0) { - if (!isdigit(*cp)) - goto errout; - cp++; - } - *cp = 0; - return str; - } -#endif - -errout: - free(str); - return NULL; -} - - -static const char *const ignored_types[] = { - "ignore", - "iso9660", - "nfs", - "proc", - "sw", - "swap", - "tmpfs", - "devpts", - NULL -}; - -static const char *const really_wanted[] = { - "minix", - "ext2", - "ext3", - "jfs", - "reiserfs", - "xiafs", - "xfs", - NULL -}; - -#define BASE_MD "/dev/md" - -/* - * Global variables for options - */ -static char *devices[MAX_DEVICES]; -static char *args[MAX_ARGS]; -static int num_devices, num_args; - -static int verbose; -static int doall; -static int noexecute; -static int serialize; -static int skip_root; -static int like_mount; -static int notitle; -static int parallel_root; -static int progress; -static int progress_fd; -static int force_all_parallel; -static int num_running; -static int max_running; -static volatile int cancel_requested; -static int kill_sent; -static char *fstype; -static struct fs_info *filesys_info, *filesys_last; -static struct fsck_instance *instance_list; -static char *fsck_path; -static blkid_cache cache; - -static char *string_copy(const char *s) -{ - char *ret; - - if (!s) - return 0; - ret = xstrdup(s); - return ret; -} - -static int string_to_int(const char *s) -{ - long l; - char *p; - - l = strtol(s, &p, 0); - if (*p || l == LONG_MIN || l == LONG_MAX || l < 0 || l > INT_MAX) - return -1; - else - return (int) l; -} - -static char *skip_over_blank(char *cp) -{ - while (*cp && isspace(*cp)) - cp++; - return cp; -} - -static char *skip_over_word(char *cp) -{ - while (*cp && !isspace(*cp)) - cp++; - return cp; -} - -static void strip_line(char *line) -{ - char *p; - - while (*line) { - p = line + strlen(line) - 1; - if ((*p == '\n') || (*p == '\r')) - *p = 0; - else - break; - } -} - -static char *parse_word(char **buf) -{ - char *word, *next; - - word = *buf; - if (*word == 0) - return 0; - - word = skip_over_blank(word); - next = skip_over_word(word); - if (*next) - *next++ = 0; - *buf = next; - return word; -} - -static void parse_escape(char *word) -{ - char *q, c; - const char *p; - - if (!word) - return; - - strcpy_and_process_escape_sequences(word, word); -} - -static void free_instance(struct fsck_instance *i) -{ - free(i->prog); - free(i->device); - free(i->base_device); - free(i); -} - -static struct fs_info *create_fs_device(const char *device, const char *mntpnt, - const char *type, const char *opts, - int freq, int passno) -{ - struct fs_info *fs; - - fs = xmalloc(sizeof(struct fs_info)); - - fs->device = string_copy(device); - fs->mountpt = string_copy(mntpnt); - fs->type = string_copy(type); - fs->opts = string_copy(opts ? opts : ""); - fs->freq = freq; - fs->passno = passno; - fs->flags = 0; - fs->next = NULL; - - if (!filesys_info) - filesys_info = fs; - else - filesys_last->next = fs; - filesys_last = fs; - - return fs; -} - - - -static int parse_fstab_line(char *line, struct fs_info **ret_fs) -{ - char *dev, *device, *mntpnt, *type, *opts, *freq, *passno, *cp; - struct fs_info *fs; - - *ret_fs = 0; - strip_line(line); - if ((cp = strchr(line, '#'))) - *cp = 0; /* Ignore everything after the comment char */ - cp = line; - - device = parse_word(&cp); - mntpnt = parse_word(&cp); - type = parse_word(&cp); - opts = parse_word(&cp); - freq = parse_word(&cp); - passno = parse_word(&cp); - - if (!device) - return 0; /* Allow blank lines */ - - if (!mntpnt || !type) - return -1; - - parse_escape(device); - parse_escape(mntpnt); - parse_escape(type); - parse_escape(opts); - parse_escape(freq); - parse_escape(passno); - - dev = blkid_get_devname(cache, device, NULL); - if (dev) - device = dev; - - if (strchr(type, ',')) - type = 0; - - fs = create_fs_device(device, mntpnt, type ? type : "auto", opts, - freq ? atoi(freq) : -1, - passno ? atoi(passno) : -1); - free(dev); - - if (!fs) - return -1; - *ret_fs = fs; - return 0; -} - -static void interpret_type(struct fs_info *fs) -{ - char *t; - - if (strcmp(fs->type, "auto") != 0) - return; - t = blkid_get_tag_value(cache, "TYPE", fs->device); - if (t) { - free(fs->type); - fs->type = t; - } -} - -/* - * Load the filesystem database from /etc/fstab - */ -static void load_fs_info(const char *filename) -{ - FILE *f; - char buf[1024]; - int lineno = 0; - int old_fstab = 1; - struct fs_info *fs; - - if ((f = fopen_or_warn(filename, "r")) == NULL) { - return; - } - while (!feof(f)) { - lineno++; - if (!fgets(buf, sizeof(buf), f)) - break; - buf[sizeof(buf)-1] = 0; - if (parse_fstab_line(buf, &fs) < 0) { - bb_error_msg("WARNING: bad format " - "on line %d of %s\n", lineno, filename); - continue; - } - if (!fs) - continue; - if (fs->passno < 0) - fs->passno = 0; - else - old_fstab = 0; - } - - fclose(f); - - if (old_fstab) { - fputs("\007\007\007" - "WARNING: Your /etc/fstab does not contain the fsck passno\n" - " field. I will kludge around things for you, but you\n" - " should fix your /etc/fstab file as soon as you can.\n\n", stderr); - - for (fs = filesys_info; fs; fs = fs->next) { - fs->passno = 1; - } - } -} - -/* Lookup filesys in /etc/fstab and return the corresponding entry. */ -static struct fs_info *lookup(char *filesys) -{ - struct fs_info *fs; - - /* No filesys name given. */ - if (filesys == NULL) - return NULL; - - for (fs = filesys_info; fs; fs = fs->next) { - if (!strcmp(filesys, fs->device) || - (fs->mountpt && !strcmp(filesys, fs->mountpt))) - break; - } - - return fs; -} - -/* Find fsck program for a given fs type. */ -static char *find_fsck(char *type) -{ - char *s; - const char *tpl; - char *p = string_copy(fsck_path); - struct stat st; - - /* Are we looking for a program or just a type? */ - tpl = (strncmp(type, "fsck.", 5) ? "%s/fsck.%s" : "%s/%s"); - - for (s = strtok(p, ":"); s; s = strtok(NULL, ":")) { - s = xasprintf(tpl, s, type); - if (stat(s, &st) == 0) break; - free(s); - } - free(p); - return s; -} - -static int progress_active(void) -{ - struct fsck_instance *inst; - - for (inst = instance_list; inst; inst = inst->next) { - if (inst->flags & FLAG_DONE) - continue; - if (inst->flags & FLAG_PROGRESS) - return 1; - } - return 0; -} - -/* - * Execute a particular fsck program, and link it into the list of - * child processes we are waiting for. - */ -static int execute(const char *type, const char *device, const char *mntpt, - int interactive) -{ - char *s, *argv[80]; - char *prog; - int argc, i; - struct fsck_instance *inst, *p; - pid_t pid; - - inst = xzalloc(sizeof(struct fsck_instance)); - - prog = xasprintf("fsck.%s", type); - argv[0] = prog; - argc = 1; - - for (i=0; i flags |= FLAG_PROGRESS; - } - } - - argv[argc++] = string_copy(device); - argv[argc] = 0; - - s = find_fsck(prog); - if (s == NULL) { - bb_error_msg("%s: not found", prog); - return ENOENT; - } - - if (verbose || noexecute) { - printf("[%s (%d) -- %s] ", s, num_running, - mntpt ? mntpt : device); - for (i=0; i < argc; i++) - printf("%s ", argv[i]); - bb_putchar('\n'); - } - - /* Fork and execute the correct program. */ - if (noexecute) - pid = -1; - else if ((pid = fork()) < 0) { - perror("vfork"+1); - return errno; - } else if (pid == 0) { - if (!interactive) - close(0); - (void) execv(s, argv); - bb_simple_perror_msg_and_die(argv[0]); - } - - for (i = 1; i < argc; i++) - free(argv[i]); - - free(s); - inst->pid = pid; - inst->prog = prog; - inst->type = string_copy(type); - inst->device = string_copy(device); - inst->base_device = base_device(device); - inst->start_time = time(0); - inst->next = NULL; - - /* - * Find the end of the list, so we add the instance on at the end. - */ - for (p = instance_list; p && p->next; p = p->next); - - if (p) - p->next = inst; - else - instance_list = inst; - - return 0; -} - -/* - * Send a signal to all outstanding fsck child processes - */ -static int kill_all(int signum) -{ - struct fsck_instance *inst; - int n = 0; - - for (inst = instance_list; inst; inst = inst->next) { - if (inst->flags & FLAG_DONE) - continue; - kill(inst->pid, signum); - n++; - } - return n; -} - -/* - * Wait for one child process to exit; when it does, unlink it from - * the list of executing child processes, and return it. - */ -static struct fsck_instance *wait_one(int flags) -{ - int status; - int sig; - struct fsck_instance *inst, *inst2, *prev; - pid_t pid; - - if (!instance_list) - return NULL; - - if (noexecute) { - inst = instance_list; - prev = 0; -#ifdef RANDOM_DEBUG - while (inst->next && (random() & 1)) { - prev = inst; - inst = inst->next; - } -#endif - inst->exit_status = 0; - goto ret_inst; - } - - /* - * gcc -Wall fails saving throw against stupidity - * (inst and prev are thought to be uninitialized variables) - */ - inst = prev = NULL; - - do { - pid = waitpid(-1, &status, flags); - if (cancel_requested && !kill_sent) { - kill_all(SIGTERM); - kill_sent++; - } - if ((pid == 0) && (flags & WNOHANG)) - return NULL; - if (pid < 0) { - if ((errno == EINTR) || (errno == EAGAIN)) - continue; - if (errno == ECHILD) { - bb_error_msg("wait: no more child process?!?"); - return NULL; - } - perror("wait"); - continue; - } - for (prev = 0, inst = instance_list; - inst; - prev = inst, inst = inst->next) { - if (inst->pid == pid) - break; - } - } while (!inst); - - if (WIFEXITED(status)) - status = WEXITSTATUS(status); - else if (WIFSIGNALED(status)) { - sig = WTERMSIG(status); - if (sig == SIGINT) { - status = EXIT_UNCORRECTED; - } else { - printf("Warning... %s for device %s exited " - "with signal %d.\n", - inst->prog, inst->device, sig); - status = EXIT_ERROR; - } - } else { - printf("%s %s: status is %x, should never happen.\n", - inst->prog, inst->device, status); - status = EXIT_ERROR; - } - inst->exit_status = status; - if (progress && (inst->flags & FLAG_PROGRESS) && - !progress_active()) { - for (inst2 = instance_list; inst2; inst2 = inst2->next) { - if (inst2->flags & FLAG_DONE) - continue; - if (strcmp(inst2->type, "ext2") && - strcmp(inst2->type, "ext3")) - continue; - /* - * If we've just started the fsck, wait a tiny - * bit before sending the kill, to give it - * time to set up the signal handler - */ - if (inst2->start_time < time(0)+2) { - if (fork() == 0) { - sleep(1); - kill(inst2->pid, SIGUSR1); - exit(0); - } - } else - kill(inst2->pid, SIGUSR1); - inst2->flags |= FLAG_PROGRESS; - break; - } - } -ret_inst: - if (prev) - prev->next = inst->next; - else - instance_list = inst->next; - if (verbose > 1) - printf("Finished with %s (exit status %d)\n", - inst->device, inst->exit_status); - num_running--; - return inst; -} - -#define FLAG_WAIT_ALL 0 -#define FLAG_WAIT_ATLEAST_ONE 1 -/* - * Wait until all executing child processes have exited; return the - * logical OR of all of their exit code values. - */ -static int wait_many(int flags) -{ - struct fsck_instance *inst; - int global_status = 0; - int wait_flags = 0; - - while ((inst = wait_one(wait_flags))) { - global_status |= inst->exit_status; - free_instance(inst); -#ifdef RANDOM_DEBUG - if (noexecute && (flags & WNOHANG) && !(random() % 3)) - break; -#endif - if (flags & FLAG_WAIT_ATLEAST_ONE) - wait_flags = WNOHANG; - } - return global_status; -} - -/* - * Run the fsck program on a particular device - * - * If the type is specified using -t, and it isn't prefixed with "no" - * (as in "noext2") and only one filesystem type is specified, then - * use that type regardless of what is specified in /etc/fstab. - * - * If the type isn't specified by the user, then use either the type - * specified in /etc/fstab, or DEFAULT_FSTYPE. - */ -static void fsck_device(struct fs_info *fs, int interactive) -{ - const char *type; - int retval; - - interpret_type(fs); - - if (strcmp(fs->type, "auto") != 0) - type = fs->type; - else if (fstype && strncmp(fstype, "no", 2) && - strncmp(fstype, "opts=", 5) && strncmp(fstype, "loop", 4) && - !strchr(fstype, ',')) - type = fstype; - else - type = DEFAULT_FSTYPE; - - num_running++; - retval = execute(type, fs->device, fs->mountpt, interactive); - if (retval) { - bb_error_msg("error %d while executing fsck.%s for %s", - retval, type, fs->device); - num_running--; - } -} - - -/* - * Deal with the fsck -t argument. - */ -struct fs_type_compile { - char **list; - int *type; - int negate; -} fs_type_compiled; - -#define FS_TYPE_NORMAL 0 -#define FS_TYPE_OPT 1 -#define FS_TYPE_NEGOPT 2 - -static const char fs_type_syntax_error[] = -"Either all or none of the filesystem types passed to -t must be prefixed\n" - "with 'no' or '!'."; - -static void compile_fs_type(char *fs_type, struct fs_type_compile *cmp) -{ - char *cp, *list, *s; - int num = 2; - int negate, first_negate = 1; - - if (fs_type) { - for (cp=fs_type; *cp; cp++) { - if (*cp == ',') - num++; - } - } - - cmp->list = xzalloc(num * sizeof(char *)); - cmp->type = xzalloc(num * sizeof(int)); - cmp->negate = 0; - - if (!fs_type) - return; - - list = string_copy(fs_type); - num = 0; - s = strtok(list, ","); - while (s) { - negate = 0; - if (strncmp(s, "no", 2) == 0) { - s += 2; - negate = 1; - } else if (*s == '!') { - s++; - negate = 1; - } - if (strcmp(s, "loop") == 0) - /* loop is really short-hand for opts=loop */ - goto loop_special_case; - else if (strncmp(s, "opts=", 5) == 0) { - s += 5; - loop_special_case: - cmp->type[num] = negate ? FS_TYPE_NEGOPT : FS_TYPE_OPT; - } else { - if (first_negate) { - cmp->negate = negate; - first_negate = 0; - } - if ((negate && !cmp->negate) || - (!negate && cmp->negate)) { - bb_error_msg_and_die("%s", fs_type_syntax_error); - } - } - cmp->list[num++] = string_copy(s); - s = strtok(NULL, ","); - } - free(list); -} - -/* - * This function returns true if a particular option appears in a - * comma-delimited options list - */ -static int opt_in_list(char *opt, char *optlist) -{ - char *list, *s; - - if (!optlist) - return 0; - list = string_copy(optlist); - - s = strtok(list, ","); - while (s) { - if (strcmp(s, opt) == 0) { - free(list); - return 1; - } - s = strtok(NULL, ","); - } - free(list); - return 0; -} - -/* See if the filesystem matches the criteria given by the -t option */ -static int fs_match(struct fs_info *fs, struct fs_type_compile *cmp) -{ - int n, ret = 0, checked_type = 0; - char *cp; - - if (cmp->list == 0 || cmp->list[0] == 0) - return 1; - - for (n=0; (cp = cmp->list[n]); n++) { - switch (cmp->type[n]) { - case FS_TYPE_NORMAL: - checked_type++; - if (strcmp(cp, fs->type) == 0) { - ret = 1; - } - break; - case FS_TYPE_NEGOPT: - if (opt_in_list(cp, fs->opts)) - return 0; - break; - case FS_TYPE_OPT: - if (!opt_in_list(cp, fs->opts)) - return 0; - break; - } - } - if (checked_type == 0) - return 1; - return (cmp->negate ? !ret : ret); -} - -/* Check if we should ignore this filesystem. */ -static int ignore(struct fs_info *fs) -{ - int wanted; - char *s; - - /* - * If the pass number is 0, ignore it. - */ - if (fs->passno == 0) - return 1; - - interpret_type(fs); - - /* - * If a specific fstype is specified, and it doesn't match, - * ignore it. - */ - if (!fs_match(fs, &fs_type_compiled)) return 1; - - /* Are we ignoring this type? */ - if (index_in_str_array(ignored_types, fs->type) >= 0) - return 1; - - /* Do we really really want to check this fs? */ - wanted = index_in_str_array(really_wanted, fs->type) >= 0; - - /* See if the program is available. */ - s = find_fsck(fs->type); - if (s == NULL) { - if (wanted) - bb_error_msg("can't check %s: fsck.%s not found", - fs->device, fs->type); - return 1; - } - free(s); - - /* We can and want to check this file system type. */ - return 0; -} - -/* - * Returns TRUE if a partition on the same disk is already being - * checked. - */ -static int device_already_active(char *device) -{ - struct fsck_instance *inst; - char *base; - - if (force_all_parallel) - return 0; - -#ifdef BASE_MD - /* Don't check a soft raid disk with any other disk */ - if (instance_list && - (!strncmp(instance_list->device, BASE_MD, sizeof(BASE_MD)-1) || - !strncmp(device, BASE_MD, sizeof(BASE_MD)-1))) - return 1; -#endif - - base = base_device(device); - /* - * If we don't know the base device, assume that the device is - * already active if there are any fsck instances running. - */ - if (!base) - return (instance_list != 0); - for (inst = instance_list; inst; inst = inst->next) { - if (!inst->base_device || !strcmp(base, inst->base_device)) { - free(base); - return 1; - } - } - free(base); - return 0; -} - -/* Check all file systems, using the /etc/fstab table. */ -static int check_all(void) -{ - struct fs_info *fs = NULL; - int status = EXIT_OK; - int not_done_yet = 1; - int passno = 1; - int pass_done; - - if (verbose) - fputs("Checking all file systems.\n", stdout); - - /* - * Do an initial scan over the filesystem; mark filesystems - * which should be ignored as done, and resolve any "auto" - * filesystem types (done as a side-effect of calling ignore()). - */ - for (fs = filesys_info; fs; fs = fs->next) { - if (ignore(fs)) - fs->flags |= FLAG_DONE; - } - - /* - * Find and check the root filesystem. - */ - if (!parallel_root) { - for (fs = filesys_info; fs; fs = fs->next) { - if (LONE_CHAR(fs->mountpt, '/')) - break; - } - if (fs) { - if (!skip_root && !ignore(fs)) { - fsck_device(fs, 1); - status |= wait_many(FLAG_WAIT_ALL); - if (status > EXIT_NONDESTRUCT) - return status; - } - fs->flags |= FLAG_DONE; - } - } - /* - * This is for the bone-headed user who enters the root - * filesystem twice. Skip root will skep all root entries. - */ - if (skip_root) - for (fs = filesys_info; fs; fs = fs->next) - if (LONE_CHAR(fs->mountpt, '/')) - fs->flags |= FLAG_DONE; - - while (not_done_yet) { - not_done_yet = 0; - pass_done = 1; - - for (fs = filesys_info; fs; fs = fs->next) { - if (cancel_requested) - break; - if (fs->flags & FLAG_DONE) - continue; - /* - * If the filesystem's pass number is higher - * than the current pass number, then we don't - * do it yet. - */ - if (fs->passno > passno) { - not_done_yet++; - continue; - } - /* - * If a filesystem on a particular device has - * already been spawned, then we need to defer - * this to another pass. - */ - if (device_already_active(fs->device)) { - pass_done = 0; - continue; - } - /* - * Spawn off the fsck process - */ - fsck_device(fs, serialize); - fs->flags |= FLAG_DONE; - - /* - * Only do one filesystem at a time, or if we - * have a limit on the number of fsck's extant - * at one time, apply that limit. - */ - if (serialize || - (max_running && (num_running >= max_running))) { - pass_done = 0; - break; - } - } - if (cancel_requested) - break; - if (verbose > 1) - printf("--waiting-- (pass %d)\n", passno); - status |= wait_many(pass_done ? FLAG_WAIT_ALL : - FLAG_WAIT_ATLEAST_ONE); - if (pass_done) { - if (verbose > 1) - printf("----------------------------------\n"); - passno++; - } else - not_done_yet++; - } - if (cancel_requested && !kill_sent) { - kill_all(SIGTERM); - kill_sent++; - } - status |= wait_many(FLAG_WAIT_ATLEAST_ONE); - return status; -} - -static void signal_cancel(int sig FSCK_ATTR((unused))) -{ - cancel_requested++; -} - -static void PRS(int argc, char **argv) -{ - int i, j; - char *arg, *dev, *tmp = NULL; - char options[128]; - int opt = 0; - int opts_for_fsck = 0; - struct sigaction sa; - - /* - * Set up signal action - */ - memset(&sa, 0, sizeof(struct sigaction)); - sa.sa_handler = signal_cancel; - sigaction(SIGINT, &sa, 0); - sigaction(SIGTERM, &sa, 0); - - num_devices = 0; - num_args = 0; - instance_list = 0; - - for (i=1; i < argc; i++) { - arg = argv[i]; - if (!arg) - continue; - if ((arg[0] == '/' && !opts_for_fsck) || strchr(arg, '=')) { - if (num_devices >= MAX_DEVICES) { - bb_error_msg_and_die("too many devices"); - } - dev = blkid_get_devname(cache, arg, NULL); - if (!dev && strchr(arg, '=')) { - /* - * Check to see if we failed because - * /proc/partitions isn't found. - */ - if (access("/proc/partitions", R_OK) < 0) { - bb_perror_msg_and_die("can't open /proc/partitions " - "(is /proc mounted?)"); - } - /* - * Check to see if this is because - * we're not running as root - */ - if (geteuid()) - bb_error_msg_and_die( - "must be root to scan for matching filesystems: %s\n", arg); - else - bb_error_msg_and_die( - "can't find matching filesystem: %s", arg); - } - devices[num_devices++] = dev ? dev : string_copy(arg); - continue; - } - if (arg[0] != '-' || opts_for_fsck) { - if (num_args >= MAX_ARGS) { - bb_error_msg_and_die("too many arguments"); - } - args[num_args++] = string_copy(arg); - continue; - } - for (j=1; arg[j]; j++) { - if (opts_for_fsck) { - options[++opt] = arg[j]; - continue; - } - switch (arg[j]) { - case 'A': - doall++; - break; - case 'C': - progress++; - if (arg[j+1]) { - progress_fd = string_to_int(arg+j+1); - if (progress_fd < 0) - progress_fd = 0; - else - goto next_arg; - } else if ((i+1) < argc - && argv[i+1][0] != '-') { - progress_fd = string_to_int(argv[i]); - if (progress_fd < 0) - progress_fd = 0; - else { - goto next_arg; - } - } - break; - case 'V': - verbose++; - break; - case 'N': - noexecute++; - break; - case 'R': - skip_root++; - break; - case 'T': - notitle++; - break; - case 'M': - like_mount++; - break; - case 'P': - parallel_root++; - break; - case 's': - serialize++; - break; - case 't': - tmp = 0; - if (fstype) - bb_show_usage(); - if (arg[j+1]) - tmp = arg+j+1; - else if ((i+1) < argc) - tmp = argv[++i]; - else - bb_show_usage(); - fstype = string_copy(tmp); - compile_fs_type(fstype, &fs_type_compiled); - goto next_arg; - case '-': - opts_for_fsck++; - break; - case '?': - bb_show_usage(); - break; - default: - options[++opt] = arg[j]; - break; - } - } - next_arg: - if (opt) { - options[0] = '-'; - options[++opt] = '\0'; - if (num_args >= MAX_ARGS) { - bb_error_msg("too many arguments"); - } - args[num_args++] = string_copy(options); - opt = 0; - } - } - if (getenv("FSCK_FORCE_ALL_PARALLEL")) - force_all_parallel++; - if ((tmp = getenv("FSCK_MAX_INST"))) - max_running = atoi(tmp); -} - -int fsck_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -int fsck_main(int argc, char **argv) -{ - int i, status = 0; - int interactive = 0; - const char *fstab; - struct fs_info *fs; - - setvbuf(stdout, NULL, _IONBF, BUFSIZ); - setvbuf(stderr, NULL, _IONBF, BUFSIZ); - - blkid_get_cache(&cache, NULL); - PRS(argc, argv); - - if (!notitle) - printf("fsck %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE); - - fstab = getenv("FSTAB_FILE"); - if (!fstab) - fstab = _PATH_MNTTAB; - load_fs_info(fstab); - - fsck_path = e2fs_set_sbin_path(); - - if ((num_devices == 1) || (serialize)) - interactive = 1; - - /* If -A was specified ("check all"), do that! */ - if (doall) - return check_all(); - - if (num_devices == 0) { - serialize++; - interactive++; - return check_all(); - } - for (i = 0; i < num_devices; i++) { - if (cancel_requested) { - if (!kill_sent) { - kill_all(SIGTERM); - kill_sent++; - } - break; - } - fs = lookup(devices[i]); - if (!fs) { - fs = create_fs_device(devices[i], 0, "auto", - 0, -1, -1); - if (!fs) - continue; - } - fsck_device(fs, interactive); - if (serialize || - (max_running && (num_running >= max_running))) { - struct fsck_instance *inst; - - inst = wait_one(0); - if (inst) { - status |= inst->exit_status; - free_instance(inst); - } - if (verbose > 1) - printf("----------------------------------\n"); - } - } - status |= wait_many(FLAG_WAIT_ALL); - blkid_put_cache(cache); - return status; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * fsck.h - */ - -#define FSCK_ATTR(x) __attribute__(x) - -#define EXIT_OK 0 -#define EXIT_NONDESTRUCT 1 -#define EXIT_DESTRUCT 2 -#define EXIT_UNCORRECTED 4 -#define EXIT_ERROR 8 -#define EXIT_USAGE 16 -#define FSCK_CANCELED 32 /* Aborted with a signal or ^C */ - -extern char *e2fs_set_sbin_path(void); diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * lsattr.c - List file attributes on an ext2 file system - * - * Copyright (C) 1993, 1994 Remy Card - * Laboratoire MASI, Institut Blaise Pascal - * Universite Pierre et Marie Curie (Paris VI) - * - * This file can be redistributed under the terms of the GNU General - * Public License - */ - -/* - * History: - * 93/10/30 - Creation - * 93/11/13 - Replace stat() calls by lstat() to avoid loops - * 94/02/27 - Integrated in Ted's distribution - * 98/12/29 - Display version info only when -V specified (G M Sipe) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ext2fs/ext2_fs.h" -#include "e2fsbb.h" -#include "e2p/e2p.h" - -#define OPT_RECUR 1 -#define OPT_ALL 2 -#define OPT_DIRS_OPT 4 -#define OPT_PF_LONG 8 -#define OPT_GENERATION 16 -static int flags; - -static void list_attributes(const char *name) -{ - unsigned long fsflags; - unsigned long generation; - - if (fgetflags(name, &fsflags) == -1) - goto read_err; - if (flags & OPT_GENERATION) { - if (fgetversion(name, &generation) == -1) - goto read_err; - printf("%5lu ", generation); - } - - if (flags & OPT_PF_LONG) { - printf("%-28s ", name); - print_e2flags(stdout, fsflags, PFOPT_LONG); - bb_putchar('\n'); - } else { - print_e2flags(stdout, fsflags, 0); - printf(" %s\n", name); - } - - return; -read_err: - bb_perror_msg("reading %s", name); -} - -static int lsattr_dir_proc(const char *, struct dirent *, void *); - -static void lsattr_args(const char *name) -{ - struct stat st; - - if (lstat(name, &st) == -1) { - bb_perror_msg("stating %s", name); - } else { - if (S_ISDIR(st.st_mode) && !(flags & OPT_DIRS_OPT)) - iterate_on_dir(name, lsattr_dir_proc, NULL); - else - list_attributes(name); - } -} - -static int lsattr_dir_proc(const char *dir_name, struct dirent *de, - void *private) -{ - struct stat st; - char *path; - - path = concat_path_file(dir_name, de->d_name); - - if (lstat(path, &st) == -1) - bb_simple_perror_msg(path); - else { - if (de->d_name[0] != '.' || (flags & OPT_ALL)) { - list_attributes(path); - if (S_ISDIR(st.st_mode) && (flags & OPT_RECUR) && - (de->d_name[0] != '.' && (de->d_name[1] != '\0' || - (de->d_name[1] != '.' && de->d_name[2] != '\0')))) { - printf("\n%s:\n", path); - iterate_on_dir(path, lsattr_dir_proc, NULL); - bb_putchar('\n'); - } - } - } - - free(path); - - return 0; -} - -int lsattr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -int lsattr_main(int argc, char **argv) -{ - int i; - - flags = getopt32(argv, "Radlv"); - - if (optind > argc - 1) - lsattr_args("."); - else - for (i = optind; i < argc; i++) - lsattr_args(argv[i]); - - return EXIT_SUCCESS; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * mke2fs.c - Make a ext2fs filesystem. - * - * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, - * 2003, 2004, 2005 by Theodore Ts'o. - * - * Licensed under GPLv2, see file LICENSE in this source tree. - */ - -/* Usage: mke2fs [options] device - * - * The device may be a block device or a image of one, but this isn't - * enforced (but it's not much fun on a character device :-). - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "e2fsbb.h" -#include "ext2fs/ext2_fs.h" -#include "uuid/uuid.h" -#include "e2p/e2p.h" -#include "ext2fs/ext2fs.h" -#include "util.h" - -#define STRIDE_LENGTH 8 - -#ifndef __sparc__ -#define ZAP_BOOTBLOCK -#endif - -static const char * device_name; - -/* Command line options */ -static int cflag; -static int quiet; -static int super_only; -static int force; -static int noaction; -static int journal_size; -static int journal_flags; -static const char *bad_blocks_filename; -static __u32 fs_stride; - -static struct ext2_super_block param; -static char *creator_os; -static char *volume_label; -static char *mount_dir; -static char *journal_device = NULL; -static int sync_kludge; /* Set using the MKE2FS_SYNC env. option */ - -static int sys_page_size = 4096; -static int linux_version_code = 0; - -static int int_log2(int arg) -{ - int l = 0; - - arg >>= 1; - while (arg) { - l++; - arg >>= 1; - } - return l; -} - -static int int_log10(unsigned int arg) -{ - int l; - - for (l = 0; arg; l++) - arg = arg / 10; - return l; -} - -/* - * This function sets the default parameters for a filesystem - * - * The type is specified by the user. The size is the maximum size - * (in megabytes) for which a set of parameters applies, with a size - * of zero meaning that it is the default parameter for the type. - * Note that order is important in the table below. - */ -#define DEF_MAX_BLOCKSIZE -1 -static const char default_str[] = "default"; -struct mke2fs_defaults { - const char *type; - int size; - int blocksize; - int inode_ratio; -}; - -static const struct mke2fs_defaults settings[] = { - { default_str, 0, 4096, 8192 }, - { default_str, 512, 1024, 4096 }, - { default_str, 3, 1024, 8192 }, - { "journal", 0, 4096, 8192 }, - { "news", 0, 4096, 4096 }, - { "largefile", 0, 4096, 1024 * 1024 }, - { "largefile4", 0, 4096, 4096 * 1024 }, - { 0, 0, 0, 0}, -}; - -static void set_fs_defaults(const char *fs_type, - struct ext2_super_block *super, - int blocksize, int sector_size, - int *inode_ratio) -{ - int megs; - int ratio = 0; - const struct mke2fs_defaults *p; - int use_bsize = 1024; - - megs = super->s_blocks_count * (EXT2_BLOCK_SIZE(super) / 1024) / 1024; - if (inode_ratio) - ratio = *inode_ratio; - if (!fs_type) - fs_type = default_str; - for (p = settings; p->type; p++) { - if ((strcmp(p->type, fs_type) != 0) && - (strcmp(p->type, default_str) != 0)) - continue; - if ((p->size != 0) && (megs > p->size)) - continue; - if (ratio == 0) - *inode_ratio = p->inode_ratio < blocksize ? - blocksize : p->inode_ratio; - use_bsize = p->blocksize; - } - if (blocksize <= 0) { - if (use_bsize == DEF_MAX_BLOCKSIZE) { - use_bsize = sys_page_size; - if ((linux_version_code < (2*65536 + 6*256)) && - (use_bsize > 4096)) - use_bsize = 4096; - } - if (sector_size && use_bsize < sector_size) - use_bsize = sector_size; - if ((blocksize < 0) && (use_bsize < (-blocksize))) - use_bsize = -blocksize; - blocksize = use_bsize; - super->s_blocks_count /= blocksize / 1024; - } - super->s_log_frag_size = super->s_log_block_size = - int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE); -} - - -/* - * Helper function for read_bb_file and test_disk - */ -static void invalid_block(ext2_filsys fs EXT2FS_ATTR((unused)), blk_t blk) -{ - bb_error_msg("Bad block %u out of range; ignored", blk); -} - -/* - * Busybox stuff - */ -static void mke2fs_error_msg_and_die(int retval, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); -static void mke2fs_error_msg_and_die(int retval, const char *fmt, ...) -{ - va_list ap; - - if (retval) { - va_start(ap, fmt); - fprintf(stderr, "\nCould not "); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); - va_end(ap); - exit(EXIT_FAILURE); - } -} - -static void mke2fs_verbose(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); -static void mke2fs_verbose(const char *fmt, ...) -{ - va_list ap; - - if (!quiet) { - va_start(ap, fmt); - vfprintf(stdout, fmt, ap); - fflush(stdout); - va_end(ap); - } -} - -static void mke2fs_verbose_done(void) -{ - mke2fs_verbose("done\n"); -} - -static void mke2fs_warning_msg(int retval, char *fmt, ... ) __attribute__ ((format (printf, 2, 3))); -static void mke2fs_warning_msg(int retval, char *fmt, ... ) -{ - va_list ap; - - if (retval) { - va_start(ap, fmt); - fprintf(stderr, "\nWarning: "); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); - va_end(ap); - } -} - -/* - * Reads the bad blocks list from a file - */ -static void read_bb_file(ext2_filsys fs, badblocks_list *bb_list, - const char *bad_blocks_file) -{ - FILE *f; - errcode_t retval; - - f = xfopen_for_read(bad_blocks_file); - retval = ext2fs_read_bb_FILE(fs, f, bb_list, invalid_block); - fclose (f); - mke2fs_error_msg_and_die(retval, "read bad blocks from list"); -} - -/* - * Runs the badblocks program to test the disk - */ -static void test_disk(ext2_filsys fs, badblocks_list *bb_list) -{ - FILE *f; - errcode_t retval; - char buf[1024]; - - sprintf(buf, "badblocks -b %u %s%s%s %d", fs->blocksize, - quiet ? "" : "-s ", (cflag > 1) ? "-w " : "", - fs->device_name, fs->super->s_blocks_count); - mke2fs_verbose("Running command: %s\n", buf); - f = popen(buf, "r"); - if (!f) { - bb_perror_msg_and_die("can't run '%s'", buf); - } - retval = ext2fs_read_bb_FILE(fs, f, bb_list, invalid_block); - pclose(f); - mke2fs_error_msg_and_die(retval, "read bad blocks from program"); -} - -static void handle_bad_blocks(ext2_filsys fs, badblocks_list bb_list) -{ - dgrp_t i; - blk_t j; - unsigned must_be_good; - blk_t blk; - badblocks_iterate bb_iter; - errcode_t retval; - blk_t group_block; - int group; - int group_bad; - - if (!bb_list) - return; - - /* - * The primary superblock and group descriptors *must* be - * good; if not, abort. - */ - must_be_good = fs->super->s_first_data_block + 1 + fs->desc_blocks; - for (i = fs->super->s_first_data_block; i <= must_be_good; i++) { - if (ext2fs_badblocks_list_test(bb_list, i)) { - bb_error_msg_and_die( - "Block %d in primary superblock/group descriptor area bad\n" - "Blocks %d through %d must be good in order to build a filesystem\n" - "Aborting ...", i, fs->super->s_first_data_block, must_be_good); - } - } - - /* - * See if any of the bad blocks are showing up in the backup - * superblocks and/or group descriptors. If so, issue a - * warning and adjust the block counts appropriately. - */ - group_block = fs->super->s_first_data_block + - fs->super->s_blocks_per_group; - - for (i = 1; i < fs->group_desc_count; i++) { - group_bad = 0; - for (j=0; j < fs->desc_blocks+1; j++) { - if (ext2fs_badblocks_list_test(bb_list, - group_block + j)) { - mke2fs_warning_msg(!group_bad, - "the backup superblock/group descriptors at block %d contain\n" - "bad blocks\n", group_block); - group_bad++; - group = ext2fs_group_of_blk(fs, group_block+j); - fs->group_desc[group].bg_free_blocks_count++; - fs->super->s_free_blocks_count++; - } - } - group_block += fs->super->s_blocks_per_group; - } - - /* - * Mark all the bad blocks as used... - */ - retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter); - mke2fs_error_msg_and_die(retval, "mark bad blocks as used"); - - while (ext2fs_badblocks_list_iterate(bb_iter, &blk)) - ext2fs_mark_block_bitmap(fs->block_map, blk); - ext2fs_badblocks_list_iterate_end(bb_iter); -} - -/* - * These functions implement a generalized progress meter. - */ -struct progress_struct { - char format[20]; - char backup[80]; - __u32 max; - int skip_progress; -}; - -static void progress_init(struct progress_struct *progress, - const char *label,__u32 max) -{ - int i; - - memset(progress, 0, sizeof(struct progress_struct)); - if (quiet) - return; - - /* - * Figure out how many digits we need - */ - i = int_log10(max); - sprintf(progress->format, "%%%dd/%%%dld", i, i); - memset(progress->backup, '\b', sizeof(progress->backup)-1); - progress->backup[sizeof(progress->backup)-1] = 0; - if ((2*i)+1 < (int) sizeof(progress->backup)) - progress->backup[(2*i)+1] = 0; - progress->max = max; - - progress->skip_progress = 0; - if (getenv("MKE2FS_SKIP_PROGRESS")) - progress->skip_progress++; - - fputs(label, stdout); - fflush(stdout); -} - -static void progress_update(struct progress_struct *progress, __u32 val) -{ - if ((progress->format[0] == 0) || progress->skip_progress) - return; - printf(progress->format, val, progress->max); - fputs(progress->backup, stdout); -} - -static void progress_close(struct progress_struct *progress) -{ - if (progress->format[0] == 0) - return; - printf("%-28s\n", "done"); -} - - -/* - * Helper function which zeros out _num_ blocks starting at _blk_. In - * case of an error, the details of the error is returned via _ret_blk_ - * and _ret_count_ if they are non-NULL pointers. Returns 0 on - * success, and an error code on an error. - * - * As a special case, if the first argument is NULL, then it will - * attempt to free the static zeroizing buffer. (This is to keep - * programs that check for memory leaks happy.) - */ -static errcode_t zero_blocks(ext2_filsys fs, blk_t blk, int num, - struct progress_struct *progress, - blk_t *ret_blk, int *ret_count) -{ - int j, count, next_update; - static char *buf; - errcode_t retval; - - /* If fs is null, clean up the static buffer and return */ - if (!fs) { - if (buf) { - free(buf); - buf = 0; - } - return 0; - } - /* Allocate the zeroizing buffer if necessary */ - if (!buf) { - buf = xzalloc(fs->blocksize * STRIDE_LENGTH); - } - /* OK, do the write loop */ - next_update = 0; - - for (j=0; j < num; j += STRIDE_LENGTH, blk += STRIDE_LENGTH) { - count = num - j; - if (count > STRIDE_LENGTH) - count = STRIDE_LENGTH; - retval = io_channel_write_blk(fs->io, blk, count, buf); - if (retval) { - if (ret_count) - *ret_count = count; - if (ret_blk) - *ret_blk = blk; - return retval; - } - if (progress && j > next_update) { - next_update += num / 100; - progress_update(progress, blk); - } - } - return 0; -} - -static void write_inode_tables(ext2_filsys fs) -{ - errcode_t retval; - blk_t blk; - dgrp_t i; - int num; - struct progress_struct progress; - - if (quiet) - memset(&progress, 0, sizeof(progress)); - else - progress_init(&progress, "Writing inode tables: ", - fs->group_desc_count); - - for (i = 0; i < fs->group_desc_count; i++) { - progress_update(&progress, i); - - blk = fs->group_desc[i].bg_inode_table; - num = fs->inode_blocks_per_group; - - retval = zero_blocks(fs, blk, num, 0, &blk, &num); - mke2fs_error_msg_and_die(retval, - "write %d blocks in inode table starting at %d.", - num, blk); - if (sync_kludge) { - if (sync_kludge == 1) - sync(); - else if ((i % sync_kludge) == 0) - sync(); - } - } - zero_blocks(0, 0, 0, 0, 0, 0); - progress_close(&progress); -} - -static void create_root_dir(ext2_filsys fs) -{ - errcode_t retval; - struct ext2_inode inode; - - retval = ext2fs_mkdir(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, 0); - mke2fs_error_msg_and_die(retval, "create root dir"); - if (geteuid()) { - retval = ext2fs_read_inode(fs, EXT2_ROOT_INO, &inode); - mke2fs_error_msg_and_die(retval, "read root inode"); - inode.i_uid = getuid(); - if (inode.i_uid) - inode.i_gid = getgid(); - retval = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode); - mke2fs_error_msg_and_die(retval, "set root inode ownership"); - } -} - -static void create_lost_and_found(ext2_filsys fs) -{ - errcode_t retval; - ext2_ino_t ino; - const char *name = "lost+found"; - int i = 1; - char *msg = "create"; - int lpf_size = 0; - - fs->umask = 077; - retval = ext2fs_mkdir(fs, EXT2_ROOT_INO, 0, name); - if (retval) { - goto CREATE_LOST_AND_FOUND_ERROR; - } - - retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name, strlen(name), 0, &ino); - if (retval) { - msg = "lookup"; - goto CREATE_LOST_AND_FOUND_ERROR; - } - - for (; i < EXT2_NDIR_BLOCKS; i++) { - if ((lpf_size += fs->blocksize) >= 16*1024) - break; - retval = ext2fs_expand_dir(fs, ino); - msg = "expand"; -CREATE_LOST_AND_FOUND_ERROR: - mke2fs_error_msg_and_die(retval, "%s %s", msg, name); - } -} - -static void create_bad_block_inode(ext2_filsys fs, badblocks_list bb_list) -{ - errcode_t retval; - - ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_BAD_INO); - fs->group_desc[0].bg_free_inodes_count--; - fs->super->s_free_inodes_count--; - retval = ext2fs_update_bb_inode(fs, bb_list); - mke2fs_error_msg_and_die(retval, "set bad block inode"); -} - -static void reserve_inodes(ext2_filsys fs) -{ - ext2_ino_t i; - int group; - - for (i = EXT2_ROOT_INO + 1; i < EXT2_FIRST_INODE(fs->super); i++) { - ext2fs_mark_inode_bitmap(fs->inode_map, i); - group = ext2fs_group_of_ino(fs, i); - fs->group_desc[group].bg_free_inodes_count--; - fs->super->s_free_inodes_count--; - } - ext2fs_mark_ib_dirty(fs); -} - -#define BSD_DISKMAGIC (0x82564557UL) /* The disk magic number */ -#define BSD_MAGICDISK (0x57455682UL) /* The disk magic number reversed */ -#define BSD_LABEL_OFFSET 64 - -static void zap_sector(ext2_filsys fs, int sect, int nsect) -{ - char *buf; - char *fmt = "could not %s %d"; - int retval; - unsigned int *magic; - - buf = xmalloc(512*nsect); - - if (sect == 0) { - /* Check for a BSD disklabel, and don't erase it if so */ - retval = io_channel_read_blk(fs->io, 0, -512, buf); - if (retval) - mke2fs_warning_msg(retval, fmt, "read block", 0); - else { - magic = (unsigned int *) (buf + BSD_LABEL_OFFSET); - if ((*magic == BSD_DISKMAGIC) || - (*magic == BSD_MAGICDISK)) - return; - } - } - - memset(buf, 0, 512*nsect); - io_channel_set_blksize(fs->io, 512); - retval = io_channel_write_blk(fs->io, sect, -512*nsect, buf); - io_channel_set_blksize(fs->io, fs->blocksize); - free(buf); - mke2fs_warning_msg(retval, fmt, "erase sector", sect); -} - -static void create_journal_dev(ext2_filsys fs) -{ - struct progress_struct progress; - errcode_t retval; - char *buf; - char *fmt = "%s journal superblock"; - blk_t blk; - int count; - - retval = ext2fs_create_journal_superblock(fs, - fs->super->s_blocks_count, 0, &buf); - mke2fs_error_msg_and_die(retval, fmt, "init"); - if (quiet) - memset(&progress, 0, sizeof(progress)); - else - progress_init(&progress, "Zeroing journal device: ", - fs->super->s_blocks_count); - - retval = zero_blocks(fs, 0, fs->super->s_blocks_count, - &progress, &blk, &count); - mke2fs_error_msg_and_die(retval, "zero journal device (block %u, count %d)", - blk, count); - zero_blocks(0, 0, 0, 0, 0, 0); - - retval = io_channel_write_blk(fs->io, - fs->super->s_first_data_block+1, - 1, buf); - mke2fs_error_msg_and_die(retval, fmt, "write"); - progress_close(&progress); -} - -static void show_stats(ext2_filsys fs) -{ - struct ext2_super_block *s = fs->super; - char *os; - blk_t group_block; - dgrp_t i; - int need, col_left; - - mke2fs_warning_msg((param.s_blocks_count != s->s_blocks_count), - "%d blocks unused\n", param.s_blocks_count - s->s_blocks_count); - os = e2p_os2string(fs->super->s_creator_os); - printf( "Filesystem label=%.*s\n" - "OS type: %s\n" - "Block size=%u (log=%u)\n" - "Fragment size=%u (log=%u)\n" - "%u inodes, %u blocks\n" - "%u blocks (%2.2f%%) reserved for the super user\n" - "First data block=%u\n", - (int) sizeof(s->s_volume_name), - s->s_volume_name, - os, - fs->blocksize, s->s_log_block_size, - fs->fragsize, s->s_log_frag_size, - s->s_inodes_count, s->s_blocks_count, - s->s_r_blocks_count, 100.0 * s->s_r_blocks_count / s->s_blocks_count, - s->s_first_data_block); - free(os); - if (s->s_reserved_gdt_blocks) { - printf("Maximum filesystem blocks=%lu\n", - (s->s_reserved_gdt_blocks + fs->desc_blocks) * - (fs->blocksize / sizeof(struct ext2_group_desc)) * - s->s_blocks_per_group); - } - printf( "%u block group%s\n" - "%u blocks per group, %u fragments per group\n" - "%u inodes per group\n", - fs->group_desc_count, (fs->group_desc_count > 1) ? "s" : "", - s->s_blocks_per_group, s->s_frags_per_group, - s->s_inodes_per_group); - if (fs->group_desc_count == 1) { - bb_putchar('\n'); - return; - } - - printf("Superblock backups stored on blocks: "); - group_block = s->s_first_data_block; - col_left = 0; - for (i = 1; i < fs->group_desc_count; i++) { - group_block += s->s_blocks_per_group; - if (!ext2fs_bg_has_super(fs, i)) - continue; - if (i != 1) - printf(", "); - need = int_log10(group_block) + 2; - if (need > col_left) { - printf("\n\t"); - col_left = 72; - } - col_left -= need; - printf("%u", group_block); - } - puts("\n"); -} - -/* - * Set the S_CREATOR_OS field. Return true if OS is known, - * otherwise, 0. - */ -static int set_os(struct ext2_super_block *sb, char *os) -{ - if (isdigit (*os)) { - sb->s_creator_os = atoi(os); - return 1; - } - - if ((sb->s_creator_os = e2p_string2os(os)) >= 0) { - return 1; - } else if (!strcasecmp("GNU", os)) { - sb->s_creator_os = EXT2_OS_HURD; - return 1; - } - return 0; -} - -static void parse_extended_opts(struct ext2_super_block *sb_param, - const char *opts) -{ - char *buf, *token, *next, *p, *arg; - int r_usage = 0; - - buf = xstrdup(opts); - for (token = buf; token && *token; token = next) { - p = strchr(token, ','); - next = 0; - if (p) { - *p = 0; - next = p+1; - } - arg = strchr(token, '='); - if (arg) { - *arg = 0; - arg++; - } - if (strcmp(token, "stride") == 0) { - if (!arg) { - r_usage++; - continue; - } - fs_stride = strtoul(arg, &p, 0); - if (*p || (fs_stride == 0)) { - bb_error_msg("Invalid stride parameter: %s", arg); - r_usage++; - continue; - } - } else if (!strcmp(token, "resize")) { - unsigned long resize, bpg, rsv_groups; - unsigned long group_desc_count, desc_blocks; - unsigned int gdpb, blocksize; - int rsv_gdb; - - if (!arg) { - r_usage++; - continue; - } - - resize = parse_num_blocks(arg, - sb_param->s_log_block_size); - - if (resize == 0) { - bb_error_msg("Invalid resize parameter: %s", arg); - r_usage++; - continue; - } - if (resize <= sb_param->s_blocks_count) { - bb_error_msg("The resize maximum must be greater " - "than the filesystem size"); - r_usage++; - continue; - } - - blocksize = EXT2_BLOCK_SIZE(sb_param); - bpg = sb_param->s_blocks_per_group; - if (!bpg) - bpg = blocksize * 8; - gdpb = blocksize / sizeof(struct ext2_group_desc); - group_desc_count = (sb_param->s_blocks_count + - bpg - 1) / bpg; - desc_blocks = (group_desc_count + - gdpb - 1) / gdpb; - rsv_groups = (resize + bpg - 1) / bpg; - rsv_gdb = (rsv_groups + gdpb - 1) / gdpb - - desc_blocks; - if (rsv_gdb > EXT2_ADDR_PER_BLOCK(sb_param)) - rsv_gdb = EXT2_ADDR_PER_BLOCK(sb_param); - - if (rsv_gdb > 0) { - sb_param->s_feature_compat |= - EXT2_FEATURE_COMPAT_RESIZE_INO; - - sb_param->s_reserved_gdt_blocks = rsv_gdb; - } - } else - r_usage++; - } - if (r_usage) { - bb_error_msg_and_die( - "\nBad options specified.\n\n" - "Extended options are separated by commas, " - "and may take an argument which\n" - "\tis set off by an equals ('=') sign.\n\n" - "Valid extended options are:\n" - "\tstride=\n" - "\tresize=\n"); - } -} - -static __u32 ok_features[3] = { - EXT3_FEATURE_COMPAT_HAS_JOURNAL | - EXT2_FEATURE_COMPAT_RESIZE_INO | - EXT2_FEATURE_COMPAT_DIR_INDEX, /* Compat */ - EXT2_FEATURE_INCOMPAT_FILETYPE| /* Incompat */ - EXT3_FEATURE_INCOMPAT_JOURNAL_DEV| - EXT2_FEATURE_INCOMPAT_META_BG, - EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER /* R/O compat */ -}; - -static int PRS(int argc, char **argv) -{ - int c; - int size; - char * tmp; - int blocksize = 0; - int inode_ratio = 0; - int inode_size = 0; - int reserved_ratio = 5; - int sector_size = 0; - int show_version_only = 0; - ext2_ino_t num_inodes = 0; - errcode_t retval; - char * extended_opts = NULL; - const char * fs_type = NULL; - blk_t dev_size; - long sysval; - - /* Update our PATH to include /sbin */ - e2fs_set_sbin_path(); - - tmp = getenv("MKE2FS_SYNC"); - if (tmp) - sync_kludge = atoi(tmp); - - /* Determine the system page size if possible */ -#if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE)) -#define _SC_PAGESIZE _SC_PAGE_SIZE -#endif -#ifdef _SC_PAGESIZE - sysval = sysconf(_SC_PAGESIZE); - if (sysval > 0) - sys_page_size = sysval; -#endif /* _SC_PAGESIZE */ - - setbuf(stdout, NULL); - setbuf(stderr, NULL); - memset(¶m, 0, sizeof(struct ext2_super_block)); - param.s_rev_level = 1; /* Create revision 1 filesystems now */ - param.s_feature_incompat |= EXT2_FEATURE_INCOMPAT_FILETYPE; - param.s_feature_ro_compat |= EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; - -#ifdef __linux__ - linux_version_code = get_linux_version_code(); - if (linux_version_code && linux_version_code < KERNEL_VERSION(2,2,0)) { - param.s_rev_level = 0; - param.s_feature_incompat = 0; - param.s_feature_compat = 0; - param.s_feature_ro_compat = 0; - } -#endif - - /* If called as mkfs.ext3, create a journal inode */ - if (last_char_is(applet_name, '3')) - journal_size = -1; - - while ((c = getopt (argc, argv, - "b:cE:f:g:i:jl:m:no:qr:R:s:tvI:J:ST:FL:M:N:O:V")) != EOF) { - switch (c) { - case 'b': - blocksize = xatou_range(optarg, EXT2_MIN_BLOCK_SIZE, EXT2_MAX_BLOCK_SIZE); - mke2fs_warning_msg((blocksize > 4096), - "blocksize %d not usable on most systems", - blocksize); - param.s_log_block_size = - int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE); - break; - case 'c': /* Check for bad blocks */ - case 't': /* deprecated */ - cflag++; - break; - case 'f': - size = xatou_range(optarg, EXT2_MIN_BLOCK_SIZE, EXT2_MAX_BLOCK_SIZE); - param.s_log_frag_size = - int_log2(size >> EXT2_MIN_BLOCK_LOG_SIZE); - mke2fs_warning_msg(1, "fragments not supported. Ignoring -f option"); - break; - case 'g': - param.s_blocks_per_group = xatou32(optarg); - if ((param.s_blocks_per_group % 8) != 0) { - bb_error_msg_and_die("blocks per group must be multiple of 8"); - } - break; - case 'i': - /* Huh? is "* 1024" correct? */ - inode_ratio = xatou_range(optarg, EXT2_MIN_BLOCK_SIZE, EXT2_MAX_BLOCK_SIZE * 1024); - break; - case 'J': - parse_journal_opts(&journal_device, &journal_flags, &journal_size, optarg); - break; - case 'j': - param.s_feature_compat |= - EXT3_FEATURE_COMPAT_HAS_JOURNAL; - if (!journal_size) - journal_size = -1; - break; - case 'l': - bad_blocks_filename = optarg; - break; - case 'm': - reserved_ratio = xatou_range(optarg, 0, 50); - break; - case 'n': - noaction++; - break; - case 'o': - creator_os = optarg; - break; - case 'r': - param.s_rev_level = xatoi_positive(optarg); - if (param.s_rev_level == EXT2_GOOD_OLD_REV) { - param.s_feature_incompat = 0; - param.s_feature_compat = 0; - param.s_feature_ro_compat = 0; - } - break; - case 's': /* deprecated */ - if (xatou(optarg)) - param.s_feature_ro_compat |= - EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; - else - param.s_feature_ro_compat &= - ~EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; - break; -#ifdef EXT2_DYNAMIC_REV - case 'I': - inode_size = xatoi_positive(optarg); - break; -#endif - case 'N': - num_inodes = xatoi_positive(optarg); - break; - case 'v': - quiet = 0; - break; - case 'q': - quiet = 1; - break; - case 'F': - force = 1; - break; - case 'L': - volume_label = optarg; - break; - case 'M': - mount_dir = optarg; - break; - case 'O': - if (!strcmp(optarg, "none")) { - param.s_feature_compat = 0; - param.s_feature_incompat = 0; - param.s_feature_ro_compat = 0; - break; - } - if (e2p_edit_feature(optarg, - ¶m.s_feature_compat, - ok_features)) { - bb_error_msg_and_die("Invalid filesystem option set: %s", optarg); - } - break; - case 'E': - case 'R': - extended_opts = optarg; - break; - case 'S': - super_only = 1; - break; - case 'T': - fs_type = optarg; - break; - case 'V': - /* Print version number and exit */ - show_version_only = 1; - quiet = 0; - break; - default: - bb_show_usage(); - } - } - if ((optind == argc) /*&& !show_version_only*/) - bb_show_usage(); - device_name = argv[optind++]; - - mke2fs_verbose("mke2fs %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE); - - if (show_version_only) { - return 0; - } - - /* - * If there's no blocksize specified and there is a journal - * device, use it to figure out the blocksize - */ - if (blocksize <= 0 && journal_device) { - ext2_filsys jfs; - io_manager io_ptr; - -#ifdef CONFIG_TESTIO_DEBUG - io_ptr = test_io_manager; - test_io_backing_manager = unix_io_manager; -#else - io_ptr = unix_io_manager; -#endif - retval = ext2fs_open(journal_device, - EXT2_FLAG_JOURNAL_DEV_OK, 0, - 0, io_ptr, &jfs); - mke2fs_error_msg_and_die(retval, "open journal device %s", journal_device); - if ((blocksize < 0) && (jfs->blocksize < (unsigned) (-blocksize))) { - bb_error_msg_and_die( - "Journal dev blocksize (%d) smaller than " - "minimum blocksize %d\n", jfs->blocksize, - -blocksize); - } - blocksize = jfs->blocksize; - param.s_log_block_size = - int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE); - ext2fs_close(jfs); - } - - if (blocksize > sys_page_size) { - mke2fs_warning_msg(1, "%d-byte blocks too big for system (max %d)", - blocksize, sys_page_size); - if (!force) { - proceed_question(); - } - bb_error_msg("Forced to continue"); - } - mke2fs_warning_msg(((blocksize > 4096) && - (param.s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)), - "some 2.4 kernels do not support " - "blocksizes greater than 4096 using ext3.\n" - "Use -b 4096 if this is an issue for you\n"); - - if (optind < argc) { - param.s_blocks_count = parse_num_blocks(argv[optind++], - param.s_log_block_size); - mke2fs_error_msg_and_die(!param.s_blocks_count, "invalid blocks count - %s", argv[optind - 1]); - } - if (optind < argc) - bb_show_usage(); - - if (param.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) { - if (!fs_type) - fs_type = "journal"; - reserved_ratio = 0; - param.s_feature_incompat = EXT3_FEATURE_INCOMPAT_JOURNAL_DEV; - param.s_feature_compat = 0; - param.s_feature_ro_compat = 0; - } - if (param.s_rev_level == EXT2_GOOD_OLD_REV && - (param.s_feature_compat || param.s_feature_ro_compat || - param.s_feature_incompat)) - param.s_rev_level = 1; /* Create a revision 1 filesystem */ - - check_plausibility(device_name , force); - check_mount(device_name, force, "filesystem"); - - param.s_log_frag_size = param.s_log_block_size; - - if (noaction && param.s_blocks_count) { - dev_size = param.s_blocks_count; - retval = 0; - } else { - retry: - retval = ext2fs_get_device_size(device_name, - EXT2_BLOCK_SIZE(¶m), - &dev_size); - if ((retval == EFBIG) && - (blocksize == 0) && - (param.s_log_block_size == 0)) { - param.s_log_block_size = 2; - blocksize = 4096; - goto retry; - } - } - - mke2fs_error_msg_and_die((retval && (retval != EXT2_ET_UNIMPLEMENTED)),"determine filesystem size"); - - if (!param.s_blocks_count) { - if (retval == EXT2_ET_UNIMPLEMENTED) { - mke2fs_error_msg_and_die(1, - "determine device size; you " - "must specify\nthe size of the " - "filesystem"); - } else { - if (dev_size == 0) { - bb_error_msg_and_die( - "Device size reported to be zero. " - "Invalid partition specified, or\n\t" - "partition table wasn't reread " - "after running fdisk, due to\n\t" - "a modified partition being busy " - "and in use. You may need to reboot\n\t" - "to re-read your partition table.\n" - ); - } - param.s_blocks_count = dev_size; - if (sys_page_size > EXT2_BLOCK_SIZE(¶m)) - param.s_blocks_count &= ~((sys_page_size / - EXT2_BLOCK_SIZE(¶m))-1); - } - - } else if (!force && (param.s_blocks_count > dev_size)) { - bb_error_msg("Filesystem larger than apparent device size"); - proceed_question(); - } - - /* - * If the user asked for HAS_JOURNAL, then make sure a journal - * gets created. - */ - if ((param.s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) && - !journal_size) - journal_size = -1; - - /* Set first meta blockgroup via an environment variable */ - /* (this is mostly for debugging purposes) */ - if ((param.s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) && - ((tmp = getenv("MKE2FS_FIRST_META_BG")))) - param.s_first_meta_bg = atoi(tmp); - - /* Get the hardware sector size, if available */ - retval = ext2fs_get_device_sectsize(device_name, §or_size); - mke2fs_error_msg_and_die(retval, "determine hardware sector size"); - - if ((tmp = getenv("MKE2FS_DEVICE_SECTSIZE")) != NULL) - sector_size = atoi(tmp); - - set_fs_defaults(fs_type, ¶m, blocksize, sector_size, &inode_ratio); - blocksize = EXT2_BLOCK_SIZE(¶m); - - if (extended_opts) - parse_extended_opts(¶m, extended_opts); - - /* Since sparse_super is the default, we would only have a problem - * here if it was explicitly disabled. - */ - if ((param.s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INO) && - !(param.s_feature_ro_compat&EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) { - bb_error_msg_and_die("reserved online resize blocks not supported " - "on non-sparse filesystem"); - } - - if (param.s_blocks_per_group) { - if (param.s_blocks_per_group < 256 || - param.s_blocks_per_group > 8 * (unsigned) blocksize) { - bb_error_msg_and_die("blocks per group count out of range"); - } - } - - if (!force && param.s_blocks_count >= (1 << 31)) { - bb_error_msg_and_die("Filesystem too large. No more than 2**31-1 blocks\n" - "\t (8TB using a blocksize of 4k) are currently supported."); - } - - if (inode_size) { - if (inode_size < EXT2_GOOD_OLD_INODE_SIZE || - inode_size > EXT2_BLOCK_SIZE(¶m) || - inode_size & (inode_size - 1)) { - bb_error_msg_and_die("invalid inode size %d (min %d/max %d)", - inode_size, EXT2_GOOD_OLD_INODE_SIZE, - blocksize); - } - mke2fs_warning_msg((inode_size != EXT2_GOOD_OLD_INODE_SIZE), - "%d-byte inodes not usable on most systems", - inode_size); - param.s_inode_size = inode_size; - } - - /* - * Calculate number of inodes based on the inode ratio - */ - param.s_inodes_count = num_inodes ? num_inodes : - ((__u64) param.s_blocks_count * blocksize) - / inode_ratio; - - /* - * Calculate number of blocks to reserve - */ - param.s_r_blocks_count = (param.s_blocks_count * reserved_ratio) / 100; - return 1; -} - -static void mke2fs_clean_up(void) -{ - if (ENABLE_FEATURE_CLEAN_UP && journal_device) free(journal_device); -} - -int mke2fs_main (int argc, char **argv); -int mke2fs_main (int argc, char **argv) -{ - errcode_t retval; - ext2_filsys fs; - badblocks_list bb_list = 0; - unsigned int i; - int val; - io_manager io_ptr; - - if (ENABLE_FEATURE_CLEAN_UP) - atexit(mke2fs_clean_up); - if (!PRS(argc, argv)) - return 0; - -#ifdef CONFIG_TESTIO_DEBUG - io_ptr = test_io_manager; - test_io_backing_manager = unix_io_manager; -#else - io_ptr = unix_io_manager; -#endif - - /* - * Initialize the superblock.... - */ - retval = ext2fs_initialize(device_name, 0, ¶m, - io_ptr, &fs); - mke2fs_error_msg_and_die(retval, "set up superblock"); - - /* - * Wipe out the old on-disk superblock - */ - if (!noaction) - zap_sector(fs, 2, 6); - - /* - * Generate a UUID for it... - */ - uuid_generate(fs->super->s_uuid); - - /* - * Initialize the directory index variables - */ - fs->super->s_def_hash_version = EXT2_HASH_TEA; - uuid_generate((unsigned char *) fs->super->s_hash_seed); - - /* - * Add "jitter" to the superblock's check interval so that we - * don't check all the filesystems at the same time. We use a - * kludgy hack of using the UUID to derive a random jitter value. - */ - for (i = 0, val = 0; i < sizeof(fs->super->s_uuid); i++) - val += fs->super->s_uuid[i]; - fs->super->s_max_mnt_count += val % EXT2_DFL_MAX_MNT_COUNT; - - /* - * Override the creator OS, if applicable - */ - if (creator_os && !set_os(fs->super, creator_os)) { - bb_error_msg_and_die("unknown os - %s", creator_os); - } - - /* - * For the Hurd, we will turn off filetype since it doesn't - * support it. - */ - if (fs->super->s_creator_os == EXT2_OS_HURD) - fs->super->s_feature_incompat &= - ~EXT2_FEATURE_INCOMPAT_FILETYPE; - - /* - * Set the volume label... - */ - if (volume_label) { - snprintf(fs->super->s_volume_name, sizeof(fs->super->s_volume_name), "%s", volume_label); - } - - /* - * Set the last mount directory - */ - if (mount_dir) { - snprintf(fs->super->s_last_mounted, sizeof(fs->super->s_last_mounted), "%s", mount_dir); - } - - if (!quiet || noaction) - show_stats(fs); - - if (noaction) - return 0; - - if (fs->super->s_feature_incompat & - EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) { - create_journal_dev(fs); - return (ext2fs_close(fs) ? 1 : 0); - } - - if (bad_blocks_filename) - read_bb_file(fs, &bb_list, bad_blocks_filename); - if (cflag) - test_disk(fs, &bb_list); - - handle_bad_blocks(fs, bb_list); - fs->stride = fs_stride; - retval = ext2fs_allocate_tables(fs); - mke2fs_error_msg_and_die(retval, "allocate filesystem tables"); - if (super_only) { - fs->super->s_state |= EXT2_ERROR_FS; - fs->flags &= ~(EXT2_FLAG_IB_DIRTY|EXT2_FLAG_BB_DIRTY); - } else { - /* rsv must be a power of two (64kB is MD RAID sb alignment) */ - unsigned int rsv = 65536 / fs->blocksize; - unsigned long blocks = fs->super->s_blocks_count; - unsigned long start; - blk_t ret_blk; - -#ifdef ZAP_BOOTBLOCK - zap_sector(fs, 0, 2); -#endif - - /* - * Wipe out any old MD RAID (or other) metadata at the end - * of the device. This will also verify that the device is - * as large as we think. Be careful with very small devices. - */ - start = (blocks & ~(rsv - 1)); - if (start > rsv) - start -= rsv; - if (start > 0) - retval = zero_blocks(fs, start, blocks - start, - NULL, &ret_blk, NULL); - - mke2fs_warning_msg(retval, "can't zero block %u at end of filesystem", ret_blk); - write_inode_tables(fs); - create_root_dir(fs); - create_lost_and_found(fs); - reserve_inodes(fs); - create_bad_block_inode(fs, bb_list); - if (fs->super->s_feature_compat & - EXT2_FEATURE_COMPAT_RESIZE_INO) { - retval = ext2fs_create_resize_inode(fs); - mke2fs_error_msg_and_die(retval, "reserve blocks for online resize"); - } - } - - if (journal_device) { - make_journal_device(journal_device, fs, quiet, force); - } else if (journal_size) { - make_journal_blocks(fs, journal_size, journal_flags, quiet); - } - - mke2fs_verbose("Writing superblocks and filesystem accounting information: "); - retval = ext2fs_flush(fs); - mke2fs_warning_msg(retval, "had trouble writing out superblocks"); - mke2fs_verbose_done(); - if (!quiet && !getenv("MKE2FS_SKIP_CHECK_MSG")) - print_check_message(fs); - val = ext2fs_close(fs); - return (retval || val) ? 1 : 0; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * tune2fs.c - Change the file system parameters on an ext2 file system - * - * Copyright (C) 1992, 1993, 1994 Remy Card - * Laboratoire MASI, Institut Blaise Pascal - * Universite Pierre et Marie Curie (Paris VI) - * - * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o. - * - * Licensed under GPLv2, see file LICENSE in this source tree. - */ - -/* - * History: - * 93/06/01 - Creation - * 93/10/31 - Added the -c option to change the maximal mount counts - * 93/12/14 - Added -l flag to list contents of superblock - * M.J.E. Mol (marcel@duteca.et.tudelft.nl) - * F.W. ten Wolde (franky@duteca.et.tudelft.nl) - * 93/12/29 - Added the -e option to change errors behavior - * 94/02/27 - Ported to use the ext2fs library - * 94/03/06 - Added the checks interval from Uwe Ohse (uwe@tirka.gun.de) - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "e2fsbb.h" -#include "ext2fs/ext2_fs.h" -#include "ext2fs/ext2fs.h" -#include "uuid/uuid.h" -#include "e2p/e2p.h" -#include "ext2fs/kernel-jbd.h" -#include "util.h" -#include "blkid/blkid.h" - -#include "libbb.h" - -static char * device_name = NULL; -static char * new_label, *new_last_mounted, *new_UUID; -static char * io_options; -static int c_flag, C_flag, e_flag, f_flag, g_flag, i_flag, l_flag, L_flag; -static int m_flag, M_flag, r_flag, s_flag = -1, u_flag, U_flag, T_flag; -static time_t last_check_time; -static int print_label; -static int max_mount_count, mount_count, mount_flags; -static unsigned long interval, reserved_blocks; -static unsigned reserved_ratio; -static unsigned long resgid, resuid; -static unsigned short errors; -static int open_flag; -static char *features_cmd; -static char *mntopts_cmd; - -static int journal_size, journal_flags; -static char *journal_device = NULL; - -static const char *please_fsck = "Please run e2fsck on the filesystem\n"; - -static __u32 ok_features[3] = { - EXT3_FEATURE_COMPAT_HAS_JOURNAL | EXT2_FEATURE_COMPAT_DIR_INDEX, - EXT2_FEATURE_INCOMPAT_FILETYPE, - EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER -}; - -/* - * Remove an external journal from the filesystem - */ -static void remove_journal_device(ext2_filsys fs) -{ - char *journal_path; - ext2_filsys jfs; - char buf[1024]; - journal_superblock_t *jsb; - int i, nr_users; - errcode_t retval; - int commit_remove_journal = 0; - io_manager io_ptr; - - if (f_flag) - commit_remove_journal = 1; /* force removal even if error */ - - uuid_unparse(fs->super->s_journal_uuid, buf); - journal_path = blkid_get_devname(NULL, "UUID", buf); - - if (!journal_path) { - journal_path = - ext2fs_find_block_device(fs->super->s_journal_dev); - if (!journal_path) - return; - } - - io_ptr = unix_io_manager; - retval = ext2fs_open(journal_path, EXT2_FLAG_RW| - EXT2_FLAG_JOURNAL_DEV_OK, 0, - fs->blocksize, io_ptr, &jfs); - if (retval) { - bb_error_msg("Failed to open external journal"); - goto no_valid_journal; - } - if (!(jfs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) { - bb_error_msg("%s is not a journal device", journal_path); - goto no_valid_journal; - } - - /* Get the journal superblock */ - if ((retval = io_channel_read_blk(jfs->io, 1, -1024, buf))) { - bb_error_msg("Failed to read journal superblock"); - goto no_valid_journal; - } - - jsb = (journal_superblock_t *) buf; - if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) || - (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2))) { - bb_error_msg("Journal superblock not found!"); - goto no_valid_journal; - } - - /* Find the filesystem UUID */ - nr_users = ntohl(jsb->s_nr_users); - for (i=0; i < nr_users; i++) { - if (memcmp(fs->super->s_uuid, - &jsb->s_users[i*16], 16) == 0) - break; - } - if (i >= nr_users) { - bb_error_msg("Filesystem's UUID not found on journal device"); - commit_remove_journal = 1; - goto no_valid_journal; - } - nr_users--; - for (i=0; i < nr_users; i++) - memcpy(&jsb->s_users[i*16], &jsb->s_users[(i+1)*16], 16); - jsb->s_nr_users = htonl(nr_users); - - /* Write back the journal superblock */ - if ((retval = io_channel_write_blk(jfs->io, 1, -1024, buf))) { - bb_error_msg("Failed to write journal superblock"); - goto no_valid_journal; - } - - commit_remove_journal = 1; - -no_valid_journal: - if (commit_remove_journal == 0) - bb_error_msg_and_die("Journal NOT removed"); - fs->super->s_journal_dev = 0; - uuid_clear(fs->super->s_journal_uuid); - ext2fs_mark_super_dirty(fs); - puts("Journal removed"); - free(journal_path); -} - -/* Helper function for remove_journal_inode */ -static int release_blocks_proc(ext2_filsys fs, blk_t *blocknr, - int blockcnt EXT2FS_ATTR((unused)), - void *private EXT2FS_ATTR((unused))) -{ - blk_t block; - int group; - - block = *blocknr; - ext2fs_unmark_block_bitmap(fs->block_map,block); - group = ext2fs_group_of_blk(fs, block); - fs->group_desc[group].bg_free_blocks_count++; - fs->super->s_free_blocks_count++; - return 0; -} - -/* - * Remove the journal inode from the filesystem - */ -static void remove_journal_inode(ext2_filsys fs) -{ - struct ext2_inode inode; - errcode_t retval; - ino_t ino = fs->super->s_journal_inum; - char *msg = "to read"; - char *s = "journal inode"; - - retval = ext2fs_read_inode(fs, ino, &inode); - if (retval) - goto REMOVE_JOURNAL_INODE_ERROR; - if (ino == EXT2_JOURNAL_INO) { - retval = ext2fs_read_bitmaps(fs); - if (retval) { - msg = "to read bitmaps"; - s = ""; - goto REMOVE_JOURNAL_INODE_ERROR; - } - retval = ext2fs_block_iterate(fs, ino, 0, NULL, - release_blocks_proc, NULL); - if (retval) { - msg = "clearing"; - goto REMOVE_JOURNAL_INODE_ERROR; - } - memset(&inode, 0, sizeof(inode)); - ext2fs_mark_bb_dirty(fs); - fs->flags &= ~EXT2_FLAG_SUPER_ONLY; - } else - inode.i_flags &= ~EXT2_IMMUTABLE_FL; - retval = ext2fs_write_inode(fs, ino, &inode); - if (retval) { - msg = "writing"; -REMOVE_JOURNAL_INODE_ERROR: - bb_error_msg_and_die("Failed %s %s", msg, s); - } - fs->super->s_journal_inum = 0; - ext2fs_mark_super_dirty(fs); -} - -/* - * Update the default mount options - */ -static void update_mntopts(ext2_filsys fs, char *mntopts) -{ - struct ext2_super_block *sb= fs->super; - - if (e2p_edit_mntopts(mntopts, &sb->s_default_mount_opts, ~0)) - bb_error_msg_and_die("Invalid mount option set: %s", mntopts); - ext2fs_mark_super_dirty(fs); -} - -/* - * Update the feature set as provided by the user. - */ -static void update_feature_set(ext2_filsys fs, char *features) -{ - int sparse, old_sparse, filetype, old_filetype; - int journal, old_journal, dxdir, old_dxdir; - struct ext2_super_block *sb= fs->super; - __u32 old_compat, old_incompat, old_ro_compat; - - old_compat = sb->s_feature_compat; - old_ro_compat = sb->s_feature_ro_compat; - old_incompat = sb->s_feature_incompat; - - old_sparse = sb->s_feature_ro_compat & - EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; - old_filetype = sb->s_feature_incompat & - EXT2_FEATURE_INCOMPAT_FILETYPE; - old_journal = sb->s_feature_compat & - EXT3_FEATURE_COMPAT_HAS_JOURNAL; - old_dxdir = sb->s_feature_compat & - EXT2_FEATURE_COMPAT_DIR_INDEX; - if (e2p_edit_feature(features, &sb->s_feature_compat, ok_features)) - bb_error_msg_and_die("Invalid filesystem option set: %s", features); - sparse = sb->s_feature_ro_compat & - EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; - filetype = sb->s_feature_incompat & - EXT2_FEATURE_INCOMPAT_FILETYPE; - journal = sb->s_feature_compat & - EXT3_FEATURE_COMPAT_HAS_JOURNAL; - dxdir = sb->s_feature_compat & - EXT2_FEATURE_COMPAT_DIR_INDEX; - if (old_journal && !journal) { - if ((mount_flags & EXT2_MF_MOUNTED) && - !(mount_flags & EXT2_MF_READONLY)) { - bb_error_msg_and_die( - "The has_journal flag may only be " - "cleared when the filesystem is\n" - "unmounted or mounted " - "read-only"); - } - if (sb->s_feature_incompat & - EXT3_FEATURE_INCOMPAT_RECOVER) { - bb_error_msg_and_die( - "The needs_recovery flag is set. " - "%s before clearing the has_journal flag.", - please_fsck); - } - if (sb->s_journal_inum) { - remove_journal_inode(fs); - } - if (sb->s_journal_dev) { - remove_journal_device(fs); - } - } - if (journal && !old_journal) { - /* - * If adding a journal flag, let the create journal - * code below handle creating setting the flag and - * creating the journal. We supply a default size if - * necessary. - */ - if (!journal_size) - journal_size = -1; - sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL; - } - if (dxdir && !old_dxdir) { - if (!sb->s_def_hash_version) - sb->s_def_hash_version = EXT2_HASH_TEA; - if (uuid_is_null((unsigned char *) sb->s_hash_seed)) - uuid_generate((unsigned char *) sb->s_hash_seed); - } - - if (sb->s_rev_level == EXT2_GOOD_OLD_REV && - (sb->s_feature_compat || sb->s_feature_ro_compat || - sb->s_feature_incompat)) - ext2fs_update_dynamic_rev(fs); - if ((sparse != old_sparse) || - (filetype != old_filetype)) { - sb->s_state &= ~EXT2_VALID_FS; - printf("\n%s\n", please_fsck); - } - if ((old_compat != sb->s_feature_compat) || - (old_ro_compat != sb->s_feature_ro_compat) || - (old_incompat != sb->s_feature_incompat)) - ext2fs_mark_super_dirty(fs); -} - -/* - * Add a journal to the filesystem. - */ -static void add_journal(ext2_filsys fs) -{ - if (fs->super->s_feature_compat & - EXT3_FEATURE_COMPAT_HAS_JOURNAL) { - bb_error_msg_and_die("The filesystem already has a journal"); - } - if (journal_device) { - make_journal_device(journal_device, fs, 0, 0); - } else if (journal_size) { - make_journal_blocks(fs, journal_size, journal_flags, 0); - /* - * If the filesystem wasn't mounted, we need to force - * the block group descriptors out. - */ - if ((mount_flags & EXT2_MF_MOUNTED) == 0) - fs->flags &= ~EXT2_FLAG_SUPER_ONLY; - } - print_check_message(fs); -} - -/* - * Busybox stuff - */ -static char * x_blkid_get_devname(const char *token) -{ - char * dev_name; - - if (!(dev_name = blkid_get_devname(NULL, token, NULL))) - bb_error_msg_and_die("Unable to resolve '%s'", token); - return dev_name; -} - -#ifdef CONFIG_E2LABEL -static void parse_e2label_options(int argc, char ** argv) -{ - if ((argc < 2) || (argc > 3)) - bb_show_usage(); - io_options = strchr(argv[1], '?'); - if (io_options) - *io_options++ = 0; - device_name = x_blkid_get_devname(argv[1]); - if (argc == 3) { - open_flag = EXT2_FLAG_RW | EXT2_FLAG_JOURNAL_DEV_OK; - L_flag = 1; - new_label = argv[2]; - } else - print_label++; -} -#else -#define parse_e2label_options(x,y) -#endif - -static time_t parse_time(char *str) -{ - struct tm ts; - - if (strcmp(str, "now") == 0) { - return time(0); - } - memset(&ts, 0, sizeof(ts)); -#ifdef HAVE_STRPTIME - strptime(str, "%Y%m%d%H%M%S", &ts); -#else - sscanf(str, "%4d%2d%2d%2d%2d%2d", &ts.tm_year, &ts.tm_mon, - &ts.tm_mday, &ts.tm_hour, &ts.tm_min, &ts.tm_sec); - ts.tm_year -= 1900; - ts.tm_mon -= 1; - if (ts.tm_year < 0 || ts.tm_mon < 0 || ts.tm_mon > 11 || - ts.tm_mday < 0 || ts.tm_mday > 31 || ts.tm_hour > 23 || - ts.tm_min > 59 || ts.tm_sec > 61) - ts.tm_mday = 0; -#endif - if (ts.tm_mday == 0) { - bb_error_msg_and_die("can't parse date/time specifier: %s", str); - } - return mktime(&ts); -} - -static void parse_tune2fs_options(int argc, char **argv) -{ - int c; - char * tmp; - - printf("tune2fs %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE); - while ((c = getopt(argc, argv, "c:e:fg:i:jlm:o:r:s:u:C:J:L:M:O:T:U:")) != EOF) - switch (c) - { - case 'c': - max_mount_count = xatou_range(optarg, 0, 16000); - if (max_mount_count == 0) - max_mount_count = -1; - c_flag = 1; - open_flag = EXT2_FLAG_RW; - break; - case 'C': - mount_count = xatou_range(optarg, 0, 16000); - C_flag = 1; - open_flag = EXT2_FLAG_RW; - break; - case 'e': - if (strcmp (optarg, "continue") == 0) - errors = EXT2_ERRORS_CONTINUE; - else if (strcmp (optarg, "remount-ro") == 0) - errors = EXT2_ERRORS_RO; - else if (strcmp (optarg, "panic") == 0) - errors = EXT2_ERRORS_PANIC; - else { - bb_error_msg_and_die("bad error behavior - %s", optarg); - } - e_flag = 1; - open_flag = EXT2_FLAG_RW; - break; - case 'f': /* Force */ - f_flag = 1; - break; - case 'g': - resgid = bb_strtoul(optarg, NULL, 10); - if (errno) - resgid = xgroup2gid(optarg); - g_flag = 1; - open_flag = EXT2_FLAG_RW; - break; - case 'i': - interval = strtoul(optarg, &tmp, 0); - switch (*tmp) { - case 's': - tmp++; - break; - case '\0': - case 'd': - case 'D': /* days */ - interval *= 86400; - if (*tmp != '\0') - tmp++; - break; - case 'm': - case 'M': /* months! */ - interval *= 86400 * 30; - tmp++; - break; - case 'w': - case 'W': /* weeks */ - interval *= 86400 * 7; - tmp++; - break; - } - if (*tmp || interval > (365 * 86400)) { - bb_error_msg_and_die("bad interval - %s", optarg); - } - i_flag = 1; - open_flag = EXT2_FLAG_RW; - break; - case 'j': - if (!journal_size) - journal_size = -1; - open_flag = EXT2_FLAG_RW; - break; - case 'J': - parse_journal_opts(&journal_device, &journal_flags, &journal_size, optarg); - open_flag = EXT2_FLAG_RW; - break; - case 'l': - l_flag = 1; - break; - case 'L': - new_label = optarg; - L_flag = 1; - open_flag = EXT2_FLAG_RW | - EXT2_FLAG_JOURNAL_DEV_OK; - break; - case 'm': - reserved_ratio = xatou_range(optarg, 0, 50); - m_flag = 1; - open_flag = EXT2_FLAG_RW; - break; - case 'M': - new_last_mounted = optarg; - M_flag = 1; - open_flag = EXT2_FLAG_RW; - break; - case 'o': - if (mntopts_cmd) { - bb_error_msg_and_die("-o may only be specified once"); - } - mntopts_cmd = optarg; - open_flag = EXT2_FLAG_RW; - break; - - case 'O': - if (features_cmd) { - bb_error_msg_and_die("-O may only be specified once"); - } - features_cmd = optarg; - open_flag = EXT2_FLAG_RW; - break; - case 'r': - reserved_blocks = xatoul(optarg); - r_flag = 1; - open_flag = EXT2_FLAG_RW; - break; - case 's': - s_flag = atoi(optarg); - open_flag = EXT2_FLAG_RW; - break; - case 'T': - T_flag = 1; - last_check_time = parse_time(optarg); - open_flag = EXT2_FLAG_RW; - break; - case 'u': - resuid = bb_strtoul(optarg, NULL, 10); - if (errno) - resuid = xuname2uid(optarg); - u_flag = 1; - open_flag = EXT2_FLAG_RW; - break; - case 'U': - new_UUID = optarg; - U_flag = 1; - open_flag = EXT2_FLAG_RW | - EXT2_FLAG_JOURNAL_DEV_OK; - break; - default: - bb_show_usage(); - } - if (optind < argc - 1 || optind == argc) - bb_show_usage(); - if (!open_flag && !l_flag) - bb_show_usage(); - io_options = strchr(argv[optind], '?'); - if (io_options) - *io_options++ = 0; - device_name = x_blkid_get_devname(argv[optind]); -} - -static void tune2fs_clean_up(void) -{ - if (ENABLE_FEATURE_CLEAN_UP && device_name) free(device_name); - if (ENABLE_FEATURE_CLEAN_UP && journal_device) free(journal_device); -} - -int tune2fs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -int tune2fs_main(int argc, char **argv) -{ - errcode_t retval; - ext2_filsys fs; - struct ext2_super_block *sb; - io_manager io_ptr; - - if (ENABLE_FEATURE_CLEAN_UP) - atexit(tune2fs_clean_up); - - if (ENABLE_E2LABEL && (applet_name[0] == 'e')) /* e2label */ - parse_e2label_options(argc, argv); - else - parse_tune2fs_options(argc, argv); /* tune2fs */ - - io_ptr = unix_io_manager; - retval = ext2fs_open2(device_name, io_options, open_flag, - 0, 0, io_ptr, &fs); - if (retval) - bb_error_msg_and_die("No valid superblock on %s", device_name); - sb = fs->super; - if (print_label) { - /* For e2label emulation */ - printf("%.*s\n", (int) sizeof(sb->s_volume_name), - sb->s_volume_name); - return 0; - } - retval = ext2fs_check_if_mounted(device_name, &mount_flags); - if (retval) - bb_error_msg_and_die("can't determine if %s is mounted", device_name); - /* Normally we only need to write out the superblock */ - fs->flags |= EXT2_FLAG_SUPER_ONLY; - - if (c_flag) { - sb->s_max_mnt_count = max_mount_count; - ext2fs_mark_super_dirty(fs); - printf("Setting maximal mount count to %d\n", max_mount_count); - } - if (C_flag) { - sb->s_mnt_count = mount_count; - ext2fs_mark_super_dirty(fs); - printf("Setting current mount count to %d\n", mount_count); - } - if (e_flag) { - sb->s_errors = errors; - ext2fs_mark_super_dirty(fs); - printf("Setting error behavior to %u\n", errors); - } - if (g_flag) { - sb->s_def_resgid = resgid; - ext2fs_mark_super_dirty(fs); - printf("Setting reserved blocks gid to %lu\n", resgid); - } - if (i_flag) { - sb->s_checkinterval = interval; - ext2fs_mark_super_dirty(fs); - printf("Setting interval between check %lu seconds\n", interval); - } - if (m_flag) { - sb->s_r_blocks_count = (sb->s_blocks_count / 100) - * reserved_ratio; - ext2fs_mark_super_dirty(fs); - printf("Setting reserved blocks percentage to %u (%u blocks)\n", - reserved_ratio, sb->s_r_blocks_count); - } - if (r_flag) { - if (reserved_blocks >= sb->s_blocks_count/2) - bb_error_msg_and_die("reserved blocks count is too big (%lu)", reserved_blocks); - sb->s_r_blocks_count = reserved_blocks; - ext2fs_mark_super_dirty(fs); - printf("Setting reserved blocks count to %lu\n", reserved_blocks); - } - if (s_flag == 1) { - if (sb->s_feature_ro_compat & - EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) - bb_error_msg("\nThe filesystem already has sparse superblocks"); - else { - sb->s_feature_ro_compat |= - EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; - sb->s_state &= ~EXT2_VALID_FS; - ext2fs_mark_super_dirty(fs); - printf("\nSparse superblock flag set. %s", please_fsck); - } - } - if (s_flag == 0) { - if (!(sb->s_feature_ro_compat & - EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)) - bb_error_msg("\nThe filesystem already has sparse superblocks disabled"); - else { - sb->s_feature_ro_compat &= - ~EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; - sb->s_state &= ~EXT2_VALID_FS; - fs->flags |= EXT2_FLAG_MASTER_SB_ONLY; - ext2fs_mark_super_dirty(fs); - printf("\nSparse superblock flag cleared. %s", please_fsck); - } - } - if (T_flag) { - sb->s_lastcheck = last_check_time; - ext2fs_mark_super_dirty(fs); - printf("Setting time filesystem last checked to %s\n", - ctime(&last_check_time)); - } - if (u_flag) { - sb->s_def_resuid = resuid; - ext2fs_mark_super_dirty(fs); - printf("Setting reserved blocks uid to %lu\n", resuid); - } - if (L_flag) { - if (strlen(new_label) > sizeof(sb->s_volume_name)) - bb_error_msg("Warning: label too long, truncating"); - memset(sb->s_volume_name, 0, sizeof(sb->s_volume_name)); - safe_strncpy(sb->s_volume_name, new_label, - sizeof(sb->s_volume_name)); - ext2fs_mark_super_dirty(fs); - } - if (M_flag) { - memset(sb->s_last_mounted, 0, sizeof(sb->s_last_mounted)); - safe_strncpy(sb->s_last_mounted, new_last_mounted, - sizeof(sb->s_last_mounted)); - ext2fs_mark_super_dirty(fs); - } - if (mntopts_cmd) - update_mntopts(fs, mntopts_cmd); - if (features_cmd) - update_feature_set(fs, features_cmd); - if (journal_size || journal_device) - add_journal(fs); - - if (U_flag) { - if ((strcasecmp(new_UUID, "null") == 0) || - (strcasecmp(new_UUID, "clear") == 0)) { - uuid_clear(sb->s_uuid); - } else if (strcasecmp(new_UUID, "time") == 0) { - uuid_generate_time(sb->s_uuid); - } else if (strcasecmp(new_UUID, "random") == 0) { - uuid_generate(sb->s_uuid); - } else if (uuid_parse(new_UUID, sb->s_uuid)) { - bb_error_msg_and_die("Invalid UUID format"); - } - ext2fs_mark_super_dirty(fs); - } - - if (l_flag) - list_super (sb); - return (ext2fs_close (fs) ? 1 : 0); -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * util.c --- helper functions used by tune2fs and mke2fs - * - * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o. - * - * Licensed under GPLv2, see file LICENSE in this source tree. - */ - -#include -#include -#include -#include -#include - -#include "e2fsbb.h" -#include "e2p/e2p.h" -#include "ext2fs/ext2_fs.h" -#include "ext2fs/ext2fs.h" -#include "blkid/blkid.h" -#include "util.h" - -void proceed_question(void) -{ - fputs("Proceed anyway? (y,n) ", stdout); - if (bb_ask_confirmation() == 0) - exit(1); -} - -void check_plausibility(const char *device, int force) -{ - int val; - struct stat s; - val = stat(device, &s); - if (force) - return; - if (val == -1) - bb_perror_msg_and_die("can't stat '%s'", device); - if (!S_ISBLK(s.st_mode)) { - printf("%s is not a block special device.\n", device); - proceed_question(); - return; - } - -#ifdef HAVE_LINUX_MAJOR_H -#ifndef MAJOR -#define MAJOR(dev) ((dev)>>8) -#define MINOR(dev) ((dev) & 0xff) -#endif -#ifndef SCSI_BLK_MAJOR -#ifdef SCSI_DISK0_MAJOR -#ifdef SCSI_DISK8_MAJOR -#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \ - ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR) || \ - ((M) >= SCSI_DISK8_MAJOR && (M) <= SCSI_DISK15_MAJOR)) -#else -#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \ - ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR)) -#endif /* defined(SCSI_DISK8_MAJOR) */ -#define SCSI_BLK_MAJOR(M) (SCSI_DISK_MAJOR((M)) || (M) == SCSI_CDROM_MAJOR) -#else -#define SCSI_BLK_MAJOR(M) ((M) == SCSI_DISK_MAJOR || (M) == SCSI_CDROM_MAJOR) -#endif /* defined(SCSI_DISK0_MAJOR) */ -#endif /* defined(SCSI_BLK_MAJOR) */ - if (((MAJOR(s.st_rdev) == HD_MAJOR && - MINOR(s.st_rdev)%64 == 0) || - (SCSI_BLK_MAJOR(MAJOR(s.st_rdev)) && - MINOR(s.st_rdev)%16 == 0))) { - printf("%s is entire device, not just one partition!\n", device); - proceed_question(); - } -#endif -} - -void check_mount(const char *device, int force, const char *type) -{ - errcode_t retval; - int mount_flags; - - retval = ext2fs_check_if_mounted(device, &mount_flags); - if (retval) { - bb_error_msg("can't determine if %s is mounted", device); - return; - } - if (mount_flags & EXT2_MF_MOUNTED) { - bb_error_msg("%s is mounted !", device); -force_check: - if (force) - bb_error_msg("badblocks forced anyways"); - else - bb_error_msg_and_die("it's not safe to run badblocks!"); - } - - if (mount_flags & EXT2_MF_BUSY) { - bb_error_msg("%s is apparently in use by the system", device); - goto force_check; - } -} - -void parse_journal_opts(char **journal_device, int *journal_flags, - int *journal_size, const char *opts) -{ - char *buf, *token, *next, *p, *arg; - int journal_usage = 0; - buf = xstrdup(opts); - for (token = buf; token && *token; token = next) { - p = strchr(token, ','); - next = 0; - if (p) { - *p = 0; - next = p+1; - } - arg = strchr(token, '='); - if (arg) { - *arg = 0; - arg++; - } - if (strcmp(token, "device") == 0) { - *journal_device = blkid_get_devname(NULL, arg, NULL); - if (!*journal_device) { - journal_usage++; - continue; - } - } else if (strcmp(token, "size") == 0) { - if (!arg) { - journal_usage++; - continue; - } - (*journal_size) = strtoul(arg, &p, 0); - if (*p) - journal_usage++; - } else if (strcmp(token, "v1_superblock") == 0) { - (*journal_flags) |= EXT2_MKJOURNAL_V1_SUPER; - continue; - } else - journal_usage++; - } - if (journal_usage) - bb_error_msg_and_die( - "\nBad journal options specified.\n\n" - "Journal options are separated by commas, " - "and may take an argument which\n" - "\tis set off by an equals ('=') sign.\n\n" - "Valid journal options are:\n" - "\tsize=\n" - "\tdevice=\n\n" - "The journal size must be between " - "1024 and 102400 filesystem blocks.\n\n"); -} - -/* - * Determine the number of journal blocks to use, either via - * user-specified # of megabytes, or via some intelligently selected - * defaults. - * - * Find a reasonable journal file size (in blocks) given the number of blocks - * in the filesystem. For very small filesystems, it is not reasonable to - * have a journal that fills more than half of the filesystem. - */ -int figure_journal_size(int size, ext2_filsys fs) -{ - blk_t j_blocks; - - if (fs->super->s_blocks_count < 2048) { - bb_error_msg("Filesystem too small for a journal"); - return 0; - } - - if (size >= 0) { - j_blocks = size * 1024 / (fs->blocksize / 1024); - if (j_blocks < 1024 || j_blocks > 102400) - bb_error_msg_and_die("\nThe requested journal " - "size is %d blocks;\n it must be " - "between 1024 and 102400 blocks; Aborting", - j_blocks); - if (j_blocks > fs->super->s_free_blocks_count) - bb_error_msg_and_die("Journal size too big for filesystem"); - return j_blocks; - } - - if (fs->super->s_blocks_count < 32768) - j_blocks = 1024; - else if (fs->super->s_blocks_count < 256*1024) - j_blocks = 4096; - else if (fs->super->s_blocks_count < 512*1024) - j_blocks = 8192; - else if (fs->super->s_blocks_count < 1024*1024) - j_blocks = 16384; - else - j_blocks = 32768; - - return j_blocks; -} - -void print_check_message(ext2_filsys fs) -{ - printf("This filesystem will be automatically " - "checked every %d mounts or\n" - "%g days, whichever comes first. " - "Use tune2fs -c or -i to override.\n", - fs->super->s_max_mnt_count, - (double)fs->super->s_checkinterval / (3600 * 24)); -} - -void make_journal_device(char *journal_device, ext2_filsys fs, int quiet, int force) -{ - errcode_t retval; - ext2_filsys jfs; - io_manager io_ptr; - - check_plausibility(journal_device, force); - check_mount(journal_device, force, "journal"); - io_ptr = unix_io_manager; - retval = ext2fs_open(journal_device, EXT2_FLAG_RW| - EXT2_FLAG_JOURNAL_DEV_OK, 0, - fs->blocksize, io_ptr, &jfs); - if (retval) - bb_error_msg_and_die("can't journal device %s", journal_device); - if (!quiet) - printf("Adding journal to device %s: ", journal_device); - fflush(stdout); - retval = ext2fs_add_journal_device(fs, jfs); - if (retval) - bb_error_msg_and_die("\nFailed to add journal to device %s", journal_device); - if (!quiet) - puts("done"); - ext2fs_close(jfs); -} - -void make_journal_blocks(ext2_filsys fs, int journal_size, int journal_flags, int quiet) -{ - unsigned long journal_blocks; - errcode_t retval; - - journal_blocks = figure_journal_size(journal_size, fs); - if (!journal_blocks) { - fs->super->s_feature_compat &= - ~EXT3_FEATURE_COMPAT_HAS_JOURNAL; - return; - } - if (!quiet) - printf("Creating journal (%lu blocks): ", journal_blocks); - fflush(stdout); - retval = ext2fs_add_journal_inode(fs, journal_blocks, - journal_flags); - if (retval) - bb_error_msg_and_die("can't create journal"); - if (!quiet) - puts("done"); -} - -char *e2fs_set_sbin_path(void) -{ - char *oldpath = getenv("PATH"); - /* Update our PATH to include /sbin */ -#define PATH_SET "/sbin" - if (oldpath) - oldpath = xasprintf("%s:%s", PATH_SET, oldpath); - else - oldpath = PATH_SET; - putenv(oldpath); - return oldpath; -} 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 @@ -/* vi: set sw=4 ts=4: */ -/* - * util.h --- header file defining prototypes for helper functions - * used by tune2fs and mke2fs - * - * Copyright 2000 by Theodore Ts'o. - * - * %Begin-Header% - * This file may be redistributed under the terms of the GNU Public - * License. - * %End-Header% - */ - -extern void proceed_question(void); -extern void check_plausibility(const char *device, int force); -extern void parse_journal_opts(char **, int *, int *, const char *opts); -extern void check_mount(const char *device, int force, const char *type); -extern int figure_journal_size(int size, ext2_filsys fs); -extern void print_check_message(ext2_filsys fs); -extern void make_journal_device(char *journal_device, ext2_filsys fs, int quiet, int force); -extern void make_journal_blocks(ext2_filsys fs, int journal_size, int journal_flags, int quiet); -extern char *e2fs_set_sbin_path(void); diff --git a/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 @@ -# Makefile for busybox -# -# Copyright (C) 1999-2005 by Erik Andersen -# -# Licensed under GPLv2, see file LICENSE in this source tree. - -NEEDED-$(CONFIG_E2FSCK) = y -NEEDED-$(CONFIG_FSCK) = y -NEEDED-$(CONFIG_MKE2FS) = y -NEEDED-$(CONFIG_TUNE2FS) = y - -lib-y:= - -INSERT -lib-$(NEEDED-y) += compare.o gen_uuid.o pack.o parse.o unpack.o unparse.o \ - uuid_time.o diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * compare.c --- compare whether or not two UUID's are the same - * - * Returns 0 if the two UUID's are different, and 1 if they are the same. - * - * Copyright (C) 1996, 1997 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ - -#include "uuidP.h" -#include - -#define UUCMP(u1,u2) if (u1 != u2) return (u1 < u2) ? -1 : 1; - -int uuid_compare(const uuid_t uu1, const uuid_t uu2) -{ - struct uuid uuid1, uuid2; - - uuid_unpack(uu1, &uuid1); - uuid_unpack(uu2, &uuid2); - - UUCMP(uuid1.time_low, uuid2.time_low); - UUCMP(uuid1.time_mid, uuid2.time_mid); - UUCMP(uuid1.time_hi_and_version, uuid2.time_hi_and_version); - UUCMP(uuid1.clock_seq, uuid2.clock_seq); - return memcmp(uuid1.node, uuid2.node, 6); -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * gen_uuid.c --- generate a DCE-compatible uuid - * - * Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_SYS_IOCTL_H -#include -#endif -#include -#ifdef HAVE_SYS_SOCKIO_H -#include -#endif -#ifdef HAVE_NET_IF_H -#include -#endif -#ifdef HAVE_NETINET_IN_H -#include -#endif -#ifdef HAVE_NET_IF_DL_H -#include -#endif - -#include "uuidP.h" - -#ifdef HAVE_SRANDOM -#define srand(x) srandom(x) -#define rand() random() -#endif - -static int get_random_fd(void) -{ - struct timeval tv; - static int fd = -2; - int i; - - if (fd == -2) { - gettimeofday(&tv, 0); - fd = open("/dev/urandom", O_RDONLY); - if (fd == -1) - fd = open("/dev/random", O_RDONLY | O_NONBLOCK); - srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec); - } - /* Crank the random number generator a few times */ - gettimeofday(&tv, 0); - for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--) - rand(); - return fd; -} - - -/* - * Generate a series of random bytes. Use /dev/urandom if possible, - * and if not, use srandom/random. - */ -static void get_random_bytes(void *buf, int nbytes) -{ - int i, n = nbytes, fd = get_random_fd(); - int lose_counter = 0; - unsigned char *cp = (unsigned char *) buf; - - if (fd >= 0) { - while (n > 0) { - i = read(fd, cp, n); - if (i <= 0) { - if (lose_counter++ > 16) - break; - continue; - } - n -= i; - cp += i; - lose_counter = 0; - } - } - - /* - * We do this all the time, but this is the only source of - * randomness if /dev/random/urandom is out to lunch. - */ - for (cp = buf, i = 0; i < nbytes; i++) - *cp++ ^= (rand() >> 7) & 0xFF; -} - -/* - * Get the ethernet hardware address, if we can find it... - */ -static int get_node_id(unsigned char *node_id) -{ -#ifdef HAVE_NET_IF_H - int sd; - struct ifreq ifr, *ifrp; - struct ifconf ifc; - char buf[1024]; - int n, i; - unsigned char *a; -#ifdef HAVE_NET_IF_DL_H - struct sockaddr_dl *sdlp; -#endif - -/* - * BSD 4.4 defines the size of an ifreq to be - * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len - * However, under earlier systems, sa_len isn't present, so the size is - * just sizeof(struct ifreq) - */ -#ifdef HAVE_SA_LEN -#ifndef max -#define max(a,b) ((a) > (b) ? (a) : (b)) -#endif -#define ifreq_size(i) max(sizeof(struct ifreq),\ - sizeof((i).ifr_name)+(i).ifr_addr.sa_len) -#else -#define ifreq_size(i) sizeof(struct ifreq) -#endif /* HAVE_SA_LEN*/ - - sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); - if (sd < 0) { - return -1; - } - memset(buf, 0, sizeof(buf)); - ifc.ifc_len = sizeof(buf); - ifc.ifc_buf = buf; - if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) { - close(sd); - return -1; - } - n = ifc.ifc_len; - for (i = 0; i < n; i+= ifreq_size(*ifrp) ) { - ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i); - strncpy_IFNAMSIZ(ifr.ifr_name, ifrp->ifr_name); -#ifdef SIOCGIFHWADDR - if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0) - continue; - a = (unsigned char *) &ifr.ifr_hwaddr.sa_data; -#else -#ifdef SIOCGENADDR - if (ioctl(sd, SIOCGENADDR, &ifr) < 0) - continue; - a = (unsigned char *) ifr.ifr_enaddr; -#else -#ifdef HAVE_NET_IF_DL_H - sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr; - if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6)) - continue; - a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen]; -#else - /* - * XXX we don't have a way of getting the hardware - * address - */ - close(sd); - return 0; -#endif /* HAVE_NET_IF_DL_H */ -#endif /* SIOCGENADDR */ -#endif /* SIOCGIFHWADDR */ - if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) - continue; - if (node_id) { - memcpy(node_id, a, 6); - close(sd); - return 1; - } - } - close(sd); -#endif - return 0; -} - -/* Assume that the gettimeofday() has microsecond granularity */ -#define MAX_ADJUSTMENT 10 - -static int get_clock(uint32_t *clock_high, uint32_t *clock_low, uint16_t *ret_clock_seq) -{ - static int adjustment = 0; - static struct timeval last = {0, 0}; - static uint16_t clock_seq; - struct timeval tv; - unsigned long long clock_reg; - -try_again: - gettimeofday(&tv, 0); - if ((last.tv_sec == 0) && (last.tv_usec == 0)) { - get_random_bytes(&clock_seq, sizeof(clock_seq)); - clock_seq &= 0x3FFF; - last = tv; - last.tv_sec--; - } - if ((tv.tv_sec < last.tv_sec) || - ((tv.tv_sec == last.tv_sec) && - (tv.tv_usec < last.tv_usec))) { - clock_seq = (clock_seq+1) & 0x3FFF; - adjustment = 0; - last = tv; - } else if ((tv.tv_sec == last.tv_sec) && - (tv.tv_usec == last.tv_usec)) { - if (adjustment >= MAX_ADJUSTMENT) - goto try_again; - adjustment++; - } else { - adjustment = 0; - last = tv; - } - - clock_reg = tv.tv_usec*10 + adjustment; - clock_reg += ((unsigned long long) tv.tv_sec)*10000000; - clock_reg += (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000; - - *clock_high = clock_reg >> 32; - *clock_low = clock_reg; - *ret_clock_seq = clock_seq; - return 0; -} - -void uuid_generate_time(uuid_t out) -{ - static unsigned char node_id[6]; - static int has_init = 0; - struct uuid uu; - uint32_t clock_mid; - - if (!has_init) { - if (get_node_id(node_id) <= 0) { - get_random_bytes(node_id, 6); - /* - * Set multicast bit, to prevent conflicts - * with IEEE 802 addresses obtained from - * network cards - */ - node_id[0] |= 0x01; - } - has_init = 1; - } - get_clock(&clock_mid, &uu.time_low, &uu.clock_seq); - uu.clock_seq |= 0x8000; - uu.time_mid = (uint16_t) clock_mid; - uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000; - memcpy(uu.node, node_id, 6); - uuid_pack(&uu, out); -} - -void uuid_generate_random(uuid_t out) -{ - uuid_t buf; - struct uuid uu; - - get_random_bytes(buf, sizeof(buf)); - uuid_unpack(buf, &uu); - - uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000; - uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000; - uuid_pack(&uu, out); -} - -/* - * This is the generic front-end to uuid_generate_random and - * uuid_generate_time. It uses uuid_generate_random only if - * /dev/urandom is available, since otherwise we won't have - * high-quality randomness. - */ -void uuid_generate(uuid_t out) -{ - if (get_random_fd() >= 0) - uuid_generate_random(out); - else - uuid_generate_time(out); -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * Internal routine for packing UUID's - * - * Copyright (C) 1996, 1997 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ - -#include -#include "uuidP.h" - -void uuid_pack(const struct uuid *uu, uuid_t ptr) -{ - uint32_t tmp; - unsigned char *out = ptr; - - tmp = uu->time_low; - out[3] = (unsigned char) tmp; - tmp >>= 8; - out[2] = (unsigned char) tmp; - tmp >>= 8; - out[1] = (unsigned char) tmp; - tmp >>= 8; - out[0] = (unsigned char) tmp; - - tmp = uu->time_mid; - out[5] = (unsigned char) tmp; - tmp >>= 8; - out[4] = (unsigned char) tmp; - - tmp = uu->time_hi_and_version; - out[7] = (unsigned char) tmp; - tmp >>= 8; - out[6] = (unsigned char) tmp; - - tmp = uu->clock_seq; - out[9] = (unsigned char) tmp; - tmp >>= 8; - out[8] = (unsigned char) tmp; - - memcpy(out+10, uu->node, 6); -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * parse.c --- UUID parsing - * - * Copyright (C) 1996, 1997 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ - -#include -#include -#include -#include - -#include "uuidP.h" - -int uuid_parse(const char *in, uuid_t uu) -{ - struct uuid uuid; - int i; - const char *cp; - char buf[3]; - - if (strlen(in) != 36) - return -1; - for (i=0, cp = in; i <= 36; i++,cp++) { - if ((i == 8) || (i == 13) || (i == 18) || - (i == 23)) { - if (*cp == '-') - continue; - else - return -1; - } - if (i== 36) - if (*cp == 0) - continue; - if (!isxdigit(*cp)) - return -1; - } - uuid.time_low = strtoul(in, NULL, 16); - uuid.time_mid = strtoul(in+9, NULL, 16); - uuid.time_hi_and_version = strtoul(in+14, NULL, 16); - uuid.clock_seq = strtoul(in+19, NULL, 16); - cp = in+24; - buf[2] = 0; - for (i=0; i < 6; i++) { - buf[0] = *cp++; - buf[1] = *cp++; - uuid.node[i] = strtoul(buf, NULL, 16); - } - - uuid_pack(&uuid, uu); - return 0; -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * Internal routine for unpacking UUID - * - * Copyright (C) 1996, 1997 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ - -#include -#include "uuidP.h" - -void uuid_unpack(const uuid_t in, struct uuid *uu) -{ - const uint8_t *ptr = in; - uint32_t tmp; - - tmp = *ptr++; - tmp = (tmp << 8) | *ptr++; - tmp = (tmp << 8) | *ptr++; - tmp = (tmp << 8) | *ptr++; - uu->time_low = tmp; - - tmp = *ptr++; - tmp = (tmp << 8) | *ptr++; - uu->time_mid = tmp; - - tmp = *ptr++; - tmp = (tmp << 8) | *ptr++; - uu->time_hi_and_version = tmp; - - tmp = *ptr++; - tmp = (tmp << 8) | *ptr++; - uu->clock_seq = tmp; - - memcpy(uu->node, ptr, 6); -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * unparse.c -- convert a UUID to string - * - * Copyright (C) 1996, 1997 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ - -#include - -#include "uuidP.h" - -static const char *fmt_lower = - "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"; - -static const char *fmt_upper = - "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"; - -#ifdef UUID_UNPARSE_DEFAULT_UPPER -#define FMT_DEFAULT fmt_upper -#else -#define FMT_DEFAULT fmt_lower -#endif - -static void uuid_unparse_x(const uuid_t uu, char *out, const char *fmt) -{ - struct uuid uuid; - - uuid_unpack(uu, &uuid); - sprintf(out, fmt, - uuid.time_low, uuid.time_mid, uuid.time_hi_and_version, - uuid.clock_seq >> 8, uuid.clock_seq & 0xFF, - uuid.node[0], uuid.node[1], uuid.node[2], - uuid.node[3], uuid.node[4], uuid.node[5]); -} - -void uuid_unparse_lower(const uuid_t uu, char *out) -{ - uuid_unparse_x(uu, out, fmt_lower); -} - -void uuid_unparse_upper(const uuid_t uu, char *out) -{ - uuid_unparse_x(uu, out, fmt_upper); -} - -void uuid_unparse(const uuid_t uu, char *out) -{ - uuid_unparse_x(uu, out, FMT_DEFAULT); -} diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * Public include file for the UUID library - * - * Copyright (C) 1996, 1997, 1998 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ -#ifndef UUID_UUID_H -#define UUID_UUID_H 1 - -#include -#include - -typedef unsigned char uuid_t[16]; - -/* UUID Variant definitions */ -#define UUID_VARIANT_NCS 0 -#define UUID_VARIANT_DCE 1 -#define UUID_VARIANT_MICROSOFT 2 -#define UUID_VARIANT_OTHER 3 - -/* UUID Type definitions */ -#define UUID_TYPE_DCE_TIME 1 -#define UUID_TYPE_DCE_RANDOM 4 - -/* Allow UUID constants to be defined */ -#ifdef __GNUC__ -#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \ - static const uuid_t name UNUSED_PARAM = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15} -#else -#define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \ - static const uuid_t name = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15} -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* clear.c */ -/*void uuid_clear(uuid_t uu);*/ -#define uuid_clear(uu) memset(uu, 0, sizeof(uu)) - -/* compare.c */ -int uuid_compare(const uuid_t uu1, const uuid_t uu2); - -/* copy.c */ -/*void uuid_copy(uuid_t dst, const uuid_t src);*/ -#define uuid_copy(dst,src) memcpy(dst, src, sizeof(dst)) - -/* gen_uuid.c */ -void uuid_generate(uuid_t out); -void uuid_generate_random(uuid_t out); -void uuid_generate_time(uuid_t out); - -/* isnull.c */ -/*int uuid_is_null(const uuid_t uu);*/ -#define uuid_is_null(uu) (!memcmp(uu, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", sizeof(uu))) - -/* parse.c */ -int uuid_parse(const char *in, uuid_t uu); - -/* unparse.c */ -void uuid_unparse(const uuid_t uu, char *out); -void uuid_unparse_lower(const uuid_t uu, char *out); -void uuid_unparse_upper(const uuid_t uu, char *out); - -/* uuid_time.c */ -time_t uuid_time(const uuid_t uu, struct timeval *ret_tv); -int uuid_type(const uuid_t uu); -int uuid_variant(const uuid_t uu); - -#ifdef __cplusplus -} -#endif - -#endif /* _UUID_UUID_H */ diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * uuid.h -- private header file for uuids - * - * Copyright (C) 1996, 1997 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ - -#include -#include - -#include "uuid.h" - -/* - * Offset between 15-Oct-1582 and 1-Jan-70 - */ -#define TIME_OFFSET_HIGH 0x01B21DD2 -#define TIME_OFFSET_LOW 0x13814000 - -struct uuid { - uint32_t time_low; - uint16_t time_mid; - uint16_t time_hi_and_version; - uint16_t clock_seq; - uint8_t node[6]; -}; - - -/* - * prototypes - */ -void uuid_pack(const struct uuid *uu, uuid_t ptr); -void uuid_unpack(const uuid_t in, struct uuid *uu); diff --git a/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 @@ -/* vi: set sw=4 ts=4: */ -/* - * uuid_time.c --- Interpret the time field from a uuid. This program - * violates the UUID abstraction barrier by reaching into the guts - * of a UUID and interpreting it. - * - * Copyright (C) 1998, 1999 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ - -#include -#include -#include -#include -#include - -#include "uuidP.h" - -time_t uuid_time(const uuid_t uu, struct timeval *ret_tv) -{ - struct uuid uuid; - uint32_t high; - struct timeval tv; - unsigned long long clock_reg; - - uuid_unpack(uu, &uuid); - - high = uuid.time_mid | ((uuid.time_hi_and_version & 0xFFF) << 16); - clock_reg = uuid.time_low | ((unsigned long long) high << 32); - - clock_reg -= (((unsigned long long) 0x01B21DD2) << 32) + 0x13814000; - tv.tv_sec = clock_reg / 10000000; - tv.tv_usec = (clock_reg % 10000000) / 10; - - if (ret_tv) - *ret_tv = tv; - - return tv.tv_sec; -} - -int uuid_type(const uuid_t uu) -{ - struct uuid uuid; - - uuid_unpack(uu, &uuid); - return ((uuid.time_hi_and_version >> 12) & 0xF); -} - -int uuid_variant(const uuid_t uu) -{ - struct uuid uuid; - int var; - - uuid_unpack(uu, &uuid); - var = uuid.clock_seq; - - if ((var & 0x8000) == 0) - return UUID_VARIANT_NCS; - if ((var & 0x4000) == 0) - return UUID_VARIANT_DCE; - if ((var & 0x2000) == 0) - return UUID_VARIANT_MICROSOFT; - return UUID_VARIANT_OTHER; -} - -#ifdef DEBUG -static const char *variant_string(int variant) -{ - switch (variant) { - case UUID_VARIANT_NCS: - return "NCS"; - case UUID_VARIANT_DCE: - return "DCE"; - case UUID_VARIANT_MICROSOFT: - return "Microsoft"; - default: - return "Other"; - } -} - - -int -main(int argc, char **argv) -{ - uuid_t buf; - time_t time_reg; - struct timeval tv; - int type, variant; - - if (argc != 2) { - fprintf(stderr, "Usage: %s uuid\n", argv[0]); - exit(1); - } - if (uuid_parse(argv[1], buf)) { - fprintf(stderr, "Invalid UUID: %s\n", argv[1]); - exit(1); - } - variant = uuid_variant(buf); - type = uuid_type(buf); - time_reg = uuid_time(buf, &tv); - - printf("UUID variant is %d (%s)\n", variant, variant_string(variant)); - if (variant != UUID_VARIANT_DCE) { - printf("Warning: This program only knows how to interpret " - "DCE UUIDs.\n\tThe rest of the output is likely " - "to be incorrect!!\n"); - } - printf("UUID type is %d", type); - switch (type) { - case 1: - printf(" (time based)\n"); - break; - case 2: - printf(" (DCE)\n"); - break; - case 3: - printf(" (name-based)\n"); - break; - case 4: - printf(" (random)\n"); - break; - default: - bb_putchar('\n'); - } - if (type != 1) { - printf("Warning: not a time-based UUID, so UUID time " - "decoding will likely not work!\n"); - } - printf("UUID time is: (%ld, %ld): %s\n", tv.tv_sec, tv.tv_usec, - ctime(&time_reg)); - - return 0; -} -#endif From 35ae2ccb40924efcd0fd0c873cc9e56c58851222 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 21 Jul 2015 19:50:48 +0200 Subject: [PATCH 166/256] sync: add support for -d -f FILE Based on the patch by Ari Sundholm function old new delta sync_main 20 163 +143 packed_usage 30653 30673 +20 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 163/0) Total: 163 bytes Signed-off-by: Denys Vlasenko --- coreutils/Config.src | 6 ---- coreutils/Kbuild.src | 1 - coreutils/sync.c | 78 +++++++++++++++++++++++++++++++++++++++++-- include/applets.src.h | 1 - 4 files changed, 75 insertions(+), 11 deletions(-) diff --git a/coreutils/Config.src b/coreutils/Config.src index 1ec3a0a99..02155d220 100644 --- a/coreutils/Config.src +++ b/coreutils/Config.src @@ -571,12 +571,6 @@ config SUM help checksum and count the blocks in a file -config SYNC - bool "sync" - default y - help - sync is used to flush filesystem buffers. - config TAC bool "tac" default y 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 lib-$(CONFIG_STAT) += stat.o lib-$(CONFIG_STTY) += stty.o lib-$(CONFIG_SUM) += sum.o -lib-$(CONFIG_SYNC) += sync.o lib-$(CONFIG_TAC) += tac.o lib-$(CONFIG_TEE) += tee.o lib-$(CONFIG_TRUE) += true.o 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 @@ * Mini sync implementation for busybox * * Copyright (C) 1995, 1996 by Bruce Perens . + * Copyright (C) 2015 by Ari Sundholm * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ /* BB_AUDIT SUSv3 N/A -- Matches GNU behavior. */ +//config:config SYNC +//config: bool "sync" +//config: default y +//config: help +//config: sync is used to flush filesystem buffers. +//config:config FEATURE_SYNC_FANCY +//config: bool "Enable -d and -f flags (requres syncfs(2) in libc)" +//config: default y +//config: depends on SYNC +//config: help +//config: sync -d FILE... executes fdatasync() on each FILE. +//config: sync -f FILE... executes syncfs() on each FILE. + +//kbuild:lib-$(CONFIG_SYNC) += sync.o +//applet:IF_SYNC(APPLET_NOFORK(sync, sync, BB_DIR_BIN, BB_SUID_DROP, sync)) //usage:#define sync_trivial_usage -//usage: "" +//usage: ""IF_FEATURE_SYNC_FANCY("[-df] [FILE]...") //usage:#define sync_full_usage "\n\n" +//usage: IF_NOT_FEATURE_SYNC_FANCY( //usage: "Write all buffered blocks to disk" +//usage: ) +//usage: IF_FEATURE_SYNC_FANCY( +//usage: "Write all buffered blocks (in FILEs) to disk" +//usage: "\n -d Avoid syncing metadata" +//usage: "\n -f Sync filesystems underlying FILEs" +//usage: ) #include "libbb.h" @@ -21,10 +44,59 @@ int sync_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int sync_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) { +#if !ENABLE_FEATURE_SYNC_FANCY /* coreutils-6.9 compat */ bb_warn_ignoring_args(argv[1]); - sync(); - return EXIT_SUCCESS; +#else + unsigned opts; + int ret = EXIT_SUCCESS; + + enum { + OPT_DATASYNC = (1 << 0), + OPT_SYNCFS = (1 << 1), + }; + + opt_complementary = "d--f:f--d"; + opts = getopt32(argv, "df"); + argv += optind; + + /* Handle the no-argument case. */ + if (!argv[0]) + sync(); + + while (*argv) { + int fd = open_or_warn(*argv, O_RDONLY); + + if (fd < 0) { + ret = EXIT_FAILURE; + goto next; + } + if (opts & OPT_DATASYNC) { + if (fdatasync(fd)) + goto err; + goto do_close; + } + if (opts & OPT_SYNCFS) { + /* + * syncfs is documented to only fail with EBADF, + * which can't happen here. So, no error checks. + */ + syncfs(fd); + goto do_close; + } + if (fsync(fd)) { + err: + bb_simple_perror_msg(*argv); + ret = EXIT_FAILURE; + } + do_close: + close(fd); + next: + ++argv; + } + + return ret; +#endif } diff --git a/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)) IF_SWAPONOFF(APPLET_ODDNAME(swapoff, swap_on_off, BB_DIR_SBIN, BB_SUID_DROP, swapoff)) IF_SWAPONOFF(APPLET_ODDNAME(swapon, swap_on_off, BB_DIR_SBIN, BB_SUID_DROP, swapon)) IF_SWITCH_ROOT(APPLET(switch_root, BB_DIR_SBIN, BB_SUID_DROP)) -IF_SYNC(APPLET_NOFORK(sync, sync, BB_DIR_BIN, BB_SUID_DROP, sync)) IF_BB_SYSCTL(APPLET(sysctl, BB_DIR_SBIN, BB_SUID_DROP)) IF_SYSLOGD(APPLET(syslogd, BB_DIR_SBIN, BB_SUID_DROP)) IF_TAC(APPLET_NOEXEC(tac, tac, BB_DIR_USR_BIN, BB_SUID_DROP, tac)) From 193ba408a4fd3313b1dc2eb5eb25885cfa4363f6 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Tue, 21 Jul 2015 22:28:09 +0200 Subject: [PATCH 167/256] less: improvements to verbose status messages Make verbose status messages (-m/-M flags) behave more like the real `less` command: - fix display of line numbers so they're correct whether lines are being truncated (-S flag) or wrapped. - don't display total lines or percentage when lines are read from stdin: we don't have that information until we reach EOF. When we do reach EOF the additional information is displayed. - when lines are read from a file count the total number of lines so that we can display percentages. Counting lines is avoided until the information is actually needed. If the user pages to EOF the separate read pass can be avoided entirely. Fixes Bug 7586 function old new delta m_status_print 195 382 +187 safe_lineno - 35 +35 reinitialize 172 182 +10 read_lines 675 685 +10 buffer_fill_and_print 178 169 -9 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 3/1 up/down: 242/-9) Total: 233 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- miscutils/less.c | 87 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 71 insertions(+), 16 deletions(-) diff --git a/miscutils/less.c b/miscutils/less.c index 90c103888..dd932c5ed 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -165,6 +165,11 @@ enum { enum { pattern_valid = 0 }; #endif +enum { + READING_FILE = -1, + READING_STDIN = -2 +}; + struct globals { int cur_fline; /* signed */ int kbd_fd; /* fd to get input from */ @@ -188,6 +193,9 @@ struct globals { unsigned current_file; char *filename; char **files; +#if ENABLE_FEATURE_LESS_FLAGS + int num_lines; /* input source if < 0, line count if >= 0 */ +#endif #if ENABLE_FEATURE_LESS_MARKS unsigned num_marks; unsigned mark_lines[15][2]; @@ -229,6 +237,7 @@ struct globals { #define current_file (G.current_file ) #define filename (G.filename ) #define files (G.files ) +#define num_lines (G.num_lines ) #define num_marks (G.num_marks ) #define mark_lines (G.mark_lines ) #if ENABLE_FEATURE_LESS_REGEXP @@ -574,6 +583,10 @@ static void read_lines(void) print_statusline(bb_msg_read_error); } } +#if ENABLE_FEATURE_LESS_FLAGS + else if (eof_error == 0) + num_lines = max_lineno; +#endif fill_match_lines(old_max_fline); #if ENABLE_FEATURE_LESS_REGEXP @@ -584,18 +597,23 @@ static void read_lines(void) } #if ENABLE_FEATURE_LESS_FLAGS -/* Interestingly, writing calc_percent as a function saves around 32 bytes - * on my build. */ -static int calc_percent(void) +static int safe_lineno(int fline) { - unsigned p = (100 * (cur_fline+max_displayed_line+1) + max_fline/2) / (max_fline+1); - return p <= 100 ? p : 100; + if (fline >= max_fline) + fline = max_fline - 1; + + /* also catches empty file (max_fline == 0) */ + if (fline < 0) + return 0; + + return LINENO(flines[fline]) + 1; } /* Print a status line if -M was specified */ static void m_status_print(void) { - int percentage; + int first, last; + unsigned percent; if (less_gets_pos >= 0) /* don't touch statusline while input is done! */ return; @@ -604,17 +622,51 @@ static void m_status_print(void) printf(HIGHLIGHT"%s", filename); if (num_files > 1) printf(" (file %i of %i)", current_file, num_files); - printf(" lines %i-%i/%i ", - cur_fline + 1, cur_fline + max_displayed_line + 1, - max_fline + 1); - if (cur_fline >= (int)(max_fline - max_displayed_line)) { - printf("(END)"NORMAL); - if (num_files > 1 && current_file != num_files) - printf(HIGHLIGHT" - next: %s"NORMAL, files[current_file]); - return; + + first = safe_lineno(cur_fline); + last = (option_mask32 & FLAG_S) + ? MIN(first + max_displayed_line, max_lineno) + : safe_lineno(cur_fline + max_displayed_line); + printf(" lines %i-%i", first, last); + + if (num_lines == READING_FILE) { + int count, fd; + ssize_t len, i; + char buf[4096]; + struct stat stbuf; + + /* count number of lines in file */ + count = 0; + fd = open(filename, O_RDONLY); + if (fd < 0) + goto skip; + if (fstat(fd, &stbuf) != 0 || !S_ISREG(stbuf.st_mode)) + goto do_close; + while ((len = safe_read(fd, buf, sizeof(buf))) > 0) { + for (i = 0; i < len; ++i) { + if (buf[i] == '\n' && ++count == MAXLINES) + goto done; + } + } + done: + num_lines = count; + do_close: + close(fd); + skip: ; } - percentage = calc_percent(); - printf("%i%%"NORMAL, percentage); + + if (num_lines >= 0) + printf("/%i", num_lines); + + if (cur_fline >= (int)(max_fline - max_displayed_line)) { + printf(" (END)"); + if (num_files > 1 && current_file != num_files) + printf(" - next: %s", files[current_file]); + } else if (num_lines > 0) { + percent = (100 * last + num_lines/2) / num_lines; + printf(" %i%%", percent <= 100 ? percent : 100); + } + printf(NORMAL); } #endif @@ -915,6 +967,9 @@ static void reinitialize(void) max_fline = -1; cur_fline = 0; max_lineno = 0; +#if ENABLE_FEATURE_LESS_FLAGS + num_lines = filename ? READING_FILE : READING_STDIN; +#endif open_file_and_read_lines(); #if ENABLE_FEATURE_LESS_ASK_TERMINAL if (G.winsize_err) From c29021e2a594fb29471c8c7e61ab8f45296622ba Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Tue, 28 Jul 2015 05:35:00 +0000 Subject: [PATCH 168/256] udhcpc: dns labels can actually start with a number While RFC1035 recommends a label not to start with a number, there is actually no such limitation in dns. One may buy a domain name like 0x1.net and use it. This commit remove this check and allow a user to use such domains. Signed-off-by: Arthur Gautier Signed-off-by: Denys Vlasenko --- networking/udhcp/dhcpc.c | 4 ---- 1 file changed, 4 deletions(-) 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) for (;;) { ch = *label; if ((ch|0x20) < 'a' || (ch|0x20) > 'z') { - if (pos == 0) { - /* label must begin with letter */ - return NULL; - } if (ch < '0' || ch > '9') { if (ch == '\0' || ch == '.') return label; From 52f2f37477affbbd416b27f051b2be9d87891dcd Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 27 Jul 2015 09:59:04 +0200 Subject: [PATCH 169/256] fbset: fix rgba parsing In commit b5c7220e7b2b6611fe5beca494c67bfe51fcfafb "fbset: respect rgba configuration lines in fb.modes" I somehow managed to swap the offset/length markers around. The man page for fb.modes says it should be offset/length not length/offset as I was accidentally parsing it. As my fb.modes file was also reversed I didn't notice until I tried someone elses fb.modes file. Mea culpa. Signed-off-by: Linus Walleij Signed-off-by: Denys Vlasenko --- util-linux/fbset.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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, int transp_offset, transp_length; sscanf(p, "%d/%d,%d/%d,%d/%d,%d/%d", - &red_offset, &red_length, - &green_offset, &green_length, - &blue_offset, &blue_length, - &transp_offset, &transp_length); + &red_length, &red_offset, + &green_length, &green_offset, + &blue_length, &blue_offset, + &transp_length, &transp_offset); base->red.offset = red_offset; base->red.length = red_length; base->red.msb_right = 0; From 670c3f7822e17c8bfdd9351fcfea071e696fc1d6 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 29 Jul 2015 23:33:16 -0400 Subject: [PATCH 170/256] echo: make escape sequences depend on fancy mode Currently when you disable fancy echo, escape sequences are hardcoded enabled (e.g. as if you used `echo -e` all the time). The opposite behavior is more desirable (always disable -e support) because: * This seems to contradict the spirit of the kconfig help text (where it says enable support for -n/-e flags), although you could say that we aren't supporting the -e flag directly as `echo -e` will show the -e flag. * POSIX makes escape sequences optional, and even says they are there only on XSI-conformant systems. * It saves space (~100 bytes on x86_64). * It makes things faster! * It makes it behave more like bash where you need an explicit -e flag in order for escape sequences to be interpreted. Signed-off-by: Mike Frysinger Signed-off-by: Denys Vlasenko --- coreutils/echo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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) unsigned buflen; #if !ENABLE_FEATURE_FANCY_ECHO enum { - eflag = '\\', + eflag = 0, /* 0 -- disable escape sequences */ nflag = 1, /* 1 -- print '\n' */ }; From ae1a9e899e0d4695834e8ce7348d41663abcef1e Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Tue, 21 Jul 2015 20:12:31 +0100 Subject: [PATCH 171/256] less: fix numeric input Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- miscutils/less.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miscutils/less.c b/miscutils/less.c index dd932c5ed..4cdfa3bbb 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -1314,7 +1314,7 @@ static void number_process(int first_digit) i = 1; while (i < sizeof(num_input)-1) { keypress = less_getch(i + 1); - if ((unsigned)keypress > 255 || !isdigit(num_input[i])) + if ((unsigned)keypress > 255 || !isdigit(keypress)) break; num_input[i] = keypress; bb_putchar(keypress); From 159e032bf4cd24535e57daaf29a381b0d5163368 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Fri, 24 Jul 2015 14:27:42 +0100 Subject: [PATCH 172/256] less: move code to count lines into a separate function function old new delta update_num_lines - 159 +159 m_status_print 409 266 -143 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/1 up/down: 159/-143) Total: 16 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- miscutils/less.c | 56 ++++++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/miscutils/less.c b/miscutils/less.c index 4cdfa3bbb..8fd0874e2 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -609,6 +609,35 @@ static int safe_lineno(int fline) return LINENO(flines[fline]) + 1; } +/* count number of lines in file */ +static void update_num_lines(void) +{ + int count, fd; + ssize_t len, i; + char buf[4096]; + struct stat stbuf; + + if (num_lines == READING_FILE) { + count = 0; + fd = open(filename, O_RDONLY); + if (fd < 0) + goto skip; + if (fstat(fd, &stbuf) != 0 || !S_ISREG(stbuf.st_mode)) + goto do_close; + while ((len = safe_read(fd, buf, sizeof(buf))) > 0) { + for (i = 0; i < len; ++i) { + if (buf[i] == '\n' && ++count == MAXLINES) + goto done; + } + } + done: + num_lines = count; + do_close: + close(fd); + skip: ; + } +} + /* Print a status line if -M was specified */ static void m_status_print(void) { @@ -629,32 +658,7 @@ static void m_status_print(void) : safe_lineno(cur_fline + max_displayed_line); printf(" lines %i-%i", first, last); - if (num_lines == READING_FILE) { - int count, fd; - ssize_t len, i; - char buf[4096]; - struct stat stbuf; - - /* count number of lines in file */ - count = 0; - fd = open(filename, O_RDONLY); - if (fd < 0) - goto skip; - if (fstat(fd, &stbuf) != 0 || !S_ISREG(stbuf.st_mode)) - goto do_close; - while ((len = safe_read(fd, buf, sizeof(buf))) > 0) { - for (i = 0; i < len; ++i) { - if (buf[i] == '\n' && ++count == MAXLINES) - goto done; - } - } - done: - num_lines = count; - do_close: - close(fd); - skip: ; - } - + update_num_lines(); if (num_lines >= 0) printf("/%i", num_lines); From 70b84be9e85969491e542cecc3ae28fa7558a7ec Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Fri, 24 Jul 2015 14:28:08 +0100 Subject: [PATCH 173/256] less: rearrange detection of non-regular files Move the code to detect non-regular files to the point where the file is being opened. If num_lines == READING_FILE guarantees that the file is regular. Detect when a file becomes unreadable between it first being opened and the call to update_num_lines. Mark the file as being non-regular so we don't try that again. function old new delta reinitialize 197 245 +48 update_num_lines 159 127 -32 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 48/-32) Total: 16 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- miscutils/less.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/miscutils/less.c b/miscutils/less.c index 8fd0874e2..91a933a3a 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -167,7 +167,8 @@ enum { pattern_valid = 0 }; enum { READING_FILE = -1, - READING_STDIN = -2 + READING_STDIN = -2, + READING_NONREG = -3 }; struct globals { @@ -615,15 +616,16 @@ static void update_num_lines(void) int count, fd; ssize_t len, i; char buf[4096]; - struct stat stbuf; + /* only do this for regular files */ if (num_lines == READING_FILE) { count = 0; fd = open(filename, O_RDONLY); - if (fd < 0) - goto skip; - if (fstat(fd, &stbuf) != 0 || !S_ISREG(stbuf.st_mode)) - goto do_close; + if (fd < 0) { + /* somebody stole my file! */ + num_lines = READING_NONREG; + return; + } while ((len = safe_read(fd, buf, sizeof(buf))) > 0) { for (i = 0; i < len; ++i) { if (buf[i] == '\n' && ++count == MAXLINES) @@ -632,9 +634,7 @@ static void update_num_lines(void) } done: num_lines = count; - do_close: close(fd); - skip: ; } } @@ -943,6 +943,13 @@ static void buffer_line(int linenum) static void open_file_and_read_lines(void) { if (filename) { +#if ENABLE_FEATURE_LESS_FLAGS + struct stat stbuf; + + xstat(filename, &stbuf); + if (!S_ISREG(stbuf.st_mode)) + num_lines = READING_NONREG; +#endif xmove_fd(xopen(filename, O_RDONLY), STDIN_FILENO); } else { /* "less" with no arguments in argv[] */ From ad1b4d5882586ad213992a97fc22f9c4bc9e0040 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Fri, 24 Jul 2015 14:28:50 +0100 Subject: [PATCH 174/256] less: add a function to detect when display is at end of file Add a function to package the test that detects whether enough has been read from the file to allow a screenful to be displayed. Also use this to determine when to display '(END)' in the status line. The previous code was incomplete and didn't handle truncated lines (-S flag) properly. function old new delta at_end - 63 +63 status_print 111 109 -2 read_lines 819 764 -55 getch_nowait 319 264 -55 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/3 up/down: 63/-112) Total: -49 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- miscutils/less.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/miscutils/less.c b/miscutils/less.c index 91a933a3a..2a1797c7b 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -406,6 +406,14 @@ static void fill_match_lines(unsigned pos); #define fill_match_lines(pos) ((void)0) #endif +static int at_end(void) +{ + return (option_mask32 & FLAG_S) + ? !(cur_fline <= max_fline && + max_lineno > LINENO(flines[cur_fline]) + max_displayed_line) + : !(max_fline > cur_fline + max_displayed_line); +} + /* Devilishly complex routine. * * Has to deal with EOF and EPIPE on input, @@ -552,11 +560,7 @@ static void read_lines(void) eof_error = 0; /* Pretend we saw EOF */ break; } - if (!(option_mask32 & FLAG_S) - ? (max_fline > cur_fline + max_displayed_line) - : (max_fline >= cur_fline - && max_lineno > LINENO(flines[cur_fline]) + max_displayed_line) - ) { + if (!at_end()) { #if !ENABLE_FEATURE_LESS_REGEXP break; #else @@ -662,7 +666,7 @@ static void m_status_print(void) if (num_lines >= 0) printf("/%i", num_lines); - if (cur_fline >= (int)(max_fline - max_displayed_line)) { + if (at_end()) { printf(" (END)"); if (num_files > 1 && current_file != num_files) printf(" - next: %s", files[current_file]); @@ -692,7 +696,7 @@ static void status_print(void) #endif clear_line(); - if (cur_fline && cur_fline < (int)(max_fline - max_displayed_line)) { + if (cur_fline && !at_end()) { bb_putchar(':'); return; } @@ -1009,12 +1013,7 @@ static int64_t getch_nowait(void) */ rd = 1; /* Are we interested in stdin? */ -//TODO: reuse code for determining this - if (!(option_mask32 & FLAG_S) - ? !(max_fline > cur_fline + max_displayed_line) - : !(max_fline >= cur_fline - && max_lineno > LINENO(flines[cur_fline]) + max_displayed_line) - ) { + if (at_end()) { if (eof_error > 0) /* did NOT reach eof yet */ rd = 0; /* yes, we are interested in stdin */ } From d542d183e10dde1168fa85751194839c67add7fe Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Fri, 24 Jul 2015 14:29:13 +0100 Subject: [PATCH 175/256] less: fix line number confusion Much of the code refers to lines using indices into the flines array (which splits lines into portions that fit on the terminal). In some cases this is wrong and actual line numbers should be used: - when lines are being truncated rather than wrapped (-S flag) - when line numbers have been entered by the user Also fix a bug in numeric input and improve the display at EOF. function old new delta goto_lineno - 111 +111 cap_cur_fline - 101 +101 buffer_to_line - 56 +56 buffer_up 35 66 +31 less_main 2606 2615 +9 goto_match 125 127 +2 buffer_down 81 56 -25 buffer_line 64 - -64 ------------------------------------------------------------------------------ (add/remove: 3/1 grow/shrink: 3/1 up/down: 310/-89) Total: 221 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- miscutils/less.c | 121 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 83 insertions(+), 38 deletions(-) diff --git a/miscutils/less.c b/miscutils/less.c index 2a1797c7b..5c53cbdbf 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -711,23 +711,6 @@ static void status_print(void) print_hilite(p); } -static void cap_cur_fline(int nlines) -{ - int diff; - if (cur_fline < 0) - cur_fline = 0; - if (cur_fline + max_displayed_line > max_fline + TILDES) { - cur_fline -= nlines; - if (cur_fline < 0) - cur_fline = 0; - diff = max_fline - (cur_fline + max_displayed_line) + TILDES; - /* As the number of lines requested was too large, we just move - * to the end of the file */ - if (diff > 0) - cur_fline += diff; - } -} - static const char controls[] ALIGN1 = /* NUL: never encountered; TAB: not converted */ /**/"\x01\x02\x03\x04\x05\x06\x07\x08" "\x0a\x0b\x0c\x0d\x0e\x0f" @@ -913,35 +896,96 @@ static void buffer_fill_and_print(void) buffer_print(); } +/* move cur_fline to a given line number, reading lines if necessary */ +static void goto_lineno(int target) +{ + if (target <= 0 ) { + cur_fline = 0; + } + else if (target > LINENO(flines[cur_fline])) { + retry: + while (LINENO(flines[cur_fline]) != target && cur_fline < max_fline) + ++cur_fline; + /* target not reached but more input is available */ + if (LINENO(flines[cur_fline]) != target && eof_error > 0) { + read_lines(); + goto retry; + } + } + else { + /* search backwards through already-read lines */ + while (LINENO(flines[cur_fline]) != target && cur_fline > 0) + --cur_fline; + } +} + +static void cap_cur_fline(void) +{ + if ((option_mask32 & FLAG_S)) { + if (cur_fline > max_fline) + cur_fline = max_fline; + if (LINENO(flines[cur_fline]) + max_displayed_line > max_lineno + TILDES) { + goto_lineno(max_lineno - max_displayed_line + TILDES); + read_lines(); + } + } + else { + if (cur_fline + max_displayed_line > max_fline + TILDES) + cur_fline = max_fline - max_displayed_line + TILDES; + if (cur_fline < 0) + cur_fline = 0; + } +} + /* Move the buffer up and down in the file in order to scroll */ static void buffer_down(int nlines) { - cur_fline += nlines; + if ((option_mask32 & FLAG_S)) + goto_lineno(LINENO(flines[cur_fline]) + nlines); + else + cur_fline += nlines; read_lines(); - cap_cur_fline(nlines); + cap_cur_fline(); buffer_fill_and_print(); } static void buffer_up(int nlines) { - cur_fline -= nlines; - if (cur_fline < 0) cur_fline = 0; + if ((option_mask32 & FLAG_S)) { + goto_lineno(LINENO(flines[cur_fline]) - nlines); + } + else { + cur_fline -= nlines; + if (cur_fline < 0) + cur_fline = 0; + } read_lines(); buffer_fill_and_print(); } +/* display a given line where the argument can be either an index into + * the flines array or a line number */ +static void buffer_to_line(int linenum, int is_lineno) +{ + if (linenum <= 0) + cur_fline = 0; + else if (is_lineno) + goto_lineno(linenum); + else + cur_fline = linenum; + read_lines(); + cap_cur_fline(); + buffer_fill_and_print(); +} + static void buffer_line(int linenum) { - if (linenum < 0) - linenum = 0; - cur_fline = linenum; - read_lines(); - if (linenum + max_displayed_line > max_fline) - linenum = max_fline - max_displayed_line + TILDES; - if (linenum < 0) - linenum = 0; - cur_fline = linenum; - buffer_fill_and_print(); + buffer_to_line(linenum, FALSE); +} + +static void buffer_lineno(int lineno) +{ + buffer_to_line(lineno, TRUE); } static void open_file_and_read_lines(void) @@ -1348,15 +1392,16 @@ static void number_process(int first_digit) buffer_up(num); break; case 'g': case '<': case 'G': case '>': - cur_fline = num + max_displayed_line; - read_lines(); - buffer_line(num - 1); + buffer_lineno(num - 1); break; case 'p': case '%': - num = num * (max_fline / 100); /* + max_fline / 2; */ - cur_fline = num + max_displayed_line; - read_lines(); - buffer_line(num); +#if ENABLE_FEATURE_LESS_FLAGS + update_num_lines(); + num = num * (num_lines > 0 ? num_lines : max_lineno) / 100; +#else + num = num * max_lineno / 100; +#endif + buffer_lineno(num); break; #if ENABLE_FEATURE_LESS_REGEXP case 'n': From 1ecb996fd2641e6ad3fdf07e78781823c71fcf13 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Fri, 24 Jul 2015 14:29:45 +0100 Subject: [PATCH 176/256] less: allow use of last column of terminal When read_lines tests whether a character will fit on the current line it checks the *next* character but in case of overflow doesn't display the *current* one. This results in the last column of the terminal never being used. The test in re_wrap (used when the terminal width changes or line numbers are enabled/disabled) is different: it does allow the use of the final column. function old new delta read_lines 764 770 +6 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/0 up/down: 6/0) Total: 6 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- miscutils/less.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/miscutils/less.c b/miscutils/less.c index 5c53cbdbf..b38fcf766 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -512,16 +512,6 @@ static void read_lines(void) *--p = '\0'; continue; } - { - size_t new_last_line_pos = last_line_pos + 1; - if (c == '\t') { - new_last_line_pos += 7; - new_last_line_pos &= (~7); - } - if ((int)new_last_line_pos >= w) - break; - last_line_pos = new_last_line_pos; - } /* ok, we will eat this char */ readpos++; if (c == '\n') { @@ -533,6 +523,16 @@ static void read_lines(void) if (c == '\0') c = '\n'; *p++ = c; *p = '\0'; + { + size_t new_last_line_pos = last_line_pos + 1; + if (c == '\t') { + new_last_line_pos += 7; + new_last_line_pos &= (~7); + } + if ((int)new_last_line_pos >= w) + break; + last_line_pos = new_last_line_pos; + } } /* end of "read chars until we have a line" loop */ #if 0 //BUG: also triggers on this: From 9dc526d0f91c37ecdf6280c2cd69107c6102076e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 31 Jul 2015 16:42:20 +0200 Subject: [PATCH 177/256] less: improve regular file detection in line counting code Signed-off-by: Denys Vlasenko --- miscutils/less.c | 49 ++++++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/miscutils/less.c b/miscutils/less.c index b38fcf766..be8d20e66 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -165,12 +165,6 @@ enum { enum { pattern_valid = 0 }; #endif -enum { - READING_FILE = -1, - READING_STDIN = -2, - READING_NONREG = -3 -}; - struct globals { int cur_fline; /* signed */ int kbd_fd; /* fd to get input from */ @@ -195,7 +189,10 @@ struct globals { char *filename; char **files; #if ENABLE_FEATURE_LESS_FLAGS - int num_lines; /* input source if < 0, line count if >= 0 */ + int num_lines; /* a flag if < 0, line count if >= 0 */ +# define REOPEN_AND_COUNT (-1) +# define REOPEN_STDIN (-2) +# define NOT_REGULAR_FILE (-3) #endif #if ENABLE_FEATURE_LESS_MARKS unsigned num_marks; @@ -622,14 +619,29 @@ static void update_num_lines(void) char buf[4096]; /* only do this for regular files */ - if (num_lines == READING_FILE) { + if (num_lines != NOT_REGULAR_FILE) { count = 0; - fd = open(filename, O_RDONLY); + fd = open("/proc/self/fd/0", O_RDONLY); + if (fd < 0 && num_lines == REOPEN_AND_COUNT) { + /* "filename" is valid only if REOPEN_AND_COUNT */ + fd = open(filename, O_RDONLY); + } if (fd < 0) { /* somebody stole my file! */ - num_lines = READING_NONREG; + num_lines = NOT_REGULAR_FILE; return; } +#if ENABLE_FEATURE_LESS_FLAGS + { + struct stat stbuf; + if (fstat(fd, &stbuf) != 0 + || !S_ISREG(stbuf.st_mode) + ) { + num_lines = NOT_REGULAR_FILE; + goto do_close; + } + } +#endif while ((len = safe_read(fd, buf, sizeof(buf))) > 0) { for (i = 0; i < len; ++i) { if (buf[i] == '\n' && ++count == MAXLINES) @@ -638,6 +650,7 @@ static void update_num_lines(void) } done: num_lines = count; + do_close: close(fd); } } @@ -991,18 +1004,17 @@ static void buffer_lineno(int lineno) static void open_file_and_read_lines(void) { if (filename) { -#if ENABLE_FEATURE_LESS_FLAGS - struct stat stbuf; - - xstat(filename, &stbuf); - if (!S_ISREG(stbuf.st_mode)) - num_lines = READING_NONREG; -#endif xmove_fd(xopen(filename, O_RDONLY), STDIN_FILENO); +#if ENABLE_FEATURE_LESS_FLAGS + num_lines = REOPEN_AND_COUNT; +#endif } else { /* "less" with no arguments in argv[] */ /* For status line only */ filename = xstrdup(bb_msg_standard_input); +#if ENABLE_FEATURE_LESS_FLAGS + num_lines = REOPEN_STDIN; +#endif } readpos = 0; readeof = 0; @@ -1026,9 +1038,6 @@ static void reinitialize(void) max_fline = -1; cur_fline = 0; max_lineno = 0; -#if ENABLE_FEATURE_LESS_FLAGS - num_lines = filename ? READING_FILE : READING_STDIN; -#endif open_file_and_read_lines(); #if ENABLE_FEATURE_LESS_ASK_TERMINAL if (G.winsize_err) From a47fccaa63449182a5d0c11cf03139a072f8c19c Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Thu, 30 Jul 2015 23:13:25 +0300 Subject: [PATCH 178/256] diff: fix -B with single line changes Fix -B with single line changes. They were always ignored regardless if they were blank or not. Signed-off-by: Aaro Koskinen Signed-off-by: Denys Vlasenko --- editors/diff.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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]) } for (j = 0; j < 2; j++) - for (k = v[j].a; k < v[j].b; k++) - nonempty |= (ix[j][k+1] - ix[j][k] != 1); + for (k = v[j].a; k <= v[j].b; k++) + nonempty |= (ix[j][k] - ix[j][k - 1] != 1); vec = xrealloc_vector(vec, 6, ++idx); memcpy(vec[idx], v, sizeof(v)); From ad27a6d3265b2e8a27030a01121afed639bed2da Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Thu, 30 Jul 2015 23:13:26 +0300 Subject: [PATCH 179/256] diff.tests: add testcases for -B and single line changes Add testcases for -B and single line changes. Signed-off-by: Aaro Koskinen Signed-off-by: Denys Vlasenko --- testsuite/diff.tests | 12 ++++++++++++ 1 file changed, 12 insertions(+) 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" \ "a\n" \ "\nb\n\n" +testing "diff -B ignores blank single line change" \ + 'diff -qB - input; echo $?' \ + "0\n" \ + "\n1\n" \ + "1\n" + +testing "diff -B does not ignore non-blank single line change" \ + 'diff -qB - input; echo $?' \ + "Files - and input differ\n1\n" \ + "0\n" \ + "1\n" + testing "diff always takes context from old file" \ "diff -ub - input | $TRIM_TAB" \ "\ From b27cf31003774e5aa13491ccb8f1f0721dc5b920 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Fri, 31 Jul 2015 17:33:24 +0100 Subject: [PATCH 180/256] less: further tweaks to regular file detection Test explicitly for REOPEN flags: update_num_lines is called unconditionally so (num_lines != NOT_REGULAR_FILE) is also true when num_lines contains a valid number of lines. The call to fstat doesn't need to be in #if ENABLE_FEATURE_LESS_FLAGS: the whole function is already in such a test. Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- miscutils/less.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/miscutils/less.c b/miscutils/less.c index be8d20e66..7a441bf7e 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -615,11 +615,12 @@ static int safe_lineno(int fline) static void update_num_lines(void) { int count, fd; + struct stat stbuf; ssize_t len, i; char buf[4096]; /* only do this for regular files */ - if (num_lines != NOT_REGULAR_FILE) { + if (num_lines == REOPEN_AND_COUNT || num_lines == REOPEN_STDIN) { count = 0; fd = open("/proc/self/fd/0", O_RDONLY); if (fd < 0 && num_lines == REOPEN_AND_COUNT) { @@ -631,17 +632,10 @@ static void update_num_lines(void) num_lines = NOT_REGULAR_FILE; return; } -#if ENABLE_FEATURE_LESS_FLAGS - { - struct stat stbuf; - if (fstat(fd, &stbuf) != 0 - || !S_ISREG(stbuf.st_mode) - ) { - num_lines = NOT_REGULAR_FILE; - goto do_close; - } + if (fstat(fd, &stbuf) != 0 || !S_ISREG(stbuf.st_mode)) { + num_lines = NOT_REGULAR_FILE; + goto do_close; } -#endif while ((len = safe_read(fd, buf, sizeof(buf))) > 0) { for (i = 0; i < len; ++i) { if (buf[i] == '\n' && ++count == MAXLINES) From 64ed5f0d3c5eefbb208d4a334654834c78be2cbd Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Sun, 12 Jul 2015 16:06:37 +0100 Subject: [PATCH 181/256] uname: make OS name configurable A mailing list thread in September 2013 discussed changing the string returned by the non-POSIX 'uname -o' option. Nothing ever came of this because there was no agreement as to what the string should be. Make the string configurable so that people can decide for themselves. Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- coreutils/Config.src | 8 ++++++++ coreutils/uname.c | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/coreutils/Config.src b/coreutils/Config.src index 02155d220..ffbef1a31 100644 --- a/coreutils/Config.src +++ b/coreutils/Config.src @@ -630,6 +630,14 @@ config UNAME help uname is used to print system information. +config UNAME_OSNAME + string "Operating system name" + default "GNU/Linux" + depends on UNAME + help + Sets the operating system name reported by uname -o. The + default is "GNU/Linux". + config UNEXPAND bool "unexpand" default y diff --git a/coreutils/uname.c b/coreutils/uname.c index 1c6aa5f79..fd677d27c 100644 --- a/coreutils/uname.c +++ b/coreutils/uname.c @@ -74,7 +74,7 @@ typedef struct { struct utsname name; char processor[sizeof(((struct utsname*)NULL)->machine)]; char platform[sizeof(((struct utsname*)NULL)->machine)]; - char os[sizeof("GNU/Linux")]; + char os[sizeof(CONFIG_UNAME_OSNAME)]; } uname_info_t; static const char options[] ALIGN1 = "snrvmpioa"; @@ -141,7 +141,7 @@ int uname_main(int argc UNUSED_PARAM, char **argv) #endif strcpy(uname_info.processor, unknown_str); strcpy(uname_info.platform, unknown_str); - strcpy(uname_info.os, "GNU/Linux"); + strcpy(uname_info.os, CONFIG_UNAME_OSNAME); #if 0 /* Fedora does something like this */ strcpy(uname_info.processor, uname_info.name.machine); From 16aa7a73c40ba5dfaabaedb8a5533619cb8b6cb6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 4 Aug 2015 03:27:56 +0200 Subject: [PATCH 182/256] zcip: simplify code function old new delta zcip_main 1411 1263 -148 Signed-off-by: Denys Vlasenko --- networking/zcip.c | 235 +++++++++++++++++++--------------------------- 1 file changed, 96 insertions(+), 139 deletions(-) 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 { } PACKED; enum { -/* 169.254.0.0 */ + /* 169.254.0.0 */ LINKLOCAL_ADDR = 0xa9fe0000, -/* protocol timeout parameters, specified in seconds */ + /* 0-1 seconds before sending 1st probe */ PROBE_WAIT = 1, + /* 1-2 seconds between probes */ PROBE_MIN = 1, PROBE_MAX = 2, - PROBE_NUM = 3, - MAX_CONFLICTS = 10, - RATE_LIMIT_INTERVAL = 60, - ANNOUNCE_WAIT = 2, - ANNOUNCE_NUM = 2, - ANNOUNCE_INTERVAL = 2, + PROBE_NUM = 3, /* total probes to send */ + ANNOUNCE_INTERVAL = 2, /* 2 seconds between announces */ + ANNOUNCE_NUM = 3, /* announces to send */ + /* if probe/announce sees a conflict, multiply RANDOM(NUM_CONFLICT) by... */ + CONFLICT_MULTIPLIER = 2, + /* if we monitor and see a conflict, how long is defend state? */ DEFEND_INTERVAL = 10 }; /* States during the configuration process. */ enum { PROBE = 0, - RATE_LIMIT_PROBE, ANNOUNCE, MONITOR, DEFEND @@ -89,13 +89,11 @@ enum { }; struct globals { - struct sockaddr saddr; + struct sockaddr iface_sockaddr; struct ether_addr eth_addr; uint32_t localnet_ip; } FIX_ALIASING; #define G (*(struct globals*)&bb_common_bufsiz1) -#define saddr (G.saddr ) -#define eth_addr (G.eth_addr) #define INIT_G() do { } while (0) @@ -113,17 +111,24 @@ static uint32_t pick_nip(void) return htonl((G.localnet_ip + 0x0100) + tmp); } +static const char *nip_to_a(uint32_t nip) +{ + struct in_addr in; + in.s_addr = nip; + return inet_ntoa(in); +} + /** * Broadcast an ARP packet. */ static void arp( /* int op, - always ARPOP_REQUEST */ - /* const struct ether_addr *source_eth, - always ð_addr */ - struct in_addr source_ip, - const struct ether_addr *target_eth, struct in_addr target_ip) + /* const struct ether_addr *source_eth, - always &G.eth_addr */ + uint32_t source_nip, + const struct ether_addr *target_eth, uint32_t target_nip) { enum { op = ARPOP_REQUEST }; -#define source_eth (ð_addr) +#define source_eth (&G.eth_addr) struct arp_packet p; memset(&p, 0, sizeof(p)); @@ -140,18 +145,18 @@ static void arp( p.arp.arp_pln = 4; p.arp.arp_op = htons(op); memcpy(&p.arp.arp_sha, source_eth, ETH_ALEN); - memcpy(&p.arp.arp_spa, &source_ip, sizeof(p.arp.arp_spa)); + memcpy(&p.arp.arp_spa, &source_nip, 4); memcpy(&p.arp.arp_tha, target_eth, ETH_ALEN); - memcpy(&p.arp.arp_tpa, &target_ip, sizeof(p.arp.arp_tpa)); + memcpy(&p.arp.arp_tpa, &target_nip, 4); // send it - // Even though sock_fd is already bound to saddr, just send() + // Even though sock_fd is already bound to G.iface_sockaddr, just send() // won't work, because "socket is not connected" // (and connect() won't fix that, "operation not supported"). - // Thus we sendto() to saddr. I wonder which sockaddr + // Thus we sendto() to G.iface_sockaddr. I wonder which sockaddr // (from bind() or from sendto()?) kernel actually uses // to determine iface to emit the packet from... - xsendto(sock_fd, &p, sizeof(p), &saddr, sizeof(saddr)); + xsendto(sock_fd, &p, sizeof(p), &G.iface_sockaddr, sizeof(G.iface_sockaddr)); #undef source_eth } @@ -159,18 +164,18 @@ static void arp( * Run a script. * argv[0]:intf argv[1]:script_name argv[2]:junk argv[3]:NULL */ -static int run(char *argv[3], const char *param, struct in_addr *ip) +static int run(char *argv[3], const char *param, uint32_t nip) { int status; - char *addr = addr; /* for gcc */ + const char *addr = addr; /* for gcc */ const char *fmt = "%s %s %s" + 3; argv[2] = (char*)param; VDBG("%s run %s %s\n", argv[0], argv[1], argv[2]); - if (ip) { - addr = inet_ntoa(*ip); + if (nip != 0) { + addr = nip_to_a(nip); xsetenv("ip", addr); fmt -= 3; } @@ -207,26 +212,22 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) // ugly trick, but I want these zeroed in one go struct { - const struct in_addr null_ip; const struct ether_addr null_addr; - struct in_addr ip; struct ifreq ifr; + uint32_t chosen_nip; int timeout_ms; /* must be signed */ unsigned conflicts; unsigned nprobes; unsigned nclaims; - int ready; int verbose; } L; -#define null_ip (L.null_ip ) #define null_addr (L.null_addr ) -#define ip (L.ip ) +#define chosen_nip (L.chosen_nip) #define ifr (L.ifr ) #define timeout_ms (L.timeout_ms) #define conflicts (L.conflicts ) #define nprobes (L.nprobes ) #define nclaims (L.nclaims ) -#define ready (L.ready ) #define verbose (L.verbose ) memset(&L, 0, sizeof(L)); @@ -264,11 +265,13 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) G.localnet_ip = ntohl(net.s_addr); } if (opts & 4) { // -r n.n.n.n + struct in_addr ip; if (inet_aton(r_opt, &ip) == 0 || (ntohl(ip.s_addr) & IN_CLASSB_NET) != G.localnet_ip ) { bb_error_msg_and_die("invalid link address"); } + chosen_nip = ip.s_addr; } argv += optind - 1; @@ -282,23 +285,23 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) xsetenv("interface", argv_intf); // initialize the interface (modprobe, ifup, etc) - if (run(argv, "init", NULL)) + if (run(argv, "init", 0)) return EXIT_FAILURE; - // initialize saddr - // saddr is: { u16 sa_family; u8 sa_data[14]; } - //memset(&saddr, 0, sizeof(saddr)); + // initialize G.iface_sockaddr + // G.iface_sockaddr is: { u16 sa_family; u8 sa_data[14]; } + //memset(&G.iface_sockaddr, 0, sizeof(G.iface_sockaddr)); //TODO: are we leaving sa_family == 0 (AF_UNSPEC)?! - safe_strncpy(saddr.sa_data, argv_intf, sizeof(saddr.sa_data)); + safe_strncpy(G.iface_sockaddr.sa_data, argv_intf, sizeof(G.iface_sockaddr.sa_data)); // bind to the interface's ARP socket - xbind(sock_fd, &saddr, sizeof(saddr)); + xbind(sock_fd, &G.iface_sockaddr, sizeof(G.iface_sockaddr)); // get the interface's ethernet address //memset(&ifr, 0, sizeof(ifr)); strncpy_IFNAMSIZ(ifr.ifr_name, argv_intf); xioctl(sock_fd, SIOCGIFHWADDR, &ifr); - memcpy(ð_addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN); + memcpy(&G.eth_addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN); // start with some stable ip address, either a function of // the hardware address or else the last address we used. @@ -308,11 +311,11 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) // depending on when we detect conflicts. { uint32_t t; - move_from_unaligned32(t, ((char *)ð_addr + 2)); + move_from_unaligned32(t, ((char *)&G.eth_addr + 2)); srand(t); } - if (ip.s_addr == 0) - ip.s_addr = pick_nip(); + if (chosen_nip == 0) + chosen_nip = pick_nip(); // FIXME cases to handle: // - zcip already running! @@ -331,7 +334,9 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) // - start with some address we want to try // - short random delay // - arp probes to see if another host uses it + // 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff, ARP (0x0806): arp who-has 169.254.194.171 tell 0.0.0.0 // - arp announcements that we're claiming it + // 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff, ARP (0x0806): arp who-has 169.254.194.171 (00:04:e2:64:23:c2) tell 169.254.194.171 // - use it // - defend it, within limits // exit if: @@ -382,78 +387,47 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) if (nprobes < PROBE_NUM) { nprobes++; VDBG("probe/%u %s@%s\n", - nprobes, argv_intf, inet_ntoa(ip)); + nprobes, argv_intf, nip_to_a(chosen_nip)); timeout_ms = PROBE_MIN * 1000; timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN); arp(/* ARPOP_REQUEST, */ - /* ð_addr, */ null_ip, - &null_addr, ip); + /* &G.eth_addr, */ 0, + &null_addr, chosen_nip); + break; } - else { - // Switch to announce state. - state = ANNOUNCE; - nclaims = 0; - VDBG("announce/%u %s@%s\n", - nclaims, argv_intf, inet_ntoa(ip)); - timeout_ms = ANNOUNCE_INTERVAL * 1000; - arp(/* ARPOP_REQUEST, */ - /* ð_addr, */ ip, - ð_addr, ip); - } - break; - case RATE_LIMIT_PROBE: - // timeouts in the RATE_LIMIT_PROBE state mean no conflicting ARP packets - // have been received, so we can move immediately to the announce state - state = ANNOUNCE; + // Switch to announce state. nclaims = 0; - VDBG("announce/%u %s@%s\n", - nclaims, argv_intf, inet_ntoa(ip)); - timeout_ms = ANNOUNCE_INTERVAL * 1000; - arp(/* ARPOP_REQUEST, */ - /* ð_addr, */ ip, - ð_addr, ip); - break; + state = ANNOUNCE; + goto send_announce; case ANNOUNCE: // timeouts in the ANNOUNCE state mean no conflicting ARP packets // have been received, so we can progress through the states if (nclaims < ANNOUNCE_NUM) { + send_announce: nclaims++; VDBG("announce/%u %s@%s\n", - nclaims, argv_intf, inet_ntoa(ip)); + nclaims, argv_intf, nip_to_a(chosen_nip)); timeout_ms = ANNOUNCE_INTERVAL * 1000; arp(/* ARPOP_REQUEST, */ - /* ð_addr, */ ip, - ð_addr, ip); - } - else { - // Switch to monitor state. - state = MONITOR; - // link is ok to use earlier - // FIXME update filters - run(argv, "config", &ip); - ready = 1; - conflicts = 0; - timeout_ms = -1; // Never timeout in the monitor state. - - // NOTE: all other exit paths - // should deconfig ... - if (QUIT) - return EXIT_SUCCESS; + /* &G.eth_addr, */ chosen_nip, + &G.eth_addr, chosen_nip); + break; } + // Switch to monitor state. + // FIXME update filters + run(argv, "config", chosen_nip); + // NOTE: all other exit paths should deconfig... + if (QUIT) + return EXIT_SUCCESS; + conflicts = 0; + timeout_ms = -1; // Never timeout in the monitor state. + state = MONITOR; break; case DEFEND: - // We won! No ARP replies, so just go back to monitor. - state = MONITOR; - timeout_ms = -1; + // Defend period ended with no ARP replies - we won. conflicts = 0; - break; - default: - // Invalid, should never happen. Restart the whole protocol. - state = PROBE; - ip.s_addr = pick_nip(); - timeout_ms = 0; - nprobes = 0; - nclaims = 0; + timeout_ms = -1; + state = MONITOR; break; } // switch (state) break; // case 0 (timeout) @@ -466,13 +440,10 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) unsigned diff = deadline_us - MONOTONIC_US(); if ((int)(diff) < 0) { // Current time is greater than the expected timeout time. - // Should never happen. - VDBG("missed an expected timeout\n"); - timeout_ms = 0; - } else { - VDBG("adjusting timeout\n"); - timeout_ms = (diff / 1000) | 1; /* never 0 */ + diff = 0; } + VDBG("adjusting timeout\n"); + timeout_ms = (diff / 1000) | 1; /* never 0 */ } if ((fds[0].revents & POLLIN) == 0) { @@ -480,8 +451,9 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) // FIXME: links routinely go down; // this shouldn't necessarily exit. bb_error_msg("iface %s is down", argv_intf); - if (ready) { - run(argv, "deconfig", &ip); + if (state >= MONITOR) { + /* only if we are in MONITOR or DEFEND */ + run(argv, "deconfig", chosen_nip); } return EXIT_FAILURE; } @@ -492,8 +464,14 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) if (safe_read(sock_fd, &p, sizeof(p)) < 0) { bb_perror_msg_and_die(bb_msg_read_error); } + if (p.eth.ether_type != htons(ETHERTYPE_ARP)) continue; + if (p.arp.arp_op != htons(ARPOP_REQUEST) + && p.arp.arp_op != htons(ARPOP_REPLY) + ) { + continue; + } #ifdef DEBUG { struct ether_addr *sha = (struct ether_addr *) p.arp.arp_sha; @@ -511,23 +489,17 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) inet_ntoa(*tpa)); } #endif - if (p.arp.arp_op != htons(ARPOP_REQUEST) - && p.arp.arp_op != htons(ARPOP_REPLY) - ) { - continue; - } - source_ip_conflict = 0; target_ip_conflict = 0; - if (memcmp(&p.arp.arp_sha, ð_addr, ETH_ALEN) != 0) { - if (memcmp(p.arp.arp_spa, &ip.s_addr, sizeof(struct in_addr)) == 0) { + if (memcmp(&p.arp.arp_sha, &G.eth_addr, ETH_ALEN) != 0) { + if (memcmp(p.arp.arp_spa, &chosen_nip, 4) == 0) { /* A probe or reply with source_ip == chosen ip */ source_ip_conflict = 1; } if (p.arp.arp_op == htons(ARPOP_REQUEST) - && memcmp(p.arp.arp_spa, &null_ip, sizeof(struct in_addr)) == 0 - && memcmp(p.arp.arp_tpa, &ip.s_addr, sizeof(struct in_addr)) == 0 + && memcmp(p.arp.arp_spa, &const_int_0, 4) == 0 + && memcmp(p.arp.arp_tpa, &chosen_nip, 4) == 0 ) { /* A probe with source_ip == 0.0.0.0, target_ip == chosen ip: * another host trying to claim this ip! @@ -545,54 +517,39 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) // and other hosts doing ARP probes (target IP conflicts). if (source_ip_conflict || target_ip_conflict) { conflicts++; - if (conflicts >= MAX_CONFLICTS) { - VDBG("%s ratelimit\n", argv_intf); - timeout_ms = RATE_LIMIT_INTERVAL * 1000; - state = RATE_LIMIT_PROBE; - } - - // restart the whole protocol - ip.s_addr = pick_nip(); - timeout_ms = 0; + timeout_ms = PROBE_MIN * 1000 + + CONFLICT_MULTIPLIER * random_delay_ms(conflicts); + chosen_nip = pick_nip(); nprobes = 0; nclaims = 0; + state = PROBE; } break; case MONITOR: // If a conflict, we try to defend with a single ARP probe. if (source_ip_conflict) { VDBG("monitor conflict -- defending\n"); - state = DEFEND; timeout_ms = DEFEND_INTERVAL * 1000; + state = DEFEND; arp(/* ARPOP_REQUEST, */ - /* ð_addr, */ ip, - ð_addr, ip); + /* &G.eth_addr, */ chosen_nip, + &G.eth_addr, chosen_nip); } break; case DEFEND: // Well, we tried. Start over (on conflict). if (source_ip_conflict) { - state = PROBE; VDBG("defend conflict -- starting over\n"); - ready = 0; - run(argv, "deconfig", &ip); + run(argv, "deconfig", chosen_nip); // restart the whole protocol - ip.s_addr = pick_nip(); timeout_ms = 0; + chosen_nip = pick_nip(); nprobes = 0; nclaims = 0; + state = PROBE; } break; - default: - // Invalid, should never happen. Restart the whole protocol. - VDBG("invalid state -- starting over\n"); - state = PROBE; - ip.s_addr = pick_nip(); - timeout_ms = 0; - nprobes = 0; - nclaims = 0; - break; } // switch state break; // case 1 (packets arriving) } // switch poll From 99e30be38bc167a3b5729154a27ccdb15bbaadb2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 4 Aug 2015 12:28:21 +0200 Subject: [PATCH 183/256] zcip: code shrink function old new delta zcip_main 1263 1230 -33 Signed-off-by: Denys Vlasenko --- networking/zcip.c | 137 ++++++++++++++++++++-------------------------- 1 file changed, 59 insertions(+), 78 deletions(-) diff --git a/networking/zcip.c b/networking/zcip.c index 69644b230..5877a8317 100644 --- a/networking/zcip.c +++ b/networking/zcip.c @@ -215,19 +215,17 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) const struct ether_addr null_addr; struct ifreq ifr; uint32_t chosen_nip; - int timeout_ms; /* must be signed */ + int timeout_ms; // must be signed unsigned conflicts; - unsigned nprobes; - unsigned nclaims; + unsigned nsent; int verbose; } L; #define null_addr (L.null_addr ) -#define chosen_nip (L.chosen_nip) #define ifr (L.ifr ) +#define chosen_nip (L.chosen_nip) #define timeout_ms (L.timeout_ms) #define conflicts (L.conflicts ) -#define nprobes (L.nprobes ) -#define nclaims (L.nclaims ) +#define nsent (L.nsent ) #define verbose (L.verbose ) memset(&L, 0, sizeof(L)); @@ -351,8 +349,7 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) struct pollfd fds[1]; unsigned deadline_us; struct arp_packet p; - int source_ip_conflict; - int target_ip_conflict; + int ip_conflict; fds[0].fd = sock_fd; fds[0].events = POLLIN; @@ -368,8 +365,8 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) // set deadline_us to the point in time when we timeout deadline_us = MONOTONIC_US() + timeout_ms * 1000; - VDBG("...wait %d %s nprobes=%u, nclaims=%u\n", - timeout_ms, argv_intf, nprobes, nclaims); + VDBG("...wait %d %s nsent=%u\n", + timeout_ms, argv_intf, nsent); switch (safe_poll(fds, 1, timeout_ms)) { @@ -384,10 +381,10 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) case PROBE: // timeouts in the PROBE state mean no conflicting ARP packets // have been received, so we can progress through the states - if (nprobes < PROBE_NUM) { - nprobes++; + if (nsent < PROBE_NUM) { + nsent++; VDBG("probe/%u %s@%s\n", - nprobes, argv_intf, nip_to_a(chosen_nip)); + nsent, argv_intf, nip_to_a(chosen_nip)); timeout_ms = PROBE_MIN * 1000; timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN); arp(/* ARPOP_REQUEST, */ @@ -395,25 +392,25 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) &null_addr, chosen_nip); break; } - // Switch to announce state. - nclaims = 0; + // Switch to announce state + nsent = 0; state = ANNOUNCE; goto send_announce; case ANNOUNCE: // timeouts in the ANNOUNCE state mean no conflicting ARP packets // have been received, so we can progress through the states - if (nclaims < ANNOUNCE_NUM) { + if (nsent < ANNOUNCE_NUM) { send_announce: - nclaims++; + nsent++; VDBG("announce/%u %s@%s\n", - nclaims, argv_intf, nip_to_a(chosen_nip)); + nsent, argv_intf, nip_to_a(chosen_nip)); timeout_ms = ANNOUNCE_INTERVAL * 1000; arp(/* ARPOP_REQUEST, */ /* &G.eth_addr, */ chosen_nip, &G.eth_addr, chosen_nip); break; } - // Switch to monitor state. + // Switch to monitor state // FIXME update filters run(argv, "config", chosen_nip); // NOTE: all other exit paths should deconfig... @@ -424,7 +421,7 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) state = MONITOR; break; case DEFEND: - // Defend period ended with no ARP replies - we won. + // Defend period ended with no ARP replies - we won conflicts = 0; timeout_ms = -1; state = MONITOR; @@ -443,7 +440,7 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) diff = 0; } VDBG("adjusting timeout\n"); - timeout_ms = (diff / 1000) | 1; /* never 0 */ + timeout_ms = (diff / 1000) | 1; // never 0 } if ((fds[0].revents & POLLIN) == 0) { @@ -452,7 +449,7 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) // this shouldn't necessarily exit. bb_error_msg("iface %s is down", argv_intf); if (state >= MONITOR) { - /* only if we are in MONITOR or DEFEND */ + // only if we are in MONITOR or DEFEND run(argv, "deconfig", chosen_nip); } return EXIT_FAILURE; @@ -478,81 +475,65 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) struct ether_addr *tha = (struct ether_addr *) p.arp.arp_tha; struct in_addr *spa = (struct in_addr *) p.arp.arp_spa; struct in_addr *tpa = (struct in_addr *) p.arp.arp_tpa; - VDBG("%s recv arp type=%d, op=%d,\n", - argv_intf, ntohs(p.eth.ether_type), - ntohs(p.arp.arp_op)); - VDBG("\tsource=%s %s\n", - ether_ntoa(sha), - inet_ntoa(*spa)); - VDBG("\ttarget=%s %s\n", - ether_ntoa(tha), - inet_ntoa(*tpa)); + VDBG("source=%s %s\n", ether_ntoa(sha), inet_ntoa(*spa)); + VDBG("target=%s %s\n", ether_ntoa(tha), inet_ntoa(*tpa)); } #endif - source_ip_conflict = 0; - target_ip_conflict = 0; - + ip_conflict = 0; if (memcmp(&p.arp.arp_sha, &G.eth_addr, ETH_ALEN) != 0) { if (memcmp(p.arp.arp_spa, &chosen_nip, 4) == 0) { - /* A probe or reply with source_ip == chosen ip */ - source_ip_conflict = 1; + // A probe or reply with source_ip == chosen ip + ip_conflict = 1; } if (p.arp.arp_op == htons(ARPOP_REQUEST) && memcmp(p.arp.arp_spa, &const_int_0, 4) == 0 && memcmp(p.arp.arp_tpa, &chosen_nip, 4) == 0 ) { - /* A probe with source_ip == 0.0.0.0, target_ip == chosen ip: - * another host trying to claim this ip! - */ - target_ip_conflict = 1; + // A probe with source_ip == 0.0.0.0, target_ip == chosen ip: + // another host trying to claim this ip! + ip_conflict |= 2; } } - - VDBG("state = %d, source ip conflict = %d, target ip conflict = %d\n", - state, source_ip_conflict, target_ip_conflict); - switch (state) { - case PROBE: - case ANNOUNCE: - // When probing or announcing, check for source IP conflicts - // and other hosts doing ARP probes (target IP conflicts). - if (source_ip_conflict || target_ip_conflict) { - conflicts++; - timeout_ms = PROBE_MIN * 1000 - + CONFLICT_MULTIPLIER * random_delay_ms(conflicts); - chosen_nip = pick_nip(); - nprobes = 0; - nclaims = 0; - state = PROBE; - } + VDBG("state:%d ip_conflict:%d\n", state, ip_conflict); + if (!ip_conflict) break; - case MONITOR: - // If a conflict, we try to defend with a single ARP probe. - if (source_ip_conflict) { - VDBG("monitor conflict -- defending\n"); + + // Either src or target IP conflict exists + if (state <= ANNOUNCE) { + // PROBE or ANNOUNCE + conflicts++; + timeout_ms = PROBE_MIN * 1000 + + CONFLICT_MULTIPLIER * random_delay_ms(conflicts); + chosen_nip = pick_nip(); + nsent = 0; + state = PROBE; + break; + } + // MONITOR or DEFEND: only src IP conflict is a problem + if (ip_conflict & 1) { + if (state == MONITOR) { + // Src IP conflict, defend with a single ARP probe + VDBG("monitor conflict - defending\n"); timeout_ms = DEFEND_INTERVAL * 1000; state = DEFEND; arp(/* ARPOP_REQUEST, */ /* &G.eth_addr, */ chosen_nip, &G.eth_addr, chosen_nip); + break; } - break; - case DEFEND: - // Well, we tried. Start over (on conflict). - if (source_ip_conflict) { - VDBG("defend conflict -- starting over\n"); - run(argv, "deconfig", chosen_nip); + // state == DEFEND + // Another src IP conflict, start over + VDBG("defend conflict - starting over\n"); + run(argv, "deconfig", chosen_nip); - // restart the whole protocol - timeout_ms = 0; - chosen_nip = pick_nip(); - nprobes = 0; - nclaims = 0; - state = PROBE; - } - break; - } // switch state - break; // case 1 (packets arriving) - } // switch poll + // restart the whole protocol + timeout_ms = 0; + chosen_nip = pick_nip(); + nsent = 0; + state = PROBE; + } + break; // case 1 (packet arrived) + } // switch (poll) } // while (1) #undef argv_intf } From e3475838354d6bba414ab8cdc2211313ad29dc9d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 4 Aug 2015 14:30:31 +0200 Subject: [PATCH 184/256] zcip: another code shrink function old new delta send_arp_request - 185 +185 zcip_main 1273 1272 -1 pick_nip 40 - -40 arp 185 - -185 ------------------------------------------------------------------------------ (add/remove: 1/2 grow/shrink: 0/1 up/down: 185/-226) Total: -41 bytes Signed-off-by: Denys Vlasenko --- networking/zcip.c | 307 ++++++++++++++++++++++------------------------ 1 file changed, 148 insertions(+), 159 deletions(-) diff --git a/networking/zcip.c b/networking/zcip.c index 5877a8317..a167c7e91 100644 --- a/networking/zcip.c +++ b/networking/zcip.c @@ -90,7 +90,7 @@ enum { struct globals { struct sockaddr iface_sockaddr; - struct ether_addr eth_addr; + struct ether_addr our_ethaddr; uint32_t localnet_ip; } FIX_ALIASING; #define G (*(struct globals*)&bb_common_bufsiz1) @@ -121,14 +121,14 @@ static const char *nip_to_a(uint32_t nip) /** * Broadcast an ARP packet. */ -static void arp( +static void send_arp_request( /* int op, - always ARPOP_REQUEST */ - /* const struct ether_addr *source_eth, - always &G.eth_addr */ + /* const struct ether_addr *source_eth, - always &G.our_ethaddr */ uint32_t source_nip, const struct ether_addr *target_eth, uint32_t target_nip) { enum { op = ARPOP_REQUEST }; -#define source_eth (&G.eth_addr) +#define source_eth (&G.our_ethaddr) struct arp_packet p; memset(&p, 0, sizeof(p)); @@ -205,35 +205,34 @@ static ALWAYS_INLINE unsigned random_delay_ms(unsigned secs) int zcip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int zcip_main(int argc UNUSED_PARAM, char **argv) { - int state; char *r_opt; const char *l_opt = "169.254.0.0"; + int state; + int nsent; unsigned opts; - // ugly trick, but I want these zeroed in one go + // Ugly trick, but I want these zeroed in one go struct { - const struct ether_addr null_addr; + const struct ether_addr null_ethaddr; struct ifreq ifr; uint32_t chosen_nip; + int conflicts; int timeout_ms; // must be signed - unsigned conflicts; - unsigned nsent; int verbose; } L; -#define null_addr (L.null_addr ) -#define ifr (L.ifr ) -#define chosen_nip (L.chosen_nip) -#define timeout_ms (L.timeout_ms) -#define conflicts (L.conflicts ) -#define nsent (L.nsent ) -#define verbose (L.verbose ) +#define null_ethaddr (L.null_ethaddr) +#define ifr (L.ifr ) +#define chosen_nip (L.chosen_nip ) +#define conflicts (L.conflicts ) +#define timeout_ms (L.timeout_ms ) +#define verbose (L.verbose ) memset(&L, 0, sizeof(L)); INIT_G(); #define FOREGROUND (opts & 1) #define QUIT (opts & 2) - // parse commandline: prog [options] ifname script + // Parse commandline: prog [options] ifname script // exactly 2 args; -v accumulates and implies -f opt_complementary = "=2:vv:vf"; opts = getopt32(argv, "fqr:l:v", &r_opt, &l_opt, &verbose); @@ -242,7 +241,7 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) if (!FOREGROUND) bb_daemonize_or_rexec(0 /*was: DAEMON_CHDIR_ROOT*/, argv); #endif - // open an ARP socket + // Open an ARP socket // (need to do it before openlog to prevent openlog from taking // fd 3 (sock_fd==3)) xmove_fd(xsocket(AF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)), sock_fd); @@ -282,26 +281,26 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) xsetenv("interface", argv_intf); - // initialize the interface (modprobe, ifup, etc) + // Initialize the interface (modprobe, ifup, etc) if (run(argv, "init", 0)) return EXIT_FAILURE; - // initialize G.iface_sockaddr + // Initialize G.iface_sockaddr // G.iface_sockaddr is: { u16 sa_family; u8 sa_data[14]; } //memset(&G.iface_sockaddr, 0, sizeof(G.iface_sockaddr)); //TODO: are we leaving sa_family == 0 (AF_UNSPEC)?! safe_strncpy(G.iface_sockaddr.sa_data, argv_intf, sizeof(G.iface_sockaddr.sa_data)); - // bind to the interface's ARP socket + // Bind to the interface's ARP socket xbind(sock_fd, &G.iface_sockaddr, sizeof(G.iface_sockaddr)); - // get the interface's ethernet address + // Get the interface's ethernet address //memset(&ifr, 0, sizeof(ifr)); strncpy_IFNAMSIZ(ifr.ifr_name, argv_intf); xioctl(sock_fd, SIOCGIFHWADDR, &ifr); - memcpy(&G.eth_addr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN); + memcpy(&G.our_ethaddr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN); - // start with some stable ip address, either a function of + // Start with some stable ip address, either a function of // the hardware address or else the last address we used. // we are taking low-order four bytes, as top-order ones // aren't random enough. @@ -309,17 +308,14 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) // depending on when we detect conflicts. { uint32_t t; - move_from_unaligned32(t, ((char *)&G.eth_addr + 2)); + move_from_unaligned32(t, ((char *)&G.our_ethaddr + 2)); srand(t); } - if (chosen_nip == 0) - chosen_nip = pick_nip(); - // FIXME cases to handle: // - zcip already running! // - link already has local address... just defend/update - // daemonize now; don't delay system startup + // Daemonize now; don't delay system startup if (!FOREGROUND) { #if BB_MMU bb_daemonize(0 /*was: DAEMON_CHDIR_ROOT*/); @@ -327,14 +323,14 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) bb_info_msg("start, interface %s", argv_intf); } - // run the dynamic address negotiation protocol, + // Run the dynamic address negotiation protocol, // restarting after address conflicts: // - start with some address we want to try // - short random delay // - arp probes to see if another host uses it - // 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff, ARP (0x0806): arp who-has 169.254.194.171 tell 0.0.0.0 + // 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff: arp who-has 169.254.194.171 tell 0.0.0.0 // - arp announcements that we're claiming it - // 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff, ARP (0x0806): arp who-has 169.254.194.171 (00:04:e2:64:23:c2) tell 169.254.194.171 + // 00:04:e2:64:23:c2 > ff:ff:ff:ff:ff:ff: arp who-has 169.254.194.171 (00:04:e2:64:23:c2) tell 169.254.194.171 // - use it // - defend it, within limits // exit if: @@ -342,73 +338,73 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) // run "