Whamcloud - gitweb
libext2fs: add a regression test for in-inode xattrs
authorAndreas Dilger <andreas.dilger@intel.com>
Fri, 13 Apr 2012 08:01:12 +0000 (02:01 -0600)
committerLi Dongyang <dongyangli@ddn.com>
Wed, 29 May 2019 04:46:39 +0000 (14:46 +1000)
Signed-off-by: Andreas Dilger <andreas.dilger@intel.com>
configure
configure.ac
lib/ext2fs/Makefile.in
lib/ext2fs/tst_read_ea.c [new file with mode: 0644]

index 8d7acd1..33b1e03 100755 (executable)
--- a/configure
+++ b/configure
@@ -12447,7 +12447,7 @@ fi
 done
 
 fi
-for ac_header in       dirent.h        errno.h         execinfo.h      getopt.h        malloc.h        mntent.h        paths.h         semaphore.h     setjmp.h        signal.h        stdarg.h        stdint.h        stdlib.h        termios.h       termio.h        unistd.h        utime.h         attr/xattr.h    linux/falloc.h  linux/fd.h      linux/fsmap.h   linux/major.h   linux/loop.h    linux/types.h   net/if_dl.h     netinet/in.h    sys/acl.h       sys/disklabel.h         sys/disk.h      sys/file.h      sys/ioctl.h     sys/key.h       sys/mkdev.h     sys/mman.h      sys/mount.h     sys/prctl.h     sys/resource.h  sys/select.h    sys/socket.h    sys/sockio.h    sys/stat.h      sys/syscall.h   sys/sysctl.h    sys/sysmacros.h         sys/time.h      sys/types.h     sys/un.h        sys/wait.h      sys/xattr.h
+for ac_header in        attr/xattr.h   dirent.h        errno.h         execinfo.h      getopt.h        malloc.h        mntent.h        paths.h         semaphore.h     setjmp.h        signal.h        stdarg.h        stdint.h        stdlib.h        termios.h       termio.h        unistd.h        utime.h         attr/xattr.h    linux/falloc.h  linux/fd.h      linux/fsmap.h   linux/major.h   linux/loop.h    linux/types.h   net/if_dl.h     netinet/in.h    sys/acl.h       sys/disklabel.h         sys/disk.h      sys/file.h      sys/ioctl.h     sys/key.h       sys/mkdev.h     sys/mman.h      sys/mount.h     sys/prctl.h     sys/resource.h  sys/select.h    sys/socket.h    sys/sockio.h    sys/stat.h      sys/syscall.h   sys/sysctl.h    sys/sysmacros.h         sys/time.h      sys/types.h     sys/un.h        sys/wait.h      sys/xattr.h
 do :
   as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
 ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
