diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 15:49:25 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 15:49:25 +0000 |
commit | 464df1d5e5ab1322e2dd0a7796939fff1aeefa9a (patch) | |
tree | 6a403684e0978f0287d7f0ec0e5aab1fd31a59e1 /lib/e2p | |
parent | Initial commit. (diff) | |
download | e2fsprogs-464df1d5e5ab1322e2dd0a7796939fff1aeefa9a.tar.xz e2fsprogs-464df1d5e5ab1322e2dd0a7796939fff1aeefa9a.zip |
Adding upstream version 1.47.0.upstream/1.47.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'lib/e2p')
-rw-r--r-- | lib/e2p/Android.bp | 58 | ||||
-rw-r--r-- | lib/e2p/Makefile.in | 223 | ||||
-rw-r--r-- | lib/e2p/crypto_mode.c | 74 | ||||
-rw-r--r-- | lib/e2p/e2p.h | 92 | ||||
-rw-r--r-- | lib/e2p/e2p.pc.in | 11 | ||||
-rw-r--r-- | lib/e2p/encoding.c | 118 | ||||
-rw-r--r-- | lib/e2p/errcode.c | 48 | ||||
-rw-r--r-- | lib/e2p/feature.c | 449 | ||||
-rw-r--r-- | lib/e2p/fgetflags.c | 117 | ||||
-rw-r--r-- | lib/e2p/fgetproject.c | 63 | ||||
-rw-r--r-- | lib/e2p/fgetversion.c | 74 | ||||
-rw-r--r-- | lib/e2p/fsetflags.c | 118 | ||||
-rw-r--r-- | lib/e2p/fsetproject.c | 69 | ||||
-rw-r--r-- | lib/e2p/fsetversion.c | 71 | ||||
-rw-r--r-- | lib/e2p/getflags.c | 71 | ||||
-rw-r--r-- | lib/e2p/getversion.c | 41 | ||||
-rw-r--r-- | lib/e2p/hashstr.c | 72 | ||||
-rw-r--r-- | lib/e2p/iod.c | 76 | ||||
-rw-r--r-- | lib/e2p/ljs.c | 134 | ||||
-rw-r--r-- | lib/e2p/ls.c | 494 | ||||
-rw-r--r-- | lib/e2p/mntopts.c | 150 | ||||
-rw-r--r-- | lib/e2p/ostype.c | 79 | ||||
-rw-r--r-- | lib/e2p/parse_num.c | 91 | ||||
-rw-r--r-- | lib/e2p/pe.c | 40 | ||||
-rw-r--r-- | lib/e2p/percent.c | 67 | ||||
-rw-r--r-- | lib/e2p/pf.c | 79 | ||||
-rw-r--r-- | lib/e2p/project.h | 27 | ||||
-rw-r--r-- | lib/e2p/ps.c | 32 | ||||
-rw-r--r-- | lib/e2p/setflags.c | 77 | ||||
-rw-r--r-- | lib/e2p/setversion.c | 40 | ||||
-rw-r--r-- | lib/e2p/uuid.c | 85 |
31 files changed, 3240 insertions, 0 deletions
diff --git a/lib/e2p/Android.bp b/lib/e2p/Android.bp new file mode 100644 index 0000000..bed92c1 --- /dev/null +++ b/lib/e2p/Android.bp @@ -0,0 +1,58 @@ +// Copyright 2017 The Android Open Source Project + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "external_e2fsprogs_license" + // to get the below license kinds: + // SPDX-license-identifier-GPL + // SPDX-license-identifier-LGPL + default_applicable_licenses: ["external_e2fsprogs_license"], +} + +cc_library { + name: "libext2_e2p", + host_supported: true, + ramdisk_available: true, + vendor_ramdisk_available: true, + recovery_available: true, + unique_host_soname: true, + defaults: ["e2fsprogs-defaults"], + srcs: [ + "encoding.c", + "errcode.c", + "feature.c", + "fgetflags.c", + "fsetflags.c", + "fgetproject.c", + "fsetproject.c", + "fgetversion.c", + "fsetversion.c", + "getflags.c", + "getversion.c", + "hashstr.c", + "iod.c", + "ljs.c", + "ls.c", + "mntopts.c", + "parse_num.c", + "pe.c", + "pf.c", + "ps.c", + "setflags.c", + "setversion.c", + "uuid.c", + "ostype.c", + "percent.c", + ], + + target: { + windows: { + enabled: true, + }, + }, + + header_libs: ["libext2-headers"], + export_include_dirs: ["."], + export_header_lib_headers: ["libext2-headers"], +} diff --git a/lib/e2p/Makefile.in b/lib/e2p/Makefile.in new file mode 100644 index 0000000..92d9c01 --- /dev/null +++ b/lib/e2p/Makefile.in @@ -0,0 +1,223 @@ +# Makefile for the second extended file system utility functions +# +# Copyright (C) 1993 Remy Card (card@masi.ibp.fr) +# +# This file can be redistributed under the terms of the GNU General +# Public License + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +top_builddir = ../.. +my_dir = lib/e2p +INSTALL = @INSTALL@ +MKDIR_P = @MKDIR_P@ + +@MCONFIG@ + +all:: e2p.pc + +OBJS= feature.o fgetflags.o fsetflags.o fgetversion.o fsetversion.o \ + getflags.o getversion.o hashstr.o iod.o ls.o ljs.o mntopts.o \ + parse_num.o pe.o pf.o ps.o setflags.o setversion.o uuid.o \ + ostype.o percent.o crypto_mode.o fgetproject.o fsetproject.o \ + encoding.o errcode.o + +SRCS= $(srcdir)/feature.c $(srcdir)/fgetflags.c \ + $(srcdir)/fsetflags.c $(srcdir)/fgetversion.c \ + $(srcdir)/fsetversion.c $(srcdir)/getflags.c \ + $(srcdir)/getversion.c $(srcdir)/hashstr.c $(srcdir)/iod.c \ + $(srcdir)/ls.c $(srcdir)/ljs.c $(srcdir)/mntopts.c \ + $(srcdir)/parse_num.c $(srcdir)/pe.c $(srcdir)/pf.c \ + $(srcdir)/ps.c $(srcdir)/setflags.c $(srcdir)/setversion.c \ + $(srcdir)/uuid.c $(srcdir)/ostype.c $(srcdir)/percent.c \ + $(srcdir)/crypto_mode.c $(srcdir)/fgetproject.c \ + $(srcdir)/fsetproject.c $(srcdir)/encoding.c \ + $(srcdir)/errcode.c + +HFILES= e2p.h + +LIBRARY= libe2p +LIBDIR= e2p + +ELF_VERSION = 2.3 +ELF_SO_VERSION = 2 +ELF_IMAGE = libe2p +ELF_MYDIR = e2p +ELF_INSTALL_DIR = $(root_libdir) +ELF_OTHER_LIBS = + +BSDLIB_VERSION = 2.1 +BSDLIB_IMAGE = libe2p +BSDLIB_MYDIR = e2p +BSDLIB_INSTALL_DIR = $(root_libdir) + +@MAKEFILE_LIBRARY@ +@MAKEFILE_ELF@ +@MAKEFILE_BSDLIB@ +@MAKEFILE_PROFILE@ + +.c.o: + $(E) " CC $<" + $(Q) $(CC) $(ALL_CFLAGS_STLIB) -c $< -o $@ + $(Q) $(CHECK_CMD) $(ALL_CFLAGS) $< + $(Q) $(CPPCHECK_CMD) $(CPPFLAGS) $< +@PROFILE_CMT@ $(Q) $(CC) $(ALL_CFLAGS_STLIB) -g -pg -o profiled/$*.o -c $< +@ELF_CMT@ $(Q) $(CC) $(ALL_CFLAGS_SHLIB) -fPIC -shared -o elfshared/$*.o -c $< +@BSDLIB_CMT@ $(Q) $(CC) $(ALL_CFLAGS_SHLIB) $(BSDLIB_PIC_FLAG) -o pic/$*.o -c $< + +e2p.pc: $(srcdir)/e2p.pc.in $(top_builddir)/config.status + $(E) " CONFIG.STATUS $@" + $(Q) cd $(top_builddir); CONFIG_FILES=lib/e2p/e2p.pc ./config.status + +tst_ostype: $(srcdir)/ostype.c + $(E) " LD $@" + $(Q) $(CC) -DTEST_PROGRAM -I$(top_srcdir)/lib -o tst_ostype \ + $(srcdir)/ostype.c $(ALL_CFLAGS) $(ALL_LDFLAGS) + +tst_feature: $(srcdir)/feature.c + $(E) " LD $@" + $(Q) $(CC) -DTEST_PROGRAM -I$(top_srcdir)/lib -o tst_feature \ + $(srcdir)/feature.c $(ALL_CFLAGS) $(ALL_LDFLAGS) + +fullcheck check:: tst_ostype tst_feature + ./tst_ostype + ./tst_feature + +installdirs:: + $(E) " MKDIR_P $(libdir) $(includedir)/e2p" + $(Q) $(MKDIR_P) $(DESTDIR)$(libdir) \ + $(DESTDIR)$(includedir)/e2p $(DESTDIR)$(pkgconfigdir) + +install:: all installdirs + $(E) " INSTALL_DATA $(libdir)/libe2p.a" + $(Q) $(INSTALL_DATA) libe2p.a $(DESTDIR)$(libdir)/libe2p.a + -$(Q) $(RANLIB) $(DESTDIR)$(libdir)/libe2p.a + $(Q) $(CHMOD) $(LIBMODE) $(DESTDIR)$(libdir)/libe2p.a + $(Q) set -e; for i in $(HFILES); do \ + echo " INSTALL_DATA $(includedir)/e2p/$$i"; \ + $(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(includedir)/e2p/$$i; \ + done + $(E) " INSTALL_DATA $(pkgconfigdir)/e2p.pc" + $(Q) $(INSTALL_DATA) e2p.pc $(DESTDIR)$(pkgconfigdir)/e2p.pc + +uninstall:: + $(RM) -f $(DESTDIR)$(libdir)/libe2p.a \ + $(DESTDIR)$(pkgconfigdir)/e2p.pc + $(RM) -rf $(DESTDIR)$(includedir)/e2p + +clean:: + $(RM) -f \#* *.s *.o *.a *~ *.bak core profiled/* + $(RM) -f ../libe2p.a ../libe2p_p.a tst_ostype tst_feature e2p.pc + +mostlyclean:: clean +distclean:: clean + $(RM) -f .depend Makefile e2p.pc \ + $(srcdir)/TAGS $(srcdir)/Makefile.in.old + +$(OBJS): subdirs + +# +++ Dependency line eater +++ +# +# Makefile dependencies follow. This must be the last section in +# the Makefile.in file +# +feature.o: $(srcdir)/feature.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 \ + $(top_srcdir)/lib/ext2fs/ext2fs.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 $(top_srcdir)/lib/ext2fs/kernel-jbd.h \ + $(top_srcdir)/lib/ext2fs/jfs_compat.h $(top_srcdir)/lib/ext2fs/kernel-list.h \ + $(top_srcdir)/lib/ext2fs/compiler.h +fgetflags.o: $(srcdir)/fgetflags.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 +fsetflags.o: $(srcdir)/fsetflags.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 +fgetversion.o: $(srcdir)/fgetversion.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 +fsetversion.o: $(srcdir)/fsetversion.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 +getflags.o: $(srcdir)/getflags.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 +getversion.o: $(srcdir)/getversion.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 +hashstr.o: $(srcdir)/hashstr.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 +iod.o: $(srcdir)/iod.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 +ls.o: $(srcdir)/ls.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 \ + $(top_srcdir)/lib/support/quotaio.h $(top_srcdir)/lib/ext2fs/ext2fs.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 $(top_srcdir)/lib/support/dqblk_v2.h \ + $(top_srcdir)/lib/support/quotaio_tree.h +ljs.o: $(srcdir)/ljs.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(top_srcdir)/lib/ext2fs/ext2_fs.h \ + $(top_builddir)/lib/ext2fs/ext2_types.h $(top_srcdir)/lib/ext2fs/ext2fs.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 $(srcdir)/e2p.h \ + $(top_srcdir)/lib/ext2fs/kernel-jbd.h $(top_srcdir)/lib/ext2fs/jfs_compat.h \ + $(top_srcdir)/lib/ext2fs/kernel-list.h $(top_srcdir)/lib/ext2fs/compiler.h +mntopts.o: $(srcdir)/mntopts.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 +parse_num.o: $(srcdir)/parse_num.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 +pe.o: $(srcdir)/pe.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 +pf.o: $(srcdir)/pf.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 +ps.o: $(srcdir)/ps.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 +setflags.o: $(srcdir)/setflags.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 +setversion.o: $(srcdir)/setversion.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 +uuid.o: $(srcdir)/uuid.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(srcdir)/e2p.h $(top_srcdir)/lib/ext2fs/ext2_fs.h +ostype.o: $(srcdir)/ostype.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 +percent.o: $(srcdir)/percent.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 +crypto_mode.o: $(srcdir)/crypto_mode.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 +fgetproject.o: $(srcdir)/fgetproject.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/project.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(srcdir)/e2p.h +fsetproject.o: $(srcdir)/fsetproject.c $(top_builddir)/lib/config.h \ + $(top_builddir)/lib/dirpaths.h $(srcdir)/project.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h \ + $(srcdir)/e2p.h +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 $(srcdir)/e2p.h \ + $(top_srcdir)/lib/ext2fs/ext2_fs.h $(top_builddir)/lib/ext2fs/ext2_types.h diff --git a/lib/e2p/crypto_mode.c b/lib/e2p/crypto_mode.c new file mode 100644 index 0000000..4933016 --- /dev/null +++ b/lib/e2p/crypto_mode.c @@ -0,0 +1,74 @@ +/* + * crypto_mode.c --- convert between encryption modes and strings + * + * Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu> + * + * %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 <stdlib.h> +#include <string.h> +#include <strings.h> +#include <ctype.h> +#include <errno.h> + +#include "e2p.h" + +struct mode { + int num; + const char *string; +}; + +static struct mode mode_list[] = { + { EXT4_ENCRYPTION_MODE_INVALID, "Invalid"}, + { EXT4_ENCRYPTION_MODE_AES_256_XTS, "AES-256-XTS"}, + { EXT4_ENCRYPTION_MODE_AES_256_GCM, "AES-256-GCM"}, + { EXT4_ENCRYPTION_MODE_AES_256_CBC, "AES-256-CBC"}, + { 0, 0 }, +}; + +const char *e2p_encmode2string(int num) +{ + struct mode *p; + static char buf[20]; + + for (p = mode_list; p->string; p++) { + if (num == p->num) + return p->string; + } + sprintf(buf, "ENC_MODE_%d", num); + return buf; +} + +/* + * Returns the hash algorithm, or -1 on error + */ +int e2p_string2encmode(char *string) +{ + struct mode *p; + char *eptr; + int num; + + for (p = mode_list; p->string; p++) { + if (!strcasecmp(string, p->string)) { + return p->num; + } + } + if (strncasecmp(string, "ENC_MODE_", 9)) + return -1; + + if (string[9] == 0) + return -1; + num = strtol(string+9, &eptr, 10); + if (num > 255 || num < 0) + return -1; + if (*eptr) + return -1; + return num; +} + diff --git a/lib/e2p/e2p.h b/lib/e2p/e2p.h new file mode 100644 index 0000000..5f4793e --- /dev/null +++ b/lib/e2p/e2p.h @@ -0,0 +1,92 @@ +/* + * e2p.h --- header file for the e2p library + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include <sys/types.h> /* Needed by dirent.h on netbsd */ +#include <stdio.h> +#include <dirent.h> + +#include <ext2fs/ext2_fs.h> + +#define E2P_FEATURE_COMPAT 0 +#define E2P_FEATURE_INCOMPAT 1 +#define E2P_FEATURE_RO_INCOMPAT 2 +#define E2P_FEATURE_TYPE_MASK 0x03 + +#define E2P_FEATURE_NEGATE_FLAG 0x80 + +#define E2P_FS_FEATURE 0 +#define E2P_JOURNAL_FEATURE 1 + +/* `options' for print_flags() */ + +#define PFOPT_LONG 1 /* Must be 1 for compatibility with `int long_format'. */ + + +int fgetflags (const char * name, unsigned long * flags); +int fgetversion (const char * name, unsigned long * version); +int fsetflags (const char * name, unsigned long flags); +int fsetversion (const char * name, unsigned long version); +int fgetproject(const char *name, unsigned long *project); +int fsetproject(const char *name, unsigned long project); +int getflags (int fd, unsigned long * flags); +int getversion (int fd, unsigned long * version); +int iterate_on_dir (const char * dir_name, + int (*func) (const char *, struct dirent *, void *), + void * private_arg); +void list_super(struct ext2_super_block * s); +void list_super2(struct ext2_super_block * s, FILE *f); +void print_fs_errors (FILE * f, unsigned short errors); +void print_flags (FILE * f, unsigned long flags, unsigned options); +void print_fs_state (FILE * f, unsigned short state); +int setflags (int fd, unsigned long flags); +int setversion (int fd, unsigned long version); + +#define E2P_LIST_JOURNAL_FLAG_FC 0x1 +void e2p_list_journal_super(FILE *f, char *journal_sb_buf, + int exp_block_size, int flags); + +void e2p_feature_to_string(int compat, unsigned int mask, char *buf, + size_t buf_len); +const char *e2p_feature2string(int compat, unsigned int mask); +const char *e2p_jrnl_feature2string(int compat, unsigned int mask); +int e2p_string2feature(char *string, int *compat, unsigned int *mask); +int e2p_jrnl_string2feature(char *string, int *compat_type, unsigned int *mask); +int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array); +int e2p_edit_feature2(const char *str, __u32 *compat_array, __u32 *ok_array, + __u32 *clear_ok_array, int *type_err, + unsigned int *mask_err); + +int e2p_is_null_uuid(void *uu); +void e2p_uuid_to_str(void *uu, char *out); +const char *e2p_uuid2str(void *uu); + +const char *e2p_hash2string(int num); +int e2p_string2hash(char *string); + +const char *e2p_mntopt2string(unsigned int mask); +int e2p_string2mntopt(char *string, unsigned int *mask); +int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok); + +unsigned long parse_num_blocks(const char *arg, int log_block_size); +unsigned long long parse_num_blocks2(const char *arg, int log_block_size); + +char *e2p_os2string(int os_type); +int e2p_string2os(char *str); + +unsigned int e2p_percent(int percent, unsigned int base); + +const char *e2p_encmode2string(int num); +int e2p_string2encmode(char *string); + +int e2p_str2encoding(const char *string); +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(unsigned int err); diff --git a/lib/e2p/e2p.pc.in b/lib/e2p/e2p.pc.in new file mode 100644 index 0000000..150b089 --- /dev/null +++ b/lib/e2p/e2p.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: e2p +Description: Ext2fs userspace programs utility library +Version: @E2FSPROGS_VERSION@ +Requires: +Cflags: -I${includedir}/e2p -I${includedir} +Libs: -L${libdir} -le2p diff --git a/lib/e2p/encoding.c b/lib/e2p/encoding.c new file mode 100644 index 0000000..24266fc --- /dev/null +++ b/lib/e2p/encoding.c @@ -0,0 +1,118 @@ +/* + * encoding.c --- convert between encoding magic numbers and strings + * + * Copyright (C) 2018 Collabora Ltd. + * + * %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 <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> +#include <stdio.h> + +#include "e2p.h" + +#define ARRAY_SIZE(array) \ + (sizeof(array) / sizeof(array[0])) + +static const struct { + const char *name; + __u16 encoding_magic; + __u16 default_flags; + +} ext4_encoding_map[] = { + { + .encoding_magic = EXT4_ENC_UTF8_12_1, + .name = "utf8-12.1", + .default_flags = 0, + }, + { + .encoding_magic = EXT4_ENC_UTF8_12_1, + .name = "utf8", + .default_flags = 0, + }, +}; + +static const struct enc_flags { + __u16 flag; + const char *param; +} encoding_flags[] = { + { EXT4_ENC_STRICT_MODE_FL, "strict" }, +}; + +/* Return a positive number < 0xff indicating the encoding magic number + * or a negative value indicating error. */ +int e2p_str2encoding(const char *string) +{ + unsigned int i; + + for (i = 0 ; i < ARRAY_SIZE(ext4_encoding_map); i++) + if (!strcmp(string, ext4_encoding_map[i].name)) + return ext4_encoding_map[i].encoding_magic; + + return -EINVAL; +} + +/* Return the name of an encoding or NULL */ +const char *e2p_encoding2str(int encoding) +{ + unsigned int i; + static char buf[32]; + + for (i = 0 ; i < ARRAY_SIZE(ext4_encoding_map); i++) + if (ext4_encoding_map[i].encoding_magic == encoding) + return ext4_encoding_map[i].name; + sprintf(buf, "UNKNOWN_ENCODING_%d", encoding); + return buf; +} + +int e2p_get_encoding_flags(int encoding) +{ + unsigned int i; + + for (i = 0 ; i < ARRAY_SIZE(ext4_encoding_map); i++) + if (ext4_encoding_map[i].encoding_magic == encoding) + return ext4_encoding_map[i].default_flags; + + return 0; +} + +int e2p_str2encoding_flags(int encoding, char *param, __u16 *flags) +{ + char *f = strtok(param, "-"); + const struct enc_flags *fl; + unsigned int i, neg = 0; + + if (encoding != EXT4_ENC_UTF8_12_1) + return -EINVAL; + while (f) { + neg = 0; + if (!strncmp("no", f, 2)) { + neg = 1; + f += 2; + } + + for (i = 0; i < ARRAY_SIZE(encoding_flags); i++) { + fl = &encoding_flags[i]; + if (!strcmp(fl->param, f)) { + if (neg) + *flags &= ~fl->flag; + else + *flags |= fl->flag; + + goto next_flag; + } + } + return -EINVAL; + next_flag: + f = strtok(NULL, "-"); + } + return 0; +} diff --git a/lib/e2p/errcode.c b/lib/e2p/errcode.c new file mode 100644 index 0000000..1627c9d --- /dev/null +++ b/lib/e2p/errcode.c @@ -0,0 +1,48 @@ +/* + * errcode.c - convert an error code to a string + */ + +#include "config.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "e2p.h" + +static const char *err_string[] = { + "", + "UNKNOWN", /* 1 */ + "EIO", /* 2 */ + "ENOMEM", /* 3 */ + "EFSBADCRC", /* 4 */ + "EFSCORRUPTED", /* 5 */ + "ENOSPC", /* 6 */ + "ENOKEY", /* 7 */ + "EROFS", /* 8 */ + "EFBIG", /* 9 */ + "EEXIST", /* 10 */ + "ERANGE", /* 11 */ + "EOVERFLOW", /* 12 */ + "EBUSY", /* 13 */ + "ENOTDIR", /* 14 */ + "ENOTEMPTY", /* 15 */ + "ESHUTDOWN", /* 16 */ + "EFAULT", /* 17 */ +}; + +#define ARRAY_SIZE(array) \ + (sizeof(array) / sizeof(array[0])) + +/* Return the name of an encoding or NULL */ +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_%u", err); + return buf; +} + + diff --git a/lib/e2p/feature.c b/lib/e2p/feature.c new file mode 100644 index 0000000..29b7b15 --- /dev/null +++ b/lib/e2p/feature.c @@ -0,0 +1,449 @@ +/* + * feature.c --- convert between features and strings + * + * Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu> + * + * %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 <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> + +#include "e2p.h" +#include <ext2fs/ext2fs.h> +#include <ext2fs/kernel-jbd.h> + +struct feature { + int compat; + unsigned int mask; + const char *string; +}; + +static struct feature feature_list[] = { + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_PREALLOC, + "dir_prealloc" }, + { E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL, + "has_journal" }, + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_IMAGIC_INODES, + "imagic_inodes" }, + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_EXT_ATTR, + "ext_attr" }, + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_INDEX, + "dir_index" }, + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_RESIZE_INODE, + "resize_inode" }, + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_LAZY_BG, + "lazy_bg" }, + { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP, + "snapshot_bitmap" }, + { E2P_FEATURE_COMPAT, EXT4_FEATURE_COMPAT_SPARSE_SUPER2, + "sparse_super2" }, + { E2P_FEATURE_COMPAT, EXT4_FEATURE_COMPAT_FAST_COMMIT, + "fast_commit" }, + { E2P_FEATURE_COMPAT, EXT4_FEATURE_COMPAT_STABLE_INODES, + "stable_inodes" }, + { E2P_FEATURE_COMPAT, EXT4_FEATURE_COMPAT_ORPHAN_FILE, + "orphan_file" }, + + { E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER, + "sparse_super" }, + { E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_LARGE_FILE, + "large_file" }, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_HUGE_FILE, + "huge_file" }, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_GDT_CSUM, + "uninit_bg" }, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_GDT_CSUM, + "uninit_groups" }, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_DIR_NLINK, + "dir_nlink" }, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE, + "extra_isize" }, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_QUOTA, + "quota" }, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_BIGALLOC, + "bigalloc"}, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_METADATA_CSUM, + "metadata_csum"}, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_REPLICA, + "replica" }, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_READONLY, + "read-only" }, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_PROJECT, + "project"}, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS, + "shared_blocks"}, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_VERITY, + "verity"}, + { E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_ORPHAN_PRESENT, + "orphan_present" }, + + { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_COMPRESSION, + "compression" }, + { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_FILETYPE, + "filetype" }, + { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_RECOVER, + "needs_recovery" }, + { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV, + "journal_dev" }, + { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS, + "extent" }, + { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS, + "extents" }, + { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_META_BG, + "meta_bg" }, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_64BIT, + "64bit" }, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_MMP, + "mmp" }, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_FLEX_BG, + "flex_bg"}, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_EA_INODE, + "ea_inode"}, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_DIRDATA, + "dirdata"}, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_CSUM_SEED, + "metadata_csum_seed"}, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_LARGEDIR, + "large_dir"}, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_INLINE_DATA, + "inline_data"}, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_ENCRYPT, + "encrypt"}, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_CASEFOLD, + "casefold"}, + { E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_CASEFOLD, + "fname_encoding"}, + { 0, 0, 0 }, +}; + +static struct feature jrnl_feature_list[] = { + { E2P_FEATURE_COMPAT, JBD2_FEATURE_COMPAT_CHECKSUM, + "journal_checksum" }, + + { E2P_FEATURE_INCOMPAT, JBD2_FEATURE_INCOMPAT_REVOKE, + "journal_incompat_revoke" }, + { E2P_FEATURE_INCOMPAT, JBD2_FEATURE_INCOMPAT_64BIT, + "journal_64bit" }, + { E2P_FEATURE_INCOMPAT, JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT, + "journal_async_commit" }, + { E2P_FEATURE_INCOMPAT, JBD2_FEATURE_INCOMPAT_CSUM_V2, + "journal_checksum_v2" }, + { E2P_FEATURE_INCOMPAT, JBD2_FEATURE_INCOMPAT_CSUM_V3, + "journal_checksum_v3" }, + { 0, 0, 0 }, +}; + +void e2p_feature_to_string(int compat, unsigned int mask, char *buf, + size_t buf_len) +{ + struct feature *f; + char fchar; + int fnum; + + for (f = feature_list; f->string; f++) { + if ((compat == f->compat) && + (mask == f->mask)) { + strncpy(buf, f->string, buf_len); + buf[buf_len - 1] = 0; + return; + } + } + switch (compat) { + case E2P_FEATURE_COMPAT: + fchar = 'C'; + break; + case E2P_FEATURE_INCOMPAT: + fchar = 'I'; + break; + case E2P_FEATURE_RO_INCOMPAT: + fchar = 'R'; + break; + default: + fchar = '?'; + break; + } + for (fnum = 0; mask >>= 1; fnum++); + sprintf(buf, "FEATURE_%c%d", fchar, fnum); +} + +const char *e2p_feature2string(int compat, unsigned int mask) +{ + static char buf[20]; + + e2p_feature_to_string(compat, mask, buf, sizeof(buf) / sizeof(buf[0])); + return buf; +} + +int e2p_string2feature(char *string, int *compat_type, unsigned int *mask) +{ + struct feature *f; + char *eptr; + int num; + + for (f = feature_list; f->string; f++) { + if (!strcasecmp(string, f->string)) { + *compat_type = f->compat; + *mask = f->mask; + return 0; + } + } + if (strncasecmp(string, "FEATURE_", 8)) + return 1; + + switch (string[8]) { + case 'c': + case 'C': + *compat_type = E2P_FEATURE_COMPAT; + break; + case 'i': + case 'I': + *compat_type = E2P_FEATURE_INCOMPAT; + break; + case 'r': + case 'R': + *compat_type = E2P_FEATURE_RO_INCOMPAT; + break; + default: + return 1; + } + if (string[9] == 0) + return 1; + num = strtol(string+9, &eptr, 10); + if (num > 31 || num < 0) + return 1; + if (*eptr) + return 1; + *mask = 1 << num; + return 0; +} + +const char *e2p_jrnl_feature2string(int compat, unsigned int mask) +{ + struct feature *f; + static char buf[20]; + char fchar; + int fnum; + + for (f = jrnl_feature_list; f->string; f++) { + if ((compat == f->compat) && + (mask == f->mask)) + return f->string; + } + switch (compat) { + case E2P_FEATURE_COMPAT: + fchar = 'C'; + break; + case E2P_FEATURE_INCOMPAT: + fchar = 'I'; + break; + case E2P_FEATURE_RO_INCOMPAT: + fchar = 'R'; + break; + default: + fchar = '?'; + break; + } + for (fnum = 0; mask >>= 1; fnum++); + sprintf(buf, "FEATURE_%c%d", fchar, fnum); + return buf; +} + +int e2p_jrnl_string2feature(char *string, int *compat_type, unsigned int *mask) +{ + struct feature *f; + char *eptr; + int num; + + for (f = jrnl_feature_list; f->string; f++) { + if (!strcasecmp(string, f->string)) { + *compat_type = f->compat; + *mask = f->mask; + return 0; + } + } + if (strncasecmp(string, "FEATURE_", 8)) + return 1; + + switch (string[8]) { + case 'c': + case 'C': + *compat_type = E2P_FEATURE_COMPAT; + break; + case 'i': + case 'I': + *compat_type = E2P_FEATURE_INCOMPAT; + break; + case 'r': + case 'R': + *compat_type = E2P_FEATURE_RO_INCOMPAT; + break; + default: + return 1; + } + if (string[9] == 0) + return 1; + num = strtol(string+9, &eptr, 10); + if (num > 31 || num < 0) + return 1; + if (*eptr) + return 1; + *mask = 1 << num; + return 0; +} +static char *skip_over_blanks(char *cp) +{ + while (*cp && isspace(*cp)) + cp++; + return cp; +} + +static char *skip_over_word(char *cp) +{ + while (*cp && !isspace(*cp) && *cp != ',') + cp++; + return cp; +} + +/* + * Edit a feature set array as requested by the user. The ok_array, + * if set, allows the application to limit what features the user is + * allowed to set or clear using this function. If clear_ok_array is set, + * then use it tell whether or not it is OK to clear a filesystem feature. + */ +int e2p_edit_feature2(const char *str, __u32 *compat_array, __u32 *ok_array, + __u32 *clear_ok_array, int *type_err, + unsigned int *mask_err) +{ + char *cp, *buf, *next; + int neg; + unsigned int mask; + int compat_type; + int rc = 0; + + if (!clear_ok_array) + clear_ok_array = ok_array; + + if (type_err) + *type_err = 0; + if (mask_err) + *mask_err = 0; + + buf = malloc(strlen(str)+1); + if (!buf) + return 1; + strcpy(buf, str); + for (cp = buf; cp && *cp; cp = next ? next+1 : 0) { + neg = 0; + cp = skip_over_blanks(cp); + next = skip_over_word(cp); + + if (*next == 0) + next = 0; + else + *next = 0; + + if ((strcasecmp(cp, "none") == 0) || + (strcasecmp(cp, "clear") == 0)) { + compat_array[0] = 0; + compat_array[1] = 0; + compat_array[2] = 0; + continue; + } + + switch (*cp) { + case '-': + case '^': + neg++; + /* fallthrough */ + case '+': + cp++; + break; + } + if (e2p_string2feature(cp, &compat_type, &mask)) { + rc = 1; + break; + } + if (neg) { + if (clear_ok_array && + !(clear_ok_array[compat_type] & mask)) { + rc = 1; + if (type_err) + *type_err = (compat_type | + E2P_FEATURE_NEGATE_FLAG); + if (mask_err) + *mask_err = mask; + break; + } + compat_array[compat_type] &= ~mask; + } else { + if (ok_array && !(ok_array[compat_type] & mask)) { + rc = 1; + if (type_err) + *type_err = compat_type; + if (mask_err) + *mask_err = mask; + break; + } + compat_array[compat_type] |= mask; + } + } + free(buf); + return rc; +} + +int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array) +{ + return e2p_edit_feature2(str, compat_array, ok_array, 0, 0, 0); +} + +#ifdef TEST_PROGRAM +int main(int argc, char **argv) +{ + int compat, compat2, i; + unsigned int mask, mask2; + const char *str; + struct feature *f; + + for (i = 0; i < 2; i++) { + if (i == 0) { + f = feature_list; + printf("Feature list:\n"); + } else { + printf("\nJournal feature list:\n"); + f = jrnl_feature_list; + } + for (; f->string; f++) { + if (i == 0) { + e2p_string2feature((char *)f->string, &compat, + &mask); + str = e2p_feature2string(compat, mask); + } else { + e2p_jrnl_string2feature((char *)f->string, + &compat, &mask); + str = e2p_jrnl_feature2string(compat, mask); + } + + printf("\tCompat = %d, Mask = %u, %s\n", + compat, mask, f->string); + if (strcmp(f->string, str)) { + if (e2p_string2feature((char *) str, &compat2, + &mask2) || + (compat2 != compat) || + (mask2 != mask)) { + fprintf(stderr, "Failure!\n"); + exit(1); + } + } + } + } + exit(0); +} +#endif diff --git a/lib/e2p/fgetflags.c b/lib/e2p/fgetflags.c new file mode 100644 index 0000000..24a7166 --- /dev/null +++ b/lib/e2p/fgetflags.c @@ -0,0 +1,117 @@ +/* + * fgetflags.c - Get a file flags on an ext2 file system + * + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr> + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * History: + * 93/10/30 - Creation + */ + +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#include "config.h" +#if HAVE_ERRNO_H +#include <errno.h> +#endif +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#if HAVE_EXT2_IOCTLS +#include <fcntl.h> +#include <sys/ioctl.h> +#endif + +#include "e2p.h" + +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif +#ifndef O_NOFOLLOW +#define O_NOFOLLOW 0 +#endif + +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_NOFOLLOW) + +int fgetflags (const char * name, unsigned long * flags) +{ +#if HAVE_STAT_FLAGS && !(APPLE_DARWIN && HAVE_EXT2_IOCTLS) + struct stat buf; + + if (stat (name, &buf) == -1) + return -1; + + *flags = 0; +#ifdef UF_IMMUTABLE + if (buf.st_flags & UF_IMMUTABLE) + *flags |= EXT2_IMMUTABLE_FL; +#endif +#ifdef UF_APPEND + if (buf.st_flags & UF_APPEND) + *flags |= EXT2_APPEND_FL; +#endif +#ifdef UF_NODUMP + if (buf.st_flags & UF_NODUMP) + *flags |= EXT2_NODUMP_FL; +#endif + + return 0; +#elif APPLE_DARWIN && HAVE_EXT2_IOCTLS + int f, save_errno = 0; + + f = -1; + save_errno = syscall(SYS_fsctl, name, EXT2_IOC_GETFLAGS, &f, 0); + *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) + errno = EOPNOTSUPP; + save_errno = errno; + } + *flags = f; + close(fd); + if (save_errno) + errno = save_errno; + return r; +#else + errno = EOPNOTSUPP; + return -1; +#endif +} diff --git a/lib/e2p/fgetproject.c b/lib/e2p/fgetproject.c new file mode 100644 index 0000000..12320b5 --- /dev/null +++ b/lib/e2p/fgetproject.c @@ -0,0 +1,63 @@ +/* + * fgetproject.c --- get project id + * + * Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu> + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#include "config.h" +#if HAVE_ERRNO_H +#include <errno.h> +#endif +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#if HAVE_EXT2_IOCTLS +#include <fcntl.h> +#include <sys/ioctl.h> +#include "project.h" +#endif + +#include "e2p.h" + +#ifdef O_LARGEFILE +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE) +#else +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK) +#endif + +int fgetproject(const char *name, unsigned long *project) +{ +#ifndef FS_IOC_FSGETXATTR + errno = EOPNOTSUPP; + return -1; +#else + int fd, r, save_errno = 0; + struct fsxattr fsx; + + fd = open (name, OPEN_FLAGS); + if (fd == -1) + return -1; + r = ioctl (fd, FS_IOC_FSGETXATTR, &fsx); + if (r == 0) + *project = fsx.fsx_projid; + save_errno = errno; + close (fd); + if (save_errno) + errno = save_errno; + return r; +#endif +} diff --git a/lib/e2p/fgetversion.c b/lib/e2p/fgetversion.c new file mode 100644 index 0000000..f3a5b4c --- /dev/null +++ b/lib/e2p/fgetversion.c @@ -0,0 +1,74 @@ +/* + * fgetversion.c - Get a file version on an ext2 file system + * + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr> + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * History: + * 93/10/30 - Creation + */ + +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#include "config.h" +#if HAVE_ERRNO_H +#include <errno.h> +#endif +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <fcntl.h> +#if HAVE_SYS_IOCTL_H +#include <sys/ioctl.h> +#endif + +#include "e2p.h" + +#ifdef O_LARGEFILE +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE) +#else +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK) +#endif + +int fgetversion(const char *name, unsigned long *version) +{ + unsigned int ver = -1; + int rc = -1; +#if HAVE_EXT2_IOCTLS +# if !APPLE_DARWIN + int fd, save_errno = 0; + + fd = open(name, OPEN_FLAGS); + if (fd == -1) + return -1; + + rc = ioctl(fd, EXT2_IOC_GETVERSION, &ver); + if (rc == -1) + save_errno = errno; + close(fd); + if (rc == -1) + errno = save_errno; +# else /* APPLE_DARWIN */ + rc = syscall(SYS_fsctl, name, EXT2_IOC_GETVERSION, &ver, 0); +# endif /* !APPLE_DARWIN */ +#else /* ! HAVE_EXT2_IOCTLS */ + errno = EOPNOTSUPP; +#endif /* ! HAVE_EXT2_IOCTLS */ + if (rc == 0) + *version = ver; + + return rc; +} diff --git a/lib/e2p/fsetflags.c b/lib/e2p/fsetflags.c new file mode 100644 index 0000000..d865d24 --- /dev/null +++ b/lib/e2p/fsetflags.c @@ -0,0 +1,118 @@ +/* + * fsetflags.c - Set a file flags on an ext2 file system + * + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr> + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * History: + * 93/10/30 - Creation + */ + +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#include "config.h" +#if HAVE_ERRNO_H +#include <errno.h> +#endif +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#if HAVE_EXT2_IOCTLS +#include <fcntl.h> +#include <sys/ioctl.h> +#endif + +#include "e2p.h" + +/* + * Deal with lame glibc's that define this function without actually + * implementing it. Can you say "attractive nuisance", boys and girls? + * I knew you could! + */ +#ifdef __linux__ +#undef HAVE_CHFLAGS +#endif + +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif +#ifndef O_NOFOLLOW +#define O_NOFOLLOW 0 +#endif + +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_NOFOLLOW) + +int fsetflags (const char * name, unsigned long flags) +{ +#if HAVE_CHFLAGS && !(APPLE_DARWIN && HAVE_EXT2_IOCTLS) + unsigned long bsd_flags = 0; + +#ifdef UF_IMMUTABLE + if (flags & EXT2_IMMUTABLE_FL) + bsd_flags |= UF_IMMUTABLE; +#endif +#ifdef UF_APPEND + if (flags & EXT2_APPEND_FL) + bsd_flags |= UF_APPEND; +#endif +#ifdef UF_NODUMP + if (flags & EXT2_NODUMP_FL) + bsd_flags |= UF_NODUMP; +#endif + + return chflags (name, bsd_flags); +#elif APPLE_DARWIN && HAVE_EXT2_IOCTLS + 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) { + if (errno == ENOTTY) + errno = EOPNOTSUPP; + save_errno = errno; + } + close(fd); + if (save_errno) + errno = save_errno; + return r; +#else + errno = EOPNOTSUPP; + return -1; +#endif +} diff --git a/lib/e2p/fsetproject.c b/lib/e2p/fsetproject.c new file mode 100644 index 0000000..5df7090 --- /dev/null +++ b/lib/e2p/fsetproject.c @@ -0,0 +1,69 @@ +/* + * fgetproject.c --- get project id + * + * Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu> + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#include "config.h" +#if HAVE_ERRNO_H +#include <errno.h> +#endif +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#if HAVE_EXT2_IOCTLS +#include <fcntl.h> +#include <sys/ioctl.h> +#include "project.h" +#endif + +#include "e2p.h" + +#ifdef O_LARGEFILE +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE) +#else +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK) +#endif + +int fsetproject(const char *name, unsigned long project) +{ +#ifndef FS_IOC_FSGETXATTR + errno = EOPNOTSUPP; + return -1; +#else + int fd, r, save_errno = 0; + struct fsxattr fsx; + + fd = open (name, OPEN_FLAGS); + if (fd == -1) + return -1; + r = ioctl (fd, FS_IOC_FSGETXATTR, &fsx); + if (r == -1) { + save_errno = errno; + goto errout; + } + fsx.fsx_projid = project; + r = ioctl (fd, FS_IOC_FSSETXATTR, &fsx); + if (r == -1) + save_errno = errno; +errout: + close (fd); + if (save_errno) + errno = save_errno; + return r; +#endif +} diff --git a/lib/e2p/fsetversion.c b/lib/e2p/fsetversion.c new file mode 100644 index 0000000..5f844b5 --- /dev/null +++ b/lib/e2p/fsetversion.c @@ -0,0 +1,71 @@ +/* + * fsetversion.c - Set a file version on an ext2 file system + * + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr> + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * History: + * 93/10/30 - Creation + */ + +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif + +#include "config.h" +#if HAVE_ERRNO_H +#include <errno.h> +#endif +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <fcntl.h> +#if HAVE_SYS_IOCTL_H +#include <sys/ioctl.h> +#endif + +#include "e2p.h" + +#ifdef O_LARGEFILE +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE) +#else +#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK) +#endif + +int fsetversion (const char * name, unsigned long version) +{ +#if HAVE_EXT2_IOCTLS +#if !APPLE_DARWIN + int fd, r, ver, save_errno = 0; + + fd = open (name, OPEN_FLAGS); + if (fd == -1) + return -1; + ver = (int) version; + r = ioctl (fd, EXT2_IOC_SETVERSION, &ver); + if (r == -1) + save_errno = errno; + close (fd); + if (save_errno) + errno = save_errno; + return r; +#else + int ver = (int)version; + return syscall(SYS_fsctl, name, EXT2_IOC_SETVERSION, &ver, 0); +#endif +#else /* ! HAVE_EXT2_IOCTLS */ + errno = EOPNOTSUPP; + return -1; +#endif /* ! HAVE_EXT2_IOCTLS */ +} diff --git a/lib/e2p/getflags.c b/lib/e2p/getflags.c new file mode 100644 index 0000000..6708cd6 --- /dev/null +++ b/lib/e2p/getflags.c @@ -0,0 +1,71 @@ +/* + * getflags.c - Get a file flags on an ext2 file system + * + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr> + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * History: + * 93/10/30 - Creation + */ + +#include "config.h" +#if HAVE_ERRNO_H +#include <errno.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#if HAVE_EXT2_IOCTLS +#include <sys/ioctl.h> +#endif + +#include "e2p.h" + +int getflags (int fd, unsigned long * flags) +{ +#if HAVE_STAT_FLAGS + struct stat buf; + + if (fstat (fd, &buf) == -1) + return -1; + + *flags = 0; +#ifdef UF_IMMUTABLE + if (buf.st_flags & UF_IMMUTABLE) + *flags |= EXT2_IMMUTABLE_FL; +#endif +#ifdef UF_APPEND + if (buf.st_flags & UF_APPEND) + *flags |= EXT2_APPEND_FL; +#endif +#ifdef UF_NODUMP + if (buf.st_flags & UF_NODUMP) + *flags |= EXT2_NODUMP_FL; +#endif + + return 0; +#else +#if HAVE_EXT2_IOCTLS + struct stat buf; + int r, f; + + if (!fstat(fd, &buf) && + !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) + goto notsupp; + r = ioctl(fd, EXT2_IOC_GETFLAGS, &f); + *flags = f; + + return r; +notsupp: +#endif /* HAVE_EXT2_IOCTLS */ +#endif + errno = EOPNOTSUPP; + return -1; +} diff --git a/lib/e2p/getversion.c b/lib/e2p/getversion.c new file mode 100644 index 0000000..d374a0e --- /dev/null +++ b/lib/e2p/getversion.c @@ -0,0 +1,41 @@ +/* + * getversion.c - Get a file version on an ext2 file system + * + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr> + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * History: + * 93/10/30 - Creation + */ + +#include "config.h" +#if HAVE_ERRNO_H +#include <errno.h> +#endif +#if HAVE_SYS_IOCTL_H +#include <sys/ioctl.h> +#endif + +#include "e2p.h" + +int getversion (int fd, unsigned long * version) +{ +#if HAVE_EXT2_IOCTLS + int r, ver; + + r = ioctl (fd, EXT2_IOC_GETVERSION, &ver); + *version = ver; + return r; +#else /* ! HAVE_EXT2_IOCTLS */ + errno = EOPNOTSUPP; + return -1; +#endif /* ! HAVE_EXT2_IOCTLS */ +} diff --git a/lib/e2p/hashstr.c b/lib/e2p/hashstr.c new file mode 100644 index 0000000..a73758c --- /dev/null +++ b/lib/e2p/hashstr.c @@ -0,0 +1,72 @@ +/* + * feature.c --- convert between features and strings + * + * Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu> + * + * %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 <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> + +#include "e2p.h" + +struct hash { + int num; + const char *string; +}; + +static struct hash hash_list[] = { + { EXT2_HASH_LEGACY, "legacy" }, + { EXT2_HASH_HALF_MD4, "half_md4" }, + { EXT2_HASH_TEA, "tea" }, + { 0, 0 }, +}; + +const char *e2p_hash2string(int num) +{ + struct hash *p; + static char buf[20]; + + for (p = hash_list; p->string; p++) { + if (num == p->num) + return p->string; + } + sprintf(buf, "HASHALG_%d", num); + return buf; +} + +/* + * Returns the hash algorithm, or -1 on error + */ +int e2p_string2hash(char *string) +{ + struct hash *p; + char *eptr; + int num; + + for (p = hash_list; p->string; p++) { + if (!strcasecmp(string, p->string)) { + return p->num; + } + } + if (strncasecmp(string, "HASHALG_", 8)) + return -1; + + if (string[8] == 0) + return -1; + num = strtol(string+8, &eptr, 10); + if (num > 255 || num < 0) + return -1; + if (*eptr) + return -1; + return num; +} + diff --git a/lib/e2p/iod.c b/lib/e2p/iod.c new file mode 100644 index 0000000..6a030dd --- /dev/null +++ b/lib/e2p/iod.c @@ -0,0 +1,76 @@ +/* + * iod.c - Iterate a function on each entry of a directory + * + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr> + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * History: + * 93/10/30 - Creation + */ + +#include "config.h" +#include "e2p.h" +#if HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <stdlib.h> +#include <string.h> + +int iterate_on_dir (const char * dir_name, + int (*func) (const char *, struct dirent *, void *), + void * private) +{ + DIR * dir; + struct dirent *de, *dep; + int max_len = -1, len, ret = 0; + +#if HAVE_PATHCONF && defined(_PC_NAME_MAX) + max_len = pathconf(dir_name, _PC_NAME_MAX); +#endif + if (max_len == -1) { +#ifdef _POSIX_NAME_MAX + max_len = _POSIX_NAME_MAX; +#else +#ifdef NAME_MAX + max_len = NAME_MAX; +#else + max_len = 256; +#endif /* NAME_MAX */ +#endif /* _POSIX_NAME_MAX */ + } + max_len += sizeof(struct dirent); + + de = malloc(max_len+1); + if (!de) + return -1; + memset(de, 0, max_len+1); + + dir = opendir (dir_name); + if (dir == NULL) { + free(de); + return -1; + } + while ((dep = readdir (dir))) { +#ifdef HAVE_RECLEN_DIRENT + len = dep->d_reclen; + if (len > max_len) + len = max_len; +#else + len = sizeof(struct dirent); +#endif + memcpy(de, dep, len); + if ((*func)(dir_name, de, private)) + ret++; + } + free(de); + closedir(dir); + return ret; +} diff --git a/lib/e2p/ljs.c b/lib/e2p/ljs.c new file mode 100644 index 0000000..5972819 --- /dev/null +++ b/lib/e2p/ljs.c @@ -0,0 +1,134 @@ +/* + * ljs.c - List the contents of an journal superblock + * + * Copyright (C) 1995, 1996, 1997 Theodore Ts'o <tytso@mit.edu> + * + * %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 <stdlib.h> +#include <sys/types.h> +#include <string.h> +#include <grp.h> +#include <pwd.h> +#include <time.h> + +#include "ext2fs/ext2_fs.h" +#include "ext2fs/ext2fs.h" +#include "e2p.h" +#include "ext2fs/kernel-jbd.h" + +#ifdef WORDS_BIGENDIAN +#define e2p_be32(x) (x) +#else +static __u32 e2p_swab32(__u32 val) +{ + return ((val>>24) | ((val>>8)&0xFF00) | + ((val<<8)&0xFF0000) | (val<<24)); +} + +#define e2p_be32(x) e2p_swab32(x) +#endif + +/* + * This function is copied from kernel-jbd.h's function + * jbd2_journal_get_num_fc_blks() to avoid inter-library dependencies. + */ +static inline int get_num_fc_blks(journal_superblock_t *jsb) +{ + int num_fc_blocks = e2p_be32(jsb->s_num_fc_blks); + + return num_fc_blocks ? num_fc_blocks : JBD2_DEFAULT_FAST_COMMIT_BLOCKS; +} + +static const char *journal_checksum_type_str(__u8 type) +{ + switch (type) { + case JBD2_CRC32C_CHKSUM: + return "crc32c"; + default: + return "unknown"; + } +} + +void e2p_list_journal_super(FILE *f, char *journal_sb_buf, + int exp_block_size, int flags) +{ + journal_superblock_t *jsb = (journal_superblock_t *) journal_sb_buf; + __u32 *mask_ptr, mask, m; + unsigned int size; + int j, printed = 0; + unsigned int i, nr_users; + int num_fc_blks = 0; + int journal_blks = 0; + + if (flags & E2P_LIST_JOURNAL_FLAG_FC) + num_fc_blks = get_num_fc_blks((journal_superblock_t *)journal_sb_buf); + journal_blks = ntohl(jsb->s_maxlen) - num_fc_blks; + fprintf(f, "%s", "Journal features: "); + for (i=0, mask_ptr=&jsb->s_feature_compat; i <3; i++,mask_ptr++) { + mask = e2p_be32(*mask_ptr); + for (j=0,m=1; j < 32; j++, m<<=1) { + if (mask & m) { + fprintf(f, " %s", e2p_jrnl_feature2string(i, m)); + printed++; + } + } + } + if (printed == 0) + fprintf(f, " (none)"); + fputc('\n', f); + fputs("Total journal size: ", f); + size = (ntohl(jsb->s_blocksize) / 1024) * ntohl(jsb->s_maxlen); + if (size < 8192) + fprintf(f, "%uk\n", size); + else + fprintf(f, "%uM\n", size >> 10); + nr_users = (unsigned int) ntohl(jsb->s_nr_users); + if (exp_block_size != (int) ntohl(jsb->s_blocksize)) + fprintf(f, "Journal block size: %u\n", + (unsigned int)ntohl(jsb->s_blocksize)); + fprintf(f, "Total journal blocks: %u\n", + (unsigned int)(journal_blks + num_fc_blks)); + fprintf(f, "Max transaction length: %u\n", + (unsigned int)journal_blks); + fprintf(f, "Fast commit length: %u\n", + (unsigned int)num_fc_blks); + + if (ntohl(jsb->s_first) != 1) + fprintf(f, "Journal first block: %u\n", + (unsigned int)ntohl(jsb->s_first)); + fprintf(f, "Journal sequence: 0x%08x\n" + "Journal start: %u\n", + (unsigned int)ntohl(jsb->s_sequence), + (unsigned int)ntohl(jsb->s_start)); + if (nr_users != 1) + fprintf(f, "Journal number of users: %u\n", nr_users); + if (jsb->s_feature_compat & e2p_be32(JBD2_FEATURE_COMPAT_CHECKSUM)) + fprintf(f, "%s", "Journal checksum type: crc32\n"); + if ((jsb->s_feature_incompat & + e2p_be32(JBD2_FEATURE_INCOMPAT_CSUM_V3)) || + (jsb->s_feature_incompat & + e2p_be32(JBD2_FEATURE_INCOMPAT_CSUM_V2))) + fprintf(f, "Journal checksum type: %s\n" + "Journal checksum: 0x%08x\n", + journal_checksum_type_str(jsb->s_checksum_type), + e2p_be32(jsb->s_checksum)); + if ((nr_users > 1) || + !e2p_is_null_uuid(&jsb->s_users[0])) { + for (i=0; i < nr_users && i < JBD2_USERS_MAX; i++) { + printf(i ? " %s\n" + : "Journal users: %s\n", + e2p_uuid2str(&jsb->s_users[i * UUID_SIZE])); + } + } + if (jsb->s_errno != 0) + fprintf(f, "Journal errno: %d\n", + (int) ntohl(jsb->s_errno)); +} diff --git a/lib/e2p/ls.c b/lib/e2p/ls.c new file mode 100644 index 0000000..0b74aea --- /dev/null +++ b/lib/e2p/ls.c @@ -0,0 +1,494 @@ +/* + * ls.c - List the contents of an ext2fs superblock + * + * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr> + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * Copyright (C) 1995, 1996, 1997 Theodore Ts'o <tytso@mit.edu> + * + * %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 <stdlib.h> +#include <sys/types.h> +#include <string.h> +#include <grp.h> +#include <pwd.h> +#include <time.h> + +#include "e2p.h" +#include "support/quotaio.h" + +static void print_user (unsigned short uid, FILE *f) +{ + struct passwd *pw; + + fprintf(f, "%u ", uid); + pw = getpwuid (uid); + if (pw == NULL) + fprintf(f, "(user unknown)\n"); + else + fprintf(f, "(user %s)\n", pw->pw_name); +} + +static void print_group (unsigned short gid, FILE *f) +{ + struct group *gr; + + fprintf(f, "%u ", gid); + gr = getgrgid (gid); + if (gr == NULL) + fprintf(f, "(group unknown)\n"); + else + fprintf(f, "(group %s)\n", gr->gr_name); +} + +#define MONTH_INT (86400 * 30) +#define WEEK_INT (86400 * 7) +#define DAY_INT (86400) +#define HOUR_INT (60 * 60) +#define MINUTE_INT (60) + +static const char *interval_string(unsigned int secs) +{ + static char buf[256], tmp[80]; + int hr, min, num; + + buf[0] = 0; + + if (secs == 0) + return "<none>"; + + if (secs >= MONTH_INT) { + num = secs / MONTH_INT; + secs -= num*MONTH_INT; + sprintf(buf, "%d month%s", num, (num>1) ? "s" : ""); + } + if (secs >= WEEK_INT) { + num = secs / WEEK_INT; + secs -= num*WEEK_INT; + sprintf(tmp, "%s%d week%s", buf[0] ? ", " : "", + num, (num>1) ? "s" : ""); + strcat(buf, tmp); + } + if (secs >= DAY_INT) { + num = secs / DAY_INT; + secs -= num*DAY_INT; + sprintf(tmp, "%s%d day%s", buf[0] ? ", " : "", + num, (num>1) ? "s" : ""); + strcat(buf, tmp); + } + if (secs > 0) { + hr = secs / HOUR_INT; + secs -= hr*HOUR_INT; + min = secs / MINUTE_INT; + secs -= min*MINUTE_INT; + sprintf(tmp, "%s%d:%02d:%02d", buf[0] ? ", " : "", + hr, min, secs); + strcat(buf, tmp); + } + return buf; +} + +static void print_features(struct ext2_super_block * s, FILE *f) +{ +#ifdef EXT2_DYNAMIC_REV + int i, j, printed=0; + __u32 *mask = &s->s_feature_compat, m; + + fprintf(f, "Filesystem features: "); + for (i=0; i <3; i++,mask++) { + for (j=0,m=1; j < 32; j++, m<<=1) { + if (*mask & m) { + fprintf(f, " %s", e2p_feature2string(i, m)); + printed++; + } + } + } + if (printed == 0) + fprintf(f, " (none)"); + fprintf(f, "\n"); +#endif +} + +static void print_mntopts(struct ext2_super_block * s, FILE *f) +{ +#ifdef EXT2_DYNAMIC_REV + int i, printed=0; + __u32 mask = s->s_default_mount_opts, m; + + fprintf(f, "Default mount options: "); + if (mask & EXT3_DEFM_JMODE) { + fprintf(f, " %s", e2p_mntopt2string(mask & EXT3_DEFM_JMODE)); + printed++; + } + for (i=0,m=1; i < 32; i++, m<<=1) { + if (m & EXT3_DEFM_JMODE) + continue; + if (mask & m) { + fprintf(f, " %s", e2p_mntopt2string(m)); + printed++; + } + } + if (printed == 0) + fprintf(f, " (none)"); + fprintf(f, "\n"); +#endif +} + +static void print_super_flags(struct ext2_super_block * s, FILE *f) +{ + int flags_found = 0; + + if (s->s_flags == 0) + return; + + fputs("Filesystem flags: ", f); + if (s->s_flags & EXT2_FLAGS_SIGNED_HASH) { + fputs("signed_directory_hash ", f); + flags_found++; + } + if (s->s_flags & EXT2_FLAGS_UNSIGNED_HASH) { + fputs("unsigned_directory_hash ", f); + flags_found++; + } + if (s->s_flags & EXT2_FLAGS_TEST_FILESYS) { + fputs("test_filesystem ", f); + flags_found++; + } + if (flags_found) + fputs("\n", f); + else + fputs("(none)\n", f); +} + +static __u64 e2p_blocks_count(struct ext2_super_block *super) +{ + return super->s_blocks_count | + (ext2fs_has_feature_64bit(super) ? + (__u64) super->s_blocks_count_hi << 32 : 0); +} + +static __u64 e2p_r_blocks_count(struct ext2_super_block *super) +{ + return super->s_r_blocks_count | + (ext2fs_has_feature_64bit(super) ? + (__u64) super->s_r_blocks_count_hi << 32 : 0); +} + +static __u64 e2p_free_blocks_count(struct ext2_super_block *super) +{ + return super->s_free_blocks_count | + (ext2fs_has_feature_64bit(super) ? + (__u64) super->s_free_blocks_hi << 32 : 0); +} + +#ifndef EXT2_INODE_SIZE +#define EXT2_INODE_SIZE(s) sizeof(struct ext2_inode) +#endif + +#ifndef EXT2_GOOD_OLD_REV +#define EXT2_GOOD_OLD_REV 0 +#endif + +static const char *checksum_type(__u8 type) +{ + switch (type) { + case EXT2_CRC32C_CHKSUM: + return "crc32c"; + default: + return "unknown"; + } +} + +static const char *quota_prefix[MAXQUOTAS] = { + [USRQUOTA] = "User quota inode:", + [GRPQUOTA] = "Group quota inode:", + [PRJQUOTA] = "Project quota inode:", +}; + +/** + * Convert type of quota to written representation + */ +static const char *quota_type2prefix(enum quota_type qtype) +{ + return quota_prefix[qtype]; +} + +void list_super2(struct ext2_super_block * sb, FILE *f) +{ + int inode_blocks_per_group; + char *str; + time_t tm; + enum quota_type qtype; + + inode_blocks_per_group = (((sb->s_inodes_per_group * + EXT2_INODE_SIZE(sb)) + + EXT2_BLOCK_SIZE(sb) - 1) / + EXT2_BLOCK_SIZE(sb)); + if (sb->s_volume_name[0]) + fprintf(f, "Filesystem volume name: %.*s\n", + EXT2_LEN_STR(sb->s_volume_name)); + else + fprintf(f, "Filesystem volume name: <none>\n"); + if (sb->s_last_mounted[0]) + fprintf(f, "Last mounted on: %.*s\n", + EXT2_LEN_STR(sb->s_last_mounted)); + else + fprintf(f, "Last mounted on: <not available>\n"); + fprintf(f, "Filesystem UUID: %s\n", e2p_uuid2str(sb->s_uuid)); + fprintf(f, "Filesystem magic number: 0x%04X\n", sb->s_magic); + fprintf(f, "Filesystem revision #: %d", sb->s_rev_level); + if (sb->s_rev_level == EXT2_GOOD_OLD_REV) { + fprintf(f, " (original)\n"); +#ifdef EXT2_DYNAMIC_REV + } else if (sb->s_rev_level == EXT2_DYNAMIC_REV) { + fprintf(f, " (dynamic)\n"); +#endif + } else + fprintf(f, " (unknown)\n"); + print_features(sb, f); + print_super_flags(sb, f); + print_mntopts(sb, f); + if (sb->s_mount_opts[0]) + fprintf(f, "Mount options: %.*s\n", + EXT2_LEN_STR(sb->s_mount_opts)); + fprintf(f, "Filesystem state: "); + print_fs_state (f, sb->s_state); + fprintf(f, "\n"); + fprintf(f, "Errors behavior: "); + print_fs_errors(f, sb->s_errors); + fprintf(f, "\n"); + str = e2p_os2string(sb->s_creator_os); + fprintf(f, "Filesystem OS type: %s\n", str); + free(str); + fprintf(f, "Inode count: %u\n", sb->s_inodes_count); + fprintf(f, "Block count: %llu\n", + (unsigned long long) e2p_blocks_count(sb)); + fprintf(f, "Reserved block count: %llu\n", + (unsigned long long) e2p_r_blocks_count(sb)); + if (sb->s_overhead_clusters) + fprintf(f, "Overhead clusters: %u\n", + sb->s_overhead_clusters); + fprintf(f, "Free blocks: %llu\n", + (unsigned long long) e2p_free_blocks_count(sb)); + fprintf(f, "Free inodes: %u\n", sb->s_free_inodes_count); + fprintf(f, "First block: %u\n", sb->s_first_data_block); + fprintf(f, "Block size: %u\n", EXT2_BLOCK_SIZE(sb)); + if (ext2fs_has_feature_bigalloc(sb)) + fprintf(f, "Cluster size: %u\n", + EXT2_CLUSTER_SIZE(sb)); + else + fprintf(f, "Fragment size: %u\n", + EXT2_CLUSTER_SIZE(sb)); + if (ext2fs_has_feature_64bit(sb)) + fprintf(f, "Group descriptor size: %u\n", sb->s_desc_size); + if (sb->s_reserved_gdt_blocks) + fprintf(f, "Reserved GDT blocks: %u\n", + sb->s_reserved_gdt_blocks); + fprintf(f, "Blocks per group: %u\n", sb->s_blocks_per_group); + if (ext2fs_has_feature_bigalloc(sb)) + fprintf(f, "Clusters per group: %u\n", + sb->s_clusters_per_group); + else + fprintf(f, "Fragments per group: %u\n", + sb->s_clusters_per_group); + fprintf(f, "Inodes per group: %u\n", sb->s_inodes_per_group); + fprintf(f, "Inode blocks per group: %u\n", inode_blocks_per_group); + if (sb->s_raid_stride) + fprintf(f, "RAID stride: %u\n", + sb->s_raid_stride); + if (sb->s_raid_stripe_width) + fprintf(f, "RAID stripe width: %u\n", + sb->s_raid_stripe_width); + if (sb->s_first_meta_bg) + fprintf(f, "First meta block group: %u\n", + sb->s_first_meta_bg); + if (sb->s_log_groups_per_flex) + fprintf(f, "Flex block group size: %u\n", + 1U << sb->s_log_groups_per_flex); + if (sb->s_mkfs_time) { + tm = sb->s_mkfs_time; + fprintf(f, "Filesystem created: %s", ctime(&tm)); + } + tm = sb->s_mtime; + fprintf(f, "Last mount time: %s", + sb->s_mtime ? ctime(&tm) : "n/a\n"); + tm = sb->s_wtime; + fprintf(f, "Last write time: %s", ctime(&tm)); + fprintf(f, "Mount count: %u\n", sb->s_mnt_count); + fprintf(f, "Maximum mount count: %d\n", sb->s_max_mnt_count); + tm = sb->s_lastcheck; + fprintf(f, "Last checked: %s", ctime(&tm)); + fprintf(f, "Check interval: %u (%s)\n", sb->s_checkinterval, + interval_string(sb->s_checkinterval)); + if (sb->s_checkinterval) + { + time_t next; + + next = sb->s_lastcheck + sb->s_checkinterval; + fprintf(f, "Next check after: %s", ctime(&next)); + } +#define POW2(x) ((__u64) 1 << (x)) + if (sb->s_kbytes_written) { + fprintf(f, "Lifetime writes: "); + if (sb->s_kbytes_written < POW2(13)) + fprintf(f, "%llu kB\n", + (unsigned long long) sb->s_kbytes_written); + else if (sb->s_kbytes_written < POW2(23)) + fprintf(f, "%llu MB\n", (unsigned long long) + (sb->s_kbytes_written + POW2(9)) >> 10); + else if (sb->s_kbytes_written < POW2(33)) + fprintf(f, "%llu GB\n", (unsigned long long) + (sb->s_kbytes_written + POW2(19)) >> 20); + else if (sb->s_kbytes_written < POW2(43)) + fprintf(f, "%llu TB\n", (unsigned long long) + (sb->s_kbytes_written + POW2(29)) >> 30); + else + fprintf(f, "%llu PB\n", (unsigned long long) + (sb->s_kbytes_written + POW2(39)) >> 40); + } + fprintf(f, "Reserved blocks uid: "); + print_user(sb->s_def_resuid, f); + fprintf(f, "Reserved blocks gid: "); + print_group(sb->s_def_resgid, f); + if (sb->s_rev_level >= EXT2_DYNAMIC_REV) { + fprintf(f, "First inode: %d\n", sb->s_first_ino); + fprintf(f, "Inode size: %d\n", sb->s_inode_size); + if (sb->s_min_extra_isize) + fprintf(f, "Required extra isize: %d\n", + sb->s_min_extra_isize); + if (sb->s_want_extra_isize) + fprintf(f, "Desired extra isize: %d\n", + sb->s_want_extra_isize); + } + if (!e2p_is_null_uuid(sb->s_journal_uuid)) + fprintf(f, "Journal UUID: %s\n", + e2p_uuid2str(sb->s_journal_uuid)); + if (sb->s_journal_inum) + fprintf(f, "Journal inode: %u\n", + sb->s_journal_inum); + if (sb->s_journal_dev) + fprintf(f, "Journal device: 0x%04x\n", + sb->s_journal_dev); + if (sb->s_last_orphan) + fprintf(f, "First orphan inode: %u\n", + sb->s_last_orphan); + if (ext2fs_has_feature_dir_index(sb) || + sb->s_def_hash_version) + fprintf(f, "Default directory hash: %s\n", + e2p_hash2string(sb->s_def_hash_version)); + if (!e2p_is_null_uuid(sb->s_hash_seed)) + fprintf(f, "Directory Hash Seed: %s\n", + e2p_uuid2str(sb->s_hash_seed)); + if (sb->s_jnl_backup_type) { + fprintf(f, "Journal backup: "); + switch (sb->s_jnl_backup_type) { + case 1: + fprintf(f, "inode blocks\n"); + break; + default: + fprintf(f, "type %u\n", sb->s_jnl_backup_type); + } + } + if (sb->s_backup_bgs[0] || sb->s_backup_bgs[1]) { + fprintf(f, "Backup block groups: "); + if (sb->s_backup_bgs[0]) + fprintf(f, "%u ", sb->s_backup_bgs[0]); + if (sb->s_backup_bgs[1]) + fprintf(f, "%u ", sb->s_backup_bgs[1]); + fputc('\n', f); + } + if (sb->s_snapshot_inum) { + fprintf(f, "Snapshot inode: %u\n", + sb->s_snapshot_inum); + fprintf(f, "Snapshot ID: %u\n", + sb->s_snapshot_id); + fprintf(f, "Snapshot reserved blocks: %llu\n", + (unsigned long long) sb->s_snapshot_r_blocks_count); + } + if (sb->s_snapshot_list) + fprintf(f, "Snapshot list head: %u\n", + sb->s_snapshot_list); + if (sb->s_error_count) + fprintf(f, "FS Error count: %u\n", + sb->s_error_count); + if (sb->s_first_error_time) { + tm = sb->s_first_error_time; + fprintf(f, "First error time: %s", ctime(&tm)); + fprintf(f, "First error function: %.*s\n", + EXT2_LEN_STR(sb->s_first_error_func)); + fprintf(f, "First error line #: %u\n", + sb->s_first_error_line); + if (sb->s_first_error_ino) + fprintf(f, "First error inode #: %u\n", + sb->s_first_error_ino); + if (sb->s_first_error_block) + fprintf(f, "First error block #: %llu\n", + (unsigned long long) sb->s_first_error_block); + if (sb->s_first_error_errcode) + fprintf(f, "First error err: %s\n", + e2p_errcode2str(sb->s_first_error_errcode)); + } + if (sb->s_last_error_time) { + tm = sb->s_last_error_time; + fprintf(f, "Last error time: %s", ctime(&tm)); + fprintf(f, "Last error function: %.*s\n", + EXT2_LEN_STR(sb->s_last_error_func)); + fprintf(f, "Last error line #: %u\n", + sb->s_last_error_line); + if (sb->s_last_error_ino) + fprintf(f, "Last error inode #: %u\n", + sb->s_last_error_ino); + if (sb->s_last_error_block) + fprintf(f, "Last error block #: %llu\n", + (unsigned long long) sb->s_last_error_block); + if (sb->s_last_error_errcode) + fprintf(f, "Last error err: %s\n", + e2p_errcode2str(sb->s_last_error_errcode)); + } + if (ext2fs_has_feature_mmp(sb)) { + fprintf(f, "MMP block number: %llu\n", + (unsigned long long) sb->s_mmp_block); + fprintf(f, "MMP update interval: %u\n", + sb->s_mmp_update_interval); + } + for (qtype = 0; qtype < MAXQUOTAS; qtype++) { + if (*quota_sb_inump(sb, qtype) != 0) + fprintf(f, "%-26s%u\n", + quota_type2prefix(qtype), + *quota_sb_inump(sb, qtype)); + } + + if (ext2fs_has_feature_metadata_csum(sb)) { + fprintf(f, "Checksum type: %s\n", + checksum_type(sb->s_checksum_type)); + fprintf(f, "Checksum: 0x%08x\n", + sb->s_checksum); + } + if (!e2p_is_null_uuid(sb->s_encrypt_pw_salt)) + fprintf(f, "Encryption PW Salt: %s\n", + e2p_uuid2str(sb->s_encrypt_pw_salt)); + + if (ext2fs_has_feature_csum_seed(sb)) + fprintf(f, "Checksum seed: 0x%08x\n", + sb->s_checksum_seed); + if (ext2fs_has_feature_casefold(sb)) + fprintf(f, "Character encoding: %s\n", + e2p_encoding2str(sb->s_encoding)); + if (ext2fs_has_feature_orphan_file(sb)) + fprintf(f, "Orphan file inode: %u\n", + sb->s_orphan_file_inum); +} + +void list_super (struct ext2_super_block * s) +{ + list_super2(s, stdout); +} + diff --git a/lib/e2p/mntopts.c b/lib/e2p/mntopts.c new file mode 100644 index 0000000..7d0ae9c --- /dev/null +++ b/lib/e2p/mntopts.c @@ -0,0 +1,150 @@ +/* + * mountopts.c --- convert between default mount options and strings + * + * Copyright (C) 2002 Theodore Ts'o <tytso@mit.edu> + * + * %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 <stdlib.h> +#include <string.h> +#include <strings.h> +#include <ctype.h> +#include <errno.h> + +#include "e2p.h" + +struct mntopt { + unsigned int mask; + const char *string; +}; + +static struct mntopt mntopt_list[] = { + { EXT2_DEFM_DEBUG, "debug" }, + { EXT2_DEFM_BSDGROUPS, "bsdgroups" }, + { EXT2_DEFM_XATTR_USER, "user_xattr" }, + { EXT2_DEFM_ACL, "acl" }, + { EXT2_DEFM_UID16, "uid16" }, + { EXT3_DEFM_JMODE_DATA, "journal_data" }, + { EXT3_DEFM_JMODE_ORDERED, "journal_data_ordered" }, + { EXT3_DEFM_JMODE_WBACK, "journal_data_writeback" }, + { EXT4_DEFM_NOBARRIER, "nobarrier" }, + { EXT4_DEFM_BLOCK_VALIDITY, "block_validity" }, + { EXT4_DEFM_DISCARD, "discard"}, + { EXT4_DEFM_NODELALLOC, "nodelalloc"}, + { 0, 0 }, +}; + +const char *e2p_mntopt2string(unsigned int mask) +{ + struct mntopt *f; + static char buf[20]; + int fnum; + + for (f = mntopt_list; f->string; f++) { + if (mask == f->mask) + return f->string; + } + for (fnum = 0; mask >>= 1; fnum++); + sprintf(buf, "MNTOPT_%d", fnum); + return buf; +} + +int e2p_string2mntopt(char *string, unsigned int *mask) +{ + struct mntopt *f; + char *eptr; + int num; + + for (f = mntopt_list; f->string; f++) { + if (!strcasecmp(string, f->string)) { + *mask = f->mask; + return 0; + } + } + if (strncasecmp(string, "MNTOPT_", 7)) + return 1; + + if (string[8] == 0) + return 1; + num = strtol(string+8, &eptr, 10); + if (num > 31 || num < 0) + return 1; + if (*eptr) + return 1; + *mask = 1 << num; + return 0; +} + +static char *skip_over_blanks(char *cp) +{ + while (*cp && isspace(*cp)) + cp++; + return cp; +} + +static char *skip_over_word(char *cp) +{ + while (*cp && !isspace(*cp) && *cp != ',') + cp++; + return cp; +} + +/* + * Edit a mntopt set array as requested by the user. The ok + * parameter, if non-zero, allows the application to limit what + * mntopts the user is allowed to set or clear using this function. + */ +int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok) +{ + char *cp, *buf, *next; + int neg; + unsigned int mask; + int rc = 0; + + buf = malloc(strlen(str)+1); + if (!buf) + return 1; + strcpy(buf, str); + cp = buf; + while (cp && *cp) { + neg = 0; + cp = skip_over_blanks(cp); + next = skip_over_word(cp); + if (*next == 0) + next = 0; + else + *next = 0; + switch (*cp) { + case '-': + case '^': + neg++; + /* fallthrough */ + case '+': + cp++; + break; + } + if (e2p_string2mntopt(cp, &mask)) { + rc = 1; + break; + } + if (ok && !(ok & mask)) { + rc = 1; + break; + } + if (mask & EXT3_DEFM_JMODE) + *mntopts &= ~EXT3_DEFM_JMODE; + if (neg) + *mntopts &= ~mask; + else + *mntopts |= mask; + cp = next ? next+1 : 0; + } + free(buf); + return rc; +} diff --git a/lib/e2p/ostype.c b/lib/e2p/ostype.c new file mode 100644 index 0000000..c5fd8ab --- /dev/null +++ b/lib/e2p/ostype.c @@ -0,0 +1,79 @@ +/* + * getostype.c - Get the Filesystem OS type + * + * Copyright (C) 2004,2005 Theodore Ts'o <tytso@mit.edu> + * + * %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 "e2p.h" +#include <string.h> +#include <stdlib.h> + +static const char *os_tab[] = + { "Linux", + "Hurd", + "Masix", + "FreeBSD", + "Lites", + 0 }; + +/* + * Convert an os_type to a string + */ +char *e2p_os2string(int os_type) +{ + const char *os; + char *ret; + + if (os_type >= 0 && os_type <= EXT2_OS_LITES) + os = os_tab[os_type]; + else + os = "(unknown os)"; + + ret = malloc(strlen(os)+1); + if (ret) + strcpy(ret, os); + return ret; +} + +/* + * Convert an os_type to a string + */ +int e2p_string2os(char *str) +{ + const char **cpp; + int i = 0; + + for (cpp = os_tab; *cpp; cpp++, i++) { + if (!strcasecmp(str, *cpp)) + return i; + } + return -1; +} + +#ifdef TEST_PROGRAM +int main(int argc, char **argv) +{ + char *s; + int i, os; + + for (i=0; i <= EXT2_OS_LITES; i++) { + s = e2p_os2string(i); + os = e2p_string2os(s); + printf("%d: %s (%d)\n", i, s, os); + free(s); + if (i != os) { + fprintf(stderr, "Failure!\n"); + exit(1); + } + } + exit(0); +} +#endif + + diff --git a/lib/e2p/parse_num.c b/lib/e2p/parse_num.c new file mode 100644 index 0000000..e8d6283 --- /dev/null +++ b/lib/e2p/parse_num.c @@ -0,0 +1,91 @@ +/* + * parse_num.c - Parse the number of blocks + * + * Copyright (C) 2004,2005 Theodore Ts'o <tytso@mit.edu> + * + * %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 "e2p.h" + +#include <stdlib.h> + +unsigned long long parse_num_blocks2(const char *arg, int log_block_size) +{ + char *p; + unsigned long long num; + + num = strtoull(arg, &p, 0); + + if (p[0] && p[1]) + return 0; + + switch (*p) { /* Using fall-through logic */ + case 'T': case 't': + num <<= 10; + /* fallthrough */ + case 'G': case 'g': + num <<= 10; + /* fallthrough */ + case 'M': case 'm': + num <<= 10; + /* fallthrough */ + case 'K': case 'k': + if (log_block_size < 0) + num <<= 10; + else + num >>= log_block_size; + break; + case 's': + if (log_block_size < 0) + num <<= 9; + else + num >>= (1+log_block_size); + break; + case '\0': + break; + default: + return 0; + } + return num; +} + +unsigned long parse_num_blocks(const char *arg, int log_block_size) +{ + return parse_num_blocks2(arg, log_block_size); +} + +#ifdef DEBUG +#include <unistd.h> +#include <stdio.h> + +main(int argc, char **argv) +{ + unsigned long num; + int log_block_size = 0; + + if (argc != 2 && argc != 3) { + fprintf(stderr, "Usage: %s arg [log_block_size]\n", argv[0]); + exit(1); + } + + if (argc == 3) { + char *p; + + log_block_size = strtol(argv[2], &p, 0); + if (*p) { + fprintf(stderr, "Bad log_block_size: %s\n", argv[2]); + exit(1); + } + } + + num = parse_num_blocks(argv[1], log_block_size); + + printf("Parsed number: %lu\n", num); + exit(0); +} +#endif diff --git a/lib/e2p/pe.c b/lib/e2p/pe.c new file mode 100644 index 0000000..1f24545 --- /dev/null +++ b/lib/e2p/pe.c @@ -0,0 +1,40 @@ +/* + * pe.c - Print a second extended filesystem errors behavior + * + * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr> + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * History: + * 94/01/09 - Creation + */ + +#include "config.h" +#include <stdio.h> + +#include "e2p.h" + +void print_fs_errors (FILE * f, unsigned short errors) +{ + switch (errors) + { + case EXT2_ERRORS_CONTINUE: + fprintf (f, "Continue"); + break; + case EXT2_ERRORS_RO: + fprintf (f, "Remount read-only"); + break; + case EXT2_ERRORS_PANIC: + fprintf (f, "Panic"); + break; + default: + fprintf (f, "Unknown (continue)"); + } +} diff --git a/lib/e2p/percent.c b/lib/e2p/percent.c new file mode 100644 index 0000000..e340cd7 --- /dev/null +++ b/lib/e2p/percent.c @@ -0,0 +1,67 @@ +/* + * percent.c - Take percentage of a number + * + * Copyright (C) 2006 Theodore Ts'o <tytso@mit.edu> + * + * %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 "e2p.h" + +#include <stdlib.h> + +/* + * We work really hard to calculate this accurately, while avoiding + * an overflow. "Is there a hyphen in anal-retentive?" :-) + */ +unsigned int e2p_percent(int percent, unsigned int base) +{ + unsigned int mask = ~((1 << (sizeof(unsigned int) - 1) * 8) - 1); + + if (!percent) + return 0; + if (100 % percent == 0) + return base / (100 / percent); + if (mask & base) + return (base / 100) * percent; + return base * percent / 100; +} + +#ifdef DEBUG +#include <unistd.h> +#include <stdio.h> + +main(int argc, char **argv) +{ + unsigned int base; + int percent; + char *p; + int log_block_size = 0; + + if (argc != 3) { + fprintf(stderr, "Usage: %s percent base\n", argv[0]); + exit(1); + } + + percent = strtoul(argv[1], &p, 0); + if (p[0] && p[1]) { + fprintf(stderr, "Bad percent: %s\n", argv[1]); + exit(1); + } + + base = strtoul(argv[2], &p, 0); + if (p[0] && p[1]) { + fprintf(stderr, "Bad base: %s\n", argv[2]); + exit(1); + } + + printf("%d percent of %u is %u.\n", percent, base, + e2p_percent(percent, base)); + + exit(0); +} +#endif diff --git a/lib/e2p/pf.c b/lib/e2p/pf.c new file mode 100644 index 0000000..81e3bb2 --- /dev/null +++ b/lib/e2p/pf.c @@ -0,0 +1,79 @@ +/* + * pf.c - Print file attributes on an ext2 file system + * + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr> + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * History: + * 93/10/30 - Creation + */ + +#include "config.h" +#include <stdio.h> + +#include "e2p.h" + +struct flags_name { + unsigned long flag; + const char *short_name; + const char *long_name; +}; + +static struct flags_name flags_array[] = { + { EXT2_SECRM_FL, "s", "Secure_Deletion" }, + { EXT2_UNRM_FL, "u" , "Undelete" }, + { EXT2_SYNC_FL, "S", "Synchronous_Updates" }, + { EXT2_DIRSYNC_FL, "D", "Synchronous_Directory_Updates" }, + { EXT2_IMMUTABLE_FL, "i", "Immutable" }, + { EXT2_APPEND_FL, "a", "Append_Only" }, + { EXT2_NODUMP_FL, "d", "No_Dump" }, + { EXT2_NOATIME_FL, "A", "No_Atime" }, + { EXT2_COMPR_FL, "c", "Compression_Requested" }, + { EXT4_ENCRYPT_FL, "E", "Encrypted" }, + { EXT3_JOURNAL_DATA_FL, "j", "Journaled_Data" }, + { EXT2_INDEX_FL, "I", "Indexed_directory" }, + { EXT2_NOTAIL_FL, "t", "No_Tailmerging" }, + { EXT2_TOPDIR_FL, "T", "Top_of_Directory_Hierarchies" }, + { EXT4_EXTENTS_FL, "e", "Extents" }, + { FS_NOCOW_FL, "C", "No_COW" }, + { FS_DAX_FL, "x", "DAX" }, + { EXT4_CASEFOLD_FL, "F", "Casefold" }, + { EXT4_INLINE_DATA_FL, "N", "Inline_Data" }, + { EXT4_PROJINHERIT_FL, "P", "Project_Hierarchy" }, + { EXT4_VERITY_FL, "V", "Verity" }, + { EXT2_NOCOMPR_FL, "m", "Dont_Compress" }, + { 0, NULL, NULL } +}; + +void print_flags (FILE * f, unsigned long flags, unsigned options) +{ + int long_opt = (options & PFOPT_LONG); + struct flags_name *fp; + int first = 1; + + for (fp = flags_array; fp->flag != 0; fp++) { + if (flags & fp->flag) { + if (long_opt) { + if (first) + first = 0; + else + fputs(", ", f); + fputs(fp->long_name, f); + } else + fputs(fp->short_name, f); + } else { + if (!long_opt) + fputs("-", f); + } + } + if (long_opt && first) + fputs("---", f); +} diff --git a/lib/e2p/project.h b/lib/e2p/project.h new file mode 100644 index 0000000..253425a --- /dev/null +++ b/lib/e2p/project.h @@ -0,0 +1,27 @@ +/* + * project.h + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +#include <ext2fs/ext2_fs.h> + +#if defined(__linux__) && !defined(FS_IOC_FSGETXATTR) +#define FS_IOC_FSGETXATTR _IOR('X', 31, struct fsxattr) +#define FS_IOC_FSSETXATTR _IOW('X', 32, struct fsxattr) + +/* + * Structure for FS_IOC_FSGETXATTR and FS_IOC_FSSETXATTR. + */ +struct fsxattr { + __u32 fsx_xflags; /* xflags field value (get/set) */ + __u32 fsx_extsize; /* extsize field value (get/set)*/ + __u32 fsx_nextents; /* nextents field value (get) */ + __u32 fsx_projid; /* project identifier (get/set) */ + unsigned char fsx_pad[12]; +}; +#endif + diff --git a/lib/e2p/ps.c b/lib/e2p/ps.c new file mode 100644 index 0000000..757f8a6 --- /dev/null +++ b/lib/e2p/ps.c @@ -0,0 +1,32 @@ +/* + * ps.c - Print filesystem state + * + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr> + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * History: + * 93/12/22 - Creation + */ + +#include "config.h" +#include <stdio.h> + +#include "e2p.h" + +void print_fs_state (FILE * f, unsigned short state) +{ + if (state & EXT2_VALID_FS) + fprintf (f, " clean"); + else + fprintf (f, " not clean"); + if (state & EXT2_ERROR_FS) + fprintf (f, " with errors"); +} diff --git a/lib/e2p/setflags.c b/lib/e2p/setflags.c new file mode 100644 index 0000000..0f6a3e0 --- /dev/null +++ b/lib/e2p/setflags.c @@ -0,0 +1,77 @@ +/* + * setflags.c - Set a file flags on an ext2 file system + * + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr> + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * History: + * 93/10/30 - Creation + */ + +#include "config.h" +#if HAVE_ERRNO_H +#include <errno.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#if HAVE_EXT2_IOCTLS +#include <sys/ioctl.h> +#endif + +#include "e2p.h" + +/* + * Deal with lame glibc's that define this function without actually + * implementing it. Can you say "attractive nuisance", boys and girls? + * I knew you could! + */ +#ifdef __linux__ +#undef HAVE_CHFLAGS +#endif + +int setflags (int fd, unsigned long flags) +{ +#if HAVE_CHFLAGS + unsigned long bsd_flags = 0; + +#ifdef UF_IMMUTABLE + if (flags & EXT2_IMMUTABLE_FL) + bsd_flags |= UF_IMMUTABLE; +#endif +#ifdef UF_APPEND + if (flags & EXT2_APPEND_FL) + bsd_flags |= UF_APPEND; +#endif +#ifdef UF_NODUMP + if (flags & EXT2_NODUMP_FL) + bsd_flags |= UF_NODUMP; +#endif + + return fchflags (fd, bsd_flags); +#else /* ! HAVE_CHFLAGS */ +#if HAVE_EXT2_IOCTLS + struct stat buf; + int f; + + if (!fstat(fd, &buf) && + !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) { + errno = EOPNOTSUPP; + return -1; + } + f = (int) flags; + + return ioctl(fd, EXT2_IOC_SETFLAGS, &f); +#else + errno = EOPNOTSUPP; + return -1; +#endif /* HAVE_EXT2_IOCTLS */ +#endif /* HAVE_CHFLAGS */ +} diff --git a/lib/e2p/setversion.c b/lib/e2p/setversion.c new file mode 100644 index 0000000..dd4a3f0 --- /dev/null +++ b/lib/e2p/setversion.c @@ -0,0 +1,40 @@ +/* + * setversion.c - Set a file version on an ext2 file system + * + * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr> + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Library + * General Public License, version 2. + * %End-Header% + */ + +/* + * History: + * 93/10/30 - Creation + */ + +#include "config.h" +#if HAVE_ERRNO_H +#include <errno.h> +#endif +#if HAVE_SYS_IOCTL_H +#include <sys/ioctl.h> +#endif + +#include "e2p.h" + +int setversion (int fd, unsigned long version) +{ +#if HAVE_EXT2_IOCTLS + int ver; + + ver = (int) version; + return ioctl (fd, EXT2_IOC_SETVERSION, &ver); +#else /* ! HAVE_EXT2_IOCTLS */ + errno = EOPNOTSUPP; + return -1; +#endif /* ! HAVE_EXT2_IOCTLS */ +} diff --git a/lib/e2p/uuid.c b/lib/e2p/uuid.c new file mode 100644 index 0000000..a102092 --- /dev/null +++ b/lib/e2p/uuid.c @@ -0,0 +1,85 @@ +/* + * uuid.c -- utility routines for manipulating UUID's. + * + * %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 <string.h> +#include <ext2fs/ext2_types.h> + +#include "e2p.h" + +struct uuid { + __u32 time_low; + __u16 time_mid; + __u16 time_hi_and_version; + __u16 clock_seq; + __u8 node[6]; +}; + +/* Returns 1 if the uuid is the NULL uuid */ +int e2p_is_null_uuid(void *uu) +{ + __u8 *cp; + int i; + + for (i=0, cp = uu; i < 16; i++) + if (*cp++) + return 0; + return 1; +} + +static void e2p_unpack_uuid(void *in, struct uuid *uu) +{ + __u8 *ptr = in; + __u32 tmp; + + tmp = *ptr++; + tmp = (tmp << 8) | *ptr++; + tmp = (tmp << 8) | *ptr++; + tmp = (tmp << 8) | *ptr++; + uu->time_low = tmp; + + tmp = *ptr++; + tmp = (tmp << 8) | *ptr++; + uu->time_mid = tmp; + + tmp = *ptr++; + tmp = (tmp << 8) | *ptr++; + uu->time_hi_and_version = tmp; + + tmp = *ptr++; + tmp = (tmp << 8) | *ptr++; + uu->clock_seq = tmp; + + memcpy(uu->node, ptr, 6); +} + +void e2p_uuid_to_str(void *uu, char *out) +{ + struct uuid uuid; + + e2p_unpack_uuid(uu, &uuid); + sprintf(out, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + uuid.time_low, uuid.time_mid, uuid.time_hi_and_version, + uuid.clock_seq >> 8, uuid.clock_seq & 0xFF, + uuid.node[0], uuid.node[1], uuid.node[2], + uuid.node[3], uuid.node[4], uuid.node[5]); +} + +const char *e2p_uuid2str(void *uu) +{ + static char buf[80]; + + if (e2p_is_null_uuid(uu)) + return "<none>"; + e2p_uuid_to_str(uu, buf); + return buf; +} + |