]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lib: [at.c] add readlink_at(), fix semantic for absolute paths
authorKarel Zak <kzak@redhat.com>
Wed, 18 May 2011 13:55:15 +0000 (15:55 +0200)
committerKarel Zak <kzak@redhat.com>
Wed, 18 May 2011 13:57:16 +0000 (15:57 +0200)
Signed-off-by: Karel Zak <kzak@redhat.com>
include/at.h
lib/at.c

index 8e0a78db61f67f5eab907cad2b6c3cc8dc981128..63a80f0c0cc6d77235d806d1875f14c28ddd3b72 100644 (file)
@@ -25,4 +25,8 @@ extern int open_at(int dir, const char *dirname,
 extern FILE *fopen_at(int dir, const char *dirname, const char *filename,
                        int flags, const char *mode);
 
+extern ssize_t readlink_at(int dir, const char *dirname, const char *pathname,
+                    char *buf, size_t bufsiz);
+
+
 #endif /* UTIL_LINUX_AT_H */
index e4838ec3cb7ffaf4ecb71cb49738234fcc4f4c27..6d1cd13f73bb81500a04a0fdec9ab962455a2b6d 100644 (file)
--- a/lib/at.c
+++ b/lib/at.c
@@ -11,6 +11,8 @@
 #include "at.h"
 #include "c.h"
 
+#undef HAVE_FSTATAT
+
 int fstat_at(int dir, const char *dirname, const char *filename,
                                struct stat *st, int nofollow)
 {
@@ -18,14 +20,18 @@ int fstat_at(int dir, const char *dirname, const char *filename,
        return fstatat(dir, filename, st,
                        nofollow ? AT_SYMLINK_NOFOLLOW : 0);
 #else
-       char path[PATH_MAX];
-       int len;
+       if (*filename != '/') {
+               char path[PATH_MAX];
+               int len;
+
+               len = snprintf(path, sizeof(path), "%s/%s", dirname, filename);
+               if (len < 0 || len + 1 > sizeof(path))
+                       return -1;
 
-       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);
+       }
 
-       return nofollow ? lstat(path, st) : stat(path, st);
+       return nofollow ? lstat(filename, st) : stat(filename, st);
 #endif
 }
 
@@ -34,14 +40,17 @@ 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;
+       if (*filename != '/') {
+               char path[PATH_MAX];
+               int len;
 
-       len = snprintf(path, sizeof(path), "%s/%s", dirname, filename);
-       if (len < 0 || len + 1 > sizeof(path))
-               return -1;
+               len = snprintf(path, sizeof(path), "%s/%s", dirname, filename);
+               if (len < 0 || len + 1 > sizeof(path))
+                       return -1;
 
-       return open(path, flags);
+               return open(path, flags);
+       }
+       return open(filename, flags);
 #endif
 }
 
@@ -56,6 +65,26 @@ FILE *fopen_at(int dir, const char *dirname, const char *filename, int flags,
        return fdopen(fd, mode);
 }
 
+ssize_t readlink_at(int dir, const char *dirname, const char *pathname,
+                   char *buf, size_t bufsiz)
+{
+#ifdef HAVE_FSTATAT
+       return readlinkat(dir, pathname, buf, bufsiz);
+#else
+       if (*pathname != '/') {
+               char path[PATH_MAX];
+               int len;
+
+               len = snprintf(path, sizeof(path), "%s/%s", dirname, pathname);
+               if (len < 0 || len + 1 > sizeof(path))
+                       return -1;
+
+               return readlink(path, buf, bufsiz);
+       }
+       return readlink(pathname, buf, bufsiz);
+#endif
+}
+
 #ifdef TEST_PROGRAM__DISABLED_FOR_NOW
 #include <errno.h>
 #include <sys/types.h>