index b392d32..728e8e7 100644 (file)
@@ -918,6 +918,7 @@ else
   AC_CHECK_PROGS(BUILD_CC, gcc cc)
 fi
 AC_CHECK_HEADERS(m4_flatten([
+       attr/xattr.h
        dirent.h
        errno.h
        execinfo.h
index 57724ef..6412d74 100644 (file)
@@ -215,6 +215,7 @@ SRCS= ext2_err.c \
        $(srcdir)/tst_byteswap.c \
        $(srcdir)/tst_getsize.c \
        $(srcdir)/tst_iscan.c \
+       $(srcdir)/tst_read_ea.c \
        $(srcdir)/undo_io.c \
        $(srcdir)/unix_io.c \
        $(srcdir)/sparse_io.c \
@@ -296,6 +297,11 @@ tst_iscan: tst_iscan.o $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBCOM_ERR)
        $(Q) $(CC) -o tst_iscan tst_iscan.o $(ALL_LDFLAGS) \
                $(STATIC_LIBEXT2FS) $(STATIC_LIBCOM_ERR) $(SYSLIBS)
 
+tst_read_ea: tst_read_ea.o $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBCOM_ERR)
+       $(E) "  LD $@"
+       $(Q) $(CC) -o tst_read_ea tst_read_ea.o $(STATIC_LIBEXT2FS) \
+               $(STATIC_LIBCOM_ERR)
+
 tst_getsize: tst_getsize.o $(STATIC_LIBEXT2FS) $(DEPSTATIC_LIBCOM_ERR)
        $(E) "  LD $@"
        $(Q) $(CC) -o tst_getsize tst_getsize.o $(ALL_LDFLAGS) \
@@ -527,7 +533,7 @@ mkjournal: mkjournal.c $(STATIC_LIBEXT2FS) $(DEPLIBCOM_ERR)
        $(Q) $(CC) -o mkjournal $(srcdir)/mkjournal.c -DDEBUG \
                $(STATIC_LIBEXT2FS) $(LIBCOM_ERR) $(ALL_CFLAGS) $(SYSLIBS)
 
-fullcheck check:: tst_bitops tst_badblocks tst_iscan tst_types tst_icount \
+fullcheck check:: tst_bitops tst_badblocks tst_iscan tst_types tst_icount tst_read_ea \
     tst_super_size tst_types tst_inode_size tst_csum tst_crc32c tst_bitmaps \
     tst_inline tst_inline_data tst_libext2fs tst_sha256 tst_sha512 \
     tst_digest_encode tst_getsize tst_getsectsize
@@ -536,6 +542,7 @@ fullcheck check:: tst_bitops tst_badblocks tst_iscan tst_types tst_icount \
        $(TESTENV) ./tst_iscan
        $(TESTENV) ./tst_types
        $(TESTENV) ./tst_icount
+       $(TESTENV) ./tst_read_ea
        $(TESTENV) ./tst_super_size
        $(TESTENV) ./tst_inode_size
        $(TESTENV) ./tst_csum
@@ -585,7 +592,7 @@ clean::
                tst_badblocks tst_iscan ext2_err.et ext2_err.c ext2_err.h \
                tst_byteswap tst_ismounted tst_getsize tst_getsectsize \
                tst_bitops tst_types tst_icount tst_super_size tst_csum \
-               tst_bitmaps tst_bitmaps_out tst_extents tst_inline \
+               tst_read_ea tst_bitmaps tst_bitmaps_out tst_extents tst_inline \
                tst_inline_data tst_inode_size tst_bitmaps_cmd.c \
                tst_digest_encode tst_sha256 tst_sha512 \
                ext2_tdbtool mkjournal debug_cmds.c tst_cmds.c extent_cmds.c \
@@ -1138,6 +1145,11 @@ tst_iscan.o: $(srcdir)/tst_iscan.c $(top_builddir)/lib/config.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)/hashmap.h $(srcdir)/bitops.h
+tst_read_ea.o: $(srcdir)/tst_read_ea.c $(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)/hashmap.h $(srcdir)/bitops.h
 undo_io.o: $(srcdir)/undo_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 \
