00001 /* 00002 Miscellaneous examples for Chap. 3 00003 AUP2, Chap. 3 00004 00005 NOTE: Some of this code is from AUP1 and no longer works. 00006 00007 Copyright 2003 by Marc J. Rochkind. All rights reserved. 00008 May be copied only for purposes and under conditions described 00009 on the Web page www.basepath.com/aup/copyright.htm. 00010 00011 The Example Files are provided "as is," without any warranty; 00012 without even the implied warranty of merchantability or fitness 00013 for a particular purpose. The author and his publisher are not 00014 responsible for any damages, direct or incidental, resulting 00015 from the use or non-use of these Example Files. 00016 00017 The Example Files may contain defects, and some contain deliberate 00018 coding mistakes that were included for educational reasons. 00019 You are responsible for determining if and how the Example Files 00020 are to be used. 00021 00022 */ 00023 #define __EXTENSIONS__ 00024 #include "defs.h" 00025 /*3-3*/ 00026 #ifdef WANT_INODE 00027 #include <sys/types.h> 00028 #include <sys/ino.h> 00029 00030 inodes() /* print i-node info */ 00031 { 00032 struct dinode di; 00033 int fd, inumber, nread; 00034 00035 if ((fd = open("/dev/hd0", 0)) == -1) 00036 syserr("open"); 00037 if (lseek(fd, 1024L + sizeof(di), 0) == -1) /* seek to i-node 2 */ 00038 syserr("lseek"); 00039 /*-*/ 00040 for (inumber = 2; inumber <= 6; inumber++) { 00041 if ((nread = read(fd, &di, sizeof(di))) != sizeof(di)) 00042 switch (nread) { 00043 case 0: 00044 fatal("EOF"); 00045 case -1: 00046 syserr("read"); 00047 default: 00048 fatal("partial read"); 00049 } 00050 printf("i-node %d; owner = %3o; size = %7ld\n", inumber, di.di_uid, di.di_size); 00051 } 00052 } 00053 /**/ 00054 #endif WANT_INODE 00055 00056 /*3-4*/ 00057 #if 0 00058 #include <sys/dir.h> 00059 00060 directory(path) /* list directory */ 00061 char *path; 00062 { 00063 struct directx { 00064 ino_t d_ino; 00065 char d_name[DIRSIZ + 1]; 00066 } dlink; 00067 int fd, nread; 00068 char *dname; 00069 /*-*/ 00070 00071 if ((fd = open(path, 0)) == -1) 00072 syserr(path); 00073 dlink.d_name[DIRSIZ] = '\0'; 00074 /*-*/ 00075 while ((nread = read(fd, &dlink, sizeof(struct direct))) == sizeof(struct direct)) { 00076 if (dlink.d_ino == 0) 00077 dname = "--- UNUSED ---"; 00078 else 00079 dname = dlink.d_name; 00080 printf("%-14s %4d\n", dname, dlink.d_ino); 00081 } 00082 /*-*/ 00083 switch (nread) { 00084 case 0: 00085 return; 00086 case -1: 00087 syserr("read"); 00088 default: 00089 fatal("partial read"); 00090 } 00091 } 00092 /**/ 00093 #endif 00094 00095 #ifdef WANT_RAWFILE 00096 00097 #include <sys/mman.h> 00098 00099 #define RAWBUFSIZE (4096*16) 00100 #define NUMBLOCKS 10000 00101 00102 #ifdef LINUX 00103 #define FILE_BLOCK "/dev/hda2" 00104 #define FILE_RAW "/dev/raw/raw2" 00105 #elif SOLARIS 00106 #define FILE_BLOCK "/dev/dsk/c0d0p0" 00107 #define FILE_RAW "/dev/rdsk/c0d0p0" 00108 #else 00109 #error "Not supported" 00110 #endif 00111 00112 void rawfile(void) 00113 { 00114 void *buf = NULL; 00115 int fd, i; 00116 off_t where[NUMBLOCKS]; 00117 00118 for (i = 0; i < NUMBLOCKS; i++) { 00119 where[i] = (random() % NUMBLOCKS) * RAWBUFSIZE; 00120 //printf("%d\n", where[i]); 00121 } 00122 printf("RAWBUFSIZE = %d; NUMBLOCKS = %d\n", RAWBUFSIZE, NUMBLOCKS); 00123 //ec_neg1( mlockall(MCL_CURRENT | MCL_FUTURE) ) 00124 #ifdef SOLARIS 00125 ec_null( buf = memalign(RAWBUFSIZE, RAWBUFSIZE) ) 00126 #else 00127 ec_nzero( errno = posix_memalign(&buf, RAWBUFSIZE, RAWBUFSIZE) ) 00128 #endif 00129 ec_neg1( fd = open(FILE_BLOCK, O_RDONLY) ) 00130 timestart(); 00131 for (i = 0; i < NUMBLOCKS; i++) { 00132 errno = 0; 00133 if (pread(fd, buf, RAWBUFSIZE, where[i]) != RAWBUFSIZE) 00134 EC_FAIL 00135 } 00136 timestop("reading " FILE_BLOCK); 00137 ec_neg1( close(fd) ) 00138 ec_neg1( fd = open(FILE_RAW, O_RDONLY) ) 00139 timestart(); 00140 for (i = 0; i < NUMBLOCKS; i++) { 00141 errno = 0; 00142 if (pread(fd, buf, RAWBUFSIZE, where[i]) != RAWBUFSIZE) 00143 EC_FAIL 00144 } 00145 timestop("reading " FILE_RAW); 00146 ec_neg1( close(fd) ) 00147 ec_neg1( fd = creat("z.tmp", PERM_FILE) ) 00148 for (i = 0; i < NUMBLOCKS; i++) { 00149 errno = 0; 00150 if (write(fd, buf, RAWBUFSIZE) != RAWBUFSIZE) 00151 EC_FAIL 00152 } 00153 ec_neg1( close(fd) ) 00154 system("ls -l z.tmp"); 00155 ec_neg1( fd = open("z.tmp", O_RDONLY) ) 00156 timestart(); 00157 for (i = 0; i < NUMBLOCKS; i++) { 00158 errno = 0; 00159 if (pread(fd, buf, RAWBUFSIZE, where[i]) != RAWBUFSIZE) 00160 EC_FAIL 00161 } 00162 timestop("reading ordinary file"); 00163 ec_neg1( close(fd) ) 00164 ec_neg1( fd = open("z.tmp", O_RDONLY | O_RSYNC | O_DSYNC) ) 00165 timestart(); 00166 for (i = 0; i < NUMBLOCKS; i++) { 00167 errno = 0; 00168 if (pread(fd, buf, RAWBUFSIZE, where[i]) != RAWBUFSIZE) 00169 EC_FAIL 00170 } 00171 timestop("reading ordinary file (O_RSYNC | O_DSYNC)"); 00172 ec_neg1( close(fd) ) 00173 return; 00174 00175 EC_CLEANUP_BGN 00176 printf("buf addr = 0x%lx\n", (long)buf); 00177 EC_FLUSH("rawfile"); 00178 EC_CLEANUP_END 00179 } 00180 00181 #endif /* WANT_RAWFILE */ 00182 00183 #if 0 00184 /*3-5*/ 00185 int mkdir(path) /* make directory; must be superuser */ 00186 char *path; 00187 { 00188 return(mknod(path, S_IFDIR | 0775, 0)); 00189 } 00190 /**/ 00191 00192 /*3-6*/ 00193 int mkdir2(path) /* make directory */ 00194 char *path; 00195 { 00196 char cmd[50]; 00197 00198 sprintf(cmd, "mkdir %s", path); 00199 if (system(cmd) == 0) 00200 return(0); 00201 else 00202 return(-1); 00203 } 00204 /**/ 00205 00206 /*3-7*/ 00207 int mkfifo(path) /* make FIFO */ 00208 char *path; 00209 { 00210 return(mknod(path, S_IFIFO | 0666, 0)); 00211 } 00212 /**/ 00213 00214 /*3-8*/ 00215 mv(from, to) /* move file or directory; must be superuser */ 00216 char *from, *to; 00217 { 00218 bool isdir(); 00219 extern int errno; 00220 00221 if (!isdir(to)) 00222 if(unlink(to) == -1 && errno != ENOENT) 00223 syserr("unlink1"); 00224 if (link(from, to) == -1) 00225 syserr("link"); 00226 if (unlink(from) == -1) 00227 syserr("unlink2"); 00228 } 00229 00230 bool isdir(path) /* is path a directory? */ 00231 char *path; 00232 { 00233 bool ans; 00234 int fd; 00235 extern int errno; 00236 00237 ans = (fd = open(path, 1)) == -1 && errno == EISDIR; 00238 if (fd != -1 && close(fd) == -1) 00239 syserr("close"); 00240 return(ans); 00241 } 00242 /**/ 00243 00244 /*3-9*/ 00245 char *parent(path, dir) /* get parent directory */ 00246 char *path, *dir; 00247 { 00248 char *lastslash, *strrchr(); 00249 00250 strcpy(dir, path); 00251 lastslash = strrchr(dir, '/'); 00252 if (lastslash == NULL) /* current directory */ 00253 strcpy(dir, "."); 00254 else if (lastslash == dir) /* root */ 00255 strcpy(dir, "/"); 00256 else 00257 *lastslash = '\0'; 00258 return(dir); 00259 } 00260 /**/ 00261 00262 mv2(from, to) /* must be superuser */ 00263 char *from, *to; 00264 { 00265 bool isdir(); 00266 extern int errno; 00267 /*3-10*/ 00268 char dir[50], *parent(); 00269 00270 if (access(parent(from, dir), 2) == -1 || access(parent(to, dir), 2) == -1) 00271 syserr(dir); 00272 /**/ 00273 if (!isdir(to)) 00274 if(unlink(to) == -1 && errno != ENOENT) 00275 syserr("unlink1"); 00276 if (link(from, to) == -1) 00277 syserr("link"); 00278 if (unlink(from) == -1) 00279 syserr("unlink2"); 00280 } 00281 #endif 00282 void fcntl_example(void) 00283 { 00284 int fd = -1, flags; 00285 00286 ec_neg1( fd = open("tmpfile", O_WRONLY | O_CREAT | O_TRUNC, 00287 PERM_FILE) ) 00288 printf("flags at open are 0%o\n", fcntl(fd, F_GETFL)); 00289 /*[setappend-right]*/ 00290 ec_neg1( flags = fcntl(fd, F_GETFL) ) 00291 ec_neg1( fcntl(fd, F_SETFL, flags | O_APPEND) ) 00292 /*[clearappend-right]*/ 00293 ec_neg1( fcntl(fd, F_SETFL, flags & ~O_APPEND) ) 00294 /*[setappend-wrong]*/ 00295 ec_neg1( fcntl(fd, F_SETFL, O_APPEND) ) /* wrong */ 00296 /*[O_ACCMODE-right]*/ 00297 ec_neg1( flags = fcntl(fd, F_GETFL) ) 00298 if ((flags & O_ACCMODE) == O_RDONLY) 00299 /* file is opened read-only */ 00300 /*[O_ACCMODE-wrong]*/ 00301 if (flags & O_RDONLY) /* wrong */ 00302 if ((flags & O_RDONLY) == O_RDONLY) /* still wrong */ 00303 /*[]*/ 00304 ; 00305 printf("flags are now 0%o\n", fcntl(fd, F_GETFL)); 00306 ec_neg1( close(fd) ) 00307 ec_neg1( unlink("tmpfile") ) 00308 return; 00309 00310 EC_CLEANUP_BGN 00311 EC_FLUSH("setappend") 00312 EC_CLEANUP_END 00313 } 00314 /**/ 00315 00316 /*[print_statvfs]*/ 00317 #if _XOPEN_SOURCE >= 4 00318 #include <sys/statvfs.h> 00319 #define FCN_NAME statvfs 00320 #define STATVFS 1 00321 00322 #elif defined(BSD_DERIVED) 00323 #include <sys/param.h> 00324 #include <sys/mount.h> 00325 #define FCN_NAME statfs 00326 00327 #else 00328 #error "Need statvfs or nonstandard substitute" 00329 #endif 00330 00331 void print_statvfs(const char *path) 00332 { 00333 struct FCN_NAME buf; 00334 00335 if (path == NULL) 00336 path = "."; 00337 ec_neg1( FCN_NAME(path, &buf) ) 00338 #ifdef STATVFS 00339 printf("block size = %lu\n", buf.f_bsize); 00340 printf("fundamental block (fblock) size = %lu\n", buf.f_frsize); 00341 #else 00342 printf("block size = %lu\n", buf.f_iosize); 00343 printf("fundamental block size = %lu\n", buf.f_bsize); 00344 #endif 00345 printf("total number of fblocks = %llu\n", 00346 (unsigned long long)buf.f_blocks); 00347 printf("number of free fblocks = %llu\n", 00348 (unsigned long long)buf.f_bfree); 00349 printf("number of avail. fblocks = %llu\n", 00350 (unsigned long long)buf.f_bavail); 00351 printf("total number of i-numbers = %llu\n", 00352 (unsigned long long)buf.f_files); 00353 printf("number of free i-numbers = %llu\n", 00354 (unsigned long long)buf.f_ffree); 00355 #ifdef STATVFS 00356 printf("number of avail. i-numbers = %llu\n", 00357 (unsigned long long)buf.f_favail); 00358 printf("file-system ID = %lu\n", buf.f_fsid); 00359 printf("Read-only = %s\n", 00360 (buf.f_flag & ST_RDONLY) == ST_RDONLY ? "yes" : "no"); 00361 printf("No setuid/setgid = %s\n", 00362 (buf.f_flag & ST_NOSUID) == ST_NOSUID ? "yes" : "no"); 00363 printf("max length of filename = %lu\n", buf.f_namemax); 00364 #else 00365 printf("Read-only = %s\n", 00366 (buf.f_flags & MNT_RDONLY) == MNT_RDONLY ? "yes" : "no"); 00367 printf("No setuid/setgid = %s\n", 00368 (buf.f_flags & MNT_NOSUID) == MNT_NOSUID ? "yes" : "no"); 00369 #endif 00370 printf("\nFree space = %.0f%%\n", 00371 (double)buf.f_bfree * 100 / buf.f_blocks); 00372 return; 00373 00374 EC_CLEANUP_BGN 00375 EC_FLUSH("print_statvfs"); 00376 EC_CLEANUP_END 00377 } 00378 /*[]*/ 00379 #undef FCN_NAME 00380 #undef STATVFS 00381 00382 static void file_ctime_test(void) 00383 { 00384 struct stat buf; 00385 int fd; 00386 00387 ec_neg1( fd = open("tmp2", O_RDWR | O_CREAT | O_TRUNC, PERM_FILE) ) 00388 ec_neg1( write(fd, &buf, sizeof(buf)) ) 00389 ec_neg1( lseek(fd, 0, SEEK_SET) ) 00390 ec_neg1( fstat(fd, &buf) ) 00391 printf("st_atime = %s", ctime(&buf.st_atime)); 00392 printf("st_mtime = %s", ctime(&buf.st_mtime)); 00393 printf("st_ctime = %s", ctime(&buf.st_ctime)); 00394 sleep(5); 00395 ec_neg1( write(fd, "x", 1) ) 00396 ec_neg1( fstat(fd, &buf) ) 00397 printf("st_atime = %s", ctime(&buf.st_atime)); 00398 printf("st_mtime = %s", ctime(&buf.st_mtime)); 00399 printf("st_ctime = %s", ctime(&buf.st_ctime)); 00400 ec_neg1( close(fd) ) 00401 00402 return; 00403 00404 EC_CLEANUP_BGN 00405 EC_FLUSH("file_ctime_test"); 00406 EC_CLEANUP_END 00407 } 00408 /*[dir_read_test]*/ 00409 static void dump(const unsigned char *buf, ssize_t n) 00410 { 00411 int i, j; 00412 00413 for (i = 0; i < n; i += 16) { 00414 printf("%4d ", i); 00415 for (j = i; j < n && j < i + 16; j++) 00416 printf(" %c", isprint((int)buf[j]) ? buf[j] : ' '); 00417 printf("\n "); 00418 for (j = i; j < n && j < i + 16; j++) 00419 printf(" %.2x", buf[j]); 00420 printf("\n\n"); 00421 } 00422 printf("\n"); 00423 } 00424 00425 static void dir_read_test(void) 00426 { 00427 int fd; 00428 unsigned char buf[96]; 00429 ssize_t nread; 00430 00431 ec_neg1( fd = open(".", O_RDONLY) ) 00432 ec_neg1( nread = read(fd, buf, sizeof(buf)) ) 00433 dump(buf, nread); 00434 return; 00435 00436 EC_CLEANUP_BGN 00437 EC_FLUSH("dir_read_test"); 00438 EC_CLEANUP_END 00439 } 00440 /*[readdir_r_test]*/ 00441 #include <dirent.h> 00442 00443 static void readdir_r_test(void) 00444 { 00445 bool ok = false; 00446 long name_max; 00447 DIR *dir = NULL; 00448 struct dirent *entry = NULL, *result; 00449 00450 errno = 0; 00451 /* failure with errno == 0 means value not found */ 00452 ec_neg1( name_max = pathconf(".", _PC_NAME_MAX) ) 00453 ec_null( entry = malloc(offsetof(struct dirent, d_name) + 00454 name_max + 1) ) 00455 ec_null( dir = opendir(".") ) 00456 while (true) { 00457 ec_rv( readdir_r(dir, entry, &result) ) 00458 if (result == NULL) 00459 break; 00460 printf("name: %s; i-number: %ld\n", result->d_name, 00461 (long)result->d_ino); 00462 } 00463 ok = true; 00464 EC_CLEANUP 00465 00466 EC_CLEANUP_BGN 00467 if (dir != NULL) 00468 (void)closedir(dir); 00469 free(entry); 00470 if (!ok) 00471 EC_FLUSH("readdir_r_test"); 00472 EC_CLEANUP_END 00473 } 00474 /*[readdir_test]*/ 00475 static void readdir_test(void) 00476 { 00477 DIR *dir = NULL; 00478 struct dirent *entry; 00479 00480 ec_null( dir = opendir(".") ) 00481 while (errno = 0, (entry = readdir(dir)) != NULL) { 00482 char buf[200]; 00483 printf("name: %s; i-number: %ld\n", entry->d_name, 00484 (long)entry->d_ino); 00485 sprintf(buf, "ls -id %s", entry->d_name); 00486 system(buf); 00487 } 00488 ec_nzero( errno ) 00489 EC_CLEANUP 00490 00491 EC_CLEANUP_BGN 00492 if (dir != NULL) 00493 (void)closedir(dir); 00494 EC_FLUSH("readdir_test"); 00495 EC_CLEANUP_END 00496 } 00497 /*[rmdir_test]*/ 00498 void rmdir_test(void) 00499 { 00500 ec_neg1( mkdir("somedir", PERM_DIRECTORY) ) 00501 ec_neg1( rmdir("somedir") ) 00502 ec_neg1( mkdir("somedir", PERM_DIRECTORY) ) 00503 ec_neg1( close(open("somedir/x", O_WRONLY | O_CREAT, PERM_FILE)) ) 00504 ec_neg1( system("ls -ld somedir; ls -l somedir") ) 00505 if (rmdir("somedir") == -1) 00506 perror("Expected error"); 00507 ec_neg1( system("rm -rf somedir") ) 00508 ec_neg1( system("ls -ld somedir") ) 00509 return; 00510 00511 EC_CLEANUP_BGN 00512 EC_FLUSH("rmdir_test"); 00513 EC_CLEANUP_END 00514 } 00515 /*[]*/ 00516 00517 static void access_test(void) 00518 { 00519 /*[access-example]*/ 00520 if (access("tmp", F_OK) == 0) 00521 printf("Exists\n"); 00522 else if (errno == EACCES) 00523 printf("Does not exist\n"); 00524 else 00525 EC_FAIL 00526 /*[]*/ 00527 return; 00528 00529 EC_CLEANUP_BGN 00530 EC_FLUSH("access_test"); 00531 EC_CLEANUP_END 00532 } 00533 00534 #ifdef _XOPEN_UNIX 00535 void getdate_example(void) 00536 { 00537 struct tm *tp; 00538 char s[100]; 00539 00540 printf("Type dates (Ctrl-d to stop)\n"); 00541 while (fgets(s, sizeof(s), stdin)) { 00542 s[strlen(s) - 1] = '\0'; 00543 printf("Trying \"%s\" ...\n", s); 00544 if ((tp = getdate(s)) == NULL) { 00545 printf("getdate_err = %d\n", getdate_err); 00546 if (getdate_err == 1) 00547 printf("***** Must set environment variable DATEMSK to " 00548 "getdate_template.txt (and EXPORT it).*****\n"); 00549 } 00550 else 00551 printf("%s", asctime(tp)); 00552 } 00553 } 00554 #endif 00555 00556 int main(int argc, char *argv[]) 00557 { 00558 /* 00559 char s[50], dir[50]; 00560 int fd; 00561 inodes(); 00562 directory("/usr/marc/stuff"); 00563 { 00564 ssize_t n; 00565 char buf[1024]; 00566 00567 ec_neg1( symlink("lunch with Mike at 11:30", "/home/marc/mylink") ) 00568 ec_neg1( n = readlink("/home/marc/mylink", buf, sizeof(buf) - 1) ) 00569 buf[n] = '\0'; 00570 00571 printf("\"%s\"\n", buf); 00572 } 00573 file_ctime_test(); 00574 */ 00575 readdir_r_test(); 00576 /* 00577 printf("-----\n"); 00578 readdir_test(); 00579 access_test(); 00580 fcntl_example(); 00581 rmdir_test(); 00582 if (argc > 1) 00583 print_statvfs(argv[1]); 00584 else 00585 print_statvfs(NULL); 00586 */ 00587 #ifdef _XOPEN_UNIX 00588 getdate_example(); 00589 #else 00590 printf("getdate not supported\n"); 00591 #endif 00592 /* 00593 rawfile(); 00594 mkdir2("dirx.tmp"); 00595 while (gets(s) != NULL) 00596 printf("\"%s\"\n", parent(s, dir)); 00597 mv2(argv[1], argv[2]); 00598 mkfifo("fifo.tmp"); 00599 if (mkdir("dir.tmp") == -1) 00600 syserr("mkdir"); 00601 system("li -ld *.tmp; rm -rf *.tmp"); 00602 if ((fd = open("z.tmp", 1)) == -1) 00603 syserr("open"); 00604 if (setappend(fd) == -1) 00605 syserr("setappend"); 00606 write(fd, "should be last\n", 15); 00607 */ 00608 return EXIT_SUCCESS; 00609 /* 00610 EC_CLEANUP_BGN 00611 return EXIT_FAILURE; 00612 EC_CLEANUP_END 00613 */ 00614 }