2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,
4 * Ken Stevens, Steve McClure
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23 * related information and legal notices. It is expected that any future
24 * projects/authors will amend these files as needed.
28 * file.c: Misc. operations on files
30 * Known contributors to this file:
57 static void fillcache(struct empfile *ep, int start);
60 ef_open(int type, int mode, int how)
62 register struct empfile *ep;
69 if (ef_check(type) < 0)
72 if ((ep->fd = open(ep->file, mode, 0660)) < 0) {
73 logerror("%s: open failed", ep->file);
77 block = blksize(ep->fd);
82 ep->fids = fsize(ep->fd) / ep->size;
83 if (ep->flags & EFF_MEM)
86 ep->csize = block / ep->size;
87 size = ep->csize * ep->size;
88 ep->cache = (s_char *)malloc(size);
89 if ((ep->cache == 0) && (size !=0)) {
90 logerror("ef_open: %s malloc(%d) failed\n", ep->file, size);
93 if (ep->flags & EFF_MEM) {
94 if (read(ep->fd, ep->cache, size) != size) {
95 logerror("ef_open: read(%s) failed\n", ep->file);
98 ep->cids = size / ep->size;
106 register struct empfile *ep;
109 if (ef_check(type) < 0)
112 if (ep->cache == 0) {
113 /* no cache implies never opened */
117 ep->flags &= ~EFF_MEM;
120 if ((r = close(ep->fd)) < 0) {
121 logerror("ef_close: %s close(%d) -> %d",
122 ep->name, ep->fd, r);
130 register struct empfile *ep;
134 if (ef_check(type) < 0)
137 if (ep->cache == 0) {
138 /* no cache implies never opened */
141 size = ep->csize * ep->size;
142 if (ep->mode > 0 && (ep->flags & EFF_MEM)) {
143 if ((r = lseek(ep->fd, 0L, 0)) < 0) {
144 logerror("ef_flush: %s cache lseek(%d, 0L, 0) -> %d",
145 ep->name, ep->fd, r);
148 if (write(ep->fd, ep->cache, size) != size) {
149 logerror("ef_flush: %s cache write(%d, %x, %d) -> %d",
150 ep->name, ep->fd, ep->cache, ep->size, r);
154 /*ef_zapcache(type);*/
159 ef_ptr(int type, int id)
161 register struct empfile *ep;
163 if (ef_check(type) < 0)
166 if (id < 0 || id >= ep->fids)
168 if ((ep->flags & EFF_MEM) == 0) {
169 logerror("ef_ptr: (%s) only valid for EFF_MEM entries",
173 return (s_char *) (ep->cache + ep->size * id);
177 * buffered read. Tries to read a large number of items.
178 * This system won't work if item size is > sizeof buffer area.
181 ef_read(int type, int id, caddr_t ptr)
183 register struct empfile *ep;
186 if (ef_check(type) < 0)
191 if (ep->flags & EFF_MEM) {
194 from = ep->cache + (id * ep->size);
196 if (id >= ep->fids) {
197 ep->fids = fsize(ep->fd) / ep->size;
201 if (ep->baseid + ep->cids <= id || ep->baseid > id)
203 from = ep->cache + (id - ep->baseid) * ep->size;
205 bcopy(from, ptr, ep->size);
208 ep->postread(id, ptr);
213 fillcache(struct empfile *ep, int start)
218 lseek(ep->fd, start * ep->size, 0);
219 n = read(ep->fd, ep->cache, ep->csize * ep->size);
220 ep->cids = n / ep->size;
229 ef_nbread(int type, int id, caddr_t ptr)
231 register struct empfile *ep;
234 if (ef_check(type) < 0)
239 if (id >= ep->fids) {
240 ep->fids = fsize(ep->fd) / ep->size;
244 if ((r = lseek(ep->fd, id * ep->size, 0)) < 0) {
245 logerror("ef_nbread: %s #%d lseek(%d, %d, 0) -> %d",
246 ep->name, id, ep->fd, id * ep->size, r);
249 if ((r = read(ep->fd, ptr, ep->size)) != ep->size) {
250 logerror("ef_nbread: %s #%d read(%d, %x, %d) -> %d",
251 ep->name, id, ep->fd, ptr, ep->size, r);
256 ep->postread(id, ptr);
262 * buffered write. Modifies read cache (if applicable)
263 * and writes through to disk.
266 ef_write(int type, int id, caddr_t ptr)
269 register struct empfile *ep;
272 if (ef_check(type) < 0)
276 /* largest unit id; this may bite us in large games */
277 logerror("ef_write: type %d id %d is too large!\n", type, id);
280 if ((r = lseek(ep->fd, id * ep->size, 0)) < 0) {
281 logerror("ef_write: %s #%d lseek(%d, %d, 0) -> %d",
282 ep->name, id, ep->fd, id * ep->size, r);
286 ep->prewrite(id, ptr);
287 if ((r = write(ep->fd, ptr, ep->size)) != ep->size) {
288 logerror("ef_write: %s #%d write(%d, %x, %d) -> %d",
289 ep->name, id, ep->fd, ptr, ep->size, r);
292 if (id >= ep->baseid && id < ep->baseid + ep->cids) {
293 /* update the cache if necessary */
294 to = ep->cache + (id - ep->baseid) * ep->size;
295 bcopy(ptr, to, ep->size);
298 logerror("WARNING ef_write: expanded %s by more than one id",
302 if (id >= ep->fids) {
303 if (ep->flags & EFF_MEM) {
304 logerror("file %s went beyond %d items; won't be able toread item w/o restart", ep->name, ep->fids);
306 /* write expanded file; ep->fids = last id + 1 */
319 ef_nbwrite(int type, int id, caddr_t ptr)
321 register struct empfile *ep;
324 if (ef_check(type) < 0)
328 /* largest unit id; this may bite us in large games */
329 logerror("ef_nbwrite: %s id %d is too large!\n", ep->name, id);
332 if ((r = lseek(ep->fd, id * ep->size, 0)) < 0) {
333 logerror("ef_nbwrite: %s #%d lseek(%d, %d, 0) -> %d",
334 ep->name, id, ep->fd, id * ep->size, r);
338 ep->prewrite(id, ptr);
339 if ((r = write(ep->fd, ptr, ep->size)) != ep->size) {
340 logerror("ef_nbwrite: %s #%d write(%d, %x, %d) -> %d",
341 ep->name, id, ep->fd, ptr, ep->size, r);
345 if (id >= ep->fids) {
346 /* write expanded file; ep->fids = last id + 1 */
354 ef_extend(int type, int count)
356 register struct empfile *ep;
362 if (ef_check(type) < 0)
365 max = ep->fids + count;
367 ptr = (s_char *)calloc(1, ep->size);
368 if ((r = lseek(ep->fd, ep->fids * ep->size, 0)) < 0) {
369 logerror("ef_extend: %s +#%d lseek(%d, %d, 0) -> %d",
370 ep->name, count, ep->fd, ep->fids * ep->size, r);
373 for (cur = ep->fids; cur < max; cur++) {
376 if ((r = write(ep->fd, ptr, ep->size)) != ep->size) {
377 logerror("ef_extend: %s +#%d write(%d, %x, %d) -> %d",
378 ep->name, count, ep->fd, ptr, ep->size, r);
383 if (ep->flags & EFF_MEM) {
384 /* XXX this will cause problems if there are ef_ptrs (to the
385 * old allocated structure) active when we do the re-open */
389 ef_open(type, mode, how);
397 ef_zapcache(int type)
399 register struct empfile *ep = &empfile[type];
400 if ((ep->flags & EFF_MEM) == 0) {
409 return empfile[type].cadef;
415 return empfile[type].fids;
421 return empfile[type].flags;
427 return file_lock(empfile[type].fd);
433 return file_unlock(empfile[type].fd);
439 extern time_t fdate(int fd);
441 if (empfile[type].fd <= 0)
443 return fdate(empfile[type].fd);
447 ef_vars(int type, register s_char *sp, u_char **nvp, u_char **vp, u_short **ap)
449 register struct empfile *ef;
451 if (ef_check(type) < 0)
454 if ((ef->flags & EFF_COM) == 0)
456 *nvp = (u_char *) (sp + ef->varoffs[0]);
457 *vp = (u_char *) (sp + ef->varoffs[1]);
458 *ap = (u_short *) (sp + ef->varoffs[2]);
463 ef_byname(s_char *name)
465 register struct empfile *ef;
470 for (i=0; i<EF_MAX; i++) {
472 if (strncmp(ef->name, name, min(len, strlen(ef->name))) == 0)
481 if (type < 0 || type >= EF_MAX)
482 return "bad item type";
483 return empfile[type].name;
489 if (type < 0 || type >= EF_MAX) {
490 logerror("ef_ptr: bad EF_type %d\n", type);