1 /* test31: mkfifo() Author: Jan-Mark Wams (jms@cs.vu.nl) */ 2 3 #include <sys/types.h> 4 #include <sys/stat.h> 5 #include <sys/wait.h> 6 #include <stdlib.h> 7 #include <unistd.h> 8 #include <string.h> 9 #include <fcntl.h> 10 #include <limits.h> 11 #include <errno.h> 12 #include <time.h> 13 #include <stdio.h> 14 15 int max_error = 4; 16 #include "common.h" 17 18 #define ITERATIONS 10 19 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 #define Stat(a,b) if (stat(a,b) != 0) printf("Can't stat %s\n", a) 24 25 int superuser; 26 char *MaxName; /* Name of maximum length */ 27 char MaxPath[PATH_MAX]; /* Same for path */ 28 char *ToLongName; /* Name of maximum +1 length */ 29 char ToLongPath[PATH_MAX + 1]; /* Same for path, both too long */ 30 31 void test31a(void); 32 void test31b(void); 33 void test31c(void); 34 void makelongnames(void); 35 36 int main(int argc, char *argv[]) 37 { 38 int i, m = 0xFFFF; 39 40 sync(); 41 if (argc == 2) m = atoi(argv[1]); 42 umask(0000); 43 start(31); 44 makelongnames(); 45 superuser = (geteuid() == 0); 46 47 48 for (i = 0; i < ITERATIONS; i++) { 49 if (m & 0001) test31a(); 50 if (m & 0002) test31b(); 51 if (m & 0004) test31c(); 52 } 53 quit(); 54 return 1; 55 } 56 57 void test31a() 58 { /* Test normal operation. */ 59 60 #define BUF_SIZE 1024 61 62 int fd; 63 char buf[BUF_SIZE]; 64 struct stat st, dirst; 65 time_t time1, time2; 66 int stat_loc, cnt; 67 68 subtest = 1; 69 70 System("rm -rf ../DIR_31/*"); 71 72 /* Check if the file status information is updated correctly */ 73 cnt = 0; 74 Stat(".", &dirst); 75 time(&time1); 76 while (time1 == time((time_t *)0)) 77 ; 78 79 do { 80 unlink("fifo"); 81 time(&time1); 82 if (mkfifo("fifo", 0644) != 0) e(1); 83 Stat("fifo", &st); 84 time(&time2); 85 } while (time1 != time2 && cnt++ < 100); 86 87 if (cnt >= 100) e(2); 88 if (st.st_uid != geteuid()) e(3); /* Uid should be set. */ 89 #if defined(NGROUPS_MAX) && NGROUPS_MAX == 0 90 if (st.st_gid != getegid()) e(4); 91 #endif /* defined(NGROUPS_MAX) && NGROUPS_MAX == 0 */ 92 if (!S_ISFIFO(st.st_mode)) e(5); 93 if ((st.st_mode & 0777) != 0644) e(6); 94 if (st.st_nlink != 1) e(7); 95 if (st.st_ctime != time1) e(8); 96 if (st.st_atime != time1) e(9); 97 if (st.st_mtime != time1) e(10); 98 if (st.st_size != 0) e(11); /* File should be empty. */ 99 100 /* Check if status for "." is updated. */ 101 Stat(".", &st); 102 if (st.st_ctime <= dirst.st_ctime) e(12); 103 if (st.st_mtime <= dirst.st_mtime) e(13); 104 105 /* Basic checking if a fifo file created with mkfifo() is a pipe. */ 106 alarm(10); /* in case fifo hangs */ 107 switch (fork()) { 108 case -1: printf("Can't fork\n"); break; 109 case 0: 110 if ((fd = open("fifo", O_RDONLY)) != 3) e(14); 111 if (read(fd, buf, BUF_SIZE) != 7) e(15); 112 if (strcmp(buf, "banana") != 0) e(16); 113 if (close(fd) != 0) e(17); 114 if ((fd = open("fifo", O_WRONLY)) != 3) e(18); 115 if (write(fd, "thanks", 7) != 7) e(19); 116 if (close(fd) != 0) e(20); 117 exit(0); 118 119 default: 120 if ((fd = open("fifo", O_WRONLY)) != 3) e(21); 121 if (write(fd, "banana", 7) != 7) e(22); 122 if (close(fd) != 0) e(23); 123 if ((fd = open("fifo", O_RDONLY)) != 3) e(24); 124 if (read(fd, buf, BUF_SIZE) != 7) e(25); 125 if (strcmp(buf, "thanks") != 0) e(26); 126 if (close(fd) != 0) e(27); 127 wait(&stat_loc); 128 if (stat_loc != 0) e(28); /* Alarm? */ 129 } 130 alarm(0); 131 } 132 133 void test31b() 134 { 135 subtest = 2; 136 137 System("rm -rf ../DIR_31/*"); 138 139 /* Test maximal file name length. */ 140 if (mkfifo(MaxName, 0777) != 0) e(1); 141 if (unlink(MaxName) != 0) e(2); 142 MaxPath[strlen(MaxPath) - 2] = '/'; 143 MaxPath[strlen(MaxPath) - 1] = 'a'; /* make ././.../a */ 144 if (mkfifo(MaxPath, 0777) != 0) e(3); 145 if (unlink(MaxPath) != 0) e(4); 146 MaxPath[strlen(MaxPath) - 1] = '/'; /* make ././.../a */ 147 } 148 149 void test31c() 150 { 151 int does_truncate; 152 subtest = 3; 153 154 System("rm -rf ../DIR_31/*"); 155 156 /* Check if mkfifo() removes, files, fifos, dirs. */ 157 if (mkfifo("fifo", 0777) != 0) e(1); 158 System("mkdir dir; > file"); 159 if (mkfifo("fifo", 0777) != -1) e(2); 160 if (errno != EEXIST) e(3); 161 if (mkfifo("dir", 0777) != -1) e(4); 162 if (errno != EEXIST) e(5); 163 if (mkfifo("file", 0777) != -1) e(6); 164 if (errno != EEXIST) e(7); 165 166 /* Test empty path. */ 167 if (mkfifo("", 0777) != -1) e(8); 168 if (errno != ENOENT) e(9); 169 if (mkfifo("/tmp/noway/out", 0777) != -1) e(10); 170 if (errno != ENOENT) e(11); 171 172 /* Test if path prefix is a directory. */ 173 if (mkfifo("/etc/passwd/nono", 0777) != -1) e(12); 174 if (errno != ENOTDIR) e(13); 175 176 mkdir("bar", 0777); /* make bar */ 177 178 /* Check if no access on part of path generates the correct error. */ 179 System("chmod 577 bar"); /* r-xrwxrwx */ 180 if (!superuser) { 181 if (mkfifo("bar/nono", 0666) != -1) e(14); 182 if (errno != EACCES) e(15); 183 } 184 if (superuser) { 185 if (mkfifo("bar/nono", 0666) != 0) e(14); 186 if (unlink("bar/nono") != 0) e(666); 187 } 188 System("chmod 677 bar"); /* rw-rwxrwx */ 189 if (!superuser) { 190 if (mkfifo("bar/../nono", 0666) != -1) e(16); 191 if (errno != EACCES) e(17); 192 } 193 if (unlink("nono") != -1) e(18); 194 195 /* Clean up bar. */ 196 System("rm -rf bar"); 197 198 /* Test ToLongName and ToLongPath */ 199 does_truncate = does_fs_truncate(); 200 if (does_truncate) { 201 if (mkfifo(ToLongName, 0777) != 0) e(19); 202 } else { 203 if (mkfifo(ToLongName, 0777) != -1) e(20); 204 if (errno != ENAMETOOLONG) e(21); 205 } 206 207 ToLongPath[PATH_MAX - 2] = '/'; 208 ToLongPath[PATH_MAX - 1] = 'a'; 209 if (mkfifo(ToLongPath, 0777) != -1) e(22); 210 if (errno != ENAMETOOLONG) e(23); 211 ToLongPath[PATH_MAX - 1] = '/'; 212 } 213 214 void makelongnames() 215 { 216 register int i; 217 int max_name_length; 218 219 max_name_length = name_max("."); /* Aka NAME_MAX, but not every FS supports 220 * the same length, hence runtime check */ 221 MaxName = malloc(max_name_length + 1); 222 ToLongName = malloc(max_name_length + 1 + 1); /* Name of maximum +1 length */ 223 memset(MaxName, 'a', max_name_length); 224 MaxName[max_name_length] = '\0'; 225 226 for (i = 0; i < PATH_MAX - 1; i++) { /* idem path */ 227 MaxPath[i++] = '.'; 228 MaxPath[i] = '/'; 229 } 230 MaxPath[PATH_MAX - 1] = '\0'; 231 232 strcpy(ToLongName, MaxName); /* copy them Max to ToLong */ 233 strcpy(ToLongPath, MaxPath); 234 235 ToLongName[max_name_length] = 'a'; 236 ToLongName[max_name_length+1] = '\0';/* extend ToLongName by one too many */ 237 ToLongPath[PATH_MAX - 1] = '/'; 238 ToLongPath[PATH_MAX] = '\0'; /* inc ToLongPath by one */ 239 } 240