diff options
Diffstat (limited to 'lib')
114 files changed, 2225 insertions, 712 deletions
diff --git a/lib/Android.bp b/lib/Android.bp index fb0ea07e..529fa238 100644 --- a/lib/Android.bp +++ b/lib/Android.bp @@ -40,7 +40,6 @@ cc_library_headers { ], } - subdirs = [ "*", ] diff --git a/lib/Makefile.darwin-lib b/lib/Makefile.darwin-lib index 95cdd4b4..95e8ee06 100644 --- a/lib/Makefile.darwin-lib +++ b/lib/Makefile.darwin-lib @@ -24,7 +24,8 @@ image: $(BSD_LIB) $(BSD_LIB): $(OBJS) $(E) " GEN_BSD_SOLIB $(BSD_LIB)" $(Q) (cd pic; $(CC) -dynamiclib -compatibility_version 1.0 -current_version $(BSDLIB_VERSION) \ - -flat_namespace -undefined warning -o $(BSD_LIB) $(OBJS)) + -install_name $(BSDLIB_INSTALL_DIR)/$(BSD_LIB) \ + -undefined dynamic_lookup -o $(BSD_LIB) $(OBJS)) $(Q) $(MV) pic/$(BSD_LIB) . $(Q) $(RM) -f ../$(BSD_LIB) $(Q) (cd ..; $(LN) $(LINK_BUILD_FLAGS) \ diff --git a/lib/blkid/Android.bp b/lib/blkid/Android.bp index eb5ae48a..891c74a3 100644 --- a/lib/blkid/Android.bp +++ b/lib/blkid/Android.bp @@ -39,25 +39,10 @@ cc_library { target: { windows: { - include_dirs: [ "external/e2fsprogs/include/mingw" ], - cflags: [ - "-Wno-pointer-to-int-cast", - "-Wno-unused-variable", - ], - clang_cflags: [ - "-Wno-error=typedef-redefinition", - ], - enabled: true + enabled: true, }, }, - cflags: [ - "-Wno-error=attributes", - "-Wno-error=pointer-sign", - "-Wno-unused-parameter", - "-fno-strict-aliasing", - ], - header_libs: ["libext2-headers"], export_include_dirs: ["."], export_header_lib_headers: ["libext2-headers"], diff --git a/lib/blkid/devno.c b/lib/blkid/devno.c index 34ceb3c4..b1cadc9d 100644 --- a/lib/blkid/devno.c +++ b/lib/blkid/devno.c @@ -37,6 +37,12 @@ #include "blkidP.h" +#if defined(__GNUC__) && __GNUC__ >= 8 +/* gcc incorrectly thinks the destination string is not being null-terminated */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-truncation" +#endif + char *blkid_strndup(const char *s, int length) { char *ret; @@ -55,6 +61,10 @@ char *blkid_strndup(const char *s, int length) return ret; } +#if defined(__GNUC__) && __GNUC__ >= 8 +#pragma GCC diagnostic pop +#endif + char *blkid_strdup(const char *s) { return blkid_strndup(s, 0); diff --git a/lib/blkid/getsize.c b/lib/blkid/getsize.c index 75f21d5c..7a6e6fd8 100644 --- a/lib/blkid/getsize.c +++ b/lib/blkid/getsize.c @@ -75,7 +75,7 @@ static int valid_offset(int fd, blkid_loff_t offset) */ blkid_loff_t blkid_get_dev_size(int fd) { - unsigned long long size64; + unsigned long long size64 __BLKID_ATTR((unused)); blkid_loff_t high, low; #if defined DKIOCGETBLOCKCOUNT && defined DKIOCGETBLOCKSIZE /* For Apple Darwin */ diff --git a/lib/blkid/libblkid.3.in b/lib/blkid/libblkid.3.in index 2fea3a9b..18c4a27f 100644 --- a/lib/blkid/libblkid.3.in +++ b/lib/blkid/libblkid.3.in @@ -18,8 +18,8 @@ libblkid \- block device identification library The .B libblkid library is used to identify block devices (disks) as to their content (e.g. -filesystem type) as well as extracting additional information such as -filesystem labels/volume names, unique identifiers/serial numbers, etc. +file system type) as well as extracting additional information such as +file system labels/volume names, unique identifiers/serial numbers, etc. A common use is to allow use of LABEL= and UUID= tags instead of hard-coding specific block device names into configuration files. .P @@ -47,7 +47,7 @@ so the use of the cache file is in this situation. .SH AUTHOR .B libblkid -was written by Andreas Dilger for the ext2 filesystem utilities, with input +was written by Andreas Dilger for the ext2 file system utilities, with input from Ted Ts'o. The library was subsequently heavily modified by Ted Ts'o. .SH FILES .TP diff --git a/lib/blkid/probe.c b/lib/blkid/probe.c index f8687cde..6a3bb247 100644 --- a/lib/blkid/probe.c +++ b/lib/blkid/probe.c @@ -17,6 +17,7 @@ #include <stdio.h> #include <string.h> #include <stdlib.h> +#include <time.h> #include <unistd.h> #include <fcntl.h> #include <ctype.h> @@ -1197,7 +1198,6 @@ static int probe_hfs(struct blkid_probe *probe __BLKID_ATTR((unused)), unsigned char *buf) { struct hfs_mdb *hfs = (struct hfs_mdb *)buf; - unsigned long long *uuid_ptr; char uuid_str[17]; __u64 uuid; @@ -1205,8 +1205,8 @@ static int probe_hfs(struct blkid_probe *probe __BLKID_ATTR((unused)), (memcmp(hfs->embed_sig, "HX", 2) == 0)) return 1; /* Not hfs, but an embedded HFS+ */ - uuid_ptr = (unsigned long long *)hfs->finder_info.id; - uuid = blkid_le64(*uuid_ptr); + memcpy(&uuid, hfs->finder_info.id, 8); + uuid = blkid_le64(uuid); if (uuid) { sprintf(uuid_str, "%016llX", uuid); blkid_set_tag(probe->dev, "UUID", uuid_str, 0); @@ -1242,7 +1242,6 @@ static int probe_hfsplus(struct blkid_probe *probe, unsigned int leaf_node_size; unsigned int leaf_block; unsigned int label_len; - unsigned long long *uuid_ptr; __u64 leaf_off, uuid; char uuid_str[17], label[512]; int ext; @@ -1273,8 +1272,8 @@ static int probe_hfsplus(struct blkid_probe *probe, (memcmp(hfsplus->signature, "HX", 2) != 0)) return 1; - uuid_ptr = (unsigned long long *)hfsplus->finder_info.id; - uuid = blkid_le64(*uuid_ptr); + memcpy(&uuid, hfsplus->finder_info.id, 8); + uuid = blkid_le64(uuid); if (uuid) { sprintf(uuid_str, "%016llX", uuid); blkid_set_tag(probe->dev, "UUID", uuid_str, 0); diff --git a/lib/blkid/probe.h b/lib/blkid/probe.h index dea4081d..063a5b5c 100644 --- a/lib/blkid/probe.h +++ b/lib/blkid/probe.h @@ -814,46 +814,6 @@ struct exfat_entry_label { #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(val & 0xFFFFFFFFUL)) << 32)); -} -#endif - -#if !defined(_BLKID_HAVE_ASM_BITOPS_) - _INLINE_ __u16 blkid_swab16(__u16 val) { return (val >> 8) | (val << 8); @@ -870,9 +830,6 @@ _INLINE_ __u64 blkid_swab64(__u64 val) return (blkid_swab32(val >> 32) | (((__u64) blkid_swab32(val & 0xFFFFFFFFUL)) << 32)); } -#endif - - #ifdef WORDS_BIGENDIAN #define blkid_le16(x) blkid_swab16(x) diff --git a/lib/blkid/save.c b/lib/blkid/save.c index 036f07a4..6f4499cf 100644 --- a/lib/blkid/save.c +++ b/lib/blkid/save.c @@ -154,7 +154,15 @@ int blkid_flush_cache(blkid_cache cache) if (backup) { sprintf(backup, "%s.old", filename); unlink(backup); +#if defined(__GNUC__) && __GNUC__ >= 5 +/* explicit (void) cast is not enough with glibc and _FORTIFY_SOURCE */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-result" +#endif (void) link(filename, backup); +#if defined(__GNUC__) && __GNUC__ >= 5 +#pragma GCC diagnostic pop +#endif free(backup); } if (rename(opened, filename) < 0) diff --git a/lib/config.h b/lib/config.h index 6ac16fec..c2288602 100644 --- a/lib/config.h +++ b/lib/config.h @@ -36,7 +36,6 @@ #if defined(_WIN32) # define HAVE_LINUX_TYPES_H 1 -# define HAVE_WINSOCK_H 1 #endif #if defined(__APPLE__) || defined(__linux__) # define HAVE_FCNTL 1 @@ -55,6 +54,9 @@ # define HAVE_SYS_SELECT_H 1 # define HAVE_SYS_WAIT_H 1 #endif +#ifdef __APPLE__ +# define HAVE_GETMNTINFO 1 +#endif #if defined(__linux__) # define HAVE_EXT2_IOCTLS 1 # define HAVE_FALLOCATE 1 diff --git a/lib/config.h.in b/lib/config.h.in index 4bc7e8e2..ab38266f 100644 --- a/lib/config.h.in +++ b/lib/config.h.in @@ -55,6 +55,9 @@ /* Define to 1 if blkid has blkid_topology_get_dax */ #undef HAVE_BLKID_TOPOLOGY_GET_DAX +/* Define to 1 if you have the BSD-style 'qsort_r' function. */ +#undef HAVE_BSD_QSORT_R + /* Define to 1 if you have the Mac OS X function CFLocaleCopyPreferredLanguages in the CoreFoundation framework. */ #undef HAVE_CFLOCALECOPYPREFERREDLANGUAGES @@ -127,6 +130,9 @@ /* Define to 1 if you have the `getdtablesize' function. */ #undef HAVE_GETDTABLESIZE +/* Define to 1 if you have the `getentropy' function. */ +#undef HAVE_GETENTROPY + /* Define to 1 if you have the `gethostname' function. */ #undef HAVE_GETHOSTNAME @@ -139,6 +145,9 @@ /* Define to 1 if you have the `getpwuid_r' function. */ #undef HAVE_GETPWUID_R +/* Define to 1 if you have the `getrandom' function. */ +#undef HAVE_GETRANDOM + /* Define to 1 if you have the `getrlimit' function. */ #undef HAVE_GETRLIMIT @@ -148,6 +157,9 @@ /* Define if the GNU gettext() function is already present or preinstalled. */ #undef HAVE_GETTEXT +/* Define to 1 if you have the GNU-style 'qsort_r' function. */ +#undef HAVE_GNU_QSORT_R + /* Define if you have the iconv() function and it works. */ #undef HAVE_ICONV @@ -202,6 +214,9 @@ /* Define to 1 if you have the `mallinfo' function. */ #undef HAVE_MALLINFO +/* Define to 1 if you have the `mallinfo2' function. */ +#undef HAVE_MALLINFO2 + /* Define to 1 if you have the <malloc.h> header file. */ #undef HAVE_MALLOC_H @@ -211,12 +226,12 @@ /* Define to 1 if you have the `memalign' function. */ #undef HAVE_MEMALIGN -/* Define to 1 if you have the <memory.h> header file. */ -#undef HAVE_MEMORY_H - /* Define to 1 if you have the `mempcpy' function. */ #undef HAVE_MEMPCPY +/* Define to 1 if you have the <minix/config.h> header file. */ +#undef HAVE_MINIX_CONFIG_H + /* Define to 1 if you have the `mmap' function. */ #undef HAVE_MMAP @@ -289,6 +304,9 @@ /* Define to 1 if you have the `pwrite64' function. */ #undef HAVE_PWRITE64 +/* Define to 1 if you have the `qsort_r' function. */ +#undef HAVE_QSORT_R + /* Define to 1 if dirent has d_reclen */ #undef HAVE_RECLEN_DIRENT @@ -334,6 +352,9 @@ /* Define to 1 if you have the <stdint.h> header file. */ #undef HAVE_STDINT_H +/* Define to 1 if you have the <stdio.h> header file. */ +#undef HAVE_STDIO_H + /* Define to 1 if you have the <stdlib.h> header file. */ #undef HAVE_STDLIB_H @@ -400,6 +421,9 @@ /* Define to 1 if you have the <sys/prctl.h> header file. */ #undef HAVE_SYS_PRCTL_H +/* Define to 1 if you have the <sys/random.h> header file. */ +#undef HAVE_SYS_RANDOM_H + /* Define to 1 if you have the <sys/resource.h> header file. */ #undef HAVE_SYS_RESOURCE_H @@ -466,6 +490,9 @@ /* Define to 1 if you have the `vprintf' function. */ #undef HAVE_VPRINTF +/* Define to 1 if you have the <wchar.h> header file. */ +#undef HAVE_WCHAR_H + /* Define to 1 if you have the `__secure_getenv' function. */ #undef HAVE___SECURE_GETENV @@ -512,7 +539,9 @@ /* The size of `time_t', as computed by sizeof. */ #undef SIZEOF_TIME_T -/* Define to 1 if you have the ANSI C header files. */ +/* Define to 1 if all of the C90 standard headers exist (not just the ones + required in a freestanding environment). This macro is provided for + backward compatibility; new code need not use it. */ #undef STDC_HEADERS /* If the compiler supports a TLS storage class define it to that here */ @@ -522,21 +551,87 @@ #ifndef _ALL_SOURCE # undef _ALL_SOURCE #endif +/* Enable general extensions on macOS. */ +#ifndef _DARWIN_C_SOURCE +# undef _DARWIN_C_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # undef _GNU_SOURCE #endif -/* Enable threading extensions on Solaris. */ +/* Enable X/Open compliant socket functions that do not require linking + with -lxnet on HP-UX 11.11. */ +#ifndef _HPUX_ALT_XOPEN_SOCKET_API +# undef _HPUX_ALT_XOPEN_SOCKET_API +#endif +/* Identify the host operating system as Minix. + This macro does not affect the system headers' behavior. + A future release of Autoconf may stop defining this macro. */ +#ifndef _MINIX +# undef _MINIX +#endif +/* Enable general extensions on NetBSD. + Enable NetBSD compatibility extensions on Minix. */ +#ifndef _NETBSD_SOURCE +# undef _NETBSD_SOURCE +#endif +/* Enable OpenBSD compatibility extensions on NetBSD. + Oddly enough, this does nothing on OpenBSD. */ +#ifndef _OPENBSD_SOURCE +# undef _OPENBSD_SOURCE +#endif +/* Define to 1 if needed for POSIX-compatible behavior. */ +#ifndef _POSIX_SOURCE +# undef _POSIX_SOURCE +#endif +/* Define to 2 if needed for POSIX-compatible behavior. */ +#ifndef _POSIX_1_SOURCE +# undef _POSIX_1_SOURCE +#endif +/* Enable POSIX-compatible threading on Solaris. */ #ifndef _POSIX_PTHREAD_SEMANTICS # undef _POSIX_PTHREAD_SEMANTICS #endif +/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */ +#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ +# undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */ +#ifndef __STDC_WANT_IEC_60559_BFP_EXT__ +# undef __STDC_WANT_IEC_60559_BFP_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */ +#ifndef __STDC_WANT_IEC_60559_DFP_EXT__ +# undef __STDC_WANT_IEC_60559_DFP_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */ +#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__ +# undef __STDC_WANT_IEC_60559_FUNCS_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */ +#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ +# undef __STDC_WANT_IEC_60559_TYPES_EXT__ +#endif +/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */ +#ifndef __STDC_WANT_LIB_EXT2__ +# undef __STDC_WANT_LIB_EXT2__ +#endif +/* Enable extensions specified by ISO/IEC 24747:2009. */ +#ifndef __STDC_WANT_MATH_SPEC_FUNCS__ +# undef __STDC_WANT_MATH_SPEC_FUNCS__ +#endif /* Enable extensions on HP NonStop. */ #ifndef _TANDEM_SOURCE # undef _TANDEM_SOURCE #endif -/* Enable general extensions on Solaris. */ -#ifndef __EXTENSIONS__ -# undef __EXTENSIONS__ +/* Enable X/Open extensions. Define to 500 only if necessary + to make mbstate_t available. */ +#ifndef _XOPEN_SOURCE +# undef _XOPEN_SOURCE #endif @@ -558,17 +653,13 @@ # endif #endif +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + /* Define to 1 if Apple Darwin libintl workaround is needed */ #undef _INTL_REDIRECT_MACROS -/* Define to 1 if on MINIX. */ -#undef _MINIX - -/* Define to 2 if the system does not provide POSIX.1 features except with - this defined. */ -#undef _POSIX_1_SOURCE - -/* Define to 1 if you need to in order for `stat' and other things to work. */ -#undef _POSIX_SOURCE +/* Define for large files, on AIX-style hosts. */ +#undef _LARGE_FILES #include <dirpaths.h> diff --git a/lib/e2p/Android.bp b/lib/e2p/Android.bp index 7be2d804..bed92c12 100644 --- a/lib/e2p/Android.bp +++ b/lib/e2p/Android.bp @@ -46,24 +46,9 @@ cc_library { "percent.c", ], - cflags: [ - "-Wno-error=attributes", - "-Wno-unused-parameter", - ], - target: { windows: { - include_dirs: [ "external/e2fsprogs/include/mingw" ], enabled: true, - cflags: [ - "-Wno-unused-variable", - ], - clang_cflags: [ - "-Wno-error=typedef-redefinition", - ], - host_ldlibs: [ - "-lws2_32", - ], }, }, diff --git a/lib/e2p/Makefile.in b/lib/e2p/Makefile.in index cd235117..92d9c018 100644 --- a/lib/e2p/Makefile.in +++ b/lib/e2p/Makefile.in @@ -219,4 +219,5 @@ encoding.o: $(srcdir)/encoding.c $(top_builddir)/lib/config.h \ $(top_builddir)/lib/dirpaths.h $(srcdir)/e2p.h \ $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h errcode.o: $(srcdir)/errcode.c $(top_builddir)/lib/config.h \ - $(top_builddir)/lib/dirpaths.h + $(top_builddir)/lib/dirpaths.h $(srcdir)/e2p.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h diff --git a/lib/e2p/e2p.h b/lib/e2p/e2p.h index 65702a7e..5f4793e6 100644 --- a/lib/e2p/e2p.h +++ b/lib/e2p/e2p.h @@ -89,4 +89,4 @@ const char *e2p_encoding2str(int encoding); int e2p_get_encoding_flags(int encoding); int e2p_str2encoding_flags(int encoding, char *param, __u16 *flags); -const char *e2p_errcode2str(int err); +const char *e2p_errcode2str(unsigned int err); diff --git a/lib/e2p/errcode.c b/lib/e2p/errcode.c index 7e426553..1627c9d7 100644 --- a/lib/e2p/errcode.c +++ b/lib/e2p/errcode.c @@ -7,6 +7,8 @@ #include <stdlib.h> #include <string.h> +#include "e2p.h" + static const char *err_string[] = { "", "UNKNOWN", /* 1 */ @@ -32,14 +34,14 @@ static const char *err_string[] = { (sizeof(array) / sizeof(array[0])) /* Return the name of an encoding or NULL */ -const char *e2p_errcode2str(int err) +const char *e2p_errcode2str(unsigned int err) { static char buf[32]; if (err < ARRAY_SIZE(err_string)) return err_string[err]; - sprintf(buf, "UNKNOWN_ERRCODE_%d", err); + sprintf(buf, "UNKNOWN_ERRCODE_%u", err); return buf; } diff --git a/lib/e2p/fgetflags.c b/lib/e2p/fgetflags.c index 93e130c6..24a7166b 100644 --- a/lib/e2p/fgetflags.c +++ b/lib/e2p/fgetflags.c @@ -79,14 +79,26 @@ int fgetflags (const char * name, unsigned long * flags) *flags = f; return (save_errno); #elif 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)) { + errno = EOPNOTSUPP; + return -1; + } fd = open(name, OPEN_FLAGS); if (fd == -1) { if (errno == ELOOP || errno == ENXIO) errno = EOPNOTSUPP; return -1; } + if (!fstat(fd, &buf) && + !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) { + close(fd); + errno = EOPNOTSUPP; + return -1; + } r = ioctl(fd, EXT2_IOC_GETFLAGS, &f); if (r == -1) { if (errno == ENOTTY) diff --git a/lib/e2p/fgetversion.c b/lib/e2p/fgetversion.c index a65e9a5c..f3a5b4cd 100644 --- a/lib/e2p/fgetversion.c +++ b/lib/e2p/fgetversion.c @@ -65,8 +65,6 @@ int fgetversion(const char *name, unsigned long *version) rc = syscall(SYS_fsctl, name, EXT2_IOC_GETVERSION, &ver, 0); # endif /* !APPLE_DARWIN */ #else /* ! HAVE_EXT2_IOCTLS */ - extern int errno; - errno = EOPNOTSUPP; #endif /* ! HAVE_EXT2_IOCTLS */ if (rc == 0) diff --git a/lib/e2p/fsetflags.c b/lib/e2p/fsetflags.c index 6455e386..d865d243 100644 --- a/lib/e2p/fsetflags.c +++ b/lib/e2p/fsetflags.c @@ -80,14 +80,26 @@ int fsetflags (const char * name, unsigned long flags) int f = (int) flags; return syscall(SYS_fsctl, name, EXT2_IOC_SETFLAGS, &f, 0); #elif 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)) { + errno = EOPNOTSUPP; + return -1; + } fd = open(name, OPEN_FLAGS); if (fd == -1) { if (errno == ELOOP || errno == ENXIO) errno = EOPNOTSUPP; return -1; } + if (!fstat(fd, &buf) && + !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) { + close(fd); + errno = EOPNOTSUPP; + return -1; + } f = (int) flags; r = ioctl(fd, EXT2_IOC_SETFLAGS, &f); if (r == -1) { diff --git a/lib/e2p/fsetversion.c b/lib/e2p/fsetversion.c index c2e04559..5f844b55 100644 --- a/lib/e2p/fsetversion.c +++ b/lib/e2p/fsetversion.c @@ -65,7 +65,6 @@ int fsetversion (const char * name, unsigned long version) return syscall(SYS_fsctl, name, EXT2_IOC_SETVERSION, &ver, 0); #endif #else /* ! HAVE_EXT2_IOCTLS */ - extern int errno; errno = EOPNOTSUPP; return -1; #endif /* ! HAVE_EXT2_IOCTLS */ diff --git a/lib/e2p/getflags.c b/lib/e2p/getflags.c index e4e2ad73..6708cd68 100644 --- a/lib/e2p/getflags.c +++ b/lib/e2p/getflags.c @@ -30,8 +30,8 @@ int getflags (int fd, unsigned long * flags) { - struct stat buf; #if HAVE_STAT_FLAGS + struct stat buf; if (fstat (fd, &buf) == -1) return -1; @@ -53,6 +53,7 @@ int getflags (int fd, unsigned long * flags) return 0; #else #if HAVE_EXT2_IOCTLS + struct stat buf; int r, f; if (!fstat(fd, &buf) && diff --git a/lib/e2p/getversion.c b/lib/e2p/getversion.c index 9f719b4a..d374a0ea 100644 --- a/lib/e2p/getversion.c +++ b/lib/e2p/getversion.c @@ -35,7 +35,6 @@ int getversion (int fd, unsigned long * version) *version = ver; return r; #else /* ! HAVE_EXT2_IOCTLS */ - extern int errno; errno = EOPNOTSUPP; return -1; #endif /* ! HAVE_EXT2_IOCTLS */ diff --git a/lib/e2p/ls.c b/lib/e2p/ls.c index 176bee0f..9511d2c7 100644 --- a/lib/e2p/ls.c +++ b/lib/e2p/ls.c @@ -312,7 +312,7 @@ void list_super2(struct ext2_super_block * sb, FILE *f) sb->s_first_meta_bg); if (sb->s_log_groups_per_flex) fprintf(f, "Flex block group size: %u\n", - 1 << sb->s_log_groups_per_flex); + 1U << sb->s_log_groups_per_flex); if (sb->s_mkfs_time) { tm = sb->s_mkfs_time; fprintf(f, "Filesystem created: %s", ctime(&tm)); diff --git a/lib/e2p/setversion.c b/lib/e2p/setversion.c index 2bc93374..dd4a3f06 100644 --- a/lib/e2p/setversion.c +++ b/lib/e2p/setversion.c @@ -34,7 +34,6 @@ int setversion (int fd, unsigned long version) ver = (int) version; return ioctl (fd, EXT2_IOC_SETVERSION, &ver); #else /* ! HAVE_EXT2_IOCTLS */ - extern int errno; errno = EOPNOTSUPP; return -1; #endif /* ! HAVE_EXT2_IOCTLS */ diff --git a/lib/et/Android.bp b/lib/et/Android.bp index 07f3c277..565feb59 100644 --- a/lib/et/Android.bp +++ b/lib/et/Android.bp @@ -31,9 +31,6 @@ cc_library { target: { windows: { enabled: true, - cflags: [ - "-Wno-unused-variable", - ], }, }, diff --git a/lib/et/com_err.c b/lib/et/com_err.c index d38998a2..7294c6d8 100644 --- a/lib/et/com_err.c +++ b/lib/et/com_err.c @@ -62,7 +62,8 @@ default_com_err_proc (const char *whoami, errcode_t code, const fflush(stderr); } -typedef void (*errf) (const char *, errcode_t, const char *, va_list); +typedef void (*errf) (const char *, errcode_t, const char *, va_list) + COM_ERR_ATTR((format(printf, 3, 0))); errf com_err_hook = default_com_err_proc; diff --git a/lib/et/error_message.c b/lib/et/error_message.c index cd9f57f5..8b9474ff 100644 --- a/lib/et/error_message.c +++ b/lib/et/error_message.c @@ -235,7 +235,6 @@ static FILE *debug_f = 0; static void init_debug(void) { char *dstr, *fn, *tmp; - int fd, flags; if (debug_mask & DEBUG_INIT) return; @@ -257,10 +256,12 @@ static void init_debug(void) if (!debug_f) debug_f = fopen("/dev/tty", "a"); if (debug_f) { - fd = fileno(debug_f); -#if defined(HAVE_FCNTL) +#ifdef HAVE_FCNTL + int fd = fileno(debug_f); + if (fd >= 0) { - flags = fcntl(fd, F_GETFD); + int flags = fcntl(fd, F_GETFD); + if (flags >= 0) flags = fcntl(fd, F_SETFD, flags | FD_CLOEXEC); if (flags < 0) { @@ -274,7 +275,6 @@ static void init_debug(void) #endif } else debug_mask = DEBUG_INIT; - } /* diff --git a/lib/et/texinfo.tex b/lib/et/texinfo.tex index dddd0140..dd526155 100644 --- a/lib/et/texinfo.tex +++ b/lib/et/texinfo.tex @@ -404,7 +404,7 @@ \def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm} \def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm} -% Each occurence of `\^^M' or `<space>\^^M' is replaced by a single space. +% Each occurrence of `\^^M' or `<space>\^^M' is replaced by a single space. % % \argremovec might leave us with trailing space, e.g., % @end itemize @c foo @@ -430,7 +430,7 @@ % to get _exactly_ the rest of the line, we had to prevent such situation. % We prepended an \empty token at the very beginning and we expand it now, % just before passing the control to \next. -% (Similarily, we have to think about #3 of \argcheckspacesY above: it is +% (Similarly, we have to think about #3 of \argcheckspacesY above: it is % either the null string, or it ends with \^^M---thus there is no danger % that a pair of braces would be stripped. % @@ -487,7 +487,7 @@ % used to check whether the current environment is the one expected. % % Non-false conditionals (@iftex, @ifset) don't fit into this, so they -% are not treated as enviroments; they don't open a group. (The +% are not treated as environments; they don't open a group. (The % implementation of @end takes care not to call \endgroup in this % special case.) @@ -510,7 +510,7 @@ \fi } -% Evironment mismatch, #1 expected: +% Environment mismatch, #1 expected: \def\badenverr{% \errhelp = \EMsimple \errmessage{This command can appear only \inenvironment\temp, @@ -4045,7 +4045,7 @@ where each line of input produces a line of output.} \chardef\maxseclevel = 3 % % A numbered section within an unnumbered changes to unnumbered too. -% To achive this, remember the "biggest" unnum. sec. we are currently in: +% To achieve this, remember the "biggest" unnum. sec. we are currently in: \chardef\unmlevel = \maxseclevel % % Trace whether the current chapter is an appendix or not: @@ -6417,7 +6417,7 @@ where each line of input produces a line of output.} % In case a @footnote appears in a vbox, save the footnote text and create % the real \insert just after the vbox finished. Otherwise, the insertion % would be lost. -% Similarily, if a @footnote appears inside an alignment, save the footnote +% Similarly, if a @footnote appears inside an alignment, save the footnote % text to a box and make the \insert when a row of the table is finished. % And the same can be done for other insert classes. --kasal, 16nov03. diff --git a/lib/ext2fs/Android.bp b/lib/ext2fs/Android.bp index 919adb13..db8b3b7e 100644 --- a/lib/ext2fs/Android.bp +++ b/lib/ext2fs/Android.bp @@ -112,23 +112,14 @@ cc_library { "libsparse", "libz", ], - cflags: ["-Wno-unused-parameter"], target: { android: { - shared_libs: [ "libext2_uuid" ], + shared_libs: ["libext2_uuid"], }, windows: { enabled: true, - include_dirs: [ "external/e2fsprogs/include/mingw" ], - cflags: [ - "-Wno-error=cpp", - "-Wno-format", - "-Wno-unused-variable", - ], - clang_cflags: [ - "-Wno-error=typedef-redefinition", - ], - host_ldlibs: ["-lws2_32"], + srcs: ["windows_io.c"], + exclude_srcs: ["unix_io.c"], }, }, diff --git a/lib/ext2fs/Makefile.in b/lib/ext2fs/Makefile.in index 5d9af86e..1b6a74b8 100644 --- a/lib/ext2fs/Makefile.in +++ b/lib/ext2fs/Makefile.in @@ -127,7 +127,7 @@ OBJS= $(DEBUGFS_LIB_OBJS) $(RESIZE_LIB_OBJS) $(E2IMAGE_LIB_OBJS) \ symlink.o \ $(TDB_OBJ) \ undo_io.o \ - unix_io.o \ + @OS_IO_FILE@.o \ sparse_io.o \ unlink.o \ valid_blk.o \ @@ -217,7 +217,7 @@ SRCS= ext2_err.c \ $(srcdir)/tst_getsize.c \ $(srcdir)/tst_iscan.c \ $(srcdir)/undo_io.c \ - $(srcdir)/unix_io.c \ + $(srcdir)/@OS_IO_FILE@.c \ $(srcdir)/sparse_io.c \ $(srcdir)/unlink.c \ $(srcdir)/valid_blk.c \ @@ -630,6 +630,19 @@ $(srcdir)/utf8data.h: -t $(top_srcdir)/util/ucd/NormalizationTest-11.0.0.txt \ -o $@ +# +# This needs to be manually maintained since "make depend" on a +# Linux system is going to blow up due to the lack of windows.h +# header file. If someone on Windows tries to run "make depend", +# they will need to comment this chunk below. +# +windows_io.o: $(srcdir)/windows_io.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/ext2_fs.h \ + $(top_builddir)/lib/ext2fs/ext2_types.h $(srcdir)/ext2fs.h \ + $(srcdir)/ext2_fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \ + $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(srcdir)/ext2_ext_attr.h $(srcdir)/bitops.h $(srcdir)/ext2fsP.h + # +++ Dependency line eater +++ # # Makefile dependencies follow. This must be the last section in @@ -1414,6 +1427,7 @@ journal.o: $(top_srcdir)/debugfs/journal.c $(top_builddir)/lib/config.h \ $(srcdir)/hashmap.h $(srcdir)/bitops.h $(srcdir)/kernel-jbd.h \ $(srcdir)/jfs_compat.h $(srcdir)/kernel-list.h $(srcdir)/compiler.h revoke.o: $(top_srcdir)/e2fsck/revoke.c $(top_srcdir)/e2fsck/jfs_user.h \ + $(top_builddir)/lib/config.h $(top_builddir)/lib/dirpaths.h \ $(srcdir)/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ $(srcdir)/ext2fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ @@ -1421,6 +1435,7 @@ revoke.o: $(top_srcdir)/e2fsck/revoke.c $(top_srcdir)/e2fsck/jfs_user.h \ $(srcdir)/kernel-jbd.h $(srcdir)/jfs_compat.h $(srcdir)/kernel-list.h \ $(srcdir)/compiler.h recovery.o: $(top_srcdir)/e2fsck/recovery.c $(top_srcdir)/e2fsck/jfs_user.h \ + $(top_builddir)/lib/config.h $(top_builddir)/lib/dirpaths.h \ $(srcdir)/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ $(srcdir)/ext2fs.h $(srcdir)/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \ $(srcdir)/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ diff --git a/lib/ext2fs/alloc_stats.c b/lib/ext2fs/alloc_stats.c index 3949f618..6f98bcc7 100644 --- a/lib/ext2fs/alloc_stats.c +++ b/lib/ext2fs/alloc_stats.c @@ -62,7 +62,8 @@ void ext2fs_block_alloc_stats2(ext2_filsys fs, blk64_t blk, int inuse) { int group = ext2fs_group_of_blk2(fs, blk); - if (blk >= ext2fs_blocks_count(fs->super)) { + if (blk < fs->super->s_first_data_block || + blk >= ext2fs_blocks_count(fs->super)) { #ifndef OMIT_COM_ERR com_err("ext2fs_block_alloc_stats", 0, "Illegal block number: %lu", (unsigned long) blk); diff --git a/lib/ext2fs/alloc_tables.c b/lib/ext2fs/alloc_tables.c index 971a6ceb..e8a1fef0 100644 --- a/lib/ext2fs/alloc_tables.c +++ b/lib/ext2fs/alloc_tables.c @@ -43,7 +43,7 @@ static blk64_t flexbg_offset(ext2_filsys fs, dgrp_t group, blk64_t start_blk, blk64_t last_blk, first_free = 0; dgrp_t last_grp; - flexbg_size = 1 << fs->super->s_log_groups_per_flex; + flexbg_size = 1U << fs->super->s_log_groups_per_flex; flexbg = group / flexbg_size; size = rem_grp * elem_size; @@ -97,7 +97,7 @@ errcode_t ext2fs_allocate_group_table(ext2_filsys fs, dgrp_t group, if (ext2fs_has_feature_flex_bg(fs->super) && fs->super->s_log_groups_per_flex) { - flexbg_size = 1 << fs->super->s_log_groups_per_flex; + flexbg_size = 1U << fs->super->s_log_groups_per_flex; last_grp = group | (flexbg_size - 1); if (last_grp > fs->group_desc_count-1) last_grp = fs->group_desc_count-1; diff --git a/lib/ext2fs/bitmaps.c b/lib/ext2fs/bitmaps.c index 834a3962..8bfa24b1 100644 --- a/lib/ext2fs/bitmaps.c +++ b/lib/ext2fs/bitmaps.c @@ -58,6 +58,9 @@ errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs, EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + if (ext2fs_has_feature_journal_dev(fs->super)) + return EXT2_ET_EXTERNAL_JOURNAL_NOSUPP; + fs->write_bitmaps = ext2fs_write_bitmaps; start = 1; @@ -91,6 +94,9 @@ errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs, EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + if (ext2fs_has_feature_journal_dev(fs->super)) + return EXT2_ET_EXTERNAL_JOURNAL_NOSUPP; + fs->write_bitmaps = ext2fs_write_bitmaps; start = EXT2FS_B2C(fs, fs->super->s_first_data_block); @@ -131,6 +137,9 @@ errcode_t ext2fs_allocate_subcluster_bitmap(ext2_filsys fs, EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + if (ext2fs_has_feature_journal_dev(fs->super)) + return EXT2_ET_EXTERNAL_JOURNAL_NOSUPP; + fs->write_bitmaps = ext2fs_write_bitmaps; if (!fs->cluster_ratio_bits) diff --git a/lib/ext2fs/bitops.c b/lib/ext2fs/bitops.c index c4a1d4e0..ce2acc46 100644 --- a/lib/ext2fs/bitops.c +++ b/lib/ext2fs/bitops.c @@ -19,14 +19,8 @@ #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 assembly language, if at all possible. - * - * C language equivalents written by Theodore Ts'o, 9/26/92. + * C language bitmap functions 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. */ @@ -65,8 +59,6 @@ int ext2fs_test_bit(unsigned int nr, const void * addr) return (mask & *ADDR); } -#endif /* !_EXT2_HAVE_ASM_BITOPS_ */ - void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg, const char *description) { @@ -78,9 +70,7 @@ void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg, #endif } -/* - * C-only 64 bit ops. - */ +/* Bitmap functions that take a 64-bit offset */ int ext2fs_set_bit64(__u64 nr, void * addr) { diff --git a/lib/ext2fs/bitops.h b/lib/ext2fs/bitops.h index 505b3c9c..9edf5944 100644 --- a/lib/ext2fs/bitops.h +++ b/lib/ext2fs/bitops.h @@ -219,14 +219,6 @@ extern errcode_t ext2fs_find_first_set_generic_bmap(ext2fs_generic_bitmap bitmap * functions at all; they will be included as normal functions in * inline.c */ -#ifdef NO_INLINE_FUNCS -#if (defined(__GNUC__) && (defined(__i386__) || defined(__i486__) || \ - defined(__i586__))) - /* This prevents bitops.c from trying to include the C */ - /* function version of these functions */ -#define _EXT2_HAVE_ASM_BITOPS_ -#endif -#endif /* NO_INLINE_FUNCS */ #if (defined(INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS)) #ifdef INCLUDE_INLINE_FUNCS @@ -285,90 +277,6 @@ _INLINE_ void ext2fs_fast_clear_bit64(__u64 nr, void * addr) *ADDR &= (unsigned char) ~(1 << (nr & 0x07)); } - -#if ((defined __GNUC__) && !defined(_EXT2_USE_C_VERSIONS_) && \ - (defined(__i386__) || defined(__i486__) || defined(__i586__))) - -#define _EXT2_HAVE_ASM_BITOPS_ -#define _EXT2_HAVE_ASM_SWAB_ - -/* - * These are done by inline assembly for speed reasons..... - * - * All bitoperations return 0 if the bit was cleared before the - * operation and != 0 if it was not. Bit 0 is the LSB of addr; bit 32 - * is the LSB of (addr+1). - */ - -/* - * Some hacks to defeat gcc over-optimizations.. - */ -struct __dummy_h { unsigned long a[100]; }; -#define EXT2FS_ADDR (*(struct __dummy_h *) addr) -#define EXT2FS_CONST_ADDR (*(const struct __dummy_h *) addr) - -_INLINE_ int ext2fs_set_bit(unsigned int nr, void * addr) -{ - int oldbit; - - addr = (void *) (((unsigned char *) addr) + (nr >> 3)); - __asm__ __volatile__("btsl %2,%1\n\tsbbl %0,%0" - :"=r" (oldbit),"+m" (EXT2FS_ADDR) - :"r" (nr & 7)); - return oldbit; -} - -_INLINE_ int ext2fs_clear_bit(unsigned int nr, void * addr) -{ - int oldbit; - - addr = (void *) (((unsigned char *) addr) + (nr >> 3)); - __asm__ __volatile__("btrl %2,%1\n\tsbbl %0,%0" - :"=r" (oldbit),"+m" (EXT2FS_ADDR) - :"r" (nr & 7)); - return oldbit; -} - -_INLINE_ int ext2fs_test_bit(unsigned int nr, const void * addr) -{ - int oldbit; - - addr = (const void *) (((const unsigned char *) addr) + (nr >> 3)); - __asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0" - :"=r" (oldbit) - :"m" (EXT2FS_CONST_ADDR),"r" (nr & 7)); - return oldbit; -} - -_INLINE_ __u32 ext2fs_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 ext2fs_swab16(__u16 val) -{ - __asm__("xchgb %b0,%h0" /* swap bytes */ \ - : "=q" (val) \ - : "0" (val)); \ - return val; -} - -#undef EXT2FS_ADDR - -#endif /* i386 */ - - -#if !defined(_EXT2_HAVE_ASM_SWAB_) - _INLINE_ __u16 ext2fs_swab16(__u16 val) { return (val >> 8) | (__u16) (val << 8); @@ -380,8 +288,6 @@ _INLINE_ __u32 ext2fs_swab32(__u32 val) ((val<<8)&0xFF0000) | (val<<24)); } -#endif /* !_EXT2_HAVE_ASM_SWAB */ - _INLINE_ __u64 ext2fs_swab64(__u64 val) { return (ext2fs_swab32((__u32) (val >> 32)) | @@ -691,12 +597,9 @@ _INLINE_ void ext2fs_fast_unmark_block_bitmap_range2(ext2fs_block_bitmap bitmap, #undef _INLINE_ #endif -#ifndef _EXT2_HAVE_ASM_BITOPS_ 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); -#endif - extern int ext2fs_set_bit64(__u64 nr,void * addr); extern int ext2fs_clear_bit64(__u64 nr, void * addr); extern int ext2fs_test_bit64(__u64 nr, const void * addr); diff --git a/lib/ext2fs/blknum.c b/lib/ext2fs/blknum.c index 3458b128..04839d81 100644 --- a/lib/ext2fs/blknum.c +++ b/lib/ext2fs/blknum.c @@ -204,7 +204,7 @@ struct ext2_group_desc *ext2fs_group_desc(ext2_filsys fs, struct ext2_group_desc *ret_gdp; errcode_t retval; static char *buf = 0; - static int bufsize = 0; + static unsigned bufsize = 0; blk64_t blk; int desc_size = EXT2_DESC_SIZE(fs->super) & ~7; int desc_per_blk = EXT2_DESC_PER_BLOCK(fs->super); diff --git a/lib/ext2fs/compiler.h b/lib/ext2fs/compiler.h index 9aa9b4ec..3bb3521d 100644 --- a/lib/ext2fs/compiler.h +++ b/lib/ext2fs/compiler.h @@ -1,22 +1,26 @@ #ifndef _EXT2FS_COMPILER_H #define _EXT2FS_COMPILER_H -#ifndef __has_builtin -#define __has_builtin(x) 0 -#endif +#include <stddef.h> + +#ifdef __GNUC__ -#undef offsetof -#if __has_builtin(__builtin_offsetof) -#define offsetof(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER) -#elif defined(__compiler_offsetof) -#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER) +#ifndef __GNUC_PREREQ +#if defined(__GNUC__) && defined(__GNUC_MINOR__) +#define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) #else -#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#define __GNUC_PREREQ(maj, min) 0 +#endif #endif -#define container_of(ptr, type, member) ({ \ - const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \ +#define container_of(ptr, type, member) ({ \ + __typeof__( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) +#else +#define container_of(ptr, type, member) \ + ((type *)((char *)(ptr) - offsetof(type, member))) +#endif #endif /* _EXT2FS_COMPILER_H */ diff --git a/lib/ext2fs/crc32c.c b/lib/ext2fs/crc32c.c index 8ad0050f..df5cf9bb 100644 --- a/lib/ext2fs/crc32c.c +++ b/lib/ext2fs/crc32c.c @@ -72,8 +72,14 @@ #if CRC_LE_BITS > 8 || CRC_BE_BITS > 8 +#if CRC_LE_BITS < 64 && CRC_BE_BITS < 64 +#define CRC_INLINE inline +#else +#define CRC_INLINE +#endif + /* implements slicing-by-4 or slicing-by-8 algorithm */ -static inline uint32_t +static CRC_INLINE uint32_t crc32_body(uint32_t crc, unsigned char const *buf, size_t len, const uint32_t (*tab)[256]) { diff --git a/lib/ext2fs/dir_iterate.c b/lib/ext2fs/dir_iterate.c index b2b77693..7798a482 100644 --- a/lib/ext2fs/dir_iterate.c +++ b/lib/ext2fs/dir_iterate.c @@ -221,6 +221,10 @@ int ext2fs_process_dir_block(ext2_filsys fs, if (ext2fs_has_feature_metadata_csum(fs->super)) csum_size = sizeof(struct ext2_dir_entry_tail); + if (buflen < 8) { + ctx->errcode = EXT2_ET_DIR_CORRUPTED; + return BLOCK_ABORT; + } while (offset < buflen - 8) { dirent = (struct ext2_dir_entry *) (ctx->buf + offset); if (ext2fs_get_rec_len(fs, dirent, &rec_len)) diff --git a/lib/ext2fs/ext2_err.c b/lib/ext2fs/ext2_err.c index 528fe9f7..322361c8 100644 --- a/lib/ext2fs/ext2_err.c +++ b/lib/ext2fs/ext2_err.c @@ -8,7 +8,7 @@ #define N_(a) a static const char * const text[] = { - N_( "EXT2FS Library version v1.46.2-1113-gb00aa279"), + N_( "EXT2FS Library version android-t-qpr1-beta-2-gpl-369-g8ed4b2673"), N_( "Wrong magic number for ext2_filsys structure"), N_( "Wrong magic number for badblocks_list structure"), N_( "Wrong magic number for badblocks_iterate structure"), @@ -189,6 +189,8 @@ static const char * const text[] = { N_( "Inode containing extended attribute value is corrupted"), N_( "Group descriptors not loaded"), N_( "The internal ext2_filsys data structure appears to be corrupted"), + N_( "Found cyclic loop in extent tree"), + N_( "Operation not supported on an external journal"), 0 }; @@ -203,7 +205,7 @@ struct et_list { }; extern struct et_list *_et_list; -const struct error_table et_ext2_error_table = { text, 2133571328L, 181 }; +const struct error_table et_ext2_error_table = { text, 2133571328L, 183 }; static struct et_list link = { 0, 0 }; diff --git a/lib/ext2fs/ext2_err.et.in b/lib/ext2fs/ext2_err.et.in index cf0e00ea..de140198 100644 --- a/lib/ext2fs/ext2_err.et.in +++ b/lib/ext2fs/ext2_err.et.in @@ -551,4 +551,10 @@ ec EXT2_ET_NO_GDESC, ec EXT2_FILSYS_CORRUPTED, "The internal ext2_filsys data structure appears to be corrupted" +ec EXT2_ET_EXTENT_CYCLE, + "Found cyclic loop in extent tree" + +ec EXT2_ET_EXTERNAL_JOURNAL_NOSUPP, + "Operation not supported on an external journal" + end diff --git a/lib/ext2fs/ext2_err.h b/lib/ext2fs/ext2_err.h index bfae93d5..3575af08 100644 --- a/lib/ext2fs/ext2_err.h +++ b/lib/ext2fs/ext2_err.h @@ -186,6 +186,8 @@ #define EXT2_ET_EA_INODE_CORRUPTED (2133571506L) #define EXT2_ET_NO_GDESC (2133571507L) #define EXT2_FILSYS_CORRUPTED (2133571508L) +#define EXT2_ET_EXTENT_CYCLE (2133571509L) +#define EXT2_ET_EXTERNAL_JOURNAL_NOSUPP (2133571510L) extern const struct error_table et_ext2_error_table; extern void initialize_ext2_error_table(void); diff --git a/lib/ext2fs/ext2_ext_attr.h b/lib/ext2fs/ext2_ext_attr.h index f2042ed5..c6068c48 100644 --- a/lib/ext2fs/ext2_ext_attr.h +++ b/lib/ext2fs/ext2_ext_attr.h @@ -57,6 +57,17 @@ struct ext2_ext_attr_entry { #define EXT2_XATTR_SIZE(size) \ (((size) + EXT2_EXT_ATTR_ROUND) & ~EXT2_EXT_ATTR_ROUND) +/* + * XATTR_SIZE_MAX is currently 64k, but for the purposes of checking + * for file system consistency errors, we use a somewhat bigger value. + * This allows XATTR_SIZE_MAX to grow in the future, but by using this + * instead of INT_MAX for certain consistency checks, we don't need to + * worry about arithmetic overflows. (Actually XATTR_SIZE_MAX is + * defined in include/uapi/linux/limits.h, so changing it is going + * not going to be trivial....) + */ +#define EXT2_XATTR_SIZE_MAX (1 << 24) + #ifdef __KERNEL__ # ifdef CONFIG_EXT2_FS_EXT_ATTR extern int ext2_get_ext_attr(struct inode *, const char *, char *, size_t, int); diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h index e92a0452..01d2573b 100644 --- a/lib/ext2fs/ext2_fs.h +++ b/lib/ext2fs/ext2_fs.h @@ -27,6 +27,18 @@ #endif #endif +#ifndef __nonstring +#ifdef __has_attribute +#if __has_attribute(__nonstring__) +#define __nonstring __attribute__((__nonstring__)) +#else +#define __nonstring +#endif /* __has_attribute(__nonstring__) */ +#else +# define __nonstring +#endif /* __has_attribute */ +#endif /* __nonstring */ + /* * The second extended filesystem constants/structures */ @@ -525,8 +537,8 @@ struct ext2_inode_large { #endif /* __GNU__ */ #endif /* defined(__KERNEL__) || defined(__linux__) */ -#define inode_uid(inode) ((inode).i_uid | (inode).osd2.linux2.l_i_uid_high << 16) -#define inode_gid(inode) ((inode).i_gid | (inode).osd2.linux2.l_i_gid_high << 16) +#define inode_uid(inode) ((inode).i_uid | (unsigned)(inode).osd2.linux2.l_i_uid_high << 16) +#define inode_gid(inode) ((inode).i_gid | (unsigned)(inode).osd2.linux2.l_i_gid_high << 16) #define inode_projid(inode) ((inode).i_projid) #define ext2fs_set_i_uid_high(inode,x) ((inode).osd2.linux2.l_i_uid_high = (x)) #define ext2fs_set_i_gid_high(inode,x) ((inode).osd2.linux2.l_i_gid_high = (x)) @@ -683,9 +695,9 @@ struct ext2_super_block { __u32 s_feature_compat; /* compatible feature set */ /*060*/ __u32 s_feature_incompat; /* incompatible feature set */ __u32 s_feature_ro_compat; /* readonly-compatible feature set */ -/*068*/ __u8 s_uuid[16]; /* 128-bit uuid for volume */ -/*078*/ __u8 s_volume_name[EXT2_LABEL_LEN]; /* volume name, no NUL? */ -/*088*/ __u8 s_last_mounted[64]; /* directory last mounted on, no NUL? */ +/*068*/ __u8 s_uuid[16] __nonstring; /* 128-bit uuid for volume */ +/*078*/ __u8 s_volume_name[EXT2_LABEL_LEN] __nonstring; /* volume name, no NUL? */ +/*088*/ __u8 s_last_mounted[64] __nonstring; /* directory last mounted on, no NUL? */ /*0c8*/ __u32 s_algorithm_usage_bitmap; /* For compression */ /* * Performance hints. Directory preallocation should only @@ -697,7 +709,7 @@ struct ext2_super_block { /* * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set. */ -/*0d0*/ __u8 s_journal_uuid[16]; /* uuid of journal superblock */ +/*0d0*/ __u8 s_journal_uuid[16] __nonstring; /* uuid of journal superblock */ /*0e0*/ __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 */ @@ -733,15 +745,15 @@ struct ext2_super_block { __u32 s_first_error_time; /* first time an error happened */ __u32 s_first_error_ino; /* inode involved in first error */ /*1a0*/ __u64 s_first_error_block; /* block involved in first error */ - __u8 s_first_error_func[32]; /* function where error hit, no NUL? */ + __u8 s_first_error_func[32] __nonstring; /* function where error hit, no NUL? */ /*1c8*/ __u32 s_first_error_line; /* line number where error happened */ __u32 s_last_error_time; /* most recent time of an error */ /*1d0*/ __u32 s_last_error_ino; /* inode involved in last error */ __u32 s_last_error_line; /* line number where error happened */ __u64 s_last_error_block; /* block involved of last error */ -/*1e0*/ __u8 s_last_error_func[32]; /* function where error hit, no NUL? */ +/*1e0*/ __u8 s_last_error_func[32] __nonstring; /* function where error hit, no NUL? */ #define EXT4_S_ERR_END ext4_offsetof(struct ext2_super_block, s_mount_opts) -/*200*/ __u8 s_mount_opts[64]; /* default mount options, no NUL? */ +/*200*/ __u8 s_mount_opts[64] __nonstring; /* default mount options, no NUL? */ /*240*/ __u32 s_usr_quota_inum; /* inode number of user quota file */ __u32 s_grp_quota_inum; /* inode number of group quota file */ __u32 s_overhead_clusters; /* overhead blocks/clusters in fs */ @@ -1137,8 +1149,8 @@ struct mmp_struct { __u32 mmp_magic; /* Magic number for MMP */ __u32 mmp_seq; /* Sequence no. updated periodically */ __u64 mmp_time; /* Time last updated (seconds) */ - __u8 mmp_nodename[64]; /* Node updating MMP block, no NUL? */ - __u8 mmp_bdevname[32]; /* Bdev updating MMP block, no NUL? */ + __u8 mmp_nodename[64] __nonstring; /* Node updating MMP block, no NUL? */ + __u8 mmp_bdevname[32] __nonstring; /* Bdev updating MMP block, no NUL? */ __u16 mmp_check_interval; /* Changed mmp_check_interval */ __u16 mmp_pad1; __u32 mmp_pad2[226]; diff --git a/lib/ext2fs/ext2_io.h b/lib/ext2fs/ext2_io.h index 95c25a7b..679184e3 100644 --- a/lib/ext2fs/ext2_io.h +++ b/lib/ext2fs/ext2_io.h @@ -142,9 +142,16 @@ extern errcode_t io_channel_cache_readahead(io_channel io, unsigned long long block, unsigned long long count); +#ifdef _WIN32 +/* windows_io.c */ +extern io_manager windows_io_manager; +#define default_io_manager windows_io_manager +#else /* unix_io.c */ extern io_manager unix_io_manager; extern io_manager unixfd_io_manager; +#define default_io_manager unix_io_manager +#endif /* sparse_io.c */ extern io_manager sparse_io_manager; diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index df150f00..b5477c10 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -18,6 +18,18 @@ #define EXT2FS_ATTR(x) #endif +#ifndef __nonstring +#ifdef __has_attribute +#if __has_attribute(__nonstring__) +#define __nonstring __attribute__((__nonstring__)) +#else +#define __nonstring +#endif /* __has_attribute(__nonstring__) */ +#else +# define __nonstring +#endif /* __has_attribute */ +#endif /* __nonstring */ + #ifdef CONFIG_TDB #define EXT2FS_NO_TDB_UNUSED #else @@ -207,6 +219,7 @@ typedef struct ext2_file *ext2_file_t; #define EXT2_FLAG_BBITMAP_TAIL_PROBLEM 0x1000000 #define EXT2_FLAG_IBITMAP_TAIL_PROBLEM 0x2000000 #define EXT2_FLAG_THREADS 0x4000000 +#define EXT2_FLAG_IGNORE_SWAP_DIRENT 0x8000000 /* * Special flag in the ext2 inode i_flag field that means that this is @@ -342,9 +355,9 @@ struct struct_ext2_filsys { #define BLOCK_INLINE_DATA_CHANGED 8 /* - * Block interate flags + * Block iterate flags * - * BLOCK_FLAG_APPEND, or BLOCK_FLAG_HOLE, indicates that the interator + * BLOCK_FLAG_APPEND, or BLOCK_FLAG_HOLE, indicates that the iterator * 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 @@ -1250,9 +1263,15 @@ extern errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir); /* ext_attr.c */ extern __u32 ext2fs_ext_attr_hash_entry(struct ext2_ext_attr_entry *entry, void *data); +extern __u32 ext2fs_ext_attr_hash_entry_signed(struct ext2_ext_attr_entry *entry, + void *data); extern errcode_t ext2fs_ext_attr_hash_entry2(ext2_filsys fs, struct ext2_ext_attr_entry *entry, void *data, __u32 *hash); +extern errcode_t ext2fs_ext_attr_hash_entry3(ext2_filsys fs, + struct ext2_ext_attr_entry *entry, + void *data, __u32 *hash, + __u32 *signed_hash); extern errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf); extern errcode_t ext2fs_read_ext_attr2(ext2_filsys fs, blk64_t block, void *buf); diff --git a/lib/ext2fs/ext2fsP.h b/lib/ext2fs/ext2fsP.h index a20a0502..06873847 100644 --- a/lib/ext2fs/ext2fsP.h +++ b/lib/ext2fs/ext2fsP.h @@ -93,7 +93,7 @@ struct ext2_inode_cache_ent { }; /* - * NLS defintions + * NLS definitions */ struct ext2fs_nls_table { int version; diff --git a/lib/ext2fs/ext_attr.c b/lib/ext2fs/ext_attr.c index 148fae5b..5525045c 100644 --- a/lib/ext2fs/ext_attr.c +++ b/lib/ext2fs/ext_attr.c @@ -48,7 +48,8 @@ static errcode_t read_ea_inode_hash(ext2_filsys fs, ext2_ino_t ino, __u32 *hash) __u32 ext2fs_ext_attr_hash_entry(struct ext2_ext_attr_entry *entry, void *data) { __u32 hash = 0; - char *name = ((char *) entry) + sizeof(struct ext2_ext_attr_entry); + unsigned char *name = (((unsigned char *) entry) + + sizeof(struct ext2_ext_attr_entry)); int n; for (n = 0; n < entry->e_name_len; n++) { @@ -71,18 +72,51 @@ __u32 ext2fs_ext_attr_hash_entry(struct ext2_ext_attr_entry *entry, void *data) return hash; } +__u32 ext2fs_ext_attr_hash_entry_signed(struct ext2_ext_attr_entry *entry, + void *data) +{ + __u32 hash = 0; + signed char *name = (((signed char *) entry) + + sizeof(struct ext2_ext_attr_entry)); + int n; + + for (n = 0; n < entry->e_name_len; n++) { + hash = (hash << NAME_HASH_SHIFT) ^ + (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^ + *name++; + } + + /* The hash needs to be calculated on the data in little-endian. */ + if (entry->e_value_inum == 0 && entry->e_value_size != 0) { + __u32 *value = (__u32 *)data; + for (n = (entry->e_value_size + EXT2_EXT_ATTR_ROUND) >> + EXT2_EXT_ATTR_PAD_BITS; n; n--) { + hash = (hash << VALUE_HASH_SHIFT) ^ + (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^ + ext2fs_le32_to_cpu(*value++); + } + } + + return hash; +} + + /* - * ext2fs_ext_attr_hash_entry2() + * ext2fs_ext_attr_hash_entry3() * - * Compute the hash of an extended attribute. - * This version of the function supports hashing entries that reference - * external inodes (ea_inode feature). + * Compute the hash of an extended attribute. This version of the + * function supports hashing entries that reference external inodes + * (ea_inode feature) as well as calculating the old legacy signed + * hash variant. */ -errcode_t ext2fs_ext_attr_hash_entry2(ext2_filsys fs, +errcode_t ext2fs_ext_attr_hash_entry3(ext2_filsys fs, struct ext2_ext_attr_entry *entry, - void *data, __u32 *hash) + void *data, __u32 *hash, + __u32 *signed_hash) { *hash = ext2fs_ext_attr_hash_entry(entry, data); + if (signed_hash) + *signed_hash = ext2fs_ext_attr_hash_entry_signed(entry, data); if (entry->e_value_inum) { __u32 ea_inode_hash; @@ -96,10 +130,29 @@ errcode_t ext2fs_ext_attr_hash_entry2(ext2_filsys fs, *hash = (*hash << VALUE_HASH_SHIFT) ^ (*hash >> (8*sizeof(*hash) - VALUE_HASH_SHIFT)) ^ ea_inode_hash; + if (signed_hash) + *signed_hash = (*signed_hash << VALUE_HASH_SHIFT) ^ + (*signed_hash >> (8*sizeof(*hash) - + VALUE_HASH_SHIFT)) ^ + ea_inode_hash; } return 0; } +/* + * ext2fs_ext_attr_hash_entry2() + * + * Compute the hash of an extended attribute. + * This version of the function supports hashing entries that reference + * external inodes (ea_inode feature). + */ +errcode_t ext2fs_ext_attr_hash_entry2(ext2_filsys fs, + struct ext2_ext_attr_entry *entry, + void *data, __u32 *hash) +{ + return ext2fs_ext_attr_hash_entry3(fs, entry, data, hash, NULL); +} + #undef NAME_HASH_SHIFT #undef VALUE_HASH_SHIFT @@ -556,10 +609,10 @@ static errcode_t convert_posix_acl_to_disk_buffer(const void *value, size_t size s = sizeof(ext4_acl_header); for (end = entry + count; entry != end;entry++) { ext4_acl_entry *disk_entry = (ext4_acl_entry*) e; - disk_entry->e_tag = ext2fs_cpu_to_le16(entry->e_tag); - disk_entry->e_perm = ext2fs_cpu_to_le16(entry->e_perm); + disk_entry->e_tag = entry->e_tag; + disk_entry->e_perm = entry->e_perm; - switch(entry->e_tag) { + switch(ext2fs_le16_to_cpu(entry->e_tag)) { case ACL_USER_OBJ: case ACL_GROUP_OBJ: case ACL_MASK: @@ -569,10 +622,12 @@ static errcode_t convert_posix_acl_to_disk_buffer(const void *value, size_t size break; case ACL_USER: case ACL_GROUP: - disk_entry->e_id = ext2fs_cpu_to_le32(entry->e_id); + disk_entry->e_id = entry->e_id; e += sizeof(ext4_acl_entry); s += sizeof(ext4_acl_entry); break; + default: + return EINVAL; } } *size_out = s; @@ -608,10 +663,10 @@ static errcode_t convert_disk_buffer_to_posix_acl(const void *value, size_t size while (size > 0) { const ext4_acl_entry *disk_entry = (const ext4_acl_entry *) cp; - entry->e_tag = ext2fs_le16_to_cpu(disk_entry->e_tag); - entry->e_perm = ext2fs_le16_to_cpu(disk_entry->e_perm); + entry->e_tag = disk_entry->e_tag; + entry->e_perm = disk_entry->e_perm; - switch(entry->e_tag) { + switch(ext2fs_le16_to_cpu(entry->e_tag)) { case ACL_USER_OBJ: case ACL_GROUP_OBJ: case ACL_MASK: @@ -622,13 +677,13 @@ static errcode_t convert_disk_buffer_to_posix_acl(const void *value, size_t size break; case ACL_USER: case ACL_GROUP: - entry->e_id = ext2fs_le32_to_cpu(disk_entry->e_id); + entry->e_id = disk_entry->e_id; cp += sizeof(ext4_acl_entry); size -= sizeof(ext4_acl_entry); break; - default: - ext2fs_free_mem(&out); - return EINVAL; + default: + ext2fs_free_mem(&out); + return EINVAL; } entry++; } @@ -938,15 +993,18 @@ static errcode_t read_xattrs_from_buffer(struct ext2_xattr_handle *handle, /* e_hash may be 0 in older inode's ea */ if (entry->e_hash != 0) { - __u32 hash; + __u32 hash, signed_hash; + void *data = (entry->e_value_inum != 0) ? 0 : value_start + entry->e_value_offs; - err = ext2fs_ext_attr_hash_entry2(handle->fs, entry, - data, &hash); + err = ext2fs_ext_attr_hash_entry3(handle->fs, entry, + data, &hash, + &signed_hash); if (err) return err; - if (entry->e_hash != hash) { + if ((entry->e_hash != hash) && + (entry->e_hash != signed_hash)) { struct ext2_inode child; /* Check whether this is an old Lustre-style diff --git a/lib/ext2fs/extent.c b/lib/ext2fs/extent.c index b324c7b0..82e75ccd 100644 --- a/lib/ext2fs/extent.c +++ b/lib/ext2fs/extent.c @@ -47,6 +47,7 @@ struct extent_path { int visit_num; int flags; blk64_t end_blk; + blk64_t blk; void *curr; }; @@ -286,6 +287,7 @@ errcode_t ext2fs_extent_open2(ext2_filsys fs, ext2_ino_t ino, handle->path[0].end_blk = (EXT2_I_SIZE(handle->inode) + fs->blocksize - 1) >> EXT2_BLOCK_SIZE_BITS(fs->super); + handle->path[0].blk = 0; handle->path[0].visit_num = 1; handle->level = 0; handle->magic = EXT2_ET_MAGIC_EXTENT_HANDLE; @@ -305,14 +307,14 @@ errout: errcode_t ext2fs_extent_get(ext2_extent_handle_t handle, int flags, struct ext2fs_extent *extent) { - struct extent_path *path, *newpath; + struct extent_path *path, *newpath, *tp; struct ext3_extent_header *eh; struct ext3_extent_idx *ix = 0; struct ext3_extent *ex; errcode_t retval; blk64_t blk; blk64_t end_blk; - int orig_op, op; + int orig_op, op, l; int failed_csum = 0; EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EXTENT_HANDLE); @@ -467,6 +469,11 @@ retry: } blk = ext2fs_le32_to_cpu(ix->ei_leaf) + ((__u64) ext2fs_le16_to_cpu(ix->ei_leaf_hi) << 32); + for (l = handle->level, tp = path; l > 0; l--, tp--) { + if (blk == tp->blk) + return EXT2_ET_EXTENT_CYCLE; + } + newpath->blk = blk; if ((handle->fs->flags & EXT2_FLAG_IMAGE_FILE) && (handle->fs->io != handle->fs->image_io)) memset(newpath->buf, 0, handle->fs->blocksize); @@ -495,6 +502,10 @@ retry: ext2fs_le16_to_cpu(eh->eh_entries); newpath->max_entries = ext2fs_le16_to_cpu(eh->eh_max); + /* Make sure there is at least one extent present */ + if (newpath->left <= 0) + return EXT2_ET_EXTENT_NO_DOWN; + if (path->left > 0) { ix++; newpath->end_blk = ext2fs_le32_to_cpu(ix->ei_block); @@ -1630,6 +1641,10 @@ errcode_t ext2fs_extent_delete(ext2_extent_handle_t handle, int flags) cp = path->curr; + /* Sanity check before memmove() */ + if (path->left < 0) + return EXT2_ET_EXTENT_LEAF_BAD; + if (path->left) { memmove(cp, cp + sizeof(struct ext3_extent_idx), path->left * sizeof(struct ext3_extent_idx)); diff --git a/lib/ext2fs/fast_commit.h b/lib/ext2fs/fast_commit.h index b83e1810..4ad38f12 100644 --- a/lib/ext2fs/fast_commit.h +++ b/lib/ext2fs/fast_commit.h @@ -155,13 +155,6 @@ struct ext4_fc_replay_state { #define region_last(__region) (((__region)->lblk) + ((__region)->len) - 1) #endif -#define fc_for_each_tl(__start, __end, __tl) \ - for (tl = (struct ext4_fc_tl *)(__start); \ - (__u8 *)tl < (__u8 *)(__end); \ - tl = (struct ext4_fc_tl *)((__u8 *)tl + \ - sizeof(struct ext4_fc_tl) + \ - + le16_to_cpu(tl->fc_len))) - static inline const char *tag2str(__u16 tag) { switch (tag) { @@ -194,10 +187,4 @@ static inline int ext4_fc_tag_len(struct ext4_fc_tl *tl) return le16_to_cpu(tl->fc_len); } -/* Get a pointer to "value" of a tlv */ -static inline __u8 *ext4_fc_tag_val(struct ext4_fc_tl *tl) -{ - return (__u8 *)tl + sizeof(*tl); -} - #endif /* __FAST_COMMIT_H__ */ diff --git a/lib/ext2fs/fileio.c b/lib/ext2fs/fileio.c index a0b5d971..818f7f05 100644 --- a/lib/ext2fs/fileio.c +++ b/lib/ext2fs/fileio.c @@ -475,8 +475,14 @@ errcode_t ext2fs_file_write(ext2_file_t file, const void *buf, if (new_block) { new_block->physblock = file->physblock; - ext2fs_hashmap_add(fs->block_sha_map, new_block, - new_block->sha, sizeof(new_block->sha)); + int ret = ext2fs_hashmap_add(fs->block_sha_map, + new_block, new_block->sha, + sizeof(new_block->sha)); + if (ret) { + retval = EXT2_ET_NO_MEMORY; + free(new_block); + goto fail; + } } if (bmap_flags & BMAP_SET) { diff --git a/lib/ext2fs/gen_bitmap64.c b/lib/ext2fs/gen_bitmap64.c index a2b89898..4289e815 100644 --- a/lib/ext2fs/gen_bitmap64.c +++ b/lib/ext2fs/gen_bitmap64.c @@ -183,11 +183,9 @@ static void ext2fs_print_bmap_statistics(ext2fs_generic_bitmap_64 bitmap) #ifdef ENABLE_BMAP_STATS_OPS float mark_seq_perc = 0.0, test_seq_perc = 0.0; float mark_back_perc = 0.0, test_back_perc = 0.0; -#endif - double inuse; struct timeval now; + double inuse; -#ifdef ENABLE_BMAP_STATS_OPS if (stats->test_count) { test_seq_perc = ((float)stats->test_seq / stats->test_count) * 100; @@ -201,7 +199,6 @@ static void ext2fs_print_bmap_statistics(ext2fs_generic_bitmap_64 bitmap) mark_back_perc = ((float)stats->mark_back / stats->mark_count) * 100; } -#endif if (gettimeofday(&now, (struct timezone *) NULL) == -1) { perror("gettimeofday"); @@ -212,6 +209,7 @@ static void ext2fs_print_bmap_statistics(ext2fs_generic_bitmap_64 bitmap) (((double) now.tv_usec) * 0.000001); inuse -= (double) stats->created.tv_sec + \ (((double) stats->created.tv_usec) * 0.000001); +#endif /* ENABLE_BMAP_STATS_OPS */ fprintf(stderr, "\n[+] %s bitmap (type %d)\n", bitmap->description, stats->type); @@ -629,10 +627,14 @@ errcode_t ext2fs_compare_generic_bmap(errcode_t neq, (bm1->end != bm2->end)) return neq; - for (i = bm1->end - ((bm1->end - bm1->start) % 8); i <= bm1->end; i++) - if (ext2fs_test_generic_bmap(gen_bm1, i) != - ext2fs_test_generic_bmap(gen_bm2, i)) + for (i = bm1->start; i < bm1->end; i++) { + int ret1, ret2; + ret1 = !!ext2fs_test_generic_bmap(gen_bm1, i); + ret2 = !!ext2fs_test_generic_bmap(gen_bm2, i); + if (ret1 != ret2) { return neq; + } + } return 0; } @@ -684,7 +686,7 @@ int ext2fs_test_block_bitmap_range2(ext2fs_block_bitmap gen_bmap, /* convert to clusters if necessary */ block >>= bmap->cluster_bits; - end += (1 << bmap->cluster_bits) - 1; + end += (1ULL << bmap->cluster_bits) - 1; end >>= bmap->cluster_bits; num = end - block; @@ -725,7 +727,7 @@ void ext2fs_mark_block_bitmap_range2(ext2fs_block_bitmap gen_bmap, /* convert to clusters if necessary */ block >>= bmap->cluster_bits; - end += (1 << bmap->cluster_bits) - 1; + end += (1ULL << bmap->cluster_bits) - 1; end >>= bmap->cluster_bits; num = end - block; @@ -766,7 +768,7 @@ void ext2fs_unmark_block_bitmap_range2(ext2fs_block_bitmap gen_bmap, /* convert to clusters if necessary */ block >>= bmap->cluster_bits; - end += (1 << bmap->cluster_bits) - 1; + end += (1ULL << bmap->cluster_bits) - 1; end >>= bmap->cluster_bits; num = end - block; @@ -948,7 +950,7 @@ errcode_t ext2fs_count_used_clusters(ext2_filsys fs, blk64_t start, { blk64_t next; blk64_t tot_set = 0; - errcode_t retval; + errcode_t retval = 0; while (start < end) { retval = ext2fs_find_first_set_block_bitmap2(fs->block_map, diff --git a/lib/ext2fs/getsectsize.c b/lib/ext2fs/getsectsize.c index d6bc3767..bd978c53 100644 --- a/lib/ext2fs/getsectsize.c +++ b/lib/ext2fs/getsectsize.c @@ -51,6 +51,11 @@ */ errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize) { +#ifdef _WIN32 + *sectsize = 512; // just guessing + return 0; +#else // not _WIN32 + int fd; fd = ext2fs_open_file(file, O_RDONLY, 0); @@ -72,6 +77,8 @@ errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize) *sectsize = 0; close(fd); return 0; + +#endif // ifdef _WIN32 } /* @@ -110,6 +117,12 @@ int ext2fs_get_dio_alignment(int fd) */ errcode_t ext2fs_get_device_phys_sectsize(const char *file, int *sectsize) { +#ifdef _WIN32 + + return ext2fs_get_device_sectsize(file, sectsize); + +#else // not _WIN32 + int fd; fd = ext2fs_open_file(file, O_RDONLY, 0); @@ -133,4 +146,6 @@ errcode_t ext2fs_get_device_phys_sectsize(const char *file, int *sectsize) *sectsize = 0; close(fd); return 0; + +#endif // ifdef _WIN32 } diff --git a/lib/ext2fs/getsize.c b/lib/ext2fs/getsize.c index be067755..a0286344 100644 --- a/lib/ext2fs/getsize.c +++ b/lib/ext2fs/getsize.c @@ -74,7 +74,8 @@ errcode_t ext2fs_get_device_size2(const char *file, int blocksize, blk64_t *retblocks) { - HANDLE dev; + int fd; + HANDLE h; PARTITION_INFORMATION pi; DISK_GEOMETRY gi; DWORD retbytes; @@ -84,20 +85,18 @@ errcode_t ext2fs_get_device_size2(const char *file, int blocksize, 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, + fd = ext2fs_open_file(file, O_RDONLY, 0); + if (fd < 0) + return errno; + h = (HANDLE)_get_osfhandle(fd); + if (DeviceIoControl(h, 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, + } else if (DeviceIoControl(h, IOCTL_DISK_GET_DRIVE_GEOMETRY, &gi, sizeof(DISK_GEOMETRY), &gi, sizeof(DISK_GEOMETRY), &retbytes, NULL)) { @@ -108,19 +107,19 @@ errcode_t ext2fs_get_device_size2(const char *file, int blocksize, gi.Cylinders.QuadPart / blocksize; #ifdef HAVE_GET_FILE_SIZE_EX - } else if (GetFileSizeEx(dev, &filesize)) { + } else if (GetFileSizeEx(h, &filesize)) { *retblocks = filesize.QuadPart / blocksize; } #else } else { - filesize = GetFileSize(dev, NULL); + filesize = GetFileSize(h, NULL); if (INVALID_FILE_SIZE != filesize) { *retblocks = filesize / blocksize; } } #endif /* HAVE_GET_FILE_SIZE_EX */ - CloseHandle(dev); + close(fd); return 0; } @@ -295,7 +294,7 @@ errcode_t ext2fs_get_device_size(const char *file, int blocksize, #ifdef DEBUG int main(int argc, char **argv) { - blk_t blocks; + blk64_t blocks; int retval; if (argc < 2) { @@ -303,13 +302,14 @@ int main(int argc, char **argv) exit(1); } - retval = ext2fs_get_device_size(argv[1], 1024, &blocks); + retval = ext2fs_get_device_size2(argv[1], 1024, &blocks); if (retval) { com_err(argv[0], retval, "while calling ext2fs_get_device_size"); exit(1); } - printf("Device %s has %u 1k blocks.\n", argv[1], blocks); + printf("Device %s has %llu 1k blocks.\n", argv[1], + (unsigned long long) locks); exit(0); } #endif diff --git a/lib/ext2fs/hashmap.c b/lib/ext2fs/hashmap.c index ffe61ce9..697b2bcc 100644 --- a/lib/ext2fs/hashmap.c +++ b/lib/ext2fs/hashmap.c @@ -36,6 +36,9 @@ struct ext2fs_hashmap *ext2fs_hashmap_create( { struct ext2fs_hashmap *h = calloc(sizeof(struct ext2fs_hashmap) + sizeof(struct ext2fs_hashmap_entry) * size, 1); + if (!h) + return NULL; + h->size = size; h->free = free_fct; h->hash = hash_fct; @@ -43,12 +46,15 @@ struct ext2fs_hashmap *ext2fs_hashmap_create( return h; } -void ext2fs_hashmap_add(struct ext2fs_hashmap *h, void *data, const void *key, - size_t key_len) +int ext2fs_hashmap_add(struct ext2fs_hashmap *h, + void *data, const void *key, size_t key_len) { uint32_t hash = h->hash(key, key_len) % h->size; struct ext2fs_hashmap_entry *e = malloc(sizeof(*e)); + if (!e) + return -1; + e->data = data; e->key = key; e->key_len = key_len; @@ -62,6 +68,8 @@ void ext2fs_hashmap_add(struct ext2fs_hashmap *h, void *data, const void *key, h->first = e; if (!h->last) h->last = e; + + return 0; } void *ext2fs_hashmap_lookup(struct ext2fs_hashmap *h, const void *key, diff --git a/lib/ext2fs/hashmap.h b/lib/ext2fs/hashmap.h index dcfa7455..0c09d2bd 100644 --- a/lib/ext2fs/hashmap.h +++ b/lib/ext2fs/hashmap.h @@ -27,8 +27,8 @@ struct ext2fs_hashmap_entry { struct ext2fs_hashmap *ext2fs_hashmap_create( uint32_t(*hash_fct)(const void*, size_t), void(*free_fct)(void*), size_t size); -void ext2fs_hashmap_add(struct ext2fs_hashmap *h, void *data, const void *key, - size_t key_len); +int ext2fs_hashmap_add(struct ext2fs_hashmap *h, + void *data, const void *key,size_t key_len); void *ext2fs_hashmap_lookup(struct ext2fs_hashmap *h, const void *key, size_t key_len); void *ext2fs_hashmap_iter_in_order(struct ext2fs_hashmap *h, diff --git a/lib/ext2fs/imager.c b/lib/ext2fs/imager.c index 586227fc..23290a6a 100644 --- a/lib/ext2fs/imager.c +++ b/lib/ext2fs/imager.c @@ -80,6 +80,11 @@ errcode_t ext2fs_image_inode_write(ext2_filsys fs, int fd, int flags) goto errout; } left = fs->inode_blocks_per_group; + if ((blk < fs->super->s_first_data_block) || + (blk + left - 1 >= ext2fs_blocks_count(fs->super))) { + retval = EXT2_ET_GDESC_BAD_INODE_TABLE; + goto errout; + } while (left) { c = BUF_BLOCKS; if (c > left) @@ -272,7 +277,7 @@ errcode_t ext2fs_image_super_write(ext2_filsys fs, int fd, retval = errno; goto errout; } - if (actual != (ssize_t)fs->blocksize * fs->desc_blocks) { + if (actual != (ssize_t)(fs->blocksize * fs->desc_blocks)) { retval = EXT2_ET_SHORT_WRITE; goto errout; } @@ -367,6 +372,8 @@ errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags) size = sizeof(buf); if (size > (cnt >> 3)) size = (cnt >> 3); + if (size == 0) + break; retval = ext2fs_get_generic_bmap_range(bmap, itr, size << 3, buf); @@ -442,6 +449,8 @@ errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags) size = sizeof(buf); if (size > (cnt >> 3)) size = (cnt >> 3); + if (size == 0) + break; actual = read(fd, buf, size); if (actual == -1) diff --git a/lib/ext2fs/inline_data.c b/lib/ext2fs/inline_data.c index b62fb676..bd52e377 100644 --- a/lib/ext2fs/inline_data.c +++ b/lib/ext2fs/inline_data.c @@ -653,7 +653,7 @@ static errcode_t file_test(ext2_filsys fs) if (size != BUFF_SIZE) { fprintf(stderr, - "tst_inline_data: size %lu != buflen %u\n", + "tst_inline_data: size %zu != buflen %u\n", size, BUFF_SIZE); retval = 1; goto err; diff --git a/lib/ext2fs/inode.c b/lib/ext2fs/inode.c index 6f42882e..957d5aa9 100644 --- a/lib/ext2fs/inode.c +++ b/lib/ext2fs/inode.c @@ -144,6 +144,10 @@ errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks, 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 (ext2fs_has_feature_journal_dev(fs->super)) + return EXT2_ET_EXTERNAL_JOURNAL_NOSUPP; + if (fs->blocksize < 1024) return EXT2_FILSYS_CORRUPTED; /* Should never happen */ @@ -766,6 +770,10 @@ errcode_t ext2fs_read_inode2(ext2_filsys fs, ext2_ino_t ino, int cache_slot, fail_csum; EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + + if (ext2fs_has_feature_journal_dev(fs->super)) + return EXT2_ET_EXTERNAL_JOURNAL_NOSUPP; + if (fs->blocksize < 1024) return EXT2_FILSYS_CORRUPTED; /* Should never happen */ @@ -898,6 +906,9 @@ errcode_t ext2fs_write_inode2(ext2_filsys fs, ext2_ino_t ino, EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); + if (ext2fs_has_feature_journal_dev(fs->super)) + return EXT2_ET_EXTERNAL_JOURNAL_NOSUPP; + /* Check to see if user provided an override function */ if (fs->write_inode) { retval = (fs->write_inode)(fs, ino, inode); diff --git a/lib/ext2fs/io_manager.c b/lib/ext2fs/io_manager.c index 996c31a1..dca6af09 100644 --- a/lib/ext2fs/io_manager.c +++ b/lib/ext2fs/io_manager.c @@ -134,8 +134,8 @@ errcode_t io_channel_alloc_buf(io_channel io, int count, void *ptr) else size = -count; - if (io->align) { - if (io->align > size) + if (io->align > 0) { + if ((unsigned) io->align > size) size = io->align; return ext2fs_get_memalign(size, io->align, ptr); } else diff --git a/lib/ext2fs/irel.h b/lib/ext2fs/irel.h index 8aaa2d2b..23741bae 100644 --- a/lib/ext2fs/irel.h +++ b/lib/ext2fs/irel.h @@ -73,7 +73,7 @@ struct ext2_inode_relocation_table { /* * The iterator function for the inode references for an - * inode. The references for only one inode can be interator + * inode. The references for only one inode can be iterator * over at a time, as the iterator state is stored in ext2_irel. */ errcode_t (*next_ref)(ext2_irel irel, diff --git a/lib/ext2fs/ismounted.c b/lib/ext2fs/ismounted.c index c9e6a9d0..8fc0b99d 100644 --- a/lib/ext2fs/ismounted.c +++ b/lib/ext2fs/ismounted.c @@ -97,7 +97,7 @@ 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; + struct stat st_buf, dir_st_buf; errcode_t retval = 0; dev_t file_dev=0, file_rdev=0; ino_t file_ino=0; @@ -144,8 +144,14 @@ static errcode_t check_mntent_file(const char *mtab_file, const char *file, if (stat(mnt->mnt_fsname, &st_buf) == 0) { if (ext2fsP_is_disk_device(st_buf.st_mode)) { #ifndef __GNU__ - if (file_rdev && (file_rdev == st_buf.st_rdev)) - break; + if (file_rdev && + (file_rdev == st_buf.st_rdev)) { + if (stat(mnt->mnt_dir, + &dir_st_buf) != 0) + continue; + if (file_rdev == dir_st_buf.st_dev) + break; + } if (check_loop_mounted(mnt->mnt_fsname, st_buf.st_rdev, file_dev, file_ino) == 1) @@ -393,7 +399,8 @@ errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags, if (is_swap_device(device)) { *mount_flags = EXT2_MF_MOUNTED | EXT2_MF_SWAP; - strncpy(mtpt, "<swap>", mtlen); + if (mtpt) + strncpy(mtpt, "<swap>", mtlen); } else { #ifdef HAVE_SETMNTENT retval = check_mntent(device, mount_flags, mtpt, mtlen); @@ -401,7 +408,7 @@ errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags, #ifdef HAVE_GETMNTINFO retval = check_getmntinfo(device, mount_flags, mtpt, mtlen); #else -#ifdef __GNUC__ +#if defined(__GNUC__) && !defined(_WIN32) #warning "Can't use getmntent or getmntinfo to check for mounted filesystems!" #endif *mount_flags = 0; diff --git a/lib/ext2fs/jfs_compat.h b/lib/ext2fs/jfs_compat.h index 96fe34a4..0e96b56c 100644 --- a/lib/ext2fs/jfs_compat.h +++ b/lib/ext2fs/jfs_compat.h @@ -7,11 +7,7 @@ #ifdef HAVE_NETINET_IN_H #include <netinet/in.h> #endif -#ifdef HAVE_WINSOCK_H -#include <winsock.h> -#else #include <arpa/inet.h> -#endif #include <stdbool.h> #define printk printf @@ -51,12 +47,6 @@ typedef unsigned int gfp_t; typedef __u64 u64; #define put_bh(x) brelse(x) -static inline __u32 jbd2_chksum(journal_t *j EXT2FS_ATTR((unused)), - __u32 crc, const void *address, - unsigned int length) -{ - return ext2fs_crc32c_le(crc, address, length); -} #define crc32_be(x, y, z) ext2fs_crc32_be((x), (y), (z)) #define spin_lock_init(x) #define spin_lock(x) @@ -67,7 +57,7 @@ static inline __u32 jbd2_chksum(journal_t *j EXT2FS_ATTR((unused)), sizeof(struct __struct), __alignof__(struct __struct),\ (__flags), NULL) -#define blkdev_issue_flush(kdev, a) sync_blockdev(kdev) +#define blkdev_issue_flush(kdev) sync_blockdev(kdev) #define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0)) #define pr_emerg(fmt) #define pr_err(...) diff --git a/lib/ext2fs/kernel-jbd.h b/lib/ext2fs/kernel-jbd.h index c94de237..e5695006 100644 --- a/lib/ext2fs/kernel-jbd.h +++ b/lib/ext2fs/kernel-jbd.h @@ -263,6 +263,7 @@ typedef struct journal_superblock_s #ifdef NO_INLINE_FUNCS extern size_t journal_tag_bytes(journal_t *journal); extern int jbd2_journal_has_csum_v2or3(journal_t *journal); +extern int jbd2_journal_get_num_fc_blks(journal_superblock_t *jsb); extern int tid_gt(tid_t x, tid_t y) EXT2FS_ATTR((unused)); extern int tid_geq(tid_t x, tid_t y) EXT2FS_ATTR((unused)); #endif @@ -443,7 +444,7 @@ extern int journal_blocks_per_page(struct inode *inode); #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_Forget 4 /* Buffer superseded 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 */ diff --git a/lib/ext2fs/link.c b/lib/ext2fs/link.c index a2c34ac5..d69b1e3d 100644 --- a/lib/ext2fs/link.c +++ b/lib/ext2fs/link.c @@ -35,7 +35,7 @@ struct dx_lookup_info { int namelen; int hash_alg; __u32 hash; - int levels; + unsigned levels; struct dx_frame frames[EXT4_HTREE_LEVEL]; }; @@ -46,7 +46,7 @@ static errcode_t alloc_dx_frame(ext2_filsys fs, struct dx_frame *frame) static void dx_release(struct dx_lookup_info *info) { - int level; + unsigned level; for (level = 0; level < info->levels; level++) { if (info->frames[level].buf == NULL) @@ -110,7 +110,8 @@ static errcode_t dx_lookup(ext2_filsys fs, ext2_ino_t dir, info->frames[0].buf); if (errcode) goto out_err; - root = info->frames[0].buf + EXT2_DX_ROOT_OFF; + root = (struct ext2_dx_root_info *) ((char *)info->frames[0].buf + + EXT2_DX_ROOT_OFF); hash_alg = root->hash_version; if (hash_alg != EXT2_HASH_TEA && hash_alg != EXT2_HASH_HALF_MD4 && hash_alg != EXT2_HASH_LEGACY) { @@ -329,19 +330,19 @@ static errcode_t dx_move_dirents(ext2_filsys fs, struct dx_hash_map *map, csum_size = sizeof(struct ext2_dir_entry_tail); for (i = 0; i < count; i++) { - de = from + map[i].off; + de = (struct ext2_dir_entry *) ((char *)from + map[i].off); rec_len = EXT2_DIR_REC_LEN(ext2fs_dirent_name_len(de)); memcpy(to, de, rec_len); retval = ext2fs_set_rec_len(fs, rec_len, to); if (retval) return retval; - to += rec_len; + to = (char *)to + rec_len; } /* * Update rec_len of the last dir entry to stretch to the end of block */ - to -= rec_len; - rec_len = fs->blocksize - (to - base) - csum_size; + to = (char *)to - rec_len; + rec_len = fs->blocksize - ((char *)to - (char *)base) - csum_size; retval = ext2fs_set_rec_len(fs, rec_len, to); if (retval) return retval; @@ -396,7 +397,7 @@ static errcode_t dx_split_leaf(ext2_filsys fs, ext2_ino_t dir, return retval; } for (offset = 0; offset < fs->blocksize; offset += rec_len) { - de = buf + offset; + de = (struct ext2_dir_entry *) ((char *)buf + offset); retval = ext2fs_get_rec_len(fs, de, &rec_len); if (retval) goto out; @@ -490,7 +491,7 @@ static errcode_t dx_grow_tree(ext2_filsys fs, ext2_ino_t dir, if (retval) return retval; /* Only leaf addition needed? */ - if (i == info->levels - 1) + if (i == (int)info->levels - 1) return dx_split_leaf(fs, dir, diri, info, buf, leaf_pblk, lblk, pblk); @@ -501,7 +502,7 @@ static errcode_t dx_grow_tree(ext2_filsys fs, ext2_ino_t dir, retval = ext2fs_set_rec_len(fs, fs->blocksize, de); if (retval) return retval; - head = buf + 8; + head = (struct ext2_dx_countlimit *) ((char *)buf + 8); count = ext2fs_le16_to_cpu(info->frames[i+1].head->count); /* Growing tree depth? */ if (i < 0) { @@ -517,7 +518,8 @@ static errcode_t dx_grow_tree(ext2_filsys fs, ext2_ino_t dir, /* Now update tree root */ info->frames[0].head->count = ext2fs_cpu_to_le16(1); info->frames[0].entries[0].block = ext2fs_cpu_to_le32(lblk); - root = info->frames[0].buf + EXT2_DX_ROOT_OFF; + root = (struct ext2_dx_root_info *) + ((char *)info->frames[0].buf + EXT2_DX_ROOT_OFF); root->indirect_levels++; } else { /* Splitting internal node in two */ @@ -558,7 +560,7 @@ static errcode_t dx_link(ext2_filsys fs, ext2_ino_t dir, struct dx_lookup_info dx_info; errcode_t retval; void *blockbuf; - int restart = 0; + unsigned restart = 0; blk64_t leaf_pblk; retval = ext2fs_get_mem(fs->blocksize, &blockbuf); diff --git a/lib/ext2fs/llseek.c b/lib/ext2fs/llseek.c index 922a0d56..45f21d09 100644 --- a/lib/ext2fs/llseek.c +++ b/lib/ext2fs/llseek.c @@ -51,7 +51,7 @@ extern long long llseek (int fd, long long offset, int origin); #else /* ! HAVE_LLSEEK */ -#if SIZEOF_LONG == SIZEOF_LONG_LONG +#if SIZEOF_LONG == SIZEOF_LONG_LONG || _FILE_OFFSET_BITS+0 == 64 #define my_llseek lseek @@ -69,7 +69,7 @@ static int _llseek (unsigned int, unsigned long, static _syscall5(int,_llseek,unsigned int,fd,unsigned long,offset_high, unsigned long, offset_low,ext2_loff_t *,result, - unsigned int, origin) + unsigned int, origin); #endif static ext2_loff_t my_llseek (int fd, ext2_loff_t offset, int origin) diff --git a/lib/ext2fs/mkjournal.c b/lib/ext2fs/mkjournal.c index 11d73e30..54772dd5 100644 --- a/lib/ext2fs/mkjournal.c +++ b/lib/ext2fs/mkjournal.c @@ -252,7 +252,7 @@ static blk64_t get_midpoint_journal_block(ext2_filsys fs) group = ext2fs_group_of_blk2(fs, (ext2fs_blocks_count(fs->super) - fs->super->s_first_data_block) / 2); - log_flex = 1 << fs->super->s_log_groups_per_flex; + log_flex = 1U << fs->super->s_log_groups_per_flex; if (fs->super->s_log_groups_per_flex && (group > log_flex)) { group = group & ~(log_flex - 1); while ((group < fs->group_desc_count) && diff --git a/lib/ext2fs/mmp.c b/lib/ext2fs/mmp.c index 9ef45809..eb941702 100644 --- a/lib/ext2fs/mmp.c +++ b/lib/ext2fs/mmp.c @@ -58,7 +58,7 @@ errcode_t ext2fs_mmp_read(ext2_filsys fs, blk64_t mmp_blk, void *buf) * the MMP block by the io_manager or the VM. It needs to be fresh. */ if (fs->mmp_fd <= 0) { struct stat st; - int flags = O_RDWR | O_DIRECT; + int flags = O_RDONLY | O_DIRECT; /* * There is no reason for using O_DIRECT if we're working with @@ -356,7 +356,7 @@ clean_seq: #ifdef HAVE_GETHOSTNAME gethostname((char *) mmp_s->mmp_nodename, sizeof(mmp_s->mmp_nodename)); #else - strcpy(mmp_s->mmp_nodename, "unknown host"); + strcpy((char *) mmp_s->mmp_nodename, "unknown host"); #endif strncpy((char *) mmp_s->mmp_bdevname, fs->device_name, sizeof(mmp_s->mmp_bdevname)); @@ -407,7 +407,7 @@ errcode_t ext2fs_mmp_stop(ext2_filsys fs) (fs->mmp_buf == NULL) || (fs->mmp_cmp == NULL)) goto mmp_error; - retval = ext2fs_mmp_read(fs, fs->super->s_mmp_block, fs->mmp_buf); + retval = ext2fs_mmp_read(fs, fs->super->s_mmp_block, NULL); if (retval) goto mmp_error; diff --git a/lib/ext2fs/nls_utf8.c b/lib/ext2fs/nls_utf8.c index 43bab9a3..b07e66e4 100644 --- a/lib/ext2fs/nls_utf8.c +++ b/lib/ext2fs/nls_utf8.c @@ -709,7 +709,7 @@ static int utf8cursor(struct utf8cursor *u8c, const struct utf8data *data, /* * Get one byte from the normalized form of the string described by u8c. * - * Returns the byte cast to an unsigned char on succes, and -1 on failure. + * Returns the byte cast to an unsigned char on success, and -1 on failure. * * The cursor keeps track of the location in the string in u8c->s. * When a character is decomposed, the current location is stored in diff --git a/lib/ext2fs/openfs.c b/lib/ext2fs/openfs.c index 5ec8ed5c..fd56a9ac 100644 --- a/lib/ext2fs/openfs.c +++ b/lib/ext2fs/openfs.c @@ -295,8 +295,12 @@ retry: } } - if (fs->super->s_log_block_size > - (unsigned) (EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE)) { + if ((fs->super->s_log_block_size > + (unsigned) (EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE)) || + (fs->super->s_log_cluster_size > + (unsigned) (EXT2_MAX_CLUSTER_LOG_SIZE - EXT2_MIN_CLUSTER_LOG_SIZE)) || + (fs->super->s_log_block_size > fs->super->s_log_cluster_size) || + (fs->super->s_log_groups_per_flex > 31)) { retval = EXT2_ET_CORRUPT_SUPERBLOCK; goto cleanup; } @@ -326,8 +330,13 @@ retry: } /* Enforce the block group descriptor size */ - if (ext2fs_has_feature_64bit(fs->super)) { - if (fs->super->s_desc_size < EXT2_MIN_DESC_SIZE_64BIT) { + if (!(flags & EXT2_FLAG_IGNORE_SB_ERRORS) && + ext2fs_has_feature_64bit(fs->super)) { + unsigned desc_size = fs->super->s_desc_size; + + if ((desc_size < EXT2_MIN_DESC_SIZE_64BIT) || + (desc_size > EXT2_MAX_DESC_SIZE) || + (desc_size & (desc_size - 1)) != 0) { retval = EXT2_ET_BAD_DESC_SIZE; goto cleanup; } @@ -376,7 +385,7 @@ retry: * Read group descriptors */ blocks_per_group = EXT2_BLOCKS_PER_GROUP(fs->super); - if (blocks_per_group == 0 || + if (blocks_per_group < 8 || blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(fs->super) || fs->inode_blocks_per_group > EXT2_MAX_INODES_PER_GROUP(fs->super) || EXT2_DESC_PER_BLOCK(fs->super) == 0 || @@ -400,6 +409,12 @@ retry: } fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count, EXT2_DESC_PER_BLOCK(fs->super)); + if (ext2fs_has_feature_meta_bg(fs->super) && + (fs->super->s_first_meta_bg > fs->desc_blocks) && + !(flags & EXT2_FLAG_IGNORE_SB_ERRORS)) { + retval = EXT2_ET_CORRUPT_SUPERBLOCK; + goto cleanup; + } if (flags & EXT2_FLAG_SUPER_ONLY) goto skip_read_bg; retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize, diff --git a/lib/ext2fs/punch.c b/lib/ext2fs/punch.c index effa1e2d..e2543e1e 100644 --- a/lib/ext2fs/punch.c +++ b/lib/ext2fs/punch.c @@ -200,6 +200,10 @@ static errcode_t punch_extent_blocks(ext2_filsys fs, ext2_ino_t ino, __u32 cluster_freed; errcode_t retval = 0; + if (free_start < fs->super->s_first_data_block || + (free_start + free_count) >= ext2fs_blocks_count(fs->super)) + return EXT2_ET_BAD_BLOCK_NUM; + /* No bigalloc? Just free each block. */ if (EXT2FS_CLUSTER_RATIO(fs) == 1) { *freed += free_count; diff --git a/lib/ext2fs/qcow2.c b/lib/ext2fs/qcow2.c index ee701f7a..20824170 100644 --- a/lib/ext2fs/qcow2.c +++ b/lib/ext2fs/qcow2.c @@ -238,7 +238,7 @@ int qcow2_write_raw_image(int qcow2_fd, int raw_fd, if (offset == 0) continue; - off_out = (l1_index * img.l2_size) + + off_out = ((__u64)l1_index * img.l2_size) + l2_index; off_out <<= img.cluster_bits; ret = qcow2_copy_data(qcow2_fd, raw_fd, offset, diff --git a/lib/ext2fs/rbtree.c b/lib/ext2fs/rbtree.c index 5b92099d..74426fa6 100644 --- a/lib/ext2fs/rbtree.c +++ b/lib/ext2fs/rbtree.c @@ -280,74 +280,6 @@ void ext2fs_rb_erase(struct rb_node *node, struct rb_root *root) __rb_erase_color(child, parent, root); } -static void ext2fs_rb_augment_path(struct rb_node *node, rb_augment_f func, void *data) -{ - struct rb_node *parent; - -up: - func(node, data); - parent = ext2fs_rb_parent(node); - if (!parent) - return; - - if (node == parent->rb_left && parent->rb_right) - func(parent->rb_right, data); - else if (parent->rb_left) - func(parent->rb_left, data); - - node = parent; - goto up; -} - -/* - * after inserting @node into the tree, update the tree to account for - * both the new entry and any damage done by rebalance - */ -void ext2fs_rb_augment_insert(struct rb_node *node, rb_augment_f func, void *data) -{ - if (node->rb_left) - node = node->rb_left; - else if (node->rb_right) - node = node->rb_right; - - ext2fs_rb_augment_path(node, func, data); -} - -/* - * before removing the node, find the deepest node on the rebalance path - * that will still be there after @node gets removed - */ -struct rb_node *ext2fs_rb_augment_erase_begin(struct rb_node *node) -{ - struct rb_node *deepest; - - if (!node->rb_right && !node->rb_left) - deepest = ext2fs_rb_parent(node); - else if (!node->rb_right) - deepest = node->rb_left; - else if (!node->rb_left) - deepest = node->rb_right; - else { - deepest = ext2fs_rb_next(node); - if (deepest->rb_right) - deepest = deepest->rb_right; - else if (ext2fs_rb_parent(deepest) != node) - deepest = ext2fs_rb_parent(deepest); - } - - return deepest; -} - -/* - * after removal, update the tree to account for the removed entry - * and any rebalance damage. - */ -void ext2fs_rb_augment_erase_end(struct rb_node *node, rb_augment_f func, void *data) -{ - if (node) - ext2fs_rb_augment_path(node, func, data); -} - /* * This function returns the first node (in sort order) of the tree. */ diff --git a/lib/ext2fs/rbtree.h b/lib/ext2fs/rbtree.h index dfeeb234..790f5c1c 100644 --- a/lib/ext2fs/rbtree.h +++ b/lib/ext2fs/rbtree.h @@ -98,6 +98,11 @@ static inline struct page * rb_insert_page_cache(struct inode * inode, #include <stdint.h> #include "compiler.h" +#if __GNUC_PREREQ (4, 6) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" +#endif + struct rb_node { uintptr_t rb_parent_color; @@ -151,14 +156,6 @@ static inline void ext2fs_rb_clear_node(struct rb_node *node) extern void ext2fs_rb_insert_color(struct rb_node *, struct rb_root *); extern void ext2fs_rb_erase(struct rb_node *, struct rb_root *); -typedef void (*rb_augment_f)(struct rb_node *node, void *data); - -extern void ext2fs_rb_augment_insert(struct rb_node *node, - rb_augment_f func, void *data); -extern struct rb_node *ext2fs_rb_augment_erase_begin(struct rb_node *node); -extern void ext2fs_rb_augment_erase_end(struct rb_node *node, - rb_augment_f func, void *data); - /* Find logical next and previous nodes in a tree */ extern struct rb_node *ext2fs_rb_next(struct rb_node *); extern struct rb_node *ext2fs_rb_prev(struct rb_node *); @@ -179,4 +176,8 @@ static inline void ext2fs_rb_link_node(struct rb_node * node, *rb_link = node; } +#if __GNUC_PREREQ (4, 6) +#pragma GCC diagnostic pop +#endif + #endif /* _LINUX_RBTREE_H */ diff --git a/lib/ext2fs/rw_bitmaps.c b/lib/ext2fs/rw_bitmaps.c index d760064c..1fe65f74 100644 --- a/lib/ext2fs/rw_bitmaps.c +++ b/lib/ext2fs/rw_bitmaps.c @@ -119,7 +119,7 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block) fs->flags |= EXT2_FLAG_DIRTY; blk = ext2fs_block_bitmap_loc(fs, i); - if (blk) { + if (blk && blk < ext2fs_blocks_count(fs->super)) { retval = io_channel_write_blk64(fs->io, blk, 1, block_buf); if (retval) { @@ -151,7 +151,7 @@ static errcode_t write_bitmaps(ext2_filsys fs, int do_inode, int do_block) fs->flags |= EXT2_FLAG_DIRTY; blk = ext2fs_inode_bitmap_loc(fs, i); - if (blk) { + if (blk && blk < ext2fs_blocks_count(fs->super)) { retval = io_channel_write_blk64(fs->io, blk, 1, inode_buf); if (retval) { @@ -204,14 +204,14 @@ static errcode_t mark_uninit_bg_group_blocks(ext2_filsys fs) * Mark block used for the block bitmap */ blk = ext2fs_block_bitmap_loc(fs, i); - if (blk) + if (blk && blk < ext2fs_blocks_count(fs->super)) ext2fs_mark_block_bitmap2(bmap, blk); /* * Mark block used for the inode bitmap */ blk = ext2fs_inode_bitmap_loc(fs, i); - if (blk) + if (blk && blk < ext2fs_blocks_count(fs->super)) ext2fs_mark_block_bitmap2(bmap, blk); } return 0; @@ -527,7 +527,7 @@ errcode_t ext2fs_rw_bitmaps(ext2_filsys fs, int flags, int num_threads) pthread_mutex_t rbt_mutex = PTHREAD_MUTEX_INITIALIZER; errcode_t retval; errcode_t rc; - unsigned flexbg_size = 1 << fs->super->s_log_groups_per_flex; + unsigned flexbg_size = 1U << fs->super->s_log_groups_per_flex; dgrp_t average_group; int i, tail_flags = 0; #endif @@ -535,6 +535,9 @@ errcode_t ext2fs_rw_bitmaps(ext2_filsys fs, int flags, int num_threads) if (flags & ~EXT2FS_BITMAPS_VALID_FLAGS) return EXT2_ET_INVALID_ARGUMENT; + if (ext2fs_has_feature_journal_dev(fs->super)) + return EXT2_ET_EXTERNAL_JOURNAL_NOSUPP; + if (flags & EXT2FS_BITMAPS_WRITE) return write_bitmaps(fs, flags & EXT2FS_BITMAPS_INODE, flags & EXT2FS_BITMAPS_BLOCK); @@ -557,13 +560,13 @@ errcode_t ext2fs_rw_bitmaps(ext2_filsys fs, int flags, int num_threads) if (num_threads < 0) num_threads = 4; - if (num_threads > fs->group_desc_count) + if ((unsigned) num_threads > fs->group_desc_count) num_threads = fs->group_desc_count; average_group = fs->group_desc_count / num_threads; if (ext2fs_has_feature_flex_bg(fs->super)) { average_group = (average_group / flexbg_size) * flexbg_size; } - if (average_group == 0) + if ((num_threads <= 1) || (average_group == 0)) goto fallback; io_channel_set_options(fs->io, "cache=off"); diff --git a/lib/ext2fs/sha256.c b/lib/ext2fs/sha256.c index f67848d4..b1506e2d 100644 --- a/lib/ext2fs/sha256.c +++ b/lib/ext2fs/sha256.c @@ -180,7 +180,7 @@ static void sha256_done(struct hash_state * md, unsigned char *out) md->sha256.curlen = 0; } - /* pad upto 56 bytes of zeroes */ + /* pad up to 56 bytes of zeroes */ while (md->sha256.curlen < 56) { md->sha256.buf[md->sha256.curlen++] = (unsigned char)0; } diff --git a/lib/ext2fs/sha512.c b/lib/ext2fs/sha512.c index fe2dd52e..f246afb5 100644 --- a/lib/ext2fs/sha512.c +++ b/lib/ext2fs/sha512.c @@ -185,7 +185,7 @@ static void sha512_done(struct hash_state * md, unsigned char *out) md->sha512.curlen = 0; } - /* pad upto 120 bytes of zeroes note: that from 112 to 120 is the 64 MSB + /* pad up to 120 bytes of zeroes note: that from 112 to 120 is the 64 MSB * of the length. We assume that you won't hash > 2^64 bits of data. */ while (md->sha512.curlen < 120) { md->sha512.buf[md->sha512.curlen++] = (unsigned char)0; diff --git a/lib/ext2fs/swapfs.c b/lib/ext2fs/swapfs.c index 1006b2d2..5e6b22f4 100644 --- a/lib/ext2fs/swapfs.c +++ b/lib/ext2fs/swapfs.c @@ -244,7 +244,7 @@ void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t, int bufsize) { unsigned i, extra_isize, attr_magic; - int has_extents, has_inline_data, islnk, fast_symlink; + int has_extents = 0, has_inline_data = 0, islnk = 0, fast_symlink = 0; unsigned int inode_size; __u32 *eaf, *eat; @@ -434,11 +434,14 @@ errcode_t ext2fs_dirent_swab_in2(ext2_filsys fs, char *buf, return retval; if ((rec_len < 8) || (rec_len % 4)) { rec_len = 8; - retval = EXT2_ET_DIR_CORRUPTED; + if (!(fs->flags & EXT2_FLAG_IGNORE_SWAP_DIRENT)) + return EXT2_ET_DIR_CORRUPTED; } else if (((name_len & 0xFF) + 8) > rec_len) - retval = EXT2_ET_DIR_CORRUPTED; + if (!(fs->flags & EXT2_FLAG_IGNORE_SWAP_DIRENT)) + return EXT2_ET_DIR_CORRUPTED; if (rec_len > left) - return EXT2_ET_DIR_CORRUPTED; + if (!(fs->flags & EXT2_FLAG_IGNORE_SWAP_DIRENT)) + return EXT2_ET_DIR_CORRUPTED; left -= rec_len; p += rec_len; } diff --git a/lib/ext2fs/tdb.c b/lib/ext2fs/tdb.c index 5091b128..b07b2917 100644 --- a/lib/ext2fs/tdb.c +++ b/lib/ext2fs/tdb.c @@ -65,6 +65,12 @@ Last Changed Date: 2007-06-22 13:36:10 -0400 (Fri, 22 Jun 2007) #include <sys/mman.h> #endif +#ifdef __GNUC__ +#define EXT2FS_ATTR(x) __attribute__(x) +#else +#define EXT2FS_ATTR(x) +#endif + #ifndef MAP_FILE #define MAP_FILE 0 #endif @@ -256,6 +262,7 @@ struct tdb_context { static int tdb_munmap(struct tdb_context *tdb); static void tdb_mmap(struct tdb_context *tdb); static int tdb_lock(struct tdb_context *tdb, int list, int ltype); +int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype); static int tdb_unlock(struct tdb_context *tdb, int list, int ltype); static int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, int rw_type, int lck_type, int probe, size_t len); static int tdb_transaction_lock(struct tdb_context *tdb, int ltype); @@ -410,7 +417,7 @@ static int _tdb_lock(struct tdb_context *tdb, int list, int ltype, int op) /* a global lock allows us to avoid per chain locks */ if (tdb->global_lock.count && - (ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) { + ((u32)ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) { return 0; } @@ -505,7 +512,7 @@ int tdb_unlock(struct tdb_context *tdb, int list, int ltype) /* a global lock allows us to avoid per chain locks */ if (tdb->global_lock.count && - (ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) { + ((u32)ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) { return 0; } @@ -626,7 +633,7 @@ static int _tdb_lockall(struct tdb_context *tdb, int ltype, int op) if (tdb->read_only || tdb->traverse_read) return TDB_ERRCODE(TDB_ERR_LOCK, -1); - if (tdb->global_lock.count && tdb->global_lock.ltype == ltype) { + if (tdb->global_lock.count && tdb->global_lock.ltype == (u32)ltype) { tdb->global_lock.count++; return 0; } @@ -670,7 +677,8 @@ static int _tdb_unlockall(struct tdb_context *tdb, int ltype) return TDB_ERRCODE(TDB_ERR_LOCK, -1); } - if (tdb->global_lock.ltype != ltype || tdb->global_lock.count == 0) { + if (tdb->global_lock.ltype != (u32)ltype || + tdb->global_lock.count == 0) { return TDB_ERRCODE(TDB_ERR_LOCK, -1); } @@ -853,7 +861,7 @@ static int tdb_oob(struct tdb_context *tdb, tdb_off_t len, int probe) return TDB_ERRCODE(TDB_ERR_IO, -1); } - if (st.st_size < (size_t)len) { + if (st.st_size < (off_t)len) { if (!probe) { /* Ensure ecode is set for log fn. */ tdb->ecode = TDB_ERR_IO; @@ -1537,7 +1545,8 @@ static void transaction_next_hash_chain(struct tdb_context *tdb, u32 *chain) /* out of bounds check during a transaction */ -static int transaction_oob(struct tdb_context *tdb, tdb_off_t len, int probe) +static int transaction_oob(struct tdb_context *tdb, tdb_off_t len, + int probe EXT2FS_ATTR((unused))) { if (len <= tdb->map_size) { return 0; @@ -1563,8 +1572,12 @@ static int transaction_expand_file(struct tdb_context *tdb, tdb_off_t size, /* brlock during a transaction - ignore them */ -static int transaction_brlock(struct tdb_context *tdb, tdb_off_t offset, - int rw_type, int lck_type, int probe, size_t len) +static int transaction_brlock(struct tdb_context *tdb EXT2FS_ATTR((unused)), + tdb_off_t offset EXT2FS_ATTR((unused)), + int rw_type EXT2FS_ATTR((unused)), + int lck_type EXT2FS_ATTR((unused)), + int probe EXT2FS_ATTR((unused)), + size_t len EXT2FS_ATTR((unused))) { return 0; } @@ -2186,6 +2199,7 @@ int tdb_transaction_recover(struct tdb_context *tdb) rec.data_len, 0) == -1) { TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to read recovery data\n")); tdb->ecode = TDB_ERR_IO; + free(data); return -1; } @@ -3006,7 +3020,7 @@ static int tdb_dump_chain(struct tdb_context *tdb, int i) void tdb_dump_all(struct tdb_context *tdb) { int i; - for (i=0;i<tdb->header.hash_size;i++) { + for (i = 0; i < (int)tdb->header.hash_size; i++) { tdb_dump_chain(tdb, i); } printf("freelist:\n"); @@ -3075,9 +3089,10 @@ void tdb_increment_seqnum_nonblock(struct tdb_context *tdb) /* we ignore errors from this, as we have no sane way of dealing with them. */ - tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum); + if (tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum) == -1) + return; seqnum++; - tdb_ofs_write(tdb, TDB_SEQNUM_OFS, &seqnum); + (void) tdb_ofs_write(tdb, TDB_SEQNUM_OFS, &seqnum); } /* @@ -3099,7 +3114,8 @@ static void tdb_increment_seqnum(struct tdb_context *tdb) tdb_brlock(tdb, TDB_SEQNUM_OFS, F_UNLCK, F_SETLKW, 1, 1); } -static int tdb_key_compare(TDB_DATA key, TDB_DATA data, void *private_data) +static int tdb_key_compare(TDB_DATA key, TDB_DATA data, + void *private_data EXT2FS_ATTR((unused))) { return memcmp(data.dptr, key.dptr, data.dsize); } @@ -3677,7 +3693,8 @@ int tdb_get_seqnum(struct tdb_context *tdb) { tdb_off_t seqnum=0; - tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum); + if (tdb_ofs_read(tdb, TDB_SEQNUM_OFS, &seqnum) == -1) + return 0; return seqnum; } @@ -3803,7 +3820,9 @@ struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags, /* a default logging function */ static void null_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4); -static void null_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...) +static void null_log_fn(struct tdb_context *tdb EXT2FS_ATTR((unused)), + enum tdb_debug_level level EXT2FS_ATTR((unused)), + const char *fmt EXT2FS_ATTR((unused)), ...) { } @@ -3897,7 +3916,8 @@ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags, } if (read(tdb->fd, &tdb->header, sizeof(tdb->header)) != sizeof(tdb->header) - || strcmp(tdb->header.magic_food, TDB_MAGIC_FOOD) != 0 + || memcmp(tdb->header.magic_food, TDB_MAGIC_FOOD, + sizeof(TDB_MAGIC_FOOD)) != 0 || (tdb->header.version != TDB_VERSION && !(rev = (tdb->header.version==TDB_BYTEREV(TDB_VERSION))))) { /* its not a valid database - possibly initialise it */ diff --git a/lib/ext2fs/test_io.c b/lib/ext2fs/test_io.c index 480e68fc..6843edbc 100644 --- a/lib/ext2fs/test_io.c +++ b/lib/ext2fs/test_io.c @@ -248,6 +248,8 @@ static errcode_t test_open(const char *name, int flags, io_channel *channel) return 0; cleanup: + if (io && io->name) + ext2fs_free_mem(&io->name); if (io) ext2fs_free_mem(&io); if (data) diff --git a/lib/ext2fs/tst_bitops.c b/lib/ext2fs/tst_bitops.c index 8262d3b7..adef12da 100644 --- a/lib/ext2fs/tst_bitops.c +++ b/lib/ext2fs/tst_bitops.c @@ -104,7 +104,7 @@ int main(int argc, char **argv) bigarray = malloc(1 << 29); if (!bigarray) { fprintf(stderr, "Failed to allocate scratch memory!\n"); - exit(1); + exit(0); } bigarray[BIG_TEST_BIT >> 3] = 0; diff --git a/lib/ext2fs/tst_getsize.c b/lib/ext2fs/tst_getsize.c index 4ac2ea1f..ba869dce 100644 --- a/lib/ext2fs/tst_getsize.c +++ b/lib/ext2fs/tst_getsize.c @@ -29,18 +29,19 @@ int main(int argc, const char *argv[]) { errcode_t retval; - blk_t blocks; + blk64_t blocks; if (argc < 2) { fprintf(stderr, "%s device\n", argv[0]); exit(1); } add_error_table(&et_ext2_error_table); - retval = ext2fs_get_device_size(argv[1], 1024, &blocks); + retval = ext2fs_get_device_size2(argv[1], 1024, &blocks); if (retval) { com_err(argv[0], retval, "while getting device size"); exit(1); } - printf("%s is device has %u blocks.\n", argv[1], blocks); + printf("%s is device has %llu blocks.\n", argv[1], + (unsigned long long) blocks); return 0; } diff --git a/lib/ext2fs/undo_io.c b/lib/ext2fs/undo_io.c index eb56f53d..f4a6d526 100644 --- a/lib/ext2fs/undo_io.c +++ b/lib/ext2fs/undo_io.c @@ -790,6 +790,8 @@ cleanup: io_channel_close(data->real); if (data) ext2fs_free_mem(&data); + if (io && io->name) + ext2fs_free_mem(&io->name); if (io) ext2fs_free_mem(&io); return retval; diff --git a/lib/ext2fs/unix_io.c b/lib/ext2fs/unix_io.c index 3bb8d238..353d85af 100644 --- a/lib/ext2fs/unix_io.c +++ b/lib/ext2fs/unix_io.c @@ -94,6 +94,7 @@ struct unix_cache { int access_time; unsigned dirty:1; unsigned in_use:1; + unsigned write_err:1; }; #define CACHE_SIZE 8 @@ -311,11 +312,11 @@ bounce_read: size += really_read; goto short_read; } - actual = size; - if (actual > align_size) - actual = align_size; - actual -= offset; - memcpy(buf, data->bounce + offset, actual); + if ((actual + offset) > align_size) + actual = align_size - offset; + if (actual > size) + actual = size; + memcpy(buf, (char *)data->bounce + offset, actual); really_read += actual; size -= actual; @@ -337,10 +338,13 @@ error_unlock: return retval; } +#define RAW_WRITE_NO_HANDLER 1 + static errcode_t raw_write_blk(io_channel channel, struct unix_private_data *data, unsigned long long block, - int count, const void *bufv) + int count, const void *bufv, + int flags) { ssize_t size; ext2_loff_t location; @@ -397,7 +401,7 @@ static errcode_t raw_write_blk(io_channel channel, mutex_lock(data, BOUNCE_MTX); if (ext2fs_llseek(data->dev, location, SEEK_SET) < 0) { retval = errno ? errno : EXT2_ET_LLSEEK_FAILED; - goto error_out; + goto error_unlock; } actual = write(data->dev, buf, size); mutex_unlock(data, BOUNCE_MTX); @@ -454,9 +458,10 @@ bounce_write: } } actual = size; - if (actual > align_size) - actual = align_size; - actual -= offset; + if ((actual + offset) > align_size) + actual = align_size - offset; + if (actual > size) + actual = size; memcpy(((char *)data->bounce) + offset, buf, actual); if (ext2fs_llseek(data->dev, aligned_blk * align_size, SEEK_SET) < 0) { retval = errno ? errno : EXT2_ET_LLSEEK_FAILED; @@ -481,7 +486,7 @@ bounce_write: error_unlock: mutex_unlock(data, BOUNCE_MTX); error_out: - if (channel->write_error) + if (((flags & RAW_WRITE_NO_HANDLER) == 0) && channel->write_error) retval = (channel->write_error)(channel, block, count, buf, size, actual, retval); return retval; @@ -575,16 +580,27 @@ static struct unix_cache *find_cached_block(struct unix_private_data *data, /* * 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 long block) +static errcode_t reuse_cache(io_channel channel, + struct unix_private_data *data, struct unix_cache *cache, + unsigned long long block) { - if (cache->dirty && cache->in_use) - raw_write_blk(channel, data, cache->block, 1, cache->buf); + if (cache->dirty && cache->in_use) { + errcode_t retval; + + retval = raw_write_blk(channel, data, cache->block, 1, + cache->buf, RAW_WRITE_NO_HANDLER); + if (retval) { + cache->write_err = 1; + return retval; + } + } cache->in_use = 1; cache->dirty = 0; + cache->write_err = 0; cache->block = block; cache->access_time = ++data->access_time; + return 0; } #define FLUSH_INVALIDATE 0x01 @@ -598,31 +614,66 @@ static errcode_t flush_cached_blocks(io_channel channel, int flags) { struct unix_cache *cache; - errcode_t retval, retval2; + errcode_t retval, retval2 = 0; int i; + int errors_found = 0; - retval2 = 0; if ((flags & FLUSH_NOLOCK) == 0) mutex_lock(data, CACHE_MTX); for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { - if (!cache->in_use) + if (!cache->in_use || !cache->dirty) continue; - - if (flags & FLUSH_INVALIDATE) - cache->in_use = 0; - - if (!cache->dirty) - continue; - retval = raw_write_blk(channel, data, - cache->block, 1, cache->buf); - if (retval) + cache->block, 1, cache->buf, + RAW_WRITE_NO_HANDLER); + if (retval) { + cache->write_err = 1; + errors_found = 1; retval2 = retval; - else + } else { cache->dirty = 0; + cache->write_err = 0; + if (flags & FLUSH_INVALIDATE) + cache->in_use = 0; + } } if ((flags & FLUSH_NOLOCK) == 0) mutex_unlock(data, CACHE_MTX); +retry: + while (errors_found) { + if ((flags & FLUSH_NOLOCK) == 0) + mutex_lock(data, CACHE_MTX); + errors_found = 0; + for (i=0, cache = data->cache; i < CACHE_SIZE; i++, cache++) { + if (!cache->in_use || !cache->write_err) + continue; + errors_found = 1; + if (cache->write_err && channel->write_error) { + char *err_buf = NULL; + unsigned long long err_block = cache->block; + + cache->dirty = 0; + cache->in_use = 0; + cache->write_err = 0; + if (io_channel_alloc_buf(channel, 0, + &err_buf)) + err_buf = NULL; + else + memcpy(err_buf, cache->buf, + channel->block_size); + mutex_unlock(data, CACHE_MTX); + (channel->write_error)(channel, err_block, + 1, err_buf, channel->block_size, -1, + retval2); + if (err_buf) + ext2fs_free_mem(&err_buf); + goto retry; + } else + cache->write_err = 0; + } + if ((flags & FLUSH_NOLOCK) == 0) + mutex_unlock(data, CACHE_MTX); + } return retval2; } #endif /* NO_IO_CACHE */ @@ -956,8 +1007,11 @@ static errcode_t unix_set_blksize(io_channel channel, int blksize) mutex_lock(data, CACHE_MTX); mutex_lock(data, BOUNCE_MTX); #ifndef NO_IO_CACHE - if ((retval = flush_cached_blocks(channel, data, FLUSH_NOLOCK))) + if ((retval = flush_cached_blocks(channel, data, FLUSH_NOLOCK))){ + mutex_unlock(data, BOUNCE_MTX); + mutex_unlock(data, CACHE_MTX); return retval; + } #endif channel->block_size = blksize; @@ -973,8 +1027,8 @@ static errcode_t unix_read_blk64(io_channel channel, unsigned long long block, int count, void *buf) { struct unix_private_data *data; - struct unix_cache *cache, *reuse[READ_DIRECT_SIZE]; - errcode_t retval = 0; + struct unix_cache *cache; + errcode_t retval; char *cp; int i, j; @@ -1001,7 +1055,7 @@ static errcode_t unix_read_blk64(io_channel channel, unsigned long long block, mutex_lock(data, CACHE_MTX); while (count > 0) { /* If it's in the cache, use it! */ - if ((cache = find_cached_block(data, block, &reuse[0]))) { + if ((cache = find_cached_block(data, block, NULL))) { #ifdef DEBUG printf("Using cached block %lu\n", block); #endif @@ -1011,46 +1065,59 @@ static errcode_t unix_read_blk64(io_channel channel, unsigned long long block, cp += channel->block_size; continue; } - if (count == 1) { - /* - * Special case where we read directly into the - * cache buffer; important in the O_DIRECT case - */ - cache = reuse[0]; - reuse_cache(channel, data, cache, block); - if ((retval = raw_read_blk(channel, data, block, 1, - cache->buf))) { - cache->in_use = 0; - break; - } - memcpy(cp, cache->buf, channel->block_size); - retval = 0; - break; - } /* * 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])) + if (find_cached_block(data, block+i, NULL)) break; #ifdef DEBUG printf("Reading %d blocks starting at %lu\n", i, block); #endif + mutex_unlock(data, CACHE_MTX); if ((retval = raw_read_blk(channel, data, block, i, cp))) - break; + return retval; + mutex_lock(data, CACHE_MTX); /* Save the results in the cache */ for (j=0; j < i; j++) { + if (!find_cached_block(data, block, &cache)) { + retval = reuse_cache(channel, data, + cache, block); + if (retval) + goto call_write_handler; + memcpy(cache->buf, cp, channel->block_size); + } count--; - cache = reuse[j]; - reuse_cache(channel, data, cache, block++); - memcpy(cache->buf, cp, channel->block_size); + block++; cp += channel->block_size; } } mutex_unlock(data, CACHE_MTX); + return 0; + +call_write_handler: + if (cache->write_err && channel->write_error) { + char *err_buf = NULL; + unsigned long long err_block = cache->block; + + cache->dirty = 0; + cache->in_use = 0; + cache->write_err = 0; + if (io_channel_alloc_buf(channel, 0, &err_buf)) + err_buf = NULL; + else + memcpy(err_buf, cache->buf, channel->block_size); + mutex_unlock(data, CACHE_MTX); + (channel->write_error)(channel, err_block, 1, err_buf, + channel->block_size, -1, + retval); + if (err_buf) + ext2fs_free_mem(&err_buf); + } else + mutex_unlock(data, CACHE_MTX); return retval; #endif /* NO_IO_CACHE */ } @@ -1075,10 +1142,10 @@ static errcode_t unix_write_blk64(io_channel channel, unsigned long long block, EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_UNIX_IO_CHANNEL); #ifdef NO_IO_CACHE - return raw_write_blk(channel, data, block, count, buf); + return raw_write_blk(channel, data, block, count, buf, 0); #else if (data->flags & IO_FLAG_NOCACHE) - return raw_write_blk(channel, data, block, count, buf); + return raw_write_blk(channel, data, block, count, buf, 0); /* * If we're doing an odd-sized write or a very large write, * flush out the cache completely and then do a direct write. @@ -1087,7 +1154,7 @@ static errcode_t unix_write_blk64(io_channel channel, unsigned long long block, if ((retval = flush_cached_blocks(channel, data, FLUSH_INVALIDATE))) return retval; - return raw_write_blk(channel, data, block, count, buf); + return raw_write_blk(channel, data, block, count, buf, 0); } /* @@ -1097,15 +1164,19 @@ static errcode_t unix_write_blk64(io_channel channel, unsigned long long block, */ writethrough = channel->flags & CHANNEL_FLAGS_WRITETHROUGH; if (writethrough) - retval = raw_write_blk(channel, data, block, count, buf); + retval = raw_write_blk(channel, data, block, count, buf, 0); cp = buf; mutex_lock(data, CACHE_MTX); while (count > 0) { cache = find_cached_block(data, block, &reuse); if (!cache) { + errcode_t err; + cache = reuse; - reuse_cache(channel, data, cache, block); + err = reuse_cache(channel, data, cache, block); + if (err) + goto call_write_handler; } if (cache->buf != cp) memcpy(cache->buf, cp, channel->block_size); @@ -1116,6 +1187,28 @@ static errcode_t unix_write_blk64(io_channel channel, unsigned long long block, } mutex_unlock(data, CACHE_MTX); return retval; + +call_write_handler: + if (cache->write_err && channel->write_error) { + char *err_buf = NULL; + unsigned long long err_block = cache->block; + + cache->dirty = 0; + cache->in_use = 0; + cache->write_err = 0; + if (io_channel_alloc_buf(channel, 0, &err_buf)) + err_buf = NULL; + else + memcpy(err_buf, cache->buf, channel->block_size); + mutex_unlock(data, CACHE_MTX); + (channel->write_error)(channel, err_block, 1, err_buf, + channel->block_size, -1, + retval); + if (err_buf) + ext2fs_free_mem(&err_buf); + } else + mutex_unlock(data, CACHE_MTX); + return retval; #endif /* NO_IO_CACHE */ } diff --git a/lib/ext2fs/windows_io.c b/lib/ext2fs/windows_io.c new file mode 100644 index 00000000..f01bbb6a --- /dev/null +++ b/lib/ext2fs/windows_io.c @@ -0,0 +1,1020 @@ +/* + * windows_io.c --- This is the Windows implementation of the I/O manager. + * + * Implements a one-block write-through cache. + * + * 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 Library + * General Public License, version 2. + * %End-Header% + */ + +#include <windows.h> +#include <winioctl.h> +#include <io.h> + +#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) +#define _XOPEN_SOURCE 600 +#define _DARWIN_C_SOURCE +#define _FILE_OFFSET_BITS 64 +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#endif + +#include "config.h" +#include <stdio.h> +#include <string.h> +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#if HAVE_ERRNO_H +#include <errno.h> +#endif +#include <fcntl.h> +#include <time.h> +#if HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#define PR_GET_DUMPABLE 3 +#if HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#include <fcntl.h> + +#undef ALIGN_DEBUG + +//#define DEBUG +#ifdef DEBUG +#define TRACE(...) {\ + char __log[256];\ + snprintf(__log, sizeof(__log), __VA_ARGS__);\ + __log[sizeof(__log)-1] = 0;\ + OutputDebugString(__log);\ + } +#else +#define TRACE(...) do { } while (0); +#endif + +#include "ext2_fs.h" +#include "ext2fs.h" +#include "ext2fsP.h" + +/* + * For checking structure magic numbers... + */ + +#define EXT2_CHECK_MAGIC(struct, code) \ + if ((struct)->magic != (code)) return (code) +#define EXT2_CHECK_MAGIC_RETURN(struct, code, ret) \ + if ((struct)->magic != (code)) return (ret) + +#define EXT2_ET_MAGIC_WINDOWS_IO_CHANNEL 0x10ed + +struct windows_cache { + char *buf; + unsigned long 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 windows_private_data { + int magic; + char name[MAX_PATH]; + HANDLE handle; + char dos_device[MAX_PATH]; + char cf_device[MAX_PATH]; + int dev; + int flags; + int align; + int access_time; + ext2_loff_t offset; + struct windows_cache cache[CACHE_SIZE]; + void *bounce; + struct struct_io_stats io_stats; +}; + +#define IS_ALIGNED(n, align) ((((uintptr_t) n) & \ + ((uintptr_t) ((align)-1))) == 0) + +static int fake_dos_name_for_device(struct windows_private_data *data) +{ + if (strncmp(data->name, "\\\\", 2) == 0) { + data->dos_device[0] = 0; + strcpy(data->cf_device, data->name); + return 0; + } + + _snprintf(data->dos_device, MAX_PATH, "fakedevice%lu", GetCurrentProcessId()); + + if (!DefineDosDevice(DDD_RAW_TARGET_PATH, data->dos_device, data->name)) + return 1; + + _snprintf(data->cf_device, MAX_PATH, "\\\\.\\%s", data->dos_device); + TRACE("e2fsprogs::fake_dos_name_for_device::DefineDosDevice(\"%s\")", data->dos_device); + + return 0; +} + +static void remove_fake_dos_name(struct windows_private_data *data) +{ + if (*data->dos_device) { + TRACE("e2fsprogs::remove_fake_dos_name::DefineDosDevice(\"%s\")", data->dos_device); + DefineDosDevice(DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE | DDD_REMOVE_DEFINITION, data->dos_device, data->name); + } +} + +static errcode_t windows_get_stats(io_channel channel, io_stats *stats) +{ + errcode_t retval = 0; + + struct windows_private_data *data; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct windows_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_WINDOWS_IO_CHANNEL); + + if (stats) + *stats = &data->io_stats; + + return retval; +} + +/* + * Here are the raw I/O functions + */ +static errcode_t raw_read_blk(io_channel channel, + struct windows_private_data *data, + unsigned long long block, + int count, void *bufv) +{ + errcode_t retval; + ssize_t size; + ext2_loff_t location; + DWORD actual = 0; + unsigned char *buf = bufv; + ssize_t really_read = 0; + + size = (count < 0) ? -count : count * channel->block_size; + data->io_stats.bytes_read += size; + location = ((ext2_loff_t) block * channel->block_size) + data->offset; + + if (data->flags & IO_FLAG_FORCE_BOUNCE) { + if (SetFilePointer(data->handle, location, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { + retval = GetLastError(); + goto error_out; + } + goto bounce_read; + } + + if (SetFilePointer(data->handle, location, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { + retval = GetLastError(); + goto error_out; + } + if ((channel->align == 0) || (IS_ALIGNED(buf, channel->align) && IS_ALIGNED(size, channel->align))) { + if (!ReadFile(data->handle, buf, size, &actual, NULL)) { + retval = GetLastError(); + goto error_out; + } + if (actual != size) { + short_read: + if (actual < 0) { + retval = GetLastError(); + actual = 0; + } else + retval = EXT2_ET_SHORT_READ; + goto error_out; + } + return 0; + } + + /* + * The buffer or size which we're trying to read isn't aligned + * to the O_DIRECT rules, so we need to do this the hard way... + */ +bounce_read: + while (size > 0) { + if (!ReadFile(data->handle, data->bounce, channel->block_size, &actual, NULL)) { + retval = GetLastError(); + goto error_out; + } + if (actual != channel->block_size) { + actual = really_read; + buf -= really_read; + size += really_read; + goto short_read; + } + actual = size; + if (size > channel->block_size) + actual = channel->block_size; + memcpy(buf, data->bounce, actual); + really_read += actual; + size -= actual; + buf += actual; + } + return 0; + +error_out: + if (actual >= 0 && actual < size) + memset((char *) buf+actual, 0, size-actual); + if (channel->read_error) + retval = (channel->read_error)(channel, block, count, buf, + size, actual, retval); + return retval; +} + +static errcode_t raw_write_blk(io_channel channel, + struct windows_private_data *data, + unsigned long long block, + int count, const void *bufv) +{ + ssize_t size; + ext2_loff_t location; + DWORD actual = 0; + errcode_t retval; + const unsigned char *buf = bufv; + + if (count == 1) + size = channel->block_size; + else { + if (count < 0) + size = -count; + else + size = count * channel->block_size; + } + data->io_stats.bytes_written += size; + + location = ((ext2_loff_t) block * channel->block_size) + data->offset; + + if (data->flags & IO_FLAG_FORCE_BOUNCE) { + if (SetFilePointer(data->handle, location, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { + retval = GetLastError(); + goto error_out; + } + goto bounce_write; + } + + if (SetFilePointer(data->handle, location, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { + retval = GetLastError(); + goto error_out; + } + + SetLastError(0); + + if ((channel->align == 0) || (IS_ALIGNED(buf, channel->align) && IS_ALIGNED(size, channel->align))) { + if (!WriteFile(data->handle, buf, size, &actual, NULL)) { + retval = GetLastError(); + goto error_out; + } + + if (actual != size) { + short_write: + retval = EXT2_ET_SHORT_WRITE; + goto error_out; + } + return 0; + } + + /* + * The buffer or size which we're trying to write isn't aligned + * to the O_DIRECT rules, so we need to do this the hard way... + */ +bounce_write: + while (size > 0) { + if (size < channel->block_size) { + if (!ReadFile(data->handle, data->bounce, channel->block_size, &actual, NULL)) { + retval = GetLastError(); + goto error_out; + } + if (actual != channel->block_size) { + if (actual < 0) { + retval = GetLastError(); + goto error_out; + } + memset((char *) data->bounce + actual, 0, + channel->block_size - actual); + } + } + actual = size; + if (size > channel->block_size) + actual = channel->block_size; + memcpy(data->bounce, buf, actual); + if (SetFilePointer(data->handle, location, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { + retval = GetLastError(); + goto error_out; + } + if (!WriteFile(data->handle, data->bounce, channel->block_size, &actual, NULL)) { + retval = GetLastError(); + goto error_out; + } + + if (actual != channel->block_size) + goto short_write; + size -= actual; + buf += actual; + location += actual; + } + 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 windows_private_data *data) +{ + errcode_t retval; + struct windows_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 (cache->buf) + ext2fs_free_mem(&cache->buf); + retval = io_channel_alloc_buf(channel, 0, &cache->buf); + if (retval) + return retval; + } + if (channel->align || data->flags & IO_FLAG_FORCE_BOUNCE) { + if (data->bounce) + ext2fs_free_mem(&data->bounce); + retval = io_channel_alloc_buf(channel, 0, &data->bounce); + } + return retval; +} + +/* Free the cache buffers */ +static void free_cache(struct windows_private_data *data) +{ + struct windows_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 (cache->buf) + ext2fs_free_mem(&cache->buf); + } + if (data->bounce) + ext2fs_free_mem(&data->bounce); +} + +#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 windows_cache *find_cached_block(struct windows_private_data *data, + unsigned long long block, + struct windows_cache **eldest) +{ + struct windows_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 windows_private_data *data, + struct windows_cache *cache, unsigned long 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 windows_private_data *data, + int invalidate) +{ + struct windows_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 windows_open_channel(struct windows_private_data *data, + int flags, io_channel *channel, + io_manager io_mgr) +{ + io_channel io = NULL; + errcode_t retval; + ext2fs_struct_stat st; + + 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 = io_mgr; + retval = ext2fs_get_mem(strlen(data->name)+1, &io->name); + if (retval) + goto cleanup; + + strcpy(io->name, data->name); + io->private_data = data; + io->block_size = 1024; + io->read_error = 0; + io->write_error = 0; + io->refcount = 1; + +#if defined(O_DIRECT) + if (flags & IO_FLAG_DIRECT_IO) + io->align = ext2fs_get_dio_alignment(data->dev); +#endif + + /* + * If the device is really a block device, then set the + * appropriate flag, otherwise we can set DISCARD_ZEROES flag + * because we are going to use punch hole instead of discard + * and if it succeed, subsequent read from sparse area returns + * zero. + */ + if (ext2fs_fstat(data->dev, &st) == 0) { + if (ext2fsP_is_disk_device(st.st_mode)) + io->flags |= CHANNEL_FLAGS_BLOCK_DEVICE; + else + io->flags |= CHANNEL_FLAGS_DISCARD_ZEROES; + } + + if ((retval = alloc_cache(io, data))) + goto cleanup; + +#ifdef BLKROGET + if (flags & IO_FLAG_RW) { + int error; + int readonly = 0; + + /* Is the block device actually writable? */ + error = ioctl(data->dev, BLKROGET, &readonly); + if (!error && readonly) { + retval = EPERM; + goto cleanup; + } + } +#endif + + *channel = io; + return 0; + +cleanup: + if (data) { + if (data->dev >= 0) + close(data->dev); + free_cache(data); + ext2fs_free_mem(&data); + } + if (io) { + if (io->name) { + ext2fs_free_mem(&io->name); + } + ext2fs_free_mem(&io); + } + return retval; +} + +static DWORD windows_open_device(struct windows_private_data *data, int open_flags) +{ + DWORD ret = 0; + + if (*data->name != '\\') + strcpy(data->cf_device, data->name); + else if (fake_dos_name_for_device(data)) + return -1; + + DWORD desired_access = GENERIC_READ | ((open_flags & O_RDWR) ? GENERIC_WRITE : 0); + DWORD share_mode = (open_flags & O_EXCL) ? 0 : FILE_SHARE_READ | ((open_flags & O_RDWR) ? FILE_SHARE_WRITE : 0); + DWORD flags_and_attributes = +#if defined(O_DIRECT) + (open_flags & O_DIRECT) ? (FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH) : FILE_ATTRIBUTE_NORMAL; +#else + FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH; +#endif + + data->handle = CreateFile(data->cf_device, desired_access, share_mode, NULL, OPEN_EXISTING, + flags_and_attributes, NULL); + + if (data->handle == INVALID_HANDLE_VALUE) { + ret = GetLastError(); + goto invalid_handle; + } + + TRACE("e2fsprogs::windows_open_device::CreateFile(\"%s\") = %p", data->cf_device, data->handle); + + data->dev = _open_osfhandle((intptr_t)data->handle, 0); + if (data->dev < 0) { + ret = GetLastError() ? GetLastError() : 9999; + goto osfhandle_error; + } + + TRACE("e2fsprogs::windows_open_device::_open_osfhandle(%p) = %d", data->handle, data->dev); + + return 0; + +osfhandle_error: + TRACE("e2fsprogs::windows_open_device::CloseHandle(%p)", data->handle); + CloseHandle(data->handle); +invalid_handle: + remove_fake_dos_name(data); + TRACE("e2fsprogs::windows_open_device() = %lu, errno = %d", ret, errno); + return ret; +} + +static struct windows_private_data *init_private_data(const char *name, int flags) +{ + struct windows_private_data *data = NULL; + + if (ext2fs_get_mem(sizeof(struct windows_private_data), &data)) + return NULL; + + memset(data, 0, sizeof(struct windows_private_data)); + strncpy(data->name, name, sizeof(data->name) - 1); + data->magic = EXT2_ET_MAGIC_WINDOWS_IO_CHANNEL; + data->io_stats.num_fields = 2; + data->flags = flags; + data->handle = INVALID_HANDLE_VALUE; + + return data; +} + +static errcode_t windows_open(const char *name, int flags, io_channel *channel) +{ + int open_flags; + struct windows_private_data *data; + + if (name == 0) + return EXT2_ET_BAD_DEVICE_NAME; + + data = init_private_data(name, flags); + if (!data) + return EXT2_ET_NO_MEMORY; + + open_flags = (flags & IO_FLAG_RW) ? O_RDWR : O_RDONLY; + if (flags & IO_FLAG_EXCLUSIVE) + open_flags |= O_EXCL; +#if defined(O_DIRECT) + if (flags & IO_FLAG_DIRECT_IO) + open_flags |= O_DIRECT; +#endif + + if (windows_open_device(data, open_flags)) { + ext2fs_free_mem(&data); + return EXT2_ET_BAD_DEVICE_NAME; + } + + return windows_open_channel(data, flags, channel, windows_io_manager); +} + +static errcode_t windows_close(io_channel channel) +{ + struct windows_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct windows_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_WINDOWS_IO_CHANNEL); + + if (--channel->refcount > 0) + return 0; + +#ifndef NO_IO_CACHE + retval = flush_cached_blocks(channel, data, 0); +#endif + + remove_fake_dos_name(data); + + if (_close(data->dev) != 0) + retval = errno; + + TRACE("e2fsprogs::windows_close::_close(%d)", data->dev); + + free_cache(data); + + ext2fs_free_mem(&channel->private_data); + if (channel->name) + ext2fs_free_mem(&channel->name); + ext2fs_free_mem(&channel); + return retval; +} + +static errcode_t windows_set_blksize(io_channel channel, int blksize) +{ + struct windows_private_data *data; + errcode_t retval; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct windows_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_WINDOWS_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 windows_read_blk64(io_channel channel, unsigned long long block, int count, void *buf) +{ + struct windows_private_data *data; + struct windows_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 windows_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_WINDOWS_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; + } + if (count == 1) { + /* + * Special case where we read directly into the + * cache buffer; important in the O_DIRECT case + */ + cache = reuse[0]; + reuse_cache(channel, data, cache, block); + if ((retval = raw_read_blk(channel, data, block, 1, + cache->buf))) { + cache->in_use = 0; + return retval; + } + memcpy(cp, cache->buf, channel->block_size); + return 0; + } + + /* + * 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 windows_read_blk(io_channel channel, unsigned long block, + int count, void *buf) +{ + return windows_read_blk64(channel, block, count, buf); +} + +static errcode_t windows_write_blk64(io_channel channel, + unsigned long long block, + int count, const void *buf) +{ + struct windows_private_data *data; + struct windows_cache *cache, *reuse; + errcode_t retval = 0; + const char *cp; + int writethrough; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct windows_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_WINDOWS_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); + } + if (cache->buf != cp) + 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 windows_cache_readahead(io_channel channel, + unsigned long long block, + unsigned long long count) +{ + return EXT2_ET_OP_NOT_SUPPORTED; +} + +static errcode_t windows_write_blk(io_channel channel, unsigned long block, + int count, const void *buf) +{ + return windows_write_blk64(channel, block, count, buf); +} + +static errcode_t windows_write_byte(io_channel channel, unsigned long offset, + int size, const void *buf) +{ + return EXT2_ET_UNIMPLEMENTED; +} + +/* + * Flush data buffers to disk. + */ +static errcode_t windows_flush(io_channel channel) +{ + struct windows_private_data *data; + errcode_t retval = 0; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct windows_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_WINDOWS_IO_CHANNEL); + +#ifndef NO_IO_CACHE + retval = flush_cached_blocks(channel, data, 0); +#endif + + return retval; +} + +static errcode_t windows_set_option(io_channel channel, const char *option, + const char *arg) +{ + struct windows_private_data *data; + unsigned long long tmp; + char *end; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct windows_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_WINDOWS_IO_CHANNEL); + + if (!strcmp(option, "offset")) { + if (!arg) + return EXT2_ET_INVALID_ARGUMENT; + + tmp = strtoull(arg, &end, 0); + if (*end) + return EXT2_ET_INVALID_ARGUMENT; + data->offset = tmp; + if (data->offset < 0) + return EXT2_ET_INVALID_ARGUMENT; + return 0; + } + return EXT2_ET_INVALID_ARGUMENT; +} + +static errcode_t windows_discard(io_channel channel, unsigned long long block, + unsigned long long count) +{ + TRACE("e2fsprogs::windows_discard::EXT2_ET_UNIMPLEMENTED"); + return EXT2_ET_UNIMPLEMENTED; +} + +/* parameters might not be used if OS doesn't support zeroout */ +#if __GNUC_PREREQ (4, 6) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif +static errcode_t windows_zeroout(io_channel channel, unsigned long long block, + unsigned long long count) +{ + struct windows_private_data *data; + int ret; + + EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL); + data = (struct windows_private_data *) channel->private_data; + EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_WINDOWS_IO_CHANNEL); + + if (channel->flags & CHANNEL_FLAGS_BLOCK_DEVICE) { + /* Not implemented until the BLKZEROOUT mess is fixed */ + goto unimplemented; + } else { + /* Regular file, try to use truncate/punch/zero. */ + struct stat statbuf; + + if (count == 0) + return 0; + /* + * If we're trying to zero a range past the end of the file, + * extend the file size, then truncate everything. + */ + ret = fstat(data->dev, &statbuf); + if (ret) + goto err; + if ((unsigned long long) statbuf.st_size < + (block + count) * channel->block_size + data->offset) { + ret = ftruncate(data->dev, + (block + count) * channel->block_size + data->offset); + if (ret) + goto err; + } + goto unimplemented; + } +err: + if (ret < 0) { + if (errno == EOPNOTSUPP) + goto unimplemented; + return errno; + } + return 0; +unimplemented: + return EXT2_ET_UNIMPLEMENTED; +} + +int ext2fs_open_file(const char *pathname, int flags, mode_t mode) +{ + flags |= O_BINARY; + + if (mode) +#if defined(HAVE_OPEN64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED) + return open64(pathname, flags, mode); + else + return open64(pathname, flags); +#else + return open(pathname, flags, mode); + else + return open(pathname, flags); +#endif +} + +int ext2fs_stat(const char *path, ext2fs_struct_stat *buf) +{ +#if defined(HAVE_FSTAT64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED) + return stat64(path, buf); +#else + return stat(path, buf); +#endif +} + +int ext2fs_fstat(int fd, ext2fs_struct_stat *buf) +{ +#if defined(HAVE_FSTAT64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED) + return fstat64(fd, buf); +#else + return fstat(fd, buf); +#endif +} + +#if __GNUC_PREREQ (4, 6) +#pragma GCC diagnostic pop +#endif + +static struct struct_io_manager struct_windows_manager = { + .magic = EXT2_ET_MAGIC_IO_MANAGER, + .name = "Windows I/O Manager", + .open = windows_open, + .close = windows_close, + .set_blksize = windows_set_blksize, + .read_blk = windows_read_blk, + .write_blk = windows_write_blk, + .flush = windows_flush, + .write_byte = windows_write_byte, + .set_option = windows_set_option, + .get_stats = windows_get_stats, + .read_blk64 = windows_read_blk64, + .write_blk64 = windows_write_blk64, + .discard = windows_discard, + .cache_readahead = windows_cache_readahead, + .zeroout = windows_zeroout, +}; + +io_manager windows_io_manager = &struct_windows_manager; diff --git a/lib/ss/Makefile.in b/lib/ss/Makefile.in index 40294db0..bb504189 100644 --- a/lib/ss/Makefile.in +++ b/lib/ss/Makefile.in @@ -125,10 +125,11 @@ ss.pc: $(srcdir)/ss.pc.in $(top_builddir)/config.status $(Q) cd $(top_builddir); CONFIG_FILES=lib/ss/ss.pc ./config.status installdirs:: - $(E) " MKDIR_P $(libdir) $(includedir)/ss $(datadir)/ss $(bindir)" + $(E) " MKDIR_P $(libdir) $(includedir)/ss $(datadir)/ss $(bindir) $(pkgconfigdir) $(man1dir)" $(Q) $(MKDIR_P) $(DESTDIR)$(libdir) \ $(DESTDIR)$(includedir)/ss $(DESTDIR)$(datadir)/ss \ - $(DESTDIR)$(bindir) $(DESTDIR)$(pkgconfigdir) + $(DESTDIR)$(bindir) $(DESTDIR)$(pkgconfigdir) \ + $(DESTDIR)$(man1dir) install:: libss.a $(INSTALL_HFILES) installdirs ss_err.h mk_cmds ss.pc $(E) " INSTALL_DATA $(DESTDIR)$(libdir)/libss.a" diff --git a/lib/ss/error.c b/lib/ss/error.c index 8d345a9f..656b71be 100644 --- a/lib/ss/error.c +++ b/lib/ss/error.c @@ -42,6 +42,8 @@ char *ss_name(int sci_idx) (strlen(infop->subsystem_name)+ strlen(infop->current_request)+ 4)); + if (ret_val == (char *)NULL) + return ((char *)NULL); cp = ret_val; cp1 = infop->subsystem_name; while (*cp1) diff --git a/lib/ss/execute_cmd.c b/lib/ss/execute_cmd.c index d443a468..d092134a 100644 --- a/lib/ss/execute_cmd.c +++ b/lib/ss/execute_cmd.c @@ -17,8 +17,6 @@ #endif #ifdef HAVE_ERRNO_H #include <errno.h> -#else -extern int errno; #endif #include "ss_internal.h" #include <stdio.h> @@ -171,6 +169,8 @@ int ss_execute_command(int sci_idx, register char *argv[]) for (argp = argv; *argp; argp++) argc++; argp = (char **)malloc((argc+1)*sizeof(char *)); + if (!argp) + return(ENOMEM); for (i = 0; i <= argc; i++) argp[i] = argv[i]; i = really_execute_command(sci_idx, argc, &argp); diff --git a/lib/ss/get_readline.c b/lib/ss/get_readline.c index 11c72b33..aa161574 100644 --- a/lib/ss/get_readline.c +++ b/lib/ss/get_readline.c @@ -37,7 +37,7 @@ static void ss_release_readline(ss_data *info) #endif /* Libraries we will try to use for readline/editline functionality */ -#define DEFAULT_LIBPATH "libreadline.so.7:libreadline.so.6:libreadline.so.5:libreadline.so.4:libreadline.so:libedit.so.2:libedit.so:libeditline.so.0:libeditline.so" +#define DEFAULT_LIBPATH "libreadline.so.8:libreadline.so.7:libreadline.so.6:libreadline.so.5:libreadline.so.4:libreadline.so:libedit.so.2:libedit.so:libeditline.so.0:libeditline.so" #ifdef HAVE_DLOPEN void ss_get_readline(int sci_idx) diff --git a/lib/ss/help.c b/lib/ss/help.c index 5204401b..54c78f23 100644 --- a/lib/ss/help.c +++ b/lib/ss/help.c @@ -20,8 +20,6 @@ #endif #ifdef HAVE_ERRNO_H #include <errno.h> -#else -extern int errno; #endif #include <fcntl.h> #include <sys/param.h> @@ -96,7 +94,12 @@ void ss_help(int argc, char const * const *argv, int sci_idx, pointer info_ptr) } if (fd < 0) { #define MSG "No info found for " - char *buf = malloc(strlen (MSG) + strlen (argv[1]) + 1); + char *buf = malloc(strlen (MSG) + strlen (argv[1]) + 1); + if (!buf) { + ss_perror(sci_idx, 0, + "couldn't allocate memory to print error message"); + return; + } strcpy(buf, MSG); strcat(buf, argv[1]); ss_perror(sci_idx, 0, buf); @@ -148,13 +151,16 @@ void ss_add_info_dir(int sci_idx, char *info_dir, int *code_ptr) dirs = (char **)realloc((char *)dirs, (unsigned)(n_dirs + 2)*sizeof(char *)); if (dirs == (char **)NULL) { - info->info_dirs = (char **)NULL; - *code_ptr = errno; + *code_ptr = ENOMEM; return; } info->info_dirs = dirs; dirs[n_dirs + 1] = (char *)NULL; dirs[n_dirs] = malloc((unsigned)strlen(info_dir)+1); + if (dirs[n_dirs] == (char *)NULL) { + *code_ptr = ENOMEM; + return; + } strcpy(dirs[n_dirs], info_dir); *code_ptr = 0; } diff --git a/lib/ss/invocation.c b/lib/ss/invocation.c index 457e7a2c..7d7458a7 100644 --- a/lib/ss/invocation.c +++ b/lib/ss/invocation.c @@ -26,29 +26,34 @@ int ss_create_invocation(const char *subsystem_name, const char *version_string, void *info_ptr, ss_request_table *request_table_ptr, int *code_ptr) { - register int sci_idx; - register ss_data *new_table; - register ss_data **table; + int sci_idx; + ss_data *new_table = NULL; + ss_data **table = NULL; + ss_data **realloc_table = NULL; *code_ptr = 0; table = _ss_table; new_table = (ss_data *) malloc(sizeof(ss_data)); + if (!new_table) + goto out; + memset(new_table, 0, sizeof(ss_data)); if (table == (ss_data **) NULL) { table = (ss_data **) malloc(2 * size); + if (!table) + goto out; table[0] = table[1] = (ss_data *)NULL; } initialize_ss_error_table (); for (sci_idx = 1; table[sci_idx] != (ss_data *)NULL; sci_idx++) ; - table = (ss_data **) realloc((char *)table, + realloc_table = (ss_data **) realloc((char *)table, ((unsigned)sci_idx+2)*size); - if (table == NULL) { - *code_ptr = ENOMEM; - free(new_table); - return 0; - } + if (realloc_table == NULL) + goto out; + + table = realloc_table; table[sci_idx+1] = (ss_data *) NULL; table[sci_idx] = new_table; @@ -57,9 +62,15 @@ int ss_create_invocation(const char *subsystem_name, const char *version_string, new_table->argv = (char **)NULL; new_table->current_request = (char *)NULL; new_table->info_dirs = (char **)malloc(sizeof(char *)); + if (!new_table->info_dirs) + goto out; + *new_table->info_dirs = (char *)NULL; new_table->info_ptr = info_ptr; new_table->prompt = malloc((unsigned)strlen(subsystem_name)+4); + if (!new_table->prompt) + goto out; + strcpy(new_table->prompt, subsystem_name); strcat(new_table->prompt, ": "); #ifdef silly @@ -71,6 +82,9 @@ int ss_create_invocation(const char *subsystem_name, const char *version_string, new_table->flags.abbrevs_disabled = 0; new_table->rqt_tables = (ss_request_table **) calloc(2, sizeof(ss_request_table *)); + if (!new_table->rqt_tables) + goto out; + *(new_table->rqt_tables) = request_table_ptr; *(new_table->rqt_tables+1) = (ss_request_table *) NULL; @@ -85,6 +99,17 @@ int ss_create_invocation(const char *subsystem_name, const char *version_string, ss_get_readline(sci_idx); #endif return(sci_idx); + +out: + if (new_table) { + free(new_table->prompt); + free(new_table->info_dirs); + } + free(new_table); + free(table); + *code_ptr = ENOMEM; + return 0; + } void diff --git a/lib/ss/list_rqs.c b/lib/ss/list_rqs.c index 021a3835..89e37bb2 100644 --- a/lib/ss/list_rqs.c +++ b/lib/ss/list_rqs.c @@ -12,6 +12,9 @@ */ #include "config.h" #include "ss_internal.h" +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif #include <signal.h> #include <setjmp.h> #include <sys/wait.h> @@ -46,6 +49,12 @@ void ss_list_requests(int argc __SS_ATTR((unused)), return; } output = fdopen(fd, "w"); + if (!output) { + perror("fdopen"); + close(fd); + (void) signal(SIGINT, func); + return; + } sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); fprintf (output, "Available %s requests:\n\n", diff --git a/lib/ss/pager.c b/lib/ss/pager.c index b9b88996..ba32b201 100644 --- a/lib/ss/pager.c +++ b/lib/ss/pager.c @@ -20,8 +20,6 @@ #endif #ifdef HAVE_ERRNO_H #include <errno.h> -#else -extern int errno; #endif #include "ss_internal.h" diff --git a/lib/ss/ss_internal.h b/lib/ss/ss_internal.h index 19a6be7a..7b1d23bd 100644 --- a/lib/ss/ss_internal.h +++ b/lib/ss/ss_internal.h @@ -85,7 +85,7 @@ void ss_delete_info_dir (int sci_idx, char *info_dir, int *code_ptr); int ss_execute_line(int sci_idx, char *line_ptr); char **ss_parse(int sci_idx, char *line_ptr, int *argc_ptr); ss_abbrev_info *ss_abbrev_initialize(char *, int *); -void ss_page_stdin(void); +void ss_page_stdin(void) __SS_ATTR((noreturn)); void ss_list_requests(int, char const * const *, int, pointer); int ss_execute_command(int sci_idx, char *argv[]); int ss_pager_create(void); diff --git a/lib/support/Android.bp b/lib/support/Android.bp index a0b064dd..af9b28df 100644 --- a/lib/support/Android.bp +++ b/lib/support/Android.bp @@ -19,6 +19,7 @@ cc_library { unique_host_soname: true, defaults: ["e2fsprogs-defaults"], srcs: [ + "devname.c", "dict.c", "mkquota.c", "parse_qtype.c", @@ -38,7 +39,7 @@ cc_library { target: { windows: { - enabled: true + enabled: true, }, }, diff --git a/lib/support/Makefile.in b/lib/support/Makefile.in index f3c7981e..b6229091 100644 --- a/lib/support/Makefile.in +++ b/lib/support/Makefile.in @@ -18,25 +18,29 @@ OBJS= cstring.o \ plausible.o \ profile.o \ parse_qtype.o \ + print_fs_flags.o \ profile_helpers.o \ prof_err.o \ quotaio.o \ quotaio_v2.o \ quotaio_tree.o \ - dict.o + dict.o \ + devname.o SRCS= $(srcdir)/argv_parse.c \ $(srcdir)/cstring.c \ $(srcdir)/mkquota.c \ $(srcdir)/parse_qtype.c \ $(srcdir)/plausible.c \ + $(srcdir)/print_fs_flags.c \ $(srcdir)/profile.c \ $(srcdir)/profile_helpers.c \ prof_err.c \ $(srcdir)/quotaio.c \ $(srcdir)/quotaio_tree.c \ $(srcdir)/quotaio_v2.c \ - $(srcdir)/dict.c + $(srcdir)/dict.c \ + $(srcdir)/devname.c LIBRARY= libsupport LIBDIR= support @@ -132,6 +136,13 @@ plausible.o: $(srcdir)/plausible.c $(top_builddir)/lib/config.h \ $(top_builddir)/lib/ext2fs/ext2_err.h \ $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/hashmap.h \ $(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/nls-enable.h +print_fs_flags.o: $(srcdir)/print_fs_flags.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/ext2fs/ext2fs.h \ + $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \ + $(top_srcdir)/lib/ext2fs/ext3_extents.h $(top_srcdir)/lib/et/com_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ + $(top_srcdir)/lib/ext2fs/ext2_ext_attr.h $(top_srcdir)/lib/ext2fs/hashmap.h \ + $(top_srcdir)/lib/ext2fs/bitops.h profile.o: $(srcdir)/profile.c $(top_builddir)/lib/config.h \ $(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/et/com_err.h \ $(srcdir)/profile.h prof_err.h @@ -169,3 +180,5 @@ quotaio_v2.o: $(srcdir)/quotaio_v2.c $(top_builddir)/lib/config.h \ $(srcdir)/quotaio_tree.h dict.o: $(srcdir)/dict.c $(top_builddir)/lib/config.h \ $(top_builddir)/lib/dirpaths.h $(srcdir)/dict.h +devname.o: $(srcdir)/devname.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/devname.h $(srcdir)/nls-enable.h diff --git a/lib/support/argv_parse.c b/lib/support/argv_parse.c index d22f6344..1f50f9e5 100644 --- a/lib/support/argv_parse.c +++ b/lib/support/argv_parse.c @@ -116,6 +116,8 @@ int argv_parse(char *in_buf, int *ret_argc, char ***ret_argv) if (argv == 0) { argv = malloc(sizeof(char *)); free(buf); + if (!argv) + return -1; } argv[argc] = 0; if (ret_argc) diff --git a/lib/support/devname.c b/lib/support/devname.c new file mode 100644 index 00000000..e0306ddf --- /dev/null +++ b/lib/support/devname.c @@ -0,0 +1,65 @@ +/* + * devname.c --- Support function to translate a user provided string + * identifying a device to an actual device path + * + * Copyright (C) 2022 Red Hat, Inc., Lukas Czerner <lczerner@redhat.com> + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include <unistd.h> +#include <string.h> +#include <stdio.h> + +#include "config.h" +#include "devname.h" +#include "nls-enable.h" + +/* + * blkid_get_devname() is primarily intended for parsing "NAME=value" + * tokens. It will return the device matching the specified token, NULL if + * nothing is found, or copy of the string if it's not in "NAME=value" + * format. + * get_devname() takes the same parameters and works the same way as + * blkid_get_devname() except it can handle '=' in the file name. + */ +char *get_devname(blkid_cache cache, const char *token, const char *value) +{ + int is_file = 0; + char *ret = NULL; + + if (!token) + goto out; + + if (value) { + ret = blkid_get_devname(cache, token, value); + goto out; + } + + if (access(token, F_OK) == 0) + is_file = 1; + + ret = blkid_get_devname(cache, token, NULL); + if (ret) { + /* + * In case of collision prefer the result from + * blkid_get_devname() to avoid a file masking file system with + * existing tag. + */ + if (is_file && (strcmp(ret, token) != 0)) { + fprintf(stderr, + _("Collision found: '%s' refers to both '%s' " + "and a file '%s'. Using '%s'!\n"), + token, ret, token, ret); + } + goto out; + } + + if (is_file) + ret = strdup(token); +out: + return ret; +} diff --git a/lib/support/devname.h b/lib/support/devname.h new file mode 100644 index 00000000..cc195612 --- /dev/null +++ b/lib/support/devname.h @@ -0,0 +1,19 @@ +/* + * devname.c --- Figure out if a pathname is ext* or something else. + * + * Copyright (C) 2022 Red Hat, Inc., Lukas Czerner <lczerner@redhat.com> + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#ifndef DEVNAME_H_ +#define DEVNAME_H_ + +#include "blkid/blkid.h" + +char *get_devname(blkid_cache cache, const char *token, const char *value); + +#endif /* DEVNAME_H_ */ diff --git a/lib/support/dict.c b/lib/support/dict.c index f8277c4a..93fdd0b2 100644 --- a/lib/support/dict.c +++ b/lib/support/dict.c @@ -16,6 +16,7 @@ * * $Id: dict.c,v 1.40.2.7 2000/11/13 01:36:44 kaz Exp $ * $Name: kazlib_1_20 $ + * The work has been modified. */ #define DICT_NODEBUG @@ -295,7 +296,7 @@ void dict_set_allocator(dict_t *dict, dnode_alloc_t al, dict->context = context; } -void dict_set_cmp_context(dict_t *dict, void *cmp_ctx) +void dict_set_cmp_context(dict_t *dict, const void *cmp_ctx) { dict_assert (!dict->cmp_ctx); dict_assert (dict_count(dict) == 0); diff --git a/lib/support/dict.h b/lib/support/dict.h index d9462a33..2d87cc00 100644 --- a/lib/support/dict.h +++ b/lib/support/dict.h @@ -16,6 +16,7 @@ * * $Id: dict.h,v 1.22.2.6 2000/11/13 01:36:44 kaz Exp $ * $Name: kazlib_1_20 $ + * The work has been modified. */ #ifndef DICT_H @@ -69,7 +70,7 @@ typedef struct dict_t { dnode_alloc_t dict_allocnode; dnode_free_t dict_freenode; void *dict_context; - void *cmp_ctx; + const void *cmp_ctx; int dict_dupes; #else int dict_dummmy; @@ -89,7 +90,7 @@ typedef struct dict_load_t { extern dict_t *dict_create(dictcount_t, dict_comp_t); extern void dict_set_allocator(dict_t *, dnode_alloc_t, dnode_free_t, void *); -extern void dict_set_cmp_context(dict_t *, void *); +extern void dict_set_cmp_context(dict_t *, const void *); extern void dict_destroy(dict_t *); extern void dict_free_nodes(dict_t *); extern void dict_free(dict_t *); diff --git a/lib/support/mkquota.c b/lib/support/mkquota.c index 71f42c2c..c89f8959 100644 --- a/lib/support/mkquota.c +++ b/lib/support/mkquota.c @@ -99,6 +99,8 @@ void quota_set_sb_inum(ext2_filsys fs, ext2_ino_t ino, enum quota_type qtype) log_debug("setting quota ino in superblock: ino=%u, type=%d", ino, qtype); + if (inump == NULL) + return; *inump = ino; ext2fs_mark_super_dirty(fs); } @@ -433,7 +435,8 @@ void quota_data_sub(quota_ctx_t qctx, struct ext2_inode_large *inode, dict = qctx->quota_dict[qtype]; if (dict) { dq = get_dq(dict, get_qid(inode, qtype)); - dq->dq_dqb.dqb_curspace -= space; + if (dq) + dq->dq_dqb.dqb_curspace -= space; } } } @@ -460,7 +463,8 @@ void quota_data_inodes(quota_ctx_t qctx, struct ext2_inode_large *inode, dict = qctx->quota_dict[qtype]; if (dict) { dq = get_dq(dict, get_qid(inode, qtype)); - dq->dq_dqb.dqb_curinodes += adjust; + if (dq) + dq->dq_dqb.dqb_curinodes += adjust; } } } @@ -501,9 +505,11 @@ errcode_t quota_compute_usage(quota_ctx_t qctx) } if (ino == 0) break; - if (inode->i_links_count && - (ino == EXT2_ROOT_INO || - ino >= EXT2_FIRST_INODE(fs->super))) { + if (!inode->i_links_count) + continue; + if (ino == EXT2_ROOT_INO || + (ino >= EXT2_FIRST_INODE(fs->super) && + ino != quota_type2inum(PRJQUOTA, fs->super))) { space = ext2fs_get_stat_i_blocks(fs, EXT2_INODE(inode)) << 9; quota_data_add(qctx, inode, ino, space); @@ -531,6 +537,8 @@ static int scan_dquots_callback(struct dquot *dquot, void *cb_data) struct dquot *dq; dq = get_dq(quota_dict, dquot->dq_id); + if (!dq) + return -1; dq->dq_id = dquot->dq_id; dq->dq_flags |= DQF_SEEN; @@ -566,48 +574,13 @@ static int scan_dquots_callback(struct dquot *dquot, void *cb_data) } /* - * Read all dquots from quota file into memory + * Read quotas from disk and updates the in-memory information determined by + * 'flags' from the on-disk data. */ -static errcode_t quota_read_all_dquots(struct quota_handle *qh, - quota_ctx_t qctx, - int update_limits EXT2FS_ATTR((unused))) +errcode_t quota_read_all_dquots(quota_ctx_t qctx, ext2_ino_t qf_ino, + enum quota_type qtype, unsigned int flags) { struct scan_dquots_data scan_data; - - scan_data.quota_dict = qctx->quota_dict[qh->qh_type]; - scan_data.check_consistency = 0; - scan_data.update_limits = 0; - scan_data.update_usage = 1; - - return qh->qh_ops->scan_dquots(qh, scan_dquots_callback, &scan_data); -} - -/* - * Write all memory dquots into quota file - */ -#if 0 /* currently unused, but may be useful in the future? */ -static errcode_t quota_write_all_dquots(struct quota_handle *qh, - quota_ctx_t qctx) -{ - errcode_t err; - - err = ext2fs_read_bitmaps(qctx->fs); - if (err) - return err; - write_dquots(qctx->quota_dict[qh->qh_type], qh); - ext2fs_mark_bb_dirty(qctx->fs); - qctx->fs->flags &= ~EXT2_FLAG_SUPER_ONLY; - ext2fs_write_bitmaps(qctx->fs); - return 0; -} -#endif - -/* - * Updates the in-memory quota limits from the given quota inode. - */ -errcode_t quota_update_limits(quota_ctx_t qctx, ext2_ino_t qf_ino, - enum quota_type qtype) -{ struct quota_handle *qh; errcode_t err; @@ -626,7 +599,11 @@ errcode_t quota_update_limits(quota_ctx_t qctx, ext2_ino_t qf_ino, goto out; } - quota_read_all_dquots(qh, qctx, 1); + scan_data.quota_dict = qctx->quota_dict[qh->qh_type]; + scan_data.check_consistency = 0; + scan_data.update_limits = !!(flags & QREAD_LIMITS); + scan_data.update_usage = !!(flags & QREAD_USAGE); + qh->qh_ops->scan_dquots(qh, scan_dquots_callback, &scan_data); err = quota_file_close(qctx, qh); if (err) { diff --git a/lib/support/plausible.c b/lib/support/plausible.c index 024f205e..65a6b2e1 100644 --- a/lib/support/plausible.c +++ b/lib/support/plausible.c @@ -103,7 +103,7 @@ static void print_ext2_info(const char *device) time_t tm; retval = ext2fs_open2(device, 0, EXT2_FLAG_64BITS, 0, 0, - unix_io_manager, &fs); + default_io_manager, &fs); if (retval) return; sb = fs->super; @@ -277,11 +277,11 @@ int check_plausibility(const char *device, int flags, int *ret_is_dev) return !has_magic; } #endif - - ret = check_partition_table(device); - if (ret >= 0) - return ret; - + if (flags & CHECK_FS_EXIST) { + ret = check_partition_table(device); + if (ret >= 0) + return ret; + } return 1; } diff --git a/lib/support/print_fs_flags.c b/lib/support/print_fs_flags.c new file mode 100644 index 00000000..f47cd665 --- /dev/null +++ b/lib/support/print_fs_flags.c @@ -0,0 +1,75 @@ +/* + * print_flags.c - Print ext2_filsys flags + * + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr> + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include "config.h" +#include <stdio.h> + +#include "ext2fs/ext2fs.h" + +struct flags_name { + unsigned long flag; + const char *name; +}; + +static const struct flags_name flags_array[] = { + { EXT2_FLAG_RW, "EXT2_FLAG_RW" }, + { EXT2_FLAG_CHANGED, "EXT2_FLAG_CHANGED" }, + { EXT2_FLAG_DIRTY, "EXT2_FLAG_DIRTY" }, + { EXT2_FLAG_VALID, "EXT2_FLAG_VALID" }, + { EXT2_FLAG_IB_DIRTY, "EXT2_FLAG_IB_DIRTY" }, + { EXT2_FLAG_BB_DIRTY, "EXT2_FLAG_BB_DIRTY" }, + { EXT2_FLAG_SWAP_BYTES, "EXT2_FLAG_SWAP_BYTES" }, + { EXT2_FLAG_SWAP_BYTES_READ, "EXT2_FLAG_SWAP_BYTES_READ" }, + { EXT2_FLAG_SWAP_BYTES_WRITE, "EXT2_FLAG_SWAP_BYTES_WRITE" }, + { EXT2_FLAG_MASTER_SB_ONLY, "EXT2_FLAG_MASTER_SB_ONLY" }, + { EXT2_FLAG_FORCE, "EXT2_FLAG_FORCE" }, + { EXT2_FLAG_SUPER_ONLY, "EXT2_FLAG_SUPER_ONLY" }, + { EXT2_FLAG_JOURNAL_DEV_OK, "EXT2_FLAG_JOURNAL_DEV_OK" }, + { EXT2_FLAG_IMAGE_FILE, "EXT2_FLAG_IMAGE_FILE" }, + { EXT2_FLAG_EXCLUSIVE, "EXT2_FLAG_EXCLUSIVE" }, + { EXT2_FLAG_SOFTSUPP_FEATURES, "EXT2_FLAG_SOFTSUPP_FEATURES" }, + { EXT2_FLAG_NOFREE_ON_ERROR, "EXT2_FLAG_NOFREE_ON_ERROR" }, + { EXT2_FLAG_64BITS, "EXT2_FLAG_64BITS" }, + { EXT2_FLAG_PRINT_PROGRESS, "EXT2_FLAG_PRINT_PROGRESS" }, + { EXT2_FLAG_DIRECT_IO, "EXT2_FLAG_DIRECT_IO" }, + { EXT2_FLAG_SKIP_MMP, "EXT2_FLAG_SKIP_MMP" }, + { EXT2_FLAG_IGNORE_CSUM_ERRORS, "EXT2_FLAG_IGNORE_CSUM_ERRORS" }, + { EXT2_FLAG_SHARE_DUP, "EXT2_FLAG_SHARE_DUP" }, + { EXT2_FLAG_IGNORE_SB_ERRORS, "EXT2_FLAG_IGNORE_SB_ERRORS" }, + { EXT2_FLAG_BBITMAP_TAIL_PROBLEM, "EXT2_FLAG_BBITMAP_TAIL_PROBLEM" }, + { EXT2_FLAG_IBITMAP_TAIL_PROBLEM, "EXT2_FLAG_IBITMAP_TAIL_PROBLEM" }, + { EXT2_FLAG_THREADS, "EXT2_FLAG_THREADS" }, + { 0, NULL }, +}; + +void print_fs_flags(FILE * f, unsigned long flags) +{ + const struct flags_name *fp; + int first = 1, pos = 16; + + for (fp = flags_array; fp->flag != 0; fp++) { + if ((flags & fp->flag) == 0) + continue; + pos += strlen(fp->name) + 1; + if (pos > 72) { + fputs("\n\t", f); + pos = 9 + strlen(fp->name); + } + if (first) + first = 0; + else + fputc(' ', f); + fputs(fp->name, f); + } + fputc('\n', f); +} diff --git a/lib/support/print_fs_flags.h b/lib/support/print_fs_flags.h new file mode 100644 index 00000000..bdd58a00 --- /dev/null +++ b/lib/support/print_fs_flags.h @@ -0,0 +1,5 @@ +/* + * print_flags.h -- header file for printing the fs flags + */ + +void print_fs_flags(FILE * f, unsigned long flags); diff --git a/lib/support/profile.c b/lib/support/profile.c index 585ed595..bdb14b17 100644 --- a/lib/support/profile.c +++ b/lib/support/profile.c @@ -1093,6 +1093,7 @@ errcode_t profile_create_node(const char *name, const char *value, if (!new) return ENOMEM; memset(new, 0, sizeof(struct profile_node)); + new->magic = PROF_MAGIC_NODE; new->name = strdup(name); if (new->name == 0) { profile_free_node(new); @@ -1105,7 +1106,6 @@ errcode_t profile_create_node(const char *name, const char *value, return ENOMEM; } } - new->magic = PROF_MAGIC_NODE; *ret_node = new; return 0; @@ -1191,7 +1191,7 @@ errcode_t profile_add_node(struct profile_node *section, const char *name, /* * Iterate through the section, returning the nodes which match - * the given name. If name is NULL, then interate through all the + * the given name. If name is NULL, then iterate through all the * nodes in the section. If section_flag is non-zero, only return the * section which matches the name; don't return relations. If value * is non-NULL, then only return relations which match the requested diff --git a/lib/support/quotaio.h b/lib/support/quotaio.h index 60689700..84fac35d 100644 --- a/lib/support/quotaio.h +++ b/lib/support/quotaio.h @@ -224,8 +224,11 @@ void quota_data_add(quota_ctx_t qctx, struct ext2_inode_large *inode, void quota_data_sub(quota_ctx_t qctx, struct ext2_inode_large *inode, ext2_ino_t ino, qsize_t space); errcode_t quota_write_inode(quota_ctx_t qctx, enum quota_type qtype); -errcode_t quota_update_limits(quota_ctx_t qctx, ext2_ino_t qf_ino, - enum quota_type type); +/* Flags for quota_read_all_dquots() */ +#define QREAD_USAGE 0x01 +#define QREAD_LIMITS 0x02 +errcode_t quota_read_all_dquots(quota_ctx_t qctx, ext2_ino_t qf_ino, + enum quota_type type, unsigned int flags); errcode_t quota_compute_usage(quota_ctx_t qctx); void quota_release_context(quota_ctx_t *qctx); errcode_t quota_remove_inode(ext2_filsys fs, enum quota_type qtype); diff --git a/lib/support/quotaio_tree.c b/lib/support/quotaio_tree.c index 6cc4fb5b..5910e637 100644 --- a/lib/support/quotaio_tree.c +++ b/lib/support/quotaio_tree.c @@ -601,7 +601,7 @@ static int report_tree(struct dquot *dquot, unsigned int blk, int depth, __le32 *ref = (__le32 *) buf; if (!buf) - return 0; + return -1; read_blk(dquot->dq_h, blk, buf); if (depth == QT_TREEDEPTH - 1) { diff --git a/lib/support/quotaio_v2.c b/lib/support/quotaio_v2.c index 23717f03..d09294be 100644 --- a/lib/support/quotaio_v2.c +++ b/lib/support/quotaio_v2.c @@ -44,6 +44,68 @@ struct quotafile_ops quotafile_ops_2 = { /* * Copy dquot from disk to memory */ +static void v2r0_disk2memdqblk(struct dquot *dquot, void *dp) +{ + struct util_dqblk *m = &dquot->dq_dqb; + struct v2r0_disk_dqblk *d = dp, empty; + + dquot->dq_id = ext2fs_le32_to_cpu(d->dqb_id); + m->dqb_ihardlimit = ext2fs_le32_to_cpu(d->dqb_ihardlimit); + m->dqb_isoftlimit = ext2fs_le32_to_cpu(d->dqb_isoftlimit); + m->dqb_bhardlimit = ext2fs_le32_to_cpu(d->dqb_bhardlimit); + m->dqb_bsoftlimit = ext2fs_le32_to_cpu(d->dqb_bsoftlimit); + m->dqb_curinodes = ext2fs_le32_to_cpu(d->dqb_curinodes); + m->dqb_curspace = ext2fs_le64_to_cpu(d->dqb_curspace); + m->dqb_itime = ext2fs_le64_to_cpu(d->dqb_itime); + m->dqb_btime = ext2fs_le64_to_cpu(d->dqb_btime); + + memset(&empty, 0, sizeof(struct v2r0_disk_dqblk)); + empty.dqb_itime = ext2fs_cpu_to_le64(1); + if (!memcmp(&empty, dp, sizeof(struct v2r0_disk_dqblk))) + m->dqb_itime = 0; +} + +/* + * Copy dquot from memory to disk + */ +static void v2r0_mem2diskdqblk(void *dp, struct dquot *dquot) +{ + struct util_dqblk *m = &dquot->dq_dqb; + struct v2r0_disk_dqblk *d = dp; + + d->dqb_ihardlimit = ext2fs_cpu_to_le32(m->dqb_ihardlimit); + d->dqb_isoftlimit = ext2fs_cpu_to_le32(m->dqb_isoftlimit); + d->dqb_bhardlimit = ext2fs_cpu_to_le32(m->dqb_bhardlimit); + d->dqb_bsoftlimit = ext2fs_cpu_to_le32(m->dqb_bsoftlimit); + d->dqb_curinodes = ext2fs_cpu_to_le32(m->dqb_curinodes); + d->dqb_curspace = ext2fs_cpu_to_le64(m->dqb_curspace); + d->dqb_itime = ext2fs_cpu_to_le64(m->dqb_itime); + d->dqb_btime = ext2fs_cpu_to_le64(m->dqb_btime); + d->dqb_id = ext2fs_cpu_to_le32(dquot->dq_id); + if (qtree_entry_unused(&dquot->dq_h->qh_info.u.v2_mdqi.dqi_qtree, dp)) + d->dqb_itime = ext2fs_cpu_to_le64(1); +} + +static int v2r0_is_id(void *dp, struct dquot *dquot) +{ + struct v2r0_disk_dqblk *d = dp; + struct qtree_mem_dqinfo *info = + &dquot->dq_h->qh_info.u.v2_mdqi.dqi_qtree; + + if (qtree_entry_unused(info, dp)) + return 0; + return ext2fs_le32_to_cpu(d->dqb_id) == dquot->dq_id; +} + +static struct qtree_fmt_operations v2r0_fmt_ops = { + .mem2disk_dqblk = v2r0_mem2diskdqblk, + .disk2mem_dqblk = v2r0_disk2memdqblk, + .is_id = v2r0_is_id, +}; + +/* + * Copy dquot from disk to memory + */ static void v2r1_disk2memdqblk(struct dquot *dquot, void *dp) { struct util_dqblk *m = &dquot->dq_dqb; @@ -161,10 +223,11 @@ static int v2_check_file(struct quota_handle *h, int type, int fmt) be_magic = ext2fs_be32_to_cpu((__force __be32)dqh.dqh_magic); if (be_magic == file_magics[type]) { - log_err("Your quota file is stored in wrong endianity"); + log_err("Your quota file is stored in wrong endianness"); return 0; } - if (V2_VERSION != ext2fs_le32_to_cpu(dqh.dqh_version)) + if (V2_VERSION_R0 != ext2fs_le32_to_cpu(dqh.dqh_version) && + V2_VERSION_R1 != ext2fs_le32_to_cpu(dqh.dqh_version)) return 0; return 1; } @@ -174,13 +237,25 @@ static int v2_check_file(struct quota_handle *h, int type, int fmt) */ static int v2_init_io(struct quota_handle *h) { + struct v2_disk_dqheader dqh; struct v2_disk_dqinfo ddqinfo; struct v2_mem_dqinfo *info; __u64 filesize; + int version; - h->qh_info.u.v2_mdqi.dqi_qtree.dqi_entry_size = - sizeof(struct v2r1_disk_dqblk); - h->qh_info.u.v2_mdqi.dqi_qtree.dqi_ops = &v2r1_fmt_ops; + if (!v2_read_header(h, &dqh)) + return -1; + version = ext2fs_le32_to_cpu(dqh.dqh_version); + + if (version == V2_VERSION_R0) { + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_entry_size = + sizeof(struct v2r0_disk_dqblk); + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_ops = &v2r0_fmt_ops; + } else { + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_entry_size = + sizeof(struct v2r1_disk_dqblk); + h->qh_info.u.v2_mdqi.dqi_qtree.dqi_ops = &v2r1_fmt_ops; + } /* Read information about quotafile */ if (h->e2fs_read(&h->qh_qf, V2_DQINFOOFF, &ddqinfo, @@ -231,7 +306,7 @@ static int v2_new_io(struct quota_handle *h) /* Write basic quota header */ ddqheader.dqh_magic = ext2fs_cpu_to_le32(file_magics[h->qh_type]); - ddqheader.dqh_version = ext2fs_cpu_to_le32(V2_VERSION); + ddqheader.dqh_version = ext2fs_cpu_to_le32(V2_VERSION_R1); if (h->e2fs_write(&h->qh_qf, 0, &ddqheader, sizeof(ddqheader)) != sizeof(ddqheader)) return -1; diff --git a/lib/support/quotaio_v2.h b/lib/support/quotaio_v2.h index de2db278..35054caf 100644 --- a/lib/support/quotaio_v2.h +++ b/lib/support/quotaio_v2.h @@ -13,7 +13,8 @@ /* Offset of info header in file */ #define V2_DQINFOOFF sizeof(struct v2_disk_dqheader) /* Supported version of quota-tree format */ -#define V2_VERSION 1 +#define V2_VERSION_R1 1 +#define V2_VERSION_R0 0 struct v2_disk_dqheader { __le32 dqh_magic; /* Magic number identifying file */ @@ -36,6 +37,20 @@ struct v2_disk_dqinfo { * free entry */ } __attribute__ ((packed)); +struct v2r0_disk_dqblk { + __le32 dqb_id; /* id this quota applies to */ + __le32 dqb_ihardlimit; /* absolute limit on allocated inodes */ + __le32 dqb_isoftlimit; /* preferred inode limit */ + __le32 dqb_curinodes; /* current # allocated inodes */ + __le32 dqb_bhardlimit; /* absolute limit on disk space + * (in QUOTABLOCK_SIZE) */ + __le32 dqb_bsoftlimit; /* preferred limit on disk space + * (in QUOTABLOCK_SIZE) */ + __le64 dqb_curspace; /* current space occupied (in bytes) */ + __le64 dqb_btime; /* time limit for excessive disk use */ + __le64 dqb_itime; /* time limit for excessive inode use */ +} __attribute__ ((packed)); + struct v2r1_disk_dqblk { __le32 dqb_id; /* id this quota applies to */ __le32 dqb_pad; diff --git a/lib/support/sort_r.h b/lib/support/sort_r.h index dc17e8af..8473ca83 100644 --- a/lib/support/sort_r.h +++ b/lib/support/sort_r.h @@ -24,12 +24,16 @@ void sort_r(void *base, size_t nel, size_t width, #define _SORT_R_INLINE inline -#if (defined __APPLE__ || defined __MACH__ || defined __DARWIN__ || \ +#if (defined HAVE_GNU_QSORT_R) +# define _SORT_R_GNU +#elif (defined HAVE_BSD_QSORT_R) +# define _SORT_R_BSD +#elif (defined __gnu_hurd__ || defined __GNU__ || \ + defined __MINGW32__ || defined __GLIBC__) +# define _SORT_R_GNU +#elif (defined __APPLE__ || defined __MACH__ || defined __DARWIN__ || \ defined __FreeBSD__ || defined __DragonFly__) # define _SORT_R_BSD -#elif (defined _GNU_SOURCE || defined __gnu_hurd__ || defined __GNU__ || \ - defined __linux__ || defined __MINGW32__ || defined __GLIBC__) -# define _SORT_R_LINUX #elif (defined _WIN32 || defined _WIN64 || defined __WINDOWS__) # define _SORT_R_WINDOWS # undef _SORT_R_INLINE @@ -260,7 +264,7 @@ static _SORT_R_INLINE void sort_r_simple(void *base, size_t nel, size_t w, #endif - #if defined _SORT_R_LINUX + #if defined _SORT_R_GNU typedef int(* __compar_d_fn_t)(const void *, const void *, void *); extern void qsort_r(void *base, size_t nel, size_t width, @@ -276,7 +280,7 @@ static _SORT_R_INLINE void sort_r_simple(void *base, size_t nel, size_t w, const void *_b, void *_arg), void *arg) { - #if defined _SORT_R_LINUX + #if defined _SORT_R_GNU #if defined __GLIBC__ && ((__GLIBC__ < 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 8)) @@ -315,7 +319,7 @@ static _SORT_R_INLINE void sort_r_simple(void *base, size_t nel, size_t w, #undef _SORT_R_INLINE #undef _SORT_R_WINDOWS -#undef _SORT_R_LINUX +#undef _SORT_R_GNU #undef _SORT_R_BSD #endif /* SORT_R_H_ */ diff --git a/lib/uuid/Android.bp b/lib/uuid/Android.bp index 67968dba..3e6048d0 100644 --- a/lib/uuid/Android.bp +++ b/lib/uuid/Android.bp @@ -39,16 +39,9 @@ cc_library { "unparse.c", "uuid_time.c", ], - cflags: [ - "-Wno-unused-function", - "-Wno-unused-parameter", - ], target: { windows: { - // Cannot suppress the _WIN32_WINNT redefined warning. - cflags: ["-Wno-error"], - include_dirs: [ "external/e2fsprogs/include/mingw" ], - enabled: true + enabled: true, }, }, header_libs: ["libext2-headers"], diff --git a/lib/uuid/gen_uuid.c b/lib/uuid/gen_uuid.c index 89179b6e..2f028867 100644 --- a/lib/uuid/gen_uuid.c +++ b/lib/uuid/gen_uuid.c @@ -41,11 +41,6 @@ #include "config.h" -#ifdef _WIN32 -#define _WIN32_WINNT 0x0500 -#include <windows.h> -#define UUID MYUUID -#endif #include <stdio.h> #ifdef HAVE_UNISTD_H #include <unistd.h> @@ -70,6 +65,9 @@ #ifdef HAVE_SYS_IOCTL_H #include <sys/ioctl.h> #endif +#ifdef HAVE_SYS_RANDOM_H +#include <sys/random.h> +#endif #ifdef HAVE_SYS_SOCKET_H #include <sys/socket.h> #endif @@ -114,27 +112,6 @@ THREAD_LOCAL unsigned short jrand_seed[3]; #endif -#ifdef _WIN32 -#ifndef USE_MINGW -static void gettimeofday (struct timeval *tv, void *dummy) -{ - FILETIME ftime; - uint64_t n; - - GetSystemTimeAsFileTime (&ftime); - n = (((uint64_t) ftime.dwHighDateTime << 32) - + (uint64_t) ftime.dwLowDateTime); - if (n) { - n /= 10; - n -= ((369 * 365 + 89) * (uint64_t) 86400) * 1000000; - } - - tv->tv_sec = n / 1000000; - tv->tv_usec = n % 1000000; -} -#endif -#endif - static int get_random_fd(void) { struct timeval tv; @@ -174,10 +151,21 @@ static int get_random_fd(void) */ static void get_random_bytes(void *buf, int nbytes) { - int i, n = nbytes, fd = get_random_fd(); + int i, n = nbytes, fd; int lose_counter = 0; unsigned char *cp = buf; +#ifdef HAVE_GETRANDOM + i = getrandom(buf, nbytes, 0); + if (i == nbytes) + return; +#endif +#ifdef HAVE_GETENTROPY + if (getentropy(buf, nbytes) == 0) + return; +#endif + + fd = get_random_fd(); if (fd >= 0) { while (n > 0) { i = read(fd, cp, n); diff --git a/lib/uuid/tst_uuid.c b/lib/uuid/tst_uuid.c index 649bfbc0..c1c29015 100644 --- a/lib/uuid/tst_uuid.c +++ b/lib/uuid/tst_uuid.c @@ -34,12 +34,6 @@ #include "config.h" -#ifdef _WIN32 -#define _WIN32_WINNT 0x0500 -#include <windows.h> -#define UUID MYUUID -#endif - #include <stdio.h> #include <stdlib.h> diff --git a/lib/uuid/uuid_time.c b/lib/uuid/uuid_time.c index af837a2c..b519d3c4 100644 --- a/lib/uuid/uuid_time.c +++ b/lib/uuid/uuid_time.c @@ -36,12 +36,6 @@ #include "config.h" -#ifdef _WIN32 -#define _WIN32_WINNT 0x0500 -#include <windows.h> -#define UUID MYUUID -#endif - #include <stdio.h> #ifdef HAVE_UNISTD_H #include <unistd.h> |