1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
|
/*
* Copyright (C) 2016- The University of Notre Dame
* This software is distributed under the GNU General Public License.
* See the file COPYING for details.
*/
#if !defined(HAS_OPENAT) || !defined(HAS_UTIMENSAT)
#include "compat-at.h"
#include "debug.h"
#include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
static int getfullpath (int dirfd, const char *path, char fullpath[PATH_MAX])
{
char dirpath[PATH_MAX] = ".";
if (path[0] == '/') {
dirpath[0] = 0;
} else if (dirfd != AT_FDCWD) {
#if defined(CCTOOLS_OPSYS_DARWIN)
if (fcntl(dirfd, F_GETPATH, dirpath) == -1)
return -1;
#elif defined(CCTOOLS_OPSYS_LINUX)
char dirpath[PATH_MAX];
char procpath[PATH_MAX];
snprintf(procpath, PATH_MAX, "/proc/self/fd/%d", dirfd);
if (readlink(procpath, dirpath, PATH_MAX) == -1)
return -1;
#else
# error "Cannot proceed without support for *at system calls."
#endif
}
int rc = snprintf(fullpath, PATH_MAX, "%s/%s", dirpath, path);
if (rc == -1)
abort();
else if (rc >= PATH_MAX)
return (errno = ENAMETOOLONG, -1);
debug(D_DEBUG, "full path %s", fullpath);
return 0;
}
#ifndef HAS_OPENAT
int cctools_faccessat (int dirfd, const char *path, int amode, int flag)
{
char fullpath[PATH_MAX];
if (getfullpath(dirfd, path, fullpath) == -1)
return -1;
(void)flag;
return access(fullpath, amode);
}
int cctools_fchmodat (int dirfd, const char *path, mode_t mode, int flag)
{
char fullpath[PATH_MAX];
if (getfullpath(dirfd, path, fullpath) == -1)
return -1;
(void)flag;
return chmod(fullpath, mode);
}
DIR *cctools_fdopendir (int dirfd)
{
char fullpath[PATH_MAX];
if (getfullpath(dirfd, ".", fullpath) == -1)
return NULL;
return opendir(fullpath);
}
int cctools_fstatat (int dirfd, const char *path, struct stat *buf, int flag)
{
char fullpath[PATH_MAX];
if (getfullpath(dirfd, path, fullpath) == -1)
return -1;
if (flag & AT_SYMLINK_NOFOLLOW) {
return lstat(fullpath, buf);
} else {
return stat(fullpath, buf);
}
}
int cctools_linkat (int dirfd, const char *path, int newdirfd, const char *newpath, int flag)
{
char fullpath[PATH_MAX];
if (getfullpath(dirfd, path, fullpath) == -1)
return -1;
char newfullpath[PATH_MAX];
if (getfullpath(newdirfd, newpath, newfullpath) == -1)
return -1;
(void)flag;
return link(fullpath, newfullpath);
}
int cctools_openat (int dirfd, const char *path, int oflag, mode_t cmode)
{
char fullpath[PATH_MAX];
if (getfullpath(dirfd, path, fullpath) == -1)
return -1;
return open(fullpath, oflag, cmode);
}
int cctools_mkdirat (int dirfd, const char *path, mode_t mode)
{
char fullpath[PATH_MAX];
if (getfullpath(dirfd, path, fullpath) == -1)
return -1;
return mkdir(fullpath, mode);
}
int cctools_readlinkat (int dirfd, const char *path, char *buf, size_t bufsize)
{
char fullpath[PATH_MAX];
if (getfullpath(dirfd, path, fullpath) == -1)
return -1;
return readlink(fullpath, buf, bufsize);
}
int cctools_renameat (int dirfd, const char *path, int newdirfd, const char *newpath)
{
char fullpath[PATH_MAX];
if (getfullpath(dirfd, path, fullpath) == -1)
return -1;
char newfullpath[PATH_MAX];
if (getfullpath(newdirfd, newpath, newfullpath) == -1)
return -1;
return rename(fullpath, newfullpath);
}
int cctools_symlinkat (const char *target, int dirfd, const char *path)
{
char fullpath[PATH_MAX];
if (getfullpath(dirfd, path, fullpath) == -1)
return -1;
return symlink(target, fullpath);
}
int cctools_unlinkat (int dirfd, const char *path, int flag)
{
char fullpath[PATH_MAX];
if (getfullpath(dirfd, path, fullpath) == -1)
return -1;
if (flag == AT_REMOVEDIR) {
return rmdir(fullpath);
} else {
return unlink(fullpath);
}
}
#endif /* HAS_OPENAT */
#ifndef HAS_UTIMENSAT
int cctools_utimensat (int dirfd, const char *path, const struct timespec times[2], int flag)
{
struct timeval tv[2] = {{.tv_sec = times[0].tv_sec}, {.tv_sec = times[1].tv_sec}};
char fullpath[PATH_MAX];
if (getfullpath(dirfd, path, fullpath) == -1)
return -1;
(void)flag;
return utimes(fullpath, tv);
}
#endif /* HAS_UTIMENSAT */
#endif /* !defined(HAS_OPENAT) || !defined(HAS_UTIMENSAT) */
/* vim: set noexpandtab tabstop=4: */
|