0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #undef NDEBUG
0019 #include <assert.h>
0020 #include <dirent.h>
0021 #include <errno.h>
0022 #include <limits.h>
0023 #include <sched.h>
0024 #include <stdio.h>
0025 #include <unistd.h>
0026 #include <sys/types.h>
0027 #include <sys/stat.h>
0028 #include <fcntl.h>
0029
0030 #include "proc.h"
0031
0032
0033 static void test_lookup_pass(const char *pathname)
0034 {
0035 struct stat st;
0036 ssize_t rv;
0037
0038 memset(&st, 0, sizeof(struct stat));
0039 rv = lstat(pathname, &st);
0040 assert(rv == 0);
0041 assert(S_ISLNK(st.st_mode));
0042 }
0043
0044 static void test_lookup_fail(const char *pathname)
0045 {
0046 struct stat st;
0047 ssize_t rv;
0048
0049 rv = lstat(pathname, &st);
0050 assert(rv == -1 && errno == ENOENT);
0051 }
0052
0053 static void test_lookup(unsigned int fd)
0054 {
0055 char buf[64];
0056 unsigned int c;
0057 unsigned int u;
0058 int i;
0059
0060 snprintf(buf, sizeof(buf), "/proc/self/fd/%u", fd);
0061 test_lookup_pass(buf);
0062
0063
0064 for (c = 1; c <= 255; c++) {
0065 if (c == '/')
0066 continue;
0067 snprintf(buf, sizeof(buf), "/proc/self/fd/%c%u", c, fd);
0068 test_lookup_fail(buf);
0069 }
0070
0071
0072 for (c = 1; c <= 255; c++) {
0073 if (c == '/')
0074 continue;
0075 snprintf(buf, sizeof(buf), "/proc/self/fd/%u%c", fd, c);
0076 test_lookup_fail(buf);
0077 }
0078
0079 for (i = INT_MIN; i < INT_MIN + 1024; i++) {
0080 snprintf(buf, sizeof(buf), "/proc/self/fd/%d", i);
0081 test_lookup_fail(buf);
0082 }
0083 for (i = -1024; i < 0; i++) {
0084 snprintf(buf, sizeof(buf), "/proc/self/fd/%d", i);
0085 test_lookup_fail(buf);
0086 }
0087 for (u = INT_MAX - 1024; u <= (unsigned int)INT_MAX + 1024; u++) {
0088 snprintf(buf, sizeof(buf), "/proc/self/fd/%u", u);
0089 test_lookup_fail(buf);
0090 }
0091 for (u = UINT_MAX - 1024; u != 0; u++) {
0092 snprintf(buf, sizeof(buf), "/proc/self/fd/%u", u);
0093 test_lookup_fail(buf);
0094 }
0095
0096
0097 }
0098
0099 int main(void)
0100 {
0101 struct dirent *de;
0102 unsigned int fd, target_fd;
0103
0104 if (unshare(CLONE_FILES) == -1)
0105 return 1;
0106
0107
0108 do {
0109 DIR *d;
0110
0111 d = opendir("/proc/self/fd");
0112 if (!d)
0113 return 1;
0114
0115 de = xreaddir(d);
0116 assert(de->d_type == DT_DIR);
0117 assert(streq(de->d_name, "."));
0118
0119 de = xreaddir(d);
0120 assert(de->d_type == DT_DIR);
0121 assert(streq(de->d_name, ".."));
0122 next:
0123 de = xreaddir(d);
0124 if (de) {
0125 unsigned long long fd_ull;
0126 unsigned int fd;
0127 char *end;
0128
0129 assert(de->d_type == DT_LNK);
0130
0131 fd_ull = xstrtoull(de->d_name, &end);
0132 assert(*end == '\0');
0133 assert(fd_ull == (unsigned int)fd_ull);
0134
0135 fd = fd_ull;
0136 if (fd == dirfd(d))
0137 goto next;
0138 close(fd);
0139 }
0140
0141 closedir(d);
0142 } while (de);
0143
0144
0145
0146 fd = open("/", O_PATH|O_DIRECTORY);
0147 assert(fd == 0);
0148 test_lookup(fd);
0149 close(fd);
0150
0151
0152
0153 fd = open("/", O_PATH|O_DIRECTORY);
0154 assert(fd == 0);
0155
0156 target_fd = 1023;
0157 while (target_fd > 0) {
0158 if (dup2(fd, target_fd) == target_fd)
0159 break;
0160 target_fd /= 2;
0161 }
0162 assert(target_fd > 0);
0163 close(fd);
0164 test_lookup(target_fd);
0165 close(target_fd);
0166
0167 return 0;
0168 }