2010-06-22 06:27:59 -05:00
|
|
|
/*
|
|
|
|
* Portable xxxat() functions.
|
|
|
|
*
|
2013-01-08 08:00:23 -06:00
|
|
|
* No copyright is claimed. This code is in the public domain; do with
|
|
|
|
* it what you wish.
|
|
|
|
*
|
|
|
|
* Written by Karel Zak <kzak@redhat.com>
|
2010-06-22 06:27:59 -05:00
|
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
|
|
|
#include "at.h"
|
2011-01-25 15:44:52 -06:00
|
|
|
#include "c.h"
|
2010-06-22 06:27:59 -05:00
|
|
|
|
|
|
|
#ifdef HAVE_FSTATAT
|
2011-08-01 04:55:11 -05:00
|
|
|
int fstat_at(int dir, const char *dirname __attribute__ ((__unused__)),
|
|
|
|
const char *filename, struct stat *st, int nofollow)
|
|
|
|
{
|
2010-06-22 06:27:59 -05:00
|
|
|
return fstatat(dir, filename, st,
|
|
|
|
nofollow ? AT_SYMLINK_NOFOLLOW : 0);
|
2011-08-01 04:55:11 -05:00
|
|
|
}
|
2010-06-22 06:27:59 -05:00
|
|
|
#else
|
2011-08-01 04:55:11 -05:00
|
|
|
int fstat_at(int dir, const char *dirname, const char *filename,
|
|
|
|
struct stat *st, int nofollow)
|
|
|
|
{
|
|
|
|
|
2011-05-18 08:55:15 -05:00
|
|
|
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;
|
2010-06-22 06:27:59 -05:00
|
|
|
|
2011-05-18 08:55:15 -05:00
|
|
|
return nofollow ? lstat(path, st) : stat(path, st);
|
|
|
|
}
|
2010-06-22 06:27:59 -05:00
|
|
|
|
2011-05-18 08:55:15 -05:00
|
|
|
return nofollow ? lstat(filename, st) : stat(filename, st);
|
2010-06-22 06:27:59 -05:00
|
|
|
}
|
2011-08-01 04:55:11 -05:00
|
|
|
#endif
|
2010-06-22 06:27:59 -05:00
|
|
|
|
|
|
|
#ifdef HAVE_FSTATAT
|
2011-08-01 04:55:11 -05:00
|
|
|
int open_at(int dir, const char *dirname __attribute__ ((__unused__)),
|
|
|
|
const char *filename, int flags)
|
|
|
|
{
|
2010-06-22 06:27:59 -05:00
|
|
|
return openat(dir, filename, flags);
|
2011-08-01 04:55:11 -05:00
|
|
|
}
|
2010-06-22 06:27:59 -05:00
|
|
|
#else
|
2011-08-01 04:55:11 -05:00
|
|
|
int open_at(int dir, const char *dirname, const char *filename, int flags)
|
|
|
|
{
|
2011-05-18 08:55:15 -05:00
|
|
|
if (*filename != '/') {
|
|
|
|
char path[PATH_MAX];
|
|
|
|
int len;
|
2010-06-22 06:27:59 -05:00
|
|
|
|
2011-05-18 08:55:15 -05:00
|
|
|
len = snprintf(path, sizeof(path), "%s/%s", dirname, filename);
|
|
|
|
if (len < 0 || len + 1 > sizeof(path))
|
|
|
|
return -1;
|
2010-06-22 06:27:59 -05:00
|
|
|
|
2011-05-18 08:55:15 -05:00
|
|
|
return open(path, flags);
|
|
|
|
}
|
|
|
|
return open(filename, flags);
|
2010-06-22 06:27:59 -05:00
|
|
|
}
|
2011-08-01 04:55:11 -05:00
|
|
|
#endif
|
2010-06-22 06:27:59 -05:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2011-05-18 08:55:15 -05:00
|
|
|
#ifdef HAVE_FSTATAT
|
2011-08-01 04:55:11 -05:00
|
|
|
ssize_t readlink_at(int dir, const char *dirname __attribute__ ((__unused__)),
|
|
|
|
const char *pathname, char *buf, size_t bufsiz)
|
|
|
|
{
|
2011-05-18 08:55:15 -05:00
|
|
|
return readlinkat(dir, pathname, buf, bufsiz);
|
2011-08-01 04:55:11 -05:00
|
|
|
}
|
2011-05-18 08:55:15 -05:00
|
|
|
#else
|
2011-08-01 04:55:11 -05:00
|
|
|
ssize_t readlink_at(int dir, const char *dirname, const char *pathname,
|
|
|
|
char *buf, size_t bufsiz)
|
|
|
|
{
|
2011-05-18 08:55:15 -05:00
|
|
|
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);
|
|
|
|
}
|
2011-08-01 04:55:11 -05:00
|
|
|
#endif
|
2011-05-18 08:55:15 -05:00
|
|
|
|
2011-05-25 09:50:44 -05:00
|
|
|
#ifdef TEST_PROGRAM_AT
|
2010-06-22 06:27:59 -05:00
|
|
|
#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)
|
2012-07-15 03:39:57 -05:00
|
|
|
err(EXIT_FAILURE, "cannot open %s", dirname);
|
2010-06-22 06:27:59 -05:00
|
|
|
|
|
|
|
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
|