1 /* test27: stat() fstat() Author: Jan-Mark Wams (jms@cs.vu.nl) */ 2 3 #include <sys/types.h> 4 #include <sys/stat.h> 5 #include <fcntl.h> 6 #include <unistd.h> 7 #include <stdlib.h> 8 #include <errno.h> 9 #include <limits.h> 10 #include <string.h> 11 #include <limits.h> 12 #include <time.h> 13 #include <stdio.h> 14 15 #define MODE_MASK (S_IRWXU | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID) 16 int max_error = 4; 17 #include "common.h" 18 19 #define ITERATIONS 2 20 21 #define System(cmd) if (system(cmd) != 0) printf("``%s'' failed\n", cmd) 22 #define Chdir(dir) if (chdir(dir) != 0) printf("Can't goto %s\n", dir) 23 24 25 int superuser; 26 char *MaxName; /* Name of maximum length */ 27 char MaxPath[PATH_MAX]; 28 char *ToLongName; /* Name of maximum +1 length */ 29 char ToLongPath[PATH_MAX + 1]; 30 31 void test27a(void); 32 void test27b(void); 33 void test27c(void); 34 void makelongnames(void); 35 36 int main(int argc, char *argv[]) 37 { 38 int i, m = 0xFFFF; 39 40 start(27); 41 if (argc == 2) m = atoi(argv[1]); 42 superuser = (getuid() == 0); 43 makelongnames(); 44 45 for (i = 0; i < ITERATIONS; i++) { 46 if (m & 0001) test27a(); 47 if (m & 0002) test27b(); 48 if (m & 0004) test27c(); 49 } 50 quit(); 51 52 return(-1); /* Unreachable */ 53 } 54 55 void test27a() 56 { /* Test Normal operation. */ 57 struct stat st1, st2; 58 time_t time1, time2; 59 int fd, pfd[2]; 60 61 subtest = 1; 62 63 time(&time1); /* get time before */ 64 while (time1 >= time((time_t *)0)) 65 ; /* Wait for time to change. */ 66 System("echo 7bytes > foo; chmod 4750 foo"); 67 if (stat("foo", &st1) != 0) e(1); /* get foo's info */ 68 time(&time2); 69 while (time2 >= time((time_t *)0)) 70 ; /* Wait for next second. */ 71 time(&time2); /* get time after */ 72 if ((st1.st_mode & MODE_MASK) != 04750) e(2); 73 if (st1.st_nlink != 1) e(3); /* check stat */ 74 if (st1.st_uid != geteuid()) e(4); 75 #if defined(NGROUPS_MAX) && NGROUPS_MAX == 0 76 if (st1.st_gid != getegid()) e(5); 77 #endif /* defined(NGROUPS_MAX) && NGROUPS_MAX == 0 */ 78 if (st1.st_size != (size_t) 7) e(6); 79 if (st1.st_atime <= time1) e(7); 80 if (st1.st_atime >= time2) e(8); 81 if (st1.st_ctime <= time1) e(9); 82 if (st1.st_ctime >= time2) e(10); 83 if (st1.st_mtime <= time1) e(11); 84 if (st1.st_mtime >= time2) e(12); 85 86 /* Compair stat and fstat. */ 87 System("echo 7bytes > bar"); 88 fd = open("bar", O_RDWR | O_APPEND); /* the bar is open! */ 89 if (fd != 3) e(13); /* should be stderr + 1 */ 90 if (stat("bar", &st1) != 0) e(14); /* get bar's info */ 91 if (fstat(fd, &st2) != 0) e(15); /* get bar's info */ 92 93 /* St1 en st2 should be the same. */ 94 if (st1.st_dev != st2.st_dev) e(16); 95 if (st1.st_ino != st2.st_ino) e(17); 96 if (st1.st_mode != st2.st_mode) e(18); 97 if (st1.st_nlink != st2.st_nlink) e(19); 98 if (st1.st_uid != st2.st_uid) e(20); 99 if (st1.st_gid != st2.st_gid) e(21); 100 if (st1.st_size != st2.st_size) e(22); 101 if (st1.st_atime != st2.st_atime) e(23); 102 if (st1.st_ctime != st2.st_ctime) e(24); 103 if (st1.st_mtime != st2.st_mtime) e(25); 104 time(&time1); /* wait a sec. */ 105 while (time1 >= time((time_t *)0)) 106 ; 107 System("chmod 755 bar"); /* chainge mode */ 108 System("rm -f foobar; ln bar foobar"); /* chainge # links */ 109 if (write(fd, "foo", 4) != 4) e(26); /* write a bit (or two) */ 110 if (stat("bar", &st2) != 0) e(27); /* get new info */ 111 if (st2.st_dev != st1.st_dev) e(28); 112 if (st2.st_ino != st1.st_ino) e(29); /* compair the fealds */ 113 if ((st2.st_mode & MODE_MASK) != 0755) e(30); 114 if (!S_ISREG(st2.st_mode)) e(31); 115 if (st2.st_nlink != st1.st_nlink + 1) e(32); 116 if (st2.st_uid != st1.st_uid) e(33); 117 if (st2.st_gid != st1.st_gid) e(34); 118 if (st2.st_size != (size_t) 11) e(35); 119 if (st2.st_atime != st1.st_atime) e(36); 120 if (st2.st_ctime <= st1.st_ctime) e(37); 121 if (st2.st_mtime <= st1.st_mtime) e(38); 122 if (close(fd) != 0) e(39); /* sorry the bar is closed */ 123 124 /* Check special file. */ 125 if (stat("/dev/tty", &st1) != 0) e(40); 126 if (!S_ISCHR(st1.st_mode)) e(41); 127 #if defined(__minix) && defined(_NETBSD_SOURCE) 128 if (stat("/dev/ram", &st1) != 0) e(42); 129 if (!S_ISBLK(st1.st_mode)) e(43); 130 #endif 131 132 /* Check fifos. */ 133 time(&time1); 134 while (time1 >= time((time_t *)0)) 135 ; 136 if (mkfifo("fifo", 0640) != 0) e(44); 137 if (stat("fifo", &st1) != 0) e(45); /* get fifo's info */ 138 time(&time2); 139 while (time2 >= time((time_t *)0)) 140 ; 141 time(&time2); 142 if (!S_ISFIFO(st1.st_mode)) e(46); 143 if (st1.st_nlink != 1) e(47); /* check the stat info */ 144 if (st1.st_uid != geteuid()) e(48); 145 #if defined(NGROUPS_MAX) && NGROUPS_MAX == 0 146 if (st1.st_gid != getegid()) e(49); 147 #endif /* defined(NGROUPS_MAX) && NGROUPS_MAX == 0 */ 148 if (st1.st_size != (size_t) 0) e(50); 149 if (st1.st_atime <= time1) e(51); 150 if (st1.st_atime >= time2) e(52); 151 if (st1.st_ctime <= time1) e(53); 152 if (st1.st_ctime >= time2) e(54); 153 if (st1.st_mtime <= time1) e(55); 154 if (st1.st_mtime >= time2) e(56); 155 156 /* Note: the st_mode of a fstat on a pipe should contain a isfifo bit. */ 157 /* Check pipes. */ 158 time(&time1); 159 while (time1 >= time((time_t *)0)) 160 ; 161 if (pipe(pfd) != 0) e(57); 162 if (fstat(pfd[0], &st1) != 0) e(58); /* get pipe input info */ 163 time(&time2); 164 while (time2 >= time((time_t *)0)) 165 ; 166 time(&time2); 167 if (!(S_ISFIFO(st1.st_mode))) e(59); /* check stat struct */ 168 if (st1.st_uid != geteuid()) e(60); 169 if (st1.st_gid != getegid()) e(61); 170 if (st1.st_size != (size_t) 0) e(62); 171 if (st1.st_atime <= time1) e(63); 172 if (st1.st_atime >= time2) e(64); 173 if (st1.st_ctime <= time1) e(65); 174 if (st1.st_ctime >= time2) e(66); 175 if (st1.st_mtime <= time1) e(67); 176 if (st1.st_mtime >= time2) e(68); 177 if (fstat(pfd[1], &st1) != 0) e(69); /* get pipe output info */ 178 if (!(S_ISFIFO(st1.st_mode))) e(70); 179 if (st1.st_uid != geteuid()) e(71); 180 if (st1.st_gid != getegid()) e(72); 181 if (st1.st_size != (size_t) 0) e(73); 182 if (st1.st_atime < time1) e(74); 183 if (st1.st_atime > time2) e(75); 184 if (st1.st_ctime < time1) e(76); 185 if (st1.st_ctime > time2) e(77); 186 if (st1.st_mtime < time1) e(78); 187 if (st1.st_mtime > time2) e(79); 188 if (close(pfd[0]) != 0) e(80); 189 if (close(pfd[1]) != 0) e(81);/* close pipe */ 190 191 /* Check dirs. */ 192 time(&time1); 193 while (time1 >= time((time_t *)0)) 194 ; 195 System("mkdir dir"); 196 if (stat("dir", &st1) != 0) e(82); /* get dir info */ 197 time(&time2); 198 while (time2 >= time((time_t *)0)) 199 ; 200 time(&time2); 201 if (!(S_ISDIR(st1.st_mode))) e(83); /* check stat struct */ 202 if (st1.st_uid != geteuid()) e(84); 203 #if defined(NGROUPS_MAX) && NGROUPS_MAX == 0 204 if (st1.st_gid != getegid()) e(85); 205 #endif /* defined(NGROUPS_MAX) && NGROUPS_MAX == 0 */ 206 if (st1.st_atime < time1) e(86); 207 if (st1.st_atime > time2) e(87); 208 if (st1.st_ctime < time1) e(88); 209 if (st1.st_ctime > time2) e(89); 210 if (st1.st_mtime < time1) e(90); 211 if (st1.st_mtime > time2) e(91); 212 System("rm -rf ../DIR_27/*"); 213 } 214 215 void test27b() 216 { /* Test maxima. */ 217 struct stat st; 218 int fd; 219 220 subtest = 2; 221 222 /* Check stats on maximum length files names. */ 223 if (mkdir(MaxName, 0777) != 0) e(1); 224 if (stat(MaxName, &st) != 0) e(2); 225 if ((fd = open(MaxName, O_RDONLY)) != 3) e(3); 226 if (fstat(fd, &st) != 0) e(4); 227 if (close(fd) != 0) e(5); 228 if (rmdir(MaxName) != 0) e(6); 229 if (stat(MaxPath, &st) != 0) e(7); 230 if ((fd = open(MaxPath, O_RDONLY)) != 3) e(8); 231 if (fstat(fd, &st) != 0) e(9); 232 if (close(fd) != 0) e(10); 233 System("rm -rf ../DIR_27/*"); 234 } 235 236 void test27c() 237 { /* Test error response. */ 238 struct stat st; 239 int fd, i; 240 241 subtest = 3; 242 243 System("echo Hi > foo"); /* Make a file called foo. */ 244 /* Check if a un searchable dir is handled ok. */ 245 Chdir(".."); /* cd .. */ 246 System("chmod 677 DIR_27"); /* no search permission */ 247 if (stat("DIR_27/nono", &st) != -1) e(1); 248 if (superuser) { 249 if (errno != ENOENT) e(2); /* su has access */ 250 } 251 if (!superuser) { 252 if (errno != EACCES) e(3); /* we don't ;-) */ 253 } 254 System("chmod 777 DIR_27"); 255 Chdir("DIR_27"); /* back to test dir */ 256 257 /* Check on ToLongName etc. */ 258 if (stat(ToLongPath, &st) != -1) e(6); /* path is too long */ 259 if (errno != ENAMETOOLONG) e(7); 260 261 /* Test some common errors. */ 262 if (stat("nono", &st) != -1) e(8); /* nono nonexistent */ 263 if (errno != ENOENT) e(9); 264 if (stat("", &st) != -1) e(10); /* try empty */ 265 if (errno != ENOENT) e(11); 266 if (stat("foo/bar", &st) != -1) e(12); /* foo is a file */ 267 if (errno != ENOTDIR) e(13); 268 269 /* Test fstat on file descriptors that are not open. */ 270 for (i = 3; i < 6; i++) { 271 if (fstat(i, &st) != -1) e(14); 272 if (errno != EBADF) e(15); 273 } 274 275 /* Test if a just closed file is `fstat()'-able. */ 276 if ((fd = open("foo", O_RDONLY)) != 3) e(16); /* open foo */ 277 if (fstat(fd, &st) != 0) e(17); /* get stat */ 278 if (close(fd) != 0) e(18); /* close it */ 279 if (fstat(fd, &st) != -1) e(19); /* get stat */ 280 if (errno != EBADF) e(20); 281 System("rm -rf ../DIR_27/*"); 282 } 283 284 void makelongnames() 285 { 286 register int i; 287 int max_name_length; 288 289 max_name_length = name_max("."); /* Aka NAME_MAX, but not every FS supports 290 * the same length, hence runtime check */ 291 MaxName = malloc(max_name_length + 1); 292 ToLongName = malloc(max_name_length + 1 + 1); /* Name of maximum +1 length */ 293 memset(MaxName, 'a', max_name_length); 294 MaxName[max_name_length] = '\0'; 295 296 for (i = 0; i < PATH_MAX - 1; i++) { /* idem path */ 297 MaxPath[i++] = '.'; 298 MaxPath[i] = '/'; 299 } 300 MaxPath[PATH_MAX - 1] = '\0'; 301 302 strcpy(ToLongName, MaxName); /* copy them Max to ToLong */ 303 strcpy(ToLongPath, MaxPath); 304 305 ToLongName[max_name_length] = 'a'; 306 ToLongName[max_name_length+1] = '\0';/* extend ToLongName by one too many */ 307 ToLongPath[PATH_MAX - 1] = '/'; 308 ToLongPath[PATH_MAX] = '\0'; /* inc ToLongPath by one */ 309 } 310 311