Implemented eaccess(), the AT_EACCESS flag of faccessat(), fchmodat(), fchownat(), fstatat(), mkdirat(), mkfifoat(), mknodat(), and futimesat().
This commit is contained in:
parent
62540ce5eb
commit
9970cc92bf
@ -13,19 +13,67 @@
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
int
|
||||
eaccess(const char* path, int accessMode)
|
||||
{
|
||||
uid_t uid = geteuid();
|
||||
int fileMode = 0;
|
||||
|
||||
struct stat st;
|
||||
if (stat(path, &st) < 0) {
|
||||
// failed to get stat information on path
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uid == 0) {
|
||||
// user is root
|
||||
// root has always read/write permission, but at least one of the
|
||||
// X bits must be set for execute permission
|
||||
fileMode = R_OK | W_OK;
|
||||
if ((st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0)
|
||||
fileMode |= X_OK;
|
||||
} else if (st.st_uid == uid) {
|
||||
// user is node owner
|
||||
if ((st.st_mode & S_IRUSR) != 0)
|
||||
fileMode |= R_OK;
|
||||
if ((st.st_mode & S_IWUSR) != 0)
|
||||
fileMode |= W_OK;
|
||||
if ((st.st_mode & S_IXUSR) != 0)
|
||||
fileMode |= X_OK;
|
||||
} else if (st.st_gid == getegid()) {
|
||||
// user is in owning group
|
||||
if ((st.st_mode & S_IRGRP) != 0)
|
||||
fileMode |= R_OK;
|
||||
if ((st.st_mode & S_IWGRP) != 0)
|
||||
fileMode |= W_OK;
|
||||
if ((st.st_mode & S_IXGRP) != 0)
|
||||
fileMode |= X_OK;
|
||||
} else {
|
||||
// user is one of the others
|
||||
if ((st.st_mode & S_IROTH) != 0)
|
||||
fileMode |= R_OK;
|
||||
if ((st.st_mode & S_IWOTH) != 0)
|
||||
fileMode |= W_OK;
|
||||
if ((st.st_mode & S_IXOTH) != 0)
|
||||
fileMode |= X_OK;
|
||||
}
|
||||
|
||||
if ((accessMode & ~fileMode) != 0) {
|
||||
errno = EACCES;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
faccessat(int fd, const char* path, int accessMode, int flag)
|
||||
{
|
||||
if ((flag & AT_EACCESS) == 0) {
|
||||
// Perform access checks using the effective user and group IDs
|
||||
// CURRENTLY UNSUPPORTED
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((flag & AT_SYMLINK_NOFOLLOW) == 0) {
|
||||
// do not dereference, instead return information about the link
|
||||
// itself
|
||||
@ -36,7 +84,8 @@ faccessat(int fd, const char* path, int accessMode, int flag)
|
||||
|
||||
if (path && path[0] == '/') {
|
||||
// path is absolute, call access() ignoring fd
|
||||
return access(path, accessMode);
|
||||
return (flag & AT_EACCESS) == 0 ? eaccess(path, accessMode)
|
||||
: access(path, accessMode);
|
||||
}
|
||||
|
||||
if (!fd) {
|
||||
@ -47,16 +96,17 @@ faccessat(int fd, const char* path, int accessMode, int flag)
|
||||
|
||||
if (fd == AT_FDCWD) {
|
||||
// fd is set to AT_FDCWD, call access()
|
||||
return access(path, accessMode);
|
||||
return (flag & AT_EACCESS) == 0 ? eaccess(path, accessMode)
|
||||
: access(path, accessMode);
|
||||
}
|
||||
|
||||
struct stat mystat;
|
||||
if (fstat(fd, &mystat) < 0) {
|
||||
// failed to grab stat information, fstat sets errno
|
||||
struct stat dirst;
|
||||
if (fstat(fd, &dirst) < 0) {
|
||||
// failed to grab stat information, fstat() sets errno
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((mystat.st_mode & S_IFDIR) != 0) {
|
||||
if ((dirst.st_mode & S_IFDIR) != 0) {
|
||||
// fd does not point to a directory
|
||||
errno = ENOTDIR;
|
||||
return -1;
|
||||
@ -81,55 +131,370 @@ faccessat(int fd, const char* path, int accessMode, int flag)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return access(dirpath, accessMode);
|
||||
return (flag & AT_EACCESS) == 0 ? eaccess(path, accessMode)
|
||||
: access(path, accessMode);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fchmodat(int fd, const char* path, mode_t mode, int flag)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
if ((flag & AT_SYMLINK_NOFOLLOW) == 0) {
|
||||
// do not dereference, instead return information about the link
|
||||
// itself
|
||||
// CURRENTLY UNSUPPORTED
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
} else if (flag != 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (path && path[0] == '/') {
|
||||
// path is absolute, call chmod() ignoring fd
|
||||
return chmod(path, mode);
|
||||
}
|
||||
|
||||
if (!fd) {
|
||||
// fd is not a valid file descriptor
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fd == AT_FDCWD) {
|
||||
// fd is set to AT_FDCWD, call chmod()
|
||||
return chmod(path, mode);
|
||||
}
|
||||
|
||||
struct stat dirst;
|
||||
if (fstat(fd, &dirst) < 0) {
|
||||
// failed to grab stat information, fstat() sets errno
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((dirst.st_mode & S_IFDIR) != 0) {
|
||||
// fd does not point to a directory
|
||||
errno = ENOTDIR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *dirpath;
|
||||
dirpath = (char *)malloc(MAXPATHLEN);
|
||||
if (dirpath == NULL) {
|
||||
// ran out of memory allocating dirpath
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fcntl(fd, F_GETPATH, dirpath) < 0) {
|
||||
// failed to get the path of fd, fcntl sets errno
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strlcat(dirpath, path, MAXPATHLEN) > MAXPATHLEN) {
|
||||
// full path is too long, set errno and return
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return chmod(dirpath, mode);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fchownat(int fd, const char* path, uid_t owner, gid_t group, int flag)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
if ((flag & AT_SYMLINK_NOFOLLOW) == 0) {
|
||||
// do not dereference, instead return information about the link
|
||||
// itself
|
||||
// CURRENTLY UNSUPPORTED
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
} else if (flag != 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (path && path[0] == '/') {
|
||||
// path is absolute, call chown() ignoring fd
|
||||
return chown(path, owner, group);
|
||||
}
|
||||
|
||||
if (!fd) {
|
||||
// fd is not a valid file descriptor
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fd == AT_FDCWD) {
|
||||
// fd is set to AT_FDCWD, call access()
|
||||
return chown(path, owner, group);
|
||||
}
|
||||
|
||||
struct stat dirst;
|
||||
if (fstat(fd, &dirst) < 0) {
|
||||
// failed to grab stat information, fstat() sets errno
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((dirst.st_mode & S_IFDIR) != 0) {
|
||||
// fd does not point to a directory
|
||||
errno = ENOTDIR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *dirpath;
|
||||
dirpath = (char *)malloc(MAXPATHLEN);
|
||||
if (dirpath == NULL) {
|
||||
// ran out of memory allocating dirpath
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fcntl(fd, F_GETPATH, dirpath) < 0) {
|
||||
// failed to get the path of fd, fcntl sets errno
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strlcat(dirpath, path, MAXPATHLEN) > MAXPATHLEN) {
|
||||
// full path is too long, set errno and return
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return chown(dirpath, owner, group);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fstatat(int fd, const char *path, struct stat *st, int flag)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
if ((flag & AT_NO_AUTOMOUNT) == 0) {
|
||||
// Don't automount the terminal ("basename") component of pathname if
|
||||
// it is a directory that is an automount point.
|
||||
// CURRENTLY UNSUPPORTED
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((flag & AT_SYMLINK_NOFOLLOW) == 0) {
|
||||
// do not dereference, instead return information about the link
|
||||
// itself
|
||||
// CURRENTLY UNSUPPORTED
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (path && path[0] == '/') {
|
||||
// path is absolute, call stat() ignoring fd
|
||||
return stat(path, st);
|
||||
}
|
||||
|
||||
if (!fd) {
|
||||
// fd is not a valid file descriptor
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fd == AT_FDCWD) {
|
||||
// fd is set to AT_FDCWD, call stat()
|
||||
return stat(path, st);
|
||||
}
|
||||
|
||||
struct stat dirst;
|
||||
if (fstat(fd, &dirst) < 0) {
|
||||
// failed to grab stat information, fstat() sets errno
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((dirst.st_mode & S_IFDIR) != 0) {
|
||||
// fd does not point to a directory
|
||||
errno = ENOTDIR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *dirpath;
|
||||
dirpath = (char *)malloc(MAXPATHLEN);
|
||||
if (dirpath == NULL) {
|
||||
// ran out of memory allocating dirpath
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fcntl(fd, F_GETPATH, dirpath) < 0) {
|
||||
// failed to get the path of fd, fcntl sets errno
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strlcat(dirpath, path, MAXPATHLEN) > MAXPATHLEN) {
|
||||
// full path is too long, set errno and return
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return stat(dirpath, st);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
mkdirat(int fd, const char *path, mode_t mode)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
if (path && path[0] == '/') {
|
||||
// path is absolute, call mkdir() ignoring fd
|
||||
return mkdir(path, mode);
|
||||
}
|
||||
|
||||
if (!fd) {
|
||||
// fd is not a valid file descriptor
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fd == AT_FDCWD) {
|
||||
// fd is set to AT_FDCWD, call mkdir()
|
||||
return mkdir(path, mode);
|
||||
}
|
||||
|
||||
struct stat dirst;
|
||||
if (fstat(fd, &dirst) < 0) {
|
||||
// failed to grab stat information, fstat() sets errno
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((dirst.st_mode & S_IFDIR) != 0) {
|
||||
// fd does not point to a directory
|
||||
errno = ENOTDIR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *dirpath;
|
||||
dirpath = (char *)malloc(MAXPATHLEN);
|
||||
if (dirpath == NULL) {
|
||||
// ran out of memory allocating dirpath
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fcntl(fd, F_GETPATH, dirpath) < 0) {
|
||||
// failed to get the path of fd, fcntl sets errno
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strlcat(dirpath, path, MAXPATHLEN) > MAXPATHLEN) {
|
||||
// full path is too long, set errno and return
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return mkdir(dirpath, mode);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
mkfifoat(int fd, const char *path, mode_t mode)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
if (path && path[0] == '/') {
|
||||
// path is absolute, call mkfifo() ignoring fd
|
||||
return mkfifo(path, mode);
|
||||
}
|
||||
|
||||
if (!fd) {
|
||||
// fd is not a valid file descriptor
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fd == AT_FDCWD) {
|
||||
// fd is set to AT_FDCWD, call mkfifo()
|
||||
return mkfifo(path, mode);
|
||||
}
|
||||
|
||||
struct stat dirst;
|
||||
if (fstat(fd, &dirst) < 0) {
|
||||
// failed to grab stat information, fstat() sets errno
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((dirst.st_mode & S_IFDIR) != 0) {
|
||||
// fd does not point to a directory
|
||||
errno = ENOTDIR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *dirpath;
|
||||
dirpath = (char *)malloc(MAXPATHLEN);
|
||||
if (dirpath == NULL) {
|
||||
// ran out of memory allocating dirpath
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fcntl(fd, F_GETPATH, dirpath) < 0) {
|
||||
// failed to get the path of fd, fcntl sets errno
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strlcat(dirpath, path, MAXPATHLEN) > MAXPATHLEN) {
|
||||
// full path is too long, set errno and return
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return mkfifo(dirpath, mode);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
mknodat(int fd, const char *name, mode_t mode, dev_t dev)
|
||||
mknodat(int fd, const char *path, mode_t mode, dev_t dev)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
if (path && path[0] == '/') {
|
||||
// path is absolute, call mknod() ignoring fd
|
||||
return mknod(path, mode, dev);
|
||||
}
|
||||
|
||||
if (!fd) {
|
||||
// fd is not a valid file descriptor
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fd == AT_FDCWD) {
|
||||
// fd is set to AT_FDCWD, call mknod()
|
||||
return mknod(path, mode, dev);
|
||||
}
|
||||
|
||||
struct stat dirst;
|
||||
if (fstat(fd, &dirst) < 0) {
|
||||
// failed to grab stat information, fstat() sets errno
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((dirst.st_mode & S_IFDIR) != 0) {
|
||||
// fd does not point to a directory
|
||||
errno = ENOTDIR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *dirpath;
|
||||
dirpath = (char *)malloc(MAXPATHLEN);
|
||||
if (dirpath == NULL) {
|
||||
// ran out of memory allocating dirpath
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fcntl(fd, F_GETPATH, dirpath) < 0) {
|
||||
// failed to get the path of fd, fcntl sets errno
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strlcat(dirpath, path, MAXPATHLEN) > MAXPATHLEN) {
|
||||
// full path is too long, set errno and return
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return mknod(dirpath, mode, dev);
|
||||
}
|
||||
|
||||
|
||||
@ -176,6 +541,52 @@ linkat(int toFD, const char *toPath, int linkFD, const char *linkPath, int flag)
|
||||
int
|
||||
futimesat(int fd, const char *path, const struct timeval times[2])
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
if (path && path[0] == '/') {
|
||||
// path is absolute, call utimes() ignoring fd
|
||||
return utimes(path, times);
|
||||
}
|
||||
|
||||
if (!fd) {
|
||||
// fd is not a valid file descriptor
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fd == AT_FDCWD) {
|
||||
// fd is set to AT_FDCWD, call utimes()
|
||||
return utimes(path, times);
|
||||
}
|
||||
|
||||
struct stat dirst;
|
||||
if (fstat(fd, &dirst) < 0) {
|
||||
// failed to grab stat information, fstat() sets errno
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((dirst.st_mode & S_IFDIR) != 0) {
|
||||
// fd does not point to a directory
|
||||
errno = ENOTDIR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *dirpath;
|
||||
dirpath = (char *)malloc(MAXPATHLEN);
|
||||
if (dirpath == NULL) {
|
||||
// ran out of memory allocating dirpath
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fcntl(fd, F_GETPATH, dirpath) < 0) {
|
||||
// failed to get the path of fd, fcntl sets errno
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strlcat(dirpath, path, MAXPATHLEN) > MAXPATHLEN) {
|
||||
// full path is too long, set errno and return
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return utimes(dirpath, times);
|
||||
}
|
||||
|
@ -13,7 +13,9 @@
|
||||
#define AT_SYMLINK_FOLLOW 0x02 /* linkat() */
|
||||
#define AT_REMOVEDIR 0x04 /* unlinkat() */
|
||||
#define AT_EACCESS 0x08 /* faccessat() */
|
||||
#define AT_NO_AUTOMOUNT 0x10 /* fstatat */
|
||||
|
||||
int eaccess(const char* path, int accessMode);
|
||||
int faccessat(int fd, const char* path, int accessMode, int flag);
|
||||
int fchmodat(int fd, const char* path, mode_t mode, int flag);
|
||||
int fchownat(int fd, const char* path, uid_t owner, gid_t group, int flag);
|
||||
|
Loading…
Reference in New Issue
Block a user