00001 /* 00002 File locking (bad example) 00003 AUP2, Sec. 7.11.1 00004 00005 Copyright 2003 by Marc J. Rochkind. All rights reserved. 00006 May be copied only for purposes and under conditions described 00007 on the Web page www.basepath.com/aup/copyright.htm. 00008 00009 The Example Files are provided "as is," without any warranty; 00010 without even the implied warranty of merchantability or fitness 00011 for a particular purpose. The author and his publisher are not 00012 responsible for any damages, direct or incidental, resulting 00013 from the use or non-use of these Example Files. 00014 00015 The Example Files may contain defects, and some contain deliberate 00016 coding mistakes that were included for educational reasons. 00017 You are responsible for determining if and how the Example Files 00018 are to be used. 00019 00020 */ 00021 #include "defs.h" 00022 /*[rec]*/ 00023 struct rec { 00024 int r_data; 00025 off_t r_next; 00026 }; 00027 /*[readrec]*/ 00028 bool readrec(int dbfd, struct rec *r, off_t off) 00029 { 00030 ssize_t nread; 00031 00032 if ((nread = pread(dbfd, r, sizeof(struct rec), off)) == 00033 sizeof(struct rec)) 00034 return true; 00035 if (nread != -1) 00036 errno = EIO; 00037 EC_FAIL 00038 return true; 00039 00040 EC_CLEANUP_BGN 00041 return false; 00042 EC_CLEANUP_END 00043 } 00044 00045 bool writerec(int dbfd, struct rec *r, off_t off) 00046 { 00047 ssize_t nwrote; 00048 00049 if ((nwrote = pwrite(dbfd, r, sizeof(struct rec), off)) == 00050 sizeof(struct rec)) 00051 return true; 00052 if (nwrote != -1) 00053 errno = EIO; 00054 EC_FAIL 00055 return true; 00056 00057 EC_CLEANUP_BGN 00058 return false; 00059 EC_CLEANUP_END 00060 } 00061 /*[store]*/ 00062 bool store(int dbfd, int data) 00063 { 00064 struct rec r, rnew; 00065 off_t end, prev; 00066 00067 ec_neg1( end = lseek(dbfd, 0, SEEK_END) ) 00068 prev = 0; 00069 ec_false( readrec(dbfd, &r, prev) ) 00070 while (r.r_next != 0) { 00071 ec_false( readrec(dbfd, &r, r.r_next) ) 00072 if (r.r_data > data) 00073 break; 00074 prev = r.r_next; 00075 } 00076 ec_false( readrec(dbfd, &r, prev) ) 00077 rnew.r_next = r.r_next; 00078 r.r_next = end; 00079 ec_false( writerec(dbfd, &r, prev) ) 00080 rnew.r_data = data; 00081 usleep(1); /* give up CPU */ 00082 ec_false( writerec(dbfd, &rnew, end) ) 00083 return true; 00084 00085 EC_CLEANUP_BGN 00086 return false; 00087 EC_CLEANUP_END 00088 } 00089 /*[process1]*/ 00090 #define DBNAME "termdb" 00091 00092 static void process1(void) 00093 { 00094 int dbfd, data; 00095 struct rec r; 00096 00097 ec_neg1( dbfd = open(DBNAME, O_CREAT | O_TRUNC | O_RDWR, PERM_FILE) ) 00098 memset(&r, 0, sizeof(r)); 00099 ec_false( writerec(dbfd, &r, 0) ) 00100 for (data = 100; data >= 0; data--) 00101 ec_false( store(dbfd, data) ) 00102 ec_neg1( close(dbfd) ) 00103 exit(EXIT_SUCCESS); 00104 00105 EC_CLEANUP_BGN 00106 exit(EXIT_FAILURE); 00107 EC_CLEANUP_END 00108 } 00109 /*[process2]*/ 00110 static void process2(void) 00111 { 00112 int try, dbfd; 00113 struct rec r1, r2; 00114 00115 for (try = 0; try < 10; try++) 00116 if ((dbfd = open(DBNAME, O_RDWR)) == -1) { 00117 if (errno == ENOENT) { 00118 continue; 00119 } 00120 else 00121 EC_FAIL 00122 } 00123 ec_neg1( dbfd ) 00124 for (try = 0; try < 100; try++) { 00125 ec_false( readrec(dbfd, &r1, 0) ) 00126 while (r1.r_next != 0) { 00127 ec_false( readrec(dbfd, &r2, r1.r_next) ) 00128 if (r1.r_data > r2.r_data) { 00129 printf("Found sorting error (try %d)\n", try); 00130 break; 00131 } 00132 r1 = r2; 00133 } 00134 } 00135 ec_neg1( close(dbfd) ) 00136 return; 00137 00138 EC_CLEANUP_BGN 00139 exit(EXIT_FAILURE); 00140 EC_CLEANUP_END 00141 } 00142 /*[main]*/ 00143 int main(void) 00144 { 00145 pid_t pid; 00146 00147 ec_neg1( pid = fork() ) 00148 if (pid == 0) 00149 process1(); 00150 else { 00151 process2(); 00152 ec_neg1( waitpid(pid, NULL, 0) ) 00153 } 00154 exit(EXIT_SUCCESS); 00155 00156 EC_CLEANUP_BGN 00157 exit(EXIT_FAILURE); 00158 EC_CLEANUP_END 00159 } 00160 /*[]*/