summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/Makefile.am1
-rw-r--r--include/at.h23
-rw-r--r--lib/Makefile.am3
-rw-r--r--lib/at.c100
4 files changed, 126 insertions, 1 deletions
diff --git a/include/Makefile.am b/include/Makefile.am
index 9f6567560..1def42a9d 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -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
index 000000000..7542f9749
--- /dev/null
+++ b/include/at.h
@@ -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 */
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