summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorKarel Zak2010-06-22 13:27:59 +0200
committerKarel Zak2011-01-03 12:28:39 +0100
commit5a5eeb1513cfb7e02a352ef0dd987e85697a83eb (patch)
tree3724af5e186729ec008d113e9bdbe5e41ed07c87 /lib
parentlibmount: add mnt_tab_parse_stream() (diff)
downloadkernel-qcow2-util-linux-5a5eeb1513cfb7e02a352ef0dd987e85697a83eb.tar.gz
kernel-qcow2-util-linux-5a5eeb1513cfb7e02a352ef0dd987e85697a83eb.tar.xz
kernel-qcow2-util-linux-5a5eeb1513cfb7e02a352ef0dd987e85697a83eb.zip
lib: add wrappers for "at" functions
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am3
-rw-r--r--lib/at.c100
2 files changed, 102 insertions, 1 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 9a3bf35bd..36396a385 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -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
index 000000000..1993f9983
--- /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