0001
0002
0003
0004
0005
0006
0007 #define _GNU_SOURCE
0008 #include <errno.h>
0009 #include <fcntl.h>
0010 #include <stdbool.h>
0011 #include <string.h>
0012 #include <syscall.h>
0013 #include <limits.h>
0014
0015 #include "helpers.h"
0016
0017 bool needs_openat2(const struct open_how *how)
0018 {
0019 return how->resolve != 0;
0020 }
0021
0022 int raw_openat2(int dfd, const char *path, void *how, size_t size)
0023 {
0024 int ret = syscall(__NR_openat2, dfd, path, how, size);
0025 return ret >= 0 ? ret : -errno;
0026 }
0027
0028 int sys_openat2(int dfd, const char *path, struct open_how *how)
0029 {
0030 return raw_openat2(dfd, path, how, sizeof(*how));
0031 }
0032
0033 int sys_openat(int dfd, const char *path, struct open_how *how)
0034 {
0035 int ret = openat(dfd, path, how->flags, how->mode);
0036 return ret >= 0 ? ret : -errno;
0037 }
0038
0039 int sys_renameat2(int olddirfd, const char *oldpath,
0040 int newdirfd, const char *newpath, unsigned int flags)
0041 {
0042 int ret = syscall(__NR_renameat2, olddirfd, oldpath,
0043 newdirfd, newpath, flags);
0044 return ret >= 0 ? ret : -errno;
0045 }
0046
0047 int touchat(int dfd, const char *path)
0048 {
0049 int fd = openat(dfd, path, O_CREAT, 0700);
0050 if (fd >= 0)
0051 close(fd);
0052 return fd;
0053 }
0054
0055 char *fdreadlink(int fd)
0056 {
0057 char *target, *tmp;
0058
0059 E_asprintf(&tmp, "/proc/self/fd/%d", fd);
0060
0061 target = malloc(PATH_MAX);
0062 if (!target)
0063 ksft_exit_fail_msg("fdreadlink: malloc failed\n");
0064 memset(target, 0, PATH_MAX);
0065
0066 E_readlink(tmp, target, PATH_MAX);
0067 free(tmp);
0068 return target;
0069 }
0070
0071 bool fdequal(int fd, int dfd, const char *path)
0072 {
0073 char *fdpath, *dfdpath, *other;
0074 bool cmp;
0075
0076 fdpath = fdreadlink(fd);
0077 dfdpath = fdreadlink(dfd);
0078
0079 if (!path)
0080 E_asprintf(&other, "%s", dfdpath);
0081 else if (*path == '/')
0082 E_asprintf(&other, "%s", path);
0083 else
0084 E_asprintf(&other, "%s/%s", dfdpath, path);
0085
0086 cmp = !strcmp(fdpath, other);
0087
0088 free(fdpath);
0089 free(dfdpath);
0090 free(other);
0091 return cmp;
0092 }
0093
0094 bool openat2_supported = false;
0095
0096 void __attribute__((constructor)) init(void)
0097 {
0098 struct open_how how = {};
0099 int fd;
0100
0101 BUILD_BUG_ON(sizeof(struct open_how) != OPEN_HOW_SIZE_VER0);
0102
0103
0104 fd = sys_openat2(AT_FDCWD, ".", &how);
0105 openat2_supported = (fd >= 0);
0106
0107 if (fd >= 0)
0108 close(fd);
0109 }