#include <nfslib.h>
#include <stdio.h>
+#include <stdio_ext.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/types.h>
*lp = len;
}
+void qword_addint(char **bpp, int *lp, int n)
+{
+ int len;
+
+ len = snprintf(*bpp, *lp, "%d ", n);
+ if (len > *lp)
+ len = *lp;
+ *bpp += len;
+ *lp -= len;
+}
+
+void qword_adduint(char **bpp, int *lp, unsigned int n)
+{
+ int len;
+
+ len = snprintf(*bpp, *lp, "%u ", n);
+ if (len > *lp)
+ len = *lp;
+ *bpp += len;
+ *lp -= len;
+}
+
+void qword_addeol(char **bpp, int *lp)
+{
+ if (*lp <= 0)
+ return;
+ **bpp = '\n';
+ (*bpp)++;
+ (*lp)--;
+}
+
static char qword_buf[8192];
void qword_print(FILE *f, char *str)
{
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);
}
return 0;
}
+#define READLINE_BUFFER_INCREMENT 2048
+
int readline(int fd, char **buf, int *lenp)
{
/* read a line into *buf, which is malloced *len long
* realloc if needed until we find a \n
* nul out the \n and return
- * 0 of eof, 1 of success
+ * 0 on eof, 1 on success
*/
- int len = *lenp;
+ int len;
- if (len == 0) {
- char *b = malloc(128);
+ if (*lenp == 0) {
+ char *b = malloc(READLINE_BUFFER_INCREMENT);
if (b == NULL)
return 0;
*buf = b;
- *lenp = 128;
+ *lenp = READLINE_BUFFER_INCREMENT;
}
- len = read(fd, *buf, len);
+ len = read(fd, *buf, *lenp);
if (len <= 0)
return 0;
while ((*buf)[len-1] != '\n') {
*/
char *new;
int nl;
- *lenp += 128;
+ *lenp += READLINE_BUFFER_INCREMENT;
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;
}
check_new_cache(void)
{
struct stat stb;
- return (stat("/proc/fs/nfs/filehandle", &stb) == 0);
+ return (stat("/proc/fs/nfs/filehandle", &stb) == 0) ||
+ (stat("/proc/fs/nfsd/filehandle", &stb) == 0);
}
+
+/* flush the kNFSd caches.
+ * Set the flush time to the mtime of _PATH_ETAB or
+ * if force, to now.
+ * the caches to flush are:
+ * auth.unix.ip nfsd.export nfsd.fh
+ */
+
+void
+cache_flush(int force)
+{
+ struct stat stb;
+ 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",
+ "auth.unix.gid",
+ "nfsd.fh",
+ "nfsd.export",
+ NULL
+ };
+ 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++) {
+ int fd;
+ sprintf(path, "/proc/net/rpc/%s/flush", cachelist[c]);
+ fd = open(path, O_RDWR);
+ if (fd >= 0) {
+ write(fd, stime, strlen(stime));
+ close(fd);
+ }
+ }
+}