diff --git a/lib/ext2fs/tst_read_ea.c b/lib/ext2fs/tst_read_ea.c
new file mode 100644 (file)
index 0000000..1722dd0
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * tst_read_ea.c --- this function tests the in-inode xattrs
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE    /* for asprintf */
+#endif
+#include <stdio.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#ifdef HAVE_ATTR_XATTR_H
+#include <attr/xattr.h>
+#elif HAVE_SYS_XATTR_H
+#include <sys/xattr.h>
+#else
+/* This is just a test program, let's try to work around the lack of header */
+extern ssize_t fgetxattr (int __filedes, const char *__name,
+                               void *__value, size_t __size);
+extern int fsetxattr (int __filedes, const char *__name,
+                     const void *__value, size_t __size, int __flags);
+#endif
+#if HAVE_MNTENT_H
+#include <mntent.h>
+#include <assert.h>
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#include "ext2_fs.h"
+#include "ext2fs.h"
+
+#define NR_XATTRS 256
+char tmpvalue[NR_XATTRS + 1];
+
+struct ea {
+       char *name;
+       char *value;
+};
+
+struct ea *ea_table;
+
+static void init_ea_table(void)
+{
+       int i;
+
+       ea_table = malloc(sizeof(struct ea) * NR_XATTRS);
+       if (ea_table == NULL) {
+               perror("maloc failed");
+               exit(1);
+       }
+       for (i = 0; i < NR_XATTRS; i ++) {
+               ea_table[i].name = malloc(i + 2 + strlen("user."));
+               if (ea_table[i].name == NULL) {
+                       perror("malloc failed");
+                       exit(1);
+               }
+               strcpy(ea_table[i].name, "user.");
+               memset(ea_table[i].name + strlen("user."), 'X', i + 1);
+               ea_table[i].name[i + 1 + strlen("user.")] = 0;
+
+               ea_table[i].value = malloc(NR_XATTRS - i + 1);
+               if (ea_table[i].value == NULL) {
+                       perror("malloc failed");
+                       exit(1);
+               }
+               memset(ea_table[i].value, 'Y', NR_XATTRS - i);
+               ea_table[i].value[NR_XATTRS - i] = 0;
+       }
+}
+
+static int set_xattrs(int fd)
+{
+       int i;
+
+       for (i = 0; i < NR_XATTRS; i ++) {
+               if (fsetxattr(fd, ea_table[i].name, ea_table[i].value,
+                             NR_XATTRS - i + 1, XATTR_CREATE) == -1) {
+                       if (errno != ENOSPC) {
+                               perror("fsetxattr failed");
+                               exit(1);
+                       }
+                       break;
+               }
+       }
+       printf("\t%d xattrs are set\n", i);
+       return i;
+}
+
+void get_xattrs1(int fd, int nr)
+{
+       int i;
+       ssize_t size;
+
+       printf("\ttesting fgetxattr .. "); fflush(stdout);
+
+       for (i = 0; i < nr; i ++) {
+               size = fgetxattr(fd, ea_table[i].name, tmpvalue,
+                                NR_XATTRS - i + 1);
+               if (size == -1) {
+                       perror("fgetxattr failed");
+                       exit(1);
+               }
+               if (memcmp(ea_table[i].value, tmpvalue, nr - i + 1)) {
+                       fprintf(stderr, "value mismatch");
+                       exit(1);
+               }
+       }
+
+       printf("%d xattrs are checked, ok\n", i);
+}
+
+void get_xattrs2(const char *device, ext2_ino_t ino, int nr)
+{
+       ext2_filsys fs;
+       int i;
+       struct ext2_inode *inode;
+       errcode_t err;
+       int size;
+
+       printf("\ttesting ext2fs_attr_get .. "); fflush(stdout);
+
+       err = ext2fs_open(device, 0, 0, 0, unix_io_manager, &fs);
+       assert(err == 0);
+
+       err = ext2fs_get_mem(EXT2_INODE_SIZE(fs->super), &inode);
+       if (err) {
+               com_err("get_xattrs2", err, "allocating memory");
+               exit(1);
+       }
+
+       err = ext2fs_read_inode_full(fs, ino, inode,
+                                    EXT2_INODE_SIZE(fs->super));
+       if (err) {
+               com_err("get_xattrs2", err, "reading inode");
+               exit(1);
+       }
+       for (i = 0; i < nr; i ++) {
+               err = ext2fs_attr_get(fs, inode, EXT2_ATTR_INDEX_USER,
+                                     ea_table[i].name + strlen("user."),
+                                     tmpvalue, sizeof(tmpvalue), &size);
+               if (err) {
+                       com_err("get_xattrs2", err, "getting xattr");
+                       exit(1);
+               }
+               assert(size == (NR_XATTRS - i + 1));
+
+               if (memcmp(ea_table[i].value, tmpvalue, size)) {
+                       fprintf(stderr, "value mismatch");
+                       exit(1);
+               }
+       }
+       ext2fs_close(fs);
+
+       printf("%d xattrs are checked, ok\n", i);
+}
+#endif /* HAVE_MNTENT_H */
+
+int main(int argc, const char *argv[])
+{
+#if HAVE_MNTENT_H
+       ext2_filsys fs;
+       FILE *f;
+       struct mntent *mnt;
+       char *name;
+       int fd;
+       errcode_t err;
+       struct stat st;
+       int nr;
+       int tested = 0;
+
+       initialize_ext2_error_table();
+
+       init_ea_table();
+
+       f = setmntent(MOUNTED, "r");
+       if (!f) {
+               fprintf(stderr, "failed to setmntent\n");
+               return 1;
+       }
+
+       while ((mnt = getmntent(f)) != NULL) {
+               if (hasmntopt(mnt, "user_xattr") == NULL)
+                       continue;
+               err = ext2fs_open(mnt->mnt_fsname, 0, 0, 0,
+                                 unix_io_manager, &fs);
+               if (err) {
+                       com_err("tst_read_ea", err, "opening fs %s:%s",
+                               mnt->mnt_fsname, mnt->mnt_type);
+                       continue;
+               }
+               ext2fs_close(fs);
+
+               printf("type=%s, fsname=%s, mtpt=%s\n", mnt->mnt_type,
+                      mnt->mnt_fsname, mnt->mnt_dir);
+
+               asprintf(&name, "%s/readeaXXXXXX", mnt->mnt_dir);
+               fd = mkstemp(name);
+               if (fd == -1) {
+                       fprintf(stderr, "tst_read_ea: mkstemp failed on %s: %s",
+                               name, strerror(errno));
+                       continue;
+               }
+               if (fstat(fd, &st)) {
+                       fprintf(stderr, "tst_read_ea: fstat failed on %s: %s\n",
+                               name, strerror(errno));
+                       exit(1);
+               }
+               nr = set_xattrs(fd);
+
+               sync();
+               get_xattrs1(fd, nr);
+               close(fd);
+
+               get_xattrs2(mnt->mnt_fsname, st.st_ino, nr);
+
+               unlink(name);
+               free(name);
+               tested = 1;
+       }
+       endmntent(f);
+
+       if (!tested)
+               fprintf(stderr,
+                       "\tno ext2 based filesystems mounted with user_xattr\n"
+                       "\thope it is ok\n");
+#endif /* HAVE_MNTENT_H */
+       return 0;
+}