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", ep->name, ep->fd, r);
129 register struct empfile *ep;
133 if (ef_check(type) < 0)
136 if (ep->cache == 0) {
137 /* no cache implies never opened */
140 size = ep->csize * ep->size;
141 if (ep->mode > 0 && (ep->flags & EFF_MEM)) {
142 if ((r = lseek(ep->fd, 0L, 0)) < 0) {
143 logerror("ef_flush: %s cache lseek(%d, 0L, 0) -> %d",
144 ep->name, ep->fd, r);
147 if (write(ep->fd, ep->cache, size) != size) {
148 logerror("ef_flush: %s cache write(%d, %x, %d) -> %d",
149 ep->name, ep->fd, ep->cache, ep->size, r);
153 /*ef_zapcache(type); */
158 ef_ptr(int type, int id)
160 register struct empfile *ep;
162 if (ef_check(type) < 0)
165 if (id < 0 || id >= ep->fids)
167 if ((ep->flags & EFF_MEM) == 0) {
168 logerror("ef_ptr: (%s) only valid for EFF_MEM entries", ep->file);
171 return (s_char *)(ep->cache + ep->size * id);
175 * buffered read. Tries to read a large number of items.
176 * This system won't work if item size is > sizeof buffer area.
179 ef_read(int type, int id, caddr_t ptr)
181 register struct empfile *ep;
184 if (ef_check(type) < 0)
189 if (ep->flags & EFF_MEM) {
192 from = ep->cache + (id * ep->size);
194 if (id >= ep->fids) {
195 ep->fids = fsize(ep->fd) / ep->size;
199 if (ep->baseid + ep->cids <= id || ep->baseid > id)
201 from = ep->cache + (id - ep->baseid) * ep->size;
203 bcopy(from, ptr, ep->size);
206 ep->postread(id, ptr);
211 fillcache(struct empfile *ep, int start)
216 lseek(ep->fd, start * ep->size, 0);
217 n = read(ep->fd, ep->cache, ep->csize * ep->size);
218 ep->cids = n / ep->size;
227 ef_nbread(int type, int id, caddr_t ptr)
229 register struct empfile *ep;
232 if (ef_check(type) < 0)
237 if (id >= ep->fids) {
238 ep->fids = fsize(ep->fd) / ep->size;
242 if ((r = lseek(ep->fd, id * ep->size, 0)) < 0) {
243 logerror("ef_nbread: %s #%d lseek(%d, %d, 0) -> %d",
244 ep->name, id, ep->fd, id * ep->size, r);
247 if ((r = read(ep->fd, ptr, ep->size)) != ep->size) {
248 logerror("ef_nbread: %s #%d read(%d, %x, %d) -> %d",
249 ep->name, id, ep->fd, ptr, ep->size, r);
254 ep->postread(id, ptr);
260 * buffered write. Modifies read cache (if applicable)
261 * and writes through to disk.
264 ef_write(int type, int id, caddr_t ptr)
267 register struct empfile *ep;
270 if (ef_check(type) < 0)
274 /* largest unit id; this may bite us in large games */
275 logerror("ef_write: type %d id %d is too large!\n", type, id);
278 if ((r = lseek(ep->fd, id * ep->size, 0)) < 0) {
279 logerror("ef_write: %s #%d lseek(%d, %d, 0) -> %d",
280 ep->name, id, ep->fd, id * ep->size, r);
284 ep->prewrite(id, ptr);
285 if ((r = write(ep->fd, ptr, ep->size)) != ep->size) {
286 logerror("ef_write: %s #%d write(%d, %x, %d) -> %d",
287 ep->name, id, ep->fd, ptr, ep->size, r);
290 if (id >= ep->baseid && id < ep->baseid + ep->cids) {
291 /* update the cache if necessary */
292 to = ep->cache + (id - ep->baseid) * ep->size;
293 bcopy(ptr, to, ep->size);
296 logerror("WARNING ef_write: expanded %s by more than one id",
300 if (id >= ep->fids) {
301 if (ep->flags & EFF_MEM) {
303 ("file %s went beyond %d items; won't be able toread item w/o restart",
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,
450 register struct empfile *ef;
452 if (ef_check(type) < 0)
455 if ((ef->flags & EFF_COM) == 0)
457 *nvp = (u_char *)(sp + ef->varoffs[0]);
458 *vp = (u_char *)(sp + ef->varoffs[1]);
459 *ap = (u_short *)(sp + ef->varoffs[2]);
464 ef_byname(s_char *name)
466 register struct empfile *ef;
471 for (i = 0; i < EF_MAX; i++) {
473 if (strncmp(ef->name, name, min(len, strlen(ef->name))) == 0)
482 if (type < 0 || type >= EF_MAX)
483 return "bad item type";
484 return empfile[type].name;
490 if (type < 0 || type >= EF_MAX) {
491 logerror("ef_ptr: bad EF_type %d\n", type);