From: Karel Zak Date: Wed, 18 May 2011 13:55:15 +0000 (+0200) Subject: lib: [at.c] add readlink_at(), fix semantic for absolute paths X-Git-Tag: v2.20-rc1~240 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cdc9c4194aac3897feb2156ad2d3d5cb663b4365;p=thirdparty%2Futil-linux.git lib: [at.c] add readlink_at(), fix semantic for absolute paths Signed-off-by: Karel Zak --- diff --git a/include/at.h b/include/at.h index 8e0a78db61..63a80f0c0c 100644 --- a/include/at.h +++ b/include/at.h @@ -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 */ diff --git a/lib/at.c b/lib/at.c index e4838ec3cb..6d1cd13f73 100644 --- 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 #include