]> git.pond.sub.org Git - empserver/blobdiff - src/lib/common/file.c
Update copyright notice.
[empserver] / src / lib / common / file.c
index bf8be5c10561898048de0898641a7de2467de073..3200da6fd57ea12cad594e48f66de78c6fa7181a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2005, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ *  Copyright (C) 1986-2007, Dave Pare, Jeff Bailey, Thomas Ruschak,
  *                           Ken Stevens, Steve McClure
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -19,9 +19,9 @@
  *
  *  ---
  *
- *  See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
- *  related information and legal notices. It is expected that any future
- *  projects/authors will amend these files as needed.
+ *  See files README, COPYING and CREDITS in the root of the source
+ *  tree for related information and legal notices.  It is expected
+ *  that future projects/authors will amend these files as needed.
  *
  *  ---
  *
  *     Markus Armbruster, 2005
  */
 
+#include <config.h>
+
 #include <errno.h>
+#if defined(_WIN32)
+#if !defined(__GNUC__)
+#include <io.h>
+#endif
+#include <share.h>
+#endif
 #include <fcntl.h>
 #include <signal.h>
-#include <stdlib.h>
-#include <string.h>
+#include <sys/types.h>
 #if !defined(_WIN32)
 #include <unistd.h>
 #endif
-#include "common.h"
 #include "file.h"
-#include "gen.h"
 #include "match.h"
 #include "misc.h"
 #include "nsc.h"
 #include "optlist.h"
+#include "prototypes.h"
 
 static int fillcache(struct empfile *, int);
 static int do_write(struct empfile *, void *, int, int);
@@ -63,6 +69,9 @@ int
 ef_open(int type, int how)
 {
     struct empfile *ep;
+#if !defined(_WIN32)
+    struct flock lock;
+#endif
     int oflags, fd, fsiz, size;
 
     if (ef_check(type) < 0)
@@ -81,12 +90,27 @@ ef_open(int type, int how)
        oflags |= O_CREAT | O_TRUNC;
 #if defined(_WIN32)
     oflags |= O_BINARY;
-#endif
+    if ((fd = sopen(ep->file, oflags,
+       how & EFF_RDONLY ? SH_DENYNO : SH_DENYWR,
+       0660)) < 0) {
+       logerror("Can't open %s (%s)", ep->file, strerror(errno));
+       return 0;
+    }
+#else
     if ((fd = open(ep->file, oflags, 0660)) < 0) {
        logerror("Can't open %s (%s)", ep->file, strerror(errno));
        return 0;
     }
 
+    lock.l_type = how & EFF_RDONLY ? F_RDLCK : F_WRLCK;
+    lock.l_whence = SEEK_SET;
+    lock.l_start = lock.l_len = 0;
+    if (fcntl(fd, F_SETLK, &lock) == -1) {
+       logerror("Can't lock %s (%s)", ep->file, strerror(errno));
+       return 0;
+    }
+#endif
+
     /* get file size */
     fsiz = fsize(fd);
     if (fsiz % ep->size) {
@@ -99,7 +123,7 @@ ef_open(int type, int how)
 
     /* allocate cache */
     if (ep->flags & EFF_STATIC) {
-       /* ep->cache already points to space for e->csize elements */
+       /* ep->cache already points to space for ep->csize elements */
        if (how & EFF_MEM) {
            if (ep->fids > ep->csize) {
                logerror("Can't open %s: file larger than %d bytes",
@@ -112,12 +136,15 @@ ef_open(int type, int how)
        if (how & EFF_MEM)
            ep->csize = ep->fids;
        else
-           ep->csize = max(1, blksize(fd) / ep->size);
+           ep->csize = blksize(fd) / ep->size;
+       /* 0 could lead to null cache, which confuses assertions */
+       if (!ep->csize)
+           ep->csize++;
        size = ep->csize * ep->size;
        if (CANT_HAPPEN(ep->cache))
            free(ep->cache);
        ep->cache = malloc(size);
-       if (ep->cache == NULL && size) {
+       if (ep->cache == NULL) {
            logerror("Can't open %s: out of memory", ep->file);
            close(fd);
            return 0;
@@ -210,10 +237,10 @@ ef_ptr(int type, int id)
     if (ef_check(type) < 0)
        return NULL;
     ep = &empfile[type];
-    if (CANT_HAPPEN(!(ep->flags & EFF_MEM)))
+    if (CANT_HAPPEN(!(ep->flags & EFF_MEM) || !ep->cache))
        return NULL;
     if (id < 0 || id >= ep->fids)
-       return NULL;            /* FIXME can this happen? */
+       return NULL;
     return ep->cache + ep->size * id;
 }
 
@@ -233,9 +260,7 @@ ef_read(int type, int id, void *into)
     ep = &empfile[type];
     if (CANT_HAPPEN(!ep->cache))
        return 0;
-    if (id < 0)
-       return 0;               /* FIXME can this happen? */
-    if (id >= ep->fids)
+    if (id < 0 || id >= ep->fids)
        return 0;
 
     if (ep->flags & EFF_MEM) {
@@ -361,7 +386,8 @@ ef_write(int type, int id, void *from)
     if (id >= ep->baseid && id < ep->baseid + ep->cids) {
        /* update the cache if necessary */
        to = ep->cache + (id - ep->baseid) * ep->size;
-       memcpy(to, from, ep->size);
+       if (to != from)
+           memcpy(to, from, ep->size);
     }
     if (id >= ep->fids) {
        /* write beyond end of file extends it, take note */
@@ -378,7 +404,7 @@ int
 ef_extend(int type, int count)
 {
     struct empfile *ep;
-    char *tmpobj;
+    void *tmpobj;
     int id, i, how;
 
     if (ef_check(type) < 0)
@@ -506,6 +532,7 @@ ef_ensure_space(int type, int id, int count)
 {
     if (ef_check(type) < 0)
        return 0;
+    CANT_HAPPEN(id < 0);
 
     while (id >= empfile[type].fids) {
        if (!ef_extend(type, count))
@@ -521,18 +548,6 @@ ef_fix_size(struct empfile *ep, int n)
     ep->csize = n + 1;
 }
 
-static void
-ef_init_chr(int type, size_t size, ptrdiff_t name_offs)
-{
-    struct empfile *ep = &empfile[type];
-    char *p;
-
-    for (p = ep->cache;
-        *((char **)(p + name_offs)) && **((char **)(p + name_offs));
-        p += size) ;
-    ef_fix_size(ep, (p - ep->cache) / size);
-}
-
 /*
  * Initialize Empire tables.
  * Must be called once, before using anything else from this module.
@@ -547,15 +562,6 @@ ef_init(void)
 
     empfile[EF_MAP].size = empfile[EF_BMAP].size = (WORLD_X * WORLD_Y) / 2;
 
-    ef_init_chr(EF_SHIP_CHR,
-               sizeof(struct mchrstr), offsetof(struct mchrstr, m_name));
-    ef_init_chr(EF_PLANE_CHR,
-               sizeof(struct plchrstr), offsetof(struct plchrstr, pl_name));
-    ef_init_chr(EF_LAND_CHR,
-               sizeof(struct lchrstr), offsetof(struct lchrstr, l_name));
-    ef_init_chr(EF_NUKE_CHR,
-               sizeof(struct nchrstr), offsetof(struct nchrstr, n_name));
-
     ca = (struct castr *)empfile[EF_META].cache;
     for (i = 0; ca[i].ca_name; i++) ;
     ef_fix_size(&empfile[EF_META], i);