]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - support/nfs/cacheio.c
Use __fpurge to ensure single-line writes to cache files
[nfs-utils.git] / support / nfs / cacheio.c
index 20d195c16ca4b792fbb7b7866688e7993ab87db8..9d271cd4733d77328a6f2b3e5ec8a80b5da8a73b 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <nfslib.h>
 #include <stdio.h>
+#include <stdio_ext.h>
 #include <ctype.h>
 #include <unistd.h>
 #include <sys/types.h>
@@ -109,10 +110,21 @@ void qword_printint(FILE *f, int num)
        fprintf(f, "%d ", num);
 }
 
-void qword_eol(FILE *f)
+int qword_eol(FILE *f)
 {
+       int err;
+
        fprintf(f,"\n");
-       fflush(f);
+       err = fflush(f);
+       /*
+        * We must send one line (and one line only) in a single write
+        * call.  In case of a write error, libc may accumulate the
+        * unwritten data and try to write it again later, resulting in a
+        * multi-line write.  So we must explicitly ask it to throw away
+        * any such cached data:
+        */
+       __fpurge(f);
+       return fflush(f);
 }
 
 
@@ -205,16 +217,17 @@ int readline(int fd, char **buf, int *lenp)
         */
                char *new;
                int nl;
-               *lenp += 128;
+               *lenp *= 2;
                new = realloc(*buf, *lenp);
                if (new == NULL)
                        return 0;
-               nl = read(fd, *buf +len, *lenp - len);
-               if (nl <= 0 )
+               *buf = new;
+               nl = read(fd, *buf + len, *lenp - len);
+               if (nl <= 0)
                        return 0;
-               new += nl;
+               len += nl;
        }
-       (*buf)[len-1] = 0;
+       (*buf)[len-1] = '\0';
        return 1;
 }
 
@@ -246,15 +259,25 @@ cache_flush(int force)
        int c;
        char stime[20];
        char path[200];
+       time_t now;
+       /* Note: the order of these caches is important.
+        * They need to be flushed in dependancy order. So
+        * a cache that references items in another cache,
+        * as nfsd.fh entries reference items in nfsd.export,
+        * must be flushed before the cache that it references.
+        */
        static char *cachelist[] = {
                "auth.unix.ip",
-               "nfsd.export",
+               "auth.unix.gid",
                "nfsd.fh",
+               "nfsd.export",
                NULL
        };
-       stb.st_mtime = time(0);
-       if (!force)
-               stat(_PATH_ETAB, &stb);
+       now = time(0);
+       if (force ||
+           stat(_PATH_ETAB, &stb) != 0 ||
+           stb.st_mtime > now)
+               stb.st_mtime = time(0);
        
        sprintf(stime, "%ld\n", stb.st_mtime);
        for (c=0; cachelist[c]; c++) {