]> err.no Git - util-linux/commitdiff
lib: add wrappers for "at" functions
authorKarel Zak <kzak@redhat.com>
Tue, 22 Jun 2010 11:27:59 +0000 (13:27 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 3 Jan 2011 11:28:39 +0000 (12:28 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
include/Makefile.am
include/at.h [new file with mode: 0644]
lib/Makefile.am
lib/at.c [new file with mode: 0644]

index 9f65675607430372ca485da33611295ae226740c..1def42a9d29ff1696c6e5462491cda0e13c4c475 100644 (file)
@@ -1,6 +1,7 @@
 include $(top_srcdir)/config/include-Makefile.am
 
 dist_noinst_HEADERS = \
+       at.h \
        bitops.h \
        blkdev.h \
        canonicalize.h \
diff --git a/include/at.h b/include/at.h
new file mode 100644 (file)
index 0000000..7542f97
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * wrappers for "at" functions.
+ *
+ * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#ifndef UTIL_LINUX_AT_H
+#define UTIL_LINUX_AT_H
+
+#include <stdio.h>
+
+extern int fstat_at(int dir, const char *dirname,
+                       const char *filename, struct stat *st, int nofollow);
+
+extern int open_at(int dir, const char *dirname,
+                       const char *filename, int flags);
+
+extern FILE *fopen_at(int dir, const char *dirname, const char *filename,
+                       int flags, const char *mode);
+
+#endif /* UTIL_LINUX_AT_H */
index 9a3bf35bdfa5fb1fcba9d8ff8e73f70c0d79c961..36396a38527779d499b7c6a5278852fb11c7865e 100644 (file)
@@ -3,7 +3,7 @@ include $(top_srcdir)/config/include-Makefile.am
 AM_CPPFLAGS += -DTEST_PROGRAM
 
 noinst_PROGRAMS = test_blkdev test_ismounted test_wholedisk test_mangle \
-                 test_tt test_canonicalize
+                 test_tt test_canonicalize test_at
 if LINUX
 if HAVE_CPU_SET_T
 noinst_PROGRAMS += test_cpuset
@@ -14,6 +14,7 @@ test_blkdev_SOURCES = blkdev.c
 test_ismounted_SOURCES = ismounted.c
 test_wholedisk_SOURCES = wholedisk.c
 test_mangle_SOURCES = mangle.c
+test_at_SOURCES = at.c
 if LINUX
 test_cpuset_SOURCES = cpuset.c
 endif
diff --git a/lib/at.c b/lib/at.c
new file mode 100644 (file)
index 0000000..1993f99
--- /dev/null
+++ b/lib/at.c
@@ -0,0 +1,100 @@
+/*
+ * Portable xxxat() functions.
+ *
+ * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include "at.h"
+
+int fstat_at(int dir, const char *dirname, const char *filename,
+                               struct stat *st, int nofollow)
+{
+#ifdef HAVE_FSTATAT
+       return fstatat(dir, filename, st,
+                       nofollow ? AT_SYMLINK_NOFOLLOW : 0);
+#else
+       char path[PATH_MAX];
+       int len;
+
+       len = snprintf(path, sizeof(path), "%s/%s", dirname, filename);
+       if (len < 0 || len + 1 > sizeof(path))
+               return -1;
+
+       return nofollow ? lstat(path, st) : stat(path, st);
+#endif
+}
+
+int open_at(int dir, const char *dirname, const char *filename, int flags)
+{
+#ifdef HAVE_FSTATAT
+       return openat(dir, filename, flags);
+#else
+       char path[PATH_MAX];
+       int len;
+
+       len = snprintf(path, sizeof(path), "%s/%s", dirname, filename);
+       if (len < 0 || len + 1 > sizeof(path))
+               return -1;
+
+       return open(path, flags);
+#endif
+}
+
+FILE *fopen_at(int dir, const char *dirname, const char *filename, int flags,
+                       const char *mode)
+{
+       int fd = open_at(dir, dirname, filename, flags);
+
+       if (fd < 0)
+               return NULL;
+
+       return fdopen(fd, mode);
+}
+
+#ifdef TEST_PROGRAM
+#include <err.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <string.h>
+
+int main(int argc, char *argv[])
+{
+       DIR *dir;
+       struct dirent *d;
+       char *dirname;
+
+       if (argc != 2) {
+               fprintf(stderr, "usage: %s <directory>\n", argv[0]);
+               exit(EXIT_FAILURE);
+       }
+       dirname = argv[1];
+
+       dir = opendir(dirname);
+       if (!dir)
+               err(EXIT_FAILURE, "%s: open failed", dirname);
+
+       while ((d = readdir(dir))) {
+               struct stat st;
+               FILE *f;
+
+               printf("%32s ", d->d_name);
+
+               if (fstat_at(dirfd(dir), dirname, d->d_name, &st, 0) == 0)
+                       printf("%16jd bytes ", st.st_size);
+               else
+                       printf("%16s bytes ", "???");
+
+               f = fopen_at(dirfd(dir), dirname, d->d_name, O_RDONLY, "r");
+               printf("   %s\n", f ? "OK" : strerror(errno));
+               if (f)
+                       fclose(f);
+       }
+       closedir(dir);
+       return EXIT_SUCCESS;
+}
+#endif