1 /* test30: creat() (p) Jan-Mark Wams. email: jms@cs.vu.nl */ 2 3 /* 4 ** Creat() should be equivalent to: 5 ** open(path, O_WRONLY | O_CREAT | O_TRUNC, mode); 6 ** Since we can not look in the source, we can not assume creat() is 7 ** a mere sysnonym (= a systemcall synonym). 8 */ 9 10 #include <sys/types.h> 11 #include <sys/stat.h> 12 #include <sys/wait.h> 13 #include <stdlib.h> 14 #include <unistd.h> 15 #include <string.h> 16 #include <fcntl.h> 17 #include <limits.h> 18 #include <errno.h> 19 #include <time.h> 20 #include <stdio.h> 21 22 int max_error = 4; 23 #include "common.h" 24 25 #define ITERATIONS 10 26 27 28 #define System(cmd) if (system(cmd) != 0) printf("``%s'' failed\n", cmd) 29 #define Chdir(dir) if (chdir(dir) != 0) printf("Can't goto %s\n", dir) 30 #define Stat(a,b) if (stat(a,b) != 0) printf("Can't stat %s\n", a) 31 32 int superuser; 33 char *MaxName; /* Name of maximum length */ 34 char MaxPath[PATH_MAX]; /* Same for path */ 35 char *ToLongName; /* Name of maximum +1 length */ 36 char ToLongPath[PATH_MAX + 1]; /* Same for path, both too long */ 37 38 void test30a(void); 39 void test30b(void); 40 void test30c(void); 41 void makelongnames(void); 42 43 int main(int argc, char *argv[]) 44 { 45 int i, m = 0xFFFF; 46 47 sync(); 48 if (argc == 2) m = atoi(argv[1]); 49 umask(0000); 50 start(30); 51 makelongnames(); 52 superuser = (geteuid() == 0); 53 54 55 for (i = 0; i < ITERATIONS; i++) { 56 if (m & 0001) test30a(); 57 if (m & 0002) test30b(); 58 if (m & 0004) test30c(); 59 } 60 quit(); 61 62 return(-1); /* Unreachable */ 63 } 64 65 void test30a() 66 { /* Test normal operation. */ 67 68 #define BUF_SIZE 1024 69 70 int fd1, fd2; 71 char buf[BUF_SIZE]; 72 struct stat st, dirst; 73 time_t time1, time2; 74 int stat_loc, cnt; 75 76 subtest = 1; 77 78 System("rm -rf ../DIR_30/*"); 79 80 /* Check if processes have independent new fds */ 81 switch (fork()) { 82 case -1: printf("Can't fork\n"); break; 83 case 0: 84 alarm(20); 85 if ((fd1 = creat("myfile", 0644)) != 3) e(1); 86 if (close(fd1) != 0) e(2); 87 exit(0); 88 default: 89 if ((fd1 = creat("myfile", 0644)) != 3) e(3); 90 if (close(fd1) != 0) e(4); 91 if (wait(&stat_loc) == -1) e(5); 92 if (stat_loc != 0) e(6); 93 } 94 95 /* Save the dir status. */ 96 Stat(".", &dirst); 97 time(&time1); 98 while (time1 == time((time_t *)0)) 99 ; 100 101 /* Check if the file status information is updated correctly */ 102 cnt = 0; 103 System("rm -rf myfile"); 104 do { 105 time(&time1); 106 if ((fd1 = creat("myfile", 0644)) != 3) e(7); 107 Stat("myfile", &st); 108 time(&time2); 109 } while (time1 != time2 && cnt++ < 100); 110 if (cnt >= 100) e(8); 111 if (st.st_uid != geteuid()) e(9); /* Uid should be set. */ 112 #if defined(NGROUPS_MAX) && NGROUPS_MAX == 0 113 if (st.st_gid != getegid()) e(10); 114 #endif /* defined(NGROUPS_MAX) && NGROUPS_MAX == 0 */ 115 if (!S_ISREG(st.st_mode)) e(11); 116 if ((st.st_mode & 0777) != 0644) e(12); 117 if (st.st_nlink != 1) e(13); 118 if (st.st_ctime != time1) e(14); /* All time fields should be updated */ 119 if (st.st_atime != time1) e(15); 120 if (st.st_mtime != time1) e(16); 121 if (st.st_size != 0) e(17); /* File should be trunked. */ 122 123 /* Check if c and mtime for "." is updated. */ 124 Stat(".", &st); 125 if (st.st_ctime <= dirst.st_ctime) e(18); 126 if (st.st_mtime <= dirst.st_mtime) e(19); 127 128 /* Let's see if cread fds are write only. */ 129 if (read(fd1, buf, 7) != -1) e(20); /* we can't read */ 130 if (errno != EBADF) e(21); /* a write only fd */ 131 if (write(fd1, "HELLO", 6) != 6) e(22); /* but we can write */ 132 133 /* No O_APPEND flag should have been used. */ 134 if (lseek(fd1, (off_t) 1, SEEK_SET) != 1) e(23); 135 if (write(fd1, "ello", 5) != 5) e(24); 136 Stat("myfile", &st); 137 if (st.st_size != 6) e(25); 138 if (st.st_size == 11) e(26); /* O_APPEND should make it 11. */ 139 if (close(fd1) != 0) e(27); 140 141 /* A creat should set the file offset to 0. */ 142 if ((fd1 = creat("myfile", 0644)) != 3) e(28); 143 if (lseek(fd1, (off_t) 0, SEEK_CUR) != 0) e(29); 144 if (close(fd1) != 0) e(30); 145 146 /* Test if file permission bits and the file ownership are unchanged. */ 147 /* So we will see if creat() is just an open() if the file exists. */ 148 if (superuser) { 149 System("echo > bar; chmod 073 bar"); /* Make bar 073 */ 150 if (chown("bar", 1, 1) != 0) e(1137); 151 fd1 = creat("bar", 0777); /* knock knock */ 152 if (fd1 == -1) e(31); 153 Stat("bar", &st); 154 if (st.st_size != (size_t) 0) e(32); /* empty file. */ 155 if (write(fd1, "foo", 3) != 3) e(33); /* rewrite bar */ 156 if (close(fd1) != 0) e(34); 157 Stat("bar", &st); 158 if (st.st_uid != 1) e(35); 159 if (st.st_gid != 1) e(36); 160 if ((st.st_mode & 0777) != 073) e(37); /* mode still is 077 */ 161 if (st.st_size != (size_t) 3) e(38); 162 } 163 164 /* Fifo's should be openable with creat(). */ 165 if (mkfifo("fifo", 0644) != 0) e(39); 166 167 /* Creat() should have no effect on FIFO files. */ 168 switch (fork()) { 169 case -1: printf("Can't fork\n"); break; 170 case 0: 171 alarm(20); /* Give child 20 seconds to live. */ 172 if ((fd1 = open("fifo", O_WRONLY)) != 3) e(40); 173 if (write(fd1, "I did see Elvis.\n", 18) != 18) e(41); 174 if ((fd2 = creat("fifo", 0644)) != 4) e(42); 175 if (write(fd2, "I DID.\n", 8) != 8) e(43); 176 if (close(fd2) != 0) e(44); 177 if (close(fd1) != 0) e(45); 178 exit(0); 179 default: 180 if ((fd1 = open("fifo", O_RDONLY)) != 3) e(46); 181 if (read(fd1, buf, 18) != 18) e(47); 182 if (strcmp(buf, "I did see Elvis.\n") != 0) e(48); 183 if (strcmp(buf, "I DID.\n") == 0) e(49); 184 if (read(fd1, buf, BUF_SIZE) != 8) e(50); 185 if (strcmp(buf, "I DID.\n") != 0) e(51); 186 if (close(fd1) != 0) e(52); 187 if (wait(&stat_loc) == -1) e(53); 188 if (stat_loc != 0) e(54); /* The alarm went off? */ 189 } 190 191 /* Creat() should have no effect on directroys. */ 192 System("mkdir dir; touch dir/f1 dir/f2 dir/f3"); 193 if ((fd1 = creat("dir", 0644)) != -1) e(55); 194 if (errno != EISDIR) e(56); 195 close(fd1); 196 197 /* The path should contain only dirs in the prefix. */ 198 if ((fd1 = creat("dir/f1/nono", 0644)) != -1) e(57); 199 if (errno != ENOTDIR) e(58); 200 close(fd1); 201 202 /* The path should contain only dirs in the prefix. */ 203 if ((fd1 = creat("", 0644)) != -1) e(59); 204 if (errno != ENOENT) e(60); 205 close(fd1); 206 if ((fd1 = creat("dir/noso/nono", 0644)) != -1) e(61); 207 if (errno != ENOENT) e(62); 208 close(fd1); 209 210 } 211 212 void test30b() 213 { 214 int fd; 215 216 subtest = 2; 217 218 System("rm -rf ../DIR_30/*"); 219 220 /* Test maximal file name length. */ 221 if ((fd = creat(MaxName, 0777)) != 3) e(1); 222 if (close(fd) != 0) e(2); 223 MaxPath[strlen(MaxPath) - 2] = '/'; 224 MaxPath[strlen(MaxPath) - 1] = 'a'; /* make ././.../a */ 225 if ((fd = creat(MaxPath, 0777)) != 3) e(3); 226 if (close(fd) != 0) e(4); 227 MaxPath[strlen(MaxPath) - 1] = '/'; /* make ././.../a */ 228 } 229 230 void test30c() 231 { 232 int fd, does_truncate; 233 234 subtest = 3; 235 236 System("rm -rf ../DIR_30/*"); 237 238 if (!superuser) { 239 /* Test if creat is not usable to open files with the wrong mode */ 240 System("> nono; chmod 177 nono"); 241 fd = creat("nono", 0777); 242 if (fd != -1) e(1); 243 if (errno != EACCES) e(2); 244 } 245 if (mkdir("bar", 0777) != 0) e(3); /* make bar */ 246 247 /* Check if no access on part of path generates the correct error. */ 248 System("chmod 577 bar"); /* r-xrwxrwx */ 249 if (!superuser) { 250 /* Normal users can't creat without write permision. */ 251 if (creat("bar/nono", 0666) != -1) e(4); 252 if (errno != EACCES) e(5); 253 if (creat("bar/../nono", 0666) != -1) e(6); 254 if (errno != EACCES) e(7); 255 } 256 if (superuser) { 257 /* Super user can still creat stuff. */ 258 if ((fd = creat("bar/nono", 0666)) != 3) e(8); 259 if (close(fd) != 0) e(9); 260 if (unlink("bar/nono") != 0) e(10); 261 } 262 263 /* Clean up bar. */ 264 System("rm -rf bar"); 265 266 /* Test ToLongName and ToLongPath */ 267 does_truncate = does_fs_truncate(); 268 fd = creat(ToLongName, 0777); 269 if (does_truncate) { 270 if (fd == -1) e(11); 271 if (close(fd) != 0) e(12); 272 } else { 273 if (fd != -1) e(13); 274 if (errno != ENAMETOOLONG) e(14); 275 (void) close(fd); /* Just in case. */ 276 } 277 278 ToLongPath[PATH_MAX - 2] = '/'; 279 ToLongPath[PATH_MAX - 1] = 'a'; 280 if ((fd = creat(ToLongPath, 0777)) != -1) e(15); 281 if (errno != ENAMETOOLONG) e(16); 282 if (close(fd) != -1) e(17); 283 ToLongPath[PATH_MAX - 1] = '/'; 284 } 285 286 void makelongnames() 287 { 288 register int i; 289 int max_name_length; 290 291 max_name_length = name_max("."); /* Aka NAME_MAX, but not every FS supports 292 * the same length, hence runtime check */ 293 MaxName = malloc(max_name_length + 1); 294 ToLongName = malloc(max_name_length + 1 + 1); /* Name of maximum +1 length */ 295 memset(MaxName, 'a', max_name_length); 296 MaxName[max_name_length] = '\0'; 297 298 for (i = 0; i < PATH_MAX - 1; i++) { /* idem path */ 299 MaxPath[i++] = '.'; 300 MaxPath[i] = '/'; 301 } 302 MaxPath[PATH_MAX - 1] = '\0'; 303 304 strcpy(ToLongName, MaxName); /* copy them Max to ToLong */ 305 strcpy(ToLongPath, MaxPath); 306 307 ToLongName[max_name_length] = 'a'; 308 ToLongName[max_name_length+1] = '\0';/* extend ToLongName by one too many */ 309 ToLongPath[PATH_MAX - 1] = '/'; 310 ToLongPath[PATH_MAX] = '\0'; /* inc ToLongPath by one */ 311 } 312