aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Android.bp1
-rw-r--r--lib/Makefile.darwin-lib3
-rw-r--r--lib/blkid/Android.bp17
-rw-r--r--lib/blkid/devno.c10
-rw-r--r--lib/blkid/getsize.c2
-rw-r--r--lib/blkid/libblkid.3.in6
-rw-r--r--lib/blkid/probe.c11
-rw-r--r--lib/blkid/probe.h43
-rw-r--r--lib/blkid/save.c8
-rw-r--r--lib/config.h4
-rw-r--r--lib/config.h.in125
-rw-r--r--lib/e2p/Android.bp15
-rw-r--r--lib/e2p/Makefile.in3
-rw-r--r--lib/e2p/e2p.h2
-rw-r--r--lib/e2p/errcode.c6
-rw-r--r--lib/e2p/fgetflags.c12
-rw-r--r--lib/e2p/fgetversion.c2
-rw-r--r--lib/e2p/fsetflags.c12
-rw-r--r--lib/e2p/fsetversion.c1
-rw-r--r--lib/e2p/getflags.c3
-rw-r--r--lib/e2p/getversion.c1
-rw-r--r--lib/e2p/ls.c2
-rw-r--r--lib/e2p/setversion.c1
-rw-r--r--lib/et/Android.bp3
-rw-r--r--lib/et/com_err.c3
-rw-r--r--lib/et/error_message.c10
-rw-r--r--lib/et/texinfo.tex12
-rw-r--r--lib/ext2fs/Android.bp15
-rw-r--r--lib/ext2fs/Makefile.in19
-rw-r--r--lib/ext2fs/alloc_stats.c3
-rw-r--r--lib/ext2fs/alloc_tables.c4
-rw-r--r--lib/ext2fs/bitmaps.c9
-rw-r--r--lib/ext2fs/bitops.c14
-rw-r--r--lib/ext2fs/bitops.h97
-rw-r--r--lib/ext2fs/blknum.c2
-rw-r--r--lib/ext2fs/compiler.h26
-rw-r--r--lib/ext2fs/crc32c.c8
-rw-r--r--lib/ext2fs/dir_iterate.c4
-rw-r--r--lib/ext2fs/ext2_err.c6
-rw-r--r--lib/ext2fs/ext2_err.et.in6
-rw-r--r--lib/ext2fs/ext2_err.h2
-rw-r--r--lib/ext2fs/ext2_ext_attr.h11
-rw-r--r--lib/ext2fs/ext2_fs.h34
-rw-r--r--lib/ext2fs/ext2_io.h7
-rw-r--r--lib/ext2fs/ext2fs.h23
-rw-r--r--lib/ext2fs/ext2fsP.h2
-rw-r--r--lib/ext2fs/ext_attr.c102
-rw-r--r--lib/ext2fs/extent.c19
-rw-r--r--lib/ext2fs/fast_commit.h13
-rw-r--r--lib/ext2fs/fileio.c10
-rw-r--r--lib/ext2fs/gen_bitmap64.c24
-rw-r--r--lib/ext2fs/getsectsize.c15
-rw-r--r--lib/ext2fs/getsize.c30
-rw-r--r--lib/ext2fs/hashmap.c12
-rw-r--r--lib/ext2fs/hashmap.h4
-rw-r--r--lib/ext2fs/imager.c11
-rw-r--r--lib/ext2fs/inline_data.c2
-rw-r--r--lib/ext2fs/inode.c11
-rw-r--r--lib/ext2fs/io_manager.c4
-rw-r--r--lib/ext2fs/irel.h2
-rw-r--r--lib/ext2fs/ismounted.c17
-rw-r--r--lib/ext2fs/jfs_compat.h12
-rw-r--r--lib/ext2fs/kernel-jbd.h3
-rw-r--r--lib/ext2fs/link.c26
-rw-r--r--lib/ext2fs/llseek.c4
-rw-r--r--lib/ext2fs/mkjournal.c2
-rw-r--r--lib/ext2fs/mmp.c6
-rw-r--r--lib/ext2fs/nls_utf8.c2
-rw-r--r--lib/ext2fs/openfs.c25
-rw-r--r--lib/ext2fs/punch.c4
-rw-r--r--lib/ext2fs/qcow2.c2
-rw-r--r--lib/ext2fs/rbtree.c68
-rw-r--r--lib/ext2fs/rbtree.h17
-rw-r--r--lib/ext2fs/rw_bitmaps.c17
-rw-r--r--lib/ext2fs/sha256.c2
-rw-r--r--lib/ext2fs/sha512.c2
-rw-r--r--lib/ext2fs/swapfs.c11
-rw-r--r--lib/ext2fs/tdb.c50
-rw-r--r--lib/ext2fs/test_io.c2
-rw-r--r--lib/ext2fs/tst_bitops.c2
-rw-r--r--lib/ext2fs/tst_getsize.c7
-rw-r--r--lib/ext2fs/undo_io.c2
-rw-r--r--lib/ext2fs/unix_io.c209
-rw-r--r--lib/ext2fs/windows_io.c1020
-rw-r--r--lib/ss/Makefile.in5
-rw-r--r--lib/ss/error.c2
-rw-r--r--lib/ss/execute_cmd.c4
-rw-r--r--lib/ss/get_readline.c2
-rw-r--r--lib/ss/help.c16
-rw-r--r--lib/ss/invocation.c43
-rw-r--r--lib/ss/list_rqs.c9
-rw-r--r--lib/ss/pager.c2
-rw-r--r--lib/ss/ss_internal.h2
-rw-r--r--lib/support/Android.bp3
-rw-r--r--lib/support/Makefile.in17
-rw-r--r--lib/support/argv_parse.c2
-rw-r--r--lib/support/devname.c65
-rw-r--r--lib/support/devname.h19
-rw-r--r--lib/support/dict.c3
-rw-r--r--lib/support/dict.h5
-rw-r--r--lib/support/mkquota.c67
-rw-r--r--lib/support/plausible.c12
-rw-r--r--lib/support/print_fs_flags.c75
-rw-r--r--lib/support/print_fs_flags.h5
-rw-r--r--lib/support/profile.c4
-rw-r--r--lib/support/quotaio.h7
-rw-r--r--lib/support/quotaio_tree.c2
-rw-r--r--lib/support/quotaio_v2.c87
-rw-r--r--lib/support/quotaio_v2.h17
-rw-r--r--lib/support/sort_r.h18
-rw-r--r--lib/uuid/Android.bp9
-rw-r--r--lib/uuid/gen_uuid.c42
-rw-r--r--lib/uuid/tst_uuid.c6
-rw-r--r--lib/uuid/uuid_time.c6
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>