abstract
| - Below is the full text to dlb.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.0/dlb.c#line123]], for example. Warning! This is the source code from an old release. For the latest release, see Source code 1. /* SCCS Id: @(#)dlb.c 3.2 96/02/14 */ 2. /* Copyright (c) Kenneth Lorber, Bethesda, Maryland, 1993. */ 3. /* NetHack may be freely redistributed. See license for details. */ 4. 5. #include "config.h" 6. #include "dlb.h" 7. 8. #ifdef DLB 9. /* 10. * Data librarian. Present a STDIO-like interface to NetHack while 11. * multiplexing on one or more "data" libraries. If a file is not found 12. * in a given library, look for it outside the libraries. 13. * 14. * When initialized, we open all library files and read in their tables 15. * of contents. The library files stay open all the time. When 16. * a open is requested, the libraries' directories are searched. If 17. * successful, we return a descriptor that contains the library, file 18. * size, and current file mark. This descriptor is used for all 19. * successive calls. 20. * 21. * The ability to open more than one library is supported but used 22. * only in the Amiga port (the second library holds the sound files). 23. * For Unix, the idea would be to split the NetHack library 24. * into text and binary parts, where the text version could be shared. 25. */ 26. 27. 28. #define MAX_LIBS 4 29. static library dlb_libs[MAX_LIBS]; 30. static boolean dlb_initialized = FALSE; 31. 32. static boolean FDECL(readlibdir,(library *lp)); 33. static boolean FDECL(find_file,(const char *name, library **lib, long *startp, 34. long *sizep)); 35. 36. /* not static because shared with dlb_main.c */ 37. boolean FDECL(open_library,(const char *lib_name, library *lp)); 38. void FDECL(close_library,(library *lp)); 39. 40. /* without extern.h via hack.h, these haven't been declared for us */ 41. extern char *FDECL(eos, (char *)); 42. extern FILE *FDECL(fopen_datafile, (const char *,const char *)); 43. 44. /* 45. * Read the directory out of the library. Return 1 if successful, 46. * 0 if it failed. 47. * 48. * NOTE: An improvement of the file structure should be the file 49. * size as part of the directory entry or perhaps in place of the 50. * offset -- the offset can be calculated by a running tally of 51. * the sizes. 52. * 53. * Library file structure: 54. * 55. * HEADER: 56. * %3ld library FORMAT revision (currently rev 1) 57. * %1c space 58. * %8ld # of files in archive (includes 1 for directory) 59. * %1c space 60. * %8ld size of allocation for string space for directory names 61. * %1c space 62. * %8ld library offset - sanity check - lseek target for start of first file 63. * %1c space 64. * %8ld size - sanity check - byte size of complete archive file 65. * 66. * followed by one DIRECTORY entry for each file in the archive, including 67. * the directory itself: 68. * %1c handling information (compression, etc.) Always ' ' in rev 1. 69. * %s file name 70. * %1c space 71. * %8ld offset in archive file of start of this file 72. * %c newline 73. * 74. * followed by the contents of the files 75. */ 76. #define DLB_MIN_VERS 1 /* min library version readable by this code */ 77. #define DLB_MAX_VERS 1 /* max library version readable by this code */ 78. 79. /* 80. * Read the directory from the library file. This will allocate and 81. * fill in our globals. The file pointer is reset back to position 82. * zero. If any part fails, leave nothing that needs to be deallocated. 83. * 84. * Return TRUE on success, FALSE on failure. 85. */ 86. static boolean 87. readlibdir(lp) 88. library *lp; /* library pointer to fill in */ 89. { 90. int i; 91. char *sp; 92. long liboffset, totalsize; 93. 94. if (fscanf(lp->fdata, "%ld %ld %ld %ld %ld
", 95. &lp->rev,&lp->nentries,&lp->strsize,&liboffset,&totalsize) != 5) 96. return FALSE; 97. if (lp->rev > DLB_MAX_VERS || lp->rev < DLB_MIN_VERS) return FALSE; 98. 99. lp->dir = (libdir *) alloc(lp->nentries * sizeof(libdir)); 100. lp->sspace = (char *) alloc(lp->strsize); 101. 102. /* read in each directory entry */ 103. for (i = 0, sp = lp->sspace; i < lp->nentries; i++) { 104. lp->dir[i].fname = sp; 105. if (fscanf(lp->fdata, "%c%s %ld
", 106. &lp->dir[i].handling, sp, &lp->dir[i].foffset) != 3) { 107. free((genericptr_t) lp->dir); 108. free((genericptr_t) lp->sspace); 109. lp->dir = (libdir *) 0; 110. lp->sspace = (char *) 0; 111. return FALSE; 112. } 113. sp = eos(sp) + 1; 114. } 115. 116. /* calculate file sizes using offset information */ 117. for (i = 0; i < lp->nentries; i++) { 118. if (i == lp->nentries - 1) 119. lp->dir[i].fsize = totalsize - lp->dir[i].foffset; 120. else 121. lp->dir[i].fsize = lp->dir[i+1].foffset - lp->dir[i].foffset; 122. } 123. 124. (void) fseek(lp->fdata, 0L, SEEK_SET); /* reset back to zero */ 125. lp->fmark = 0; 126. 127. return TRUE; 128. } 129. 130. /* 131. * Look for the file in our directory structure. Return 1 if successful, 132. * 0 if not found. Fill in the size and starting position. 133. */ 134. static boolean 135. find_file(name, lib, startp, sizep) 136. const char *name; 137. library **lib; 138. long *startp, *sizep; 139. { 140. int i, j; 141. library *lp; 142. 143. for (i = 0; i < MAX_LIBS && dlb_libs[i].fdata; i++) { 144. lp = &dlb_libs[i]; 145. for (j = 0; j < lp->nentries; j++) { 146. if (FILENAME_CMP(name, lp->dir[j].fname) == 0) { 147. *lib = lp; 148. *startp = lp->dir[j].foffset; 149. *sizep = lp->dir[j].fsize; 150. return TRUE; 151. } 152. } 153. } 154. *lib = (library *) 0; 155. *startp = *sizep = 0; 156. return FALSE; 157. } 158. 159. /* 160. * Open the library of the given name and fill in the given library 161. * structure. Return TRUE if successful, FALSE otherwise. 162. */ 163. boolean 164. open_library(lib_name, lp) 165. const char *lib_name; 166. library *lp; 167. { 168. boolean status = FALSE; 169. 170. lp->fdata = fopen_datafile(lib_name, RDBMODE); 171. if (lp->fdata) { 172. if (readlibdir(lp)) { 173. status = TRUE; 174. } else { 175. (void) fclose(lp->fdata); 176. lp->fdata = (FILE *) 0; 177. } 178. } 179. return status; 180. } 181. 182. void 183. close_library(lp) 184. library *lp; 185. { 186. (void) fclose(lp->fdata); 187. free((genericptr_t) lp->dir); 188. free((genericptr_t) lp->sspace); 189. 190. (void) memset((char *)lp, 0, sizeof(library)); 191. } 192. 193. /* 194. * Open the library file once using stdio. Keep it open, but 195. * keep track of the file position. 196. */ 197. boolean 198. dlb_init() 199. { 200. if (dlb_initialized) return TRUE; 201. 202. /* zero out array */ 203. (void) memset((char *)&dlb_libs[0], 0, sizeof(dlb_libs)); 204. 205. /* To open more than one library, add open library calls here. */ 206. if (!open_library(DLBFILE, &dlb_libs[0])) return dlb_initialized; 207. #ifdef DLBFILE2 208. if (!open_library(DLBFILE2, &dlb_libs[1])) return dlb_initialized; 209. #endif 210. 211. dlb_initialized = TRUE; 212. 213. return dlb_initialized; 214. } 215. 216. void 217. dlb_cleanup() 218. { 219. int i; 220. 221. if (dlb_initialized) { 222. /* close the data file(s) */ 223. for (i = 0; i < MAX_LIBS && dlb_libs[i].fdata; i++) 224. close_library(&dlb_libs[i]); 225. 226. dlb_initialized = FALSE; 227. } 228. } 229. 230. dlb * 231. dlb_fopen(name, mode) 232. const char *name, *mode; 233. { 234. long start, size; 235. library *lp; 236. FILE *fp; 237. dlb *dp = (dlb *) 0; 238. 239. if (!dlb_initialized) return (dlb *) 0; 240. 241. /* look up file in directory */ 242. if (find_file(name, &lp, &start, &size)) { 243. dp = (dlb *) alloc(sizeof(dlb)); 244. dp->fp = (FILE *) 0; 245. dp->lib = lp; 246. dp->start = start; 247. dp->size = size; 248. dp->mark = 0; 249. } else if ((fp = fopen_datafile(name, mode)) != 0) { 250. /* use an external file */ 251. dp = (dlb *) alloc(sizeof(dlb)); 252. dp->fp = fp; 253. dp->lib = (library *) 0; 254. dp->start = 0; 255. dp->size = 0; 256. dp->mark = 0; 257. } 258. return dp; 259. } 260. 261. int 262. dlb_fclose(dp) 263. dlb *dp; 264. { 265. if (dlb_initialized) { 266. if (dp->fp) (void) fclose(dp->fp); 267. free((genericptr_t) dp); 268. } 269. return 0; 270. } 271. 272. int 273. dlb_fread(buf, size, quan, dp) 274. char *buf; 275. int size, quan; 276. dlb *dp; 277. { 278. long pos, nread, nbytes; 279. 280. if (!dlb_initialized || size <= 0 || quan <= 0) return 0; 281. if (dp->fp) return 282. #ifdef __SASC_60 283. (int) 284. #endif 285. fread(buf, size, quan, dp->fp); 286. 287. /* make sure we don't read into the next file */ 288. if ((dp->size - dp->mark) < (size * quan)) 289. quan = (dp->size - dp->mark) / size; 290. if (quan == 0) return 0; 291. 292. pos = dp->start + dp->mark; 293. if (dp->lib->fmark != pos) 294. fseek(dp->lib->fdata, pos, SEEK_SET); /* check for error??? */ 295. 296. nread = fread(buf, size, quan, dp->lib->fdata); 297. nbytes = nread * size; 298. dp->mark += nbytes; 299. dp->lib->fmark += nbytes; 300. 301. return nread; 302. } 303. 304. int 305. dlb_fseek(dp, pos, whence) 306. dlb *dp; 307. long pos; 308. int whence; 309. { 310. long curpos; 311. 312. if (!dlb_initialized) return EOF; 313. if (dp->fp) return fseek(dp->fp, pos, whence); 314. 315. switch (whence) { 316. case SEEK_CUR: curpos = dp->mark + pos; break; 317. case SEEK_END: curpos = dp->size - pos; break; 318. default: /* set */ curpos = pos; break; 319. } 320. if (curpos < 0) curpos = 0; 321. if (curpos > dp->size) curpos = dp->size; 322. 323. dp->mark = curpos; 324. return 0; 325. } 326. 327. char * 328. dlb_fgets(buf, len, dp) 329. char *buf; 330. int len; 331. dlb *dp; 332. { 333. int i; 334. char *bp, c = 0; 335. 336. if (!dlb_initialized) return (char *) 0; 337. if (dp->fp) return fgets(buf, len, dp->fp); 338. 339. if (len <= 0) return buf; /* sanity check */ 340. 341. /* return NULL on EOF */ 342. if (dp->mark >= dp->size) return (char *) 0; 343. 344. len--; /* save room for null */ 345. for (i = 0, bp = buf; 346. i < len && dp->mark < dp->size && c != '
'; i++, bp++) { 347. if (dlb_fread(bp, 1, 1, dp) <= 0) break; /* EOF or error */ 348. c = *bp; 349. } 350. *bp = '\0'; 351. 352. return buf; 353. } 354. 355. int 356. dlb_fgetc(dp) 357. dlb *dp; 358. { 359. char c; 360. 361. if (!dlb_initialized) return EOF; 362. if (dp->fp) return fgetc(dp->fp); 363. 364. if (dlb_fread(&c, 1, 1, dp) != 1) return EOF; 365. return (int) c; 366. } 367. 368. long 369. dlb_ftell(dp) 370. dlb *dp; 371. { 372. if (!dlb_initialized) return 0; 373. if (dp->fp) return ftell(dp->fp); 374. return dp->mark; 375. } 376. 377. #endif /* DLB */ 378. 379. /*dlb.c*/
|