2 * support/nfs/cacheio.c
3 * support IO on the cache channel files in 2.5 and beyond.
4 * These use 'qwords' which are like words, but with a little quoting.
10 * Support routines for text-based upcalls.
11 * Fields are separated by spaces.
12 * Fields are either mangled to quote space tab newline slosh with slosh
13 * or a hexified with a leading \x
14 * Record is terminated with newline.
22 #include <sys/types.h>
27 void qword_add(char **bpp, int *lp, char *str)
35 while ((c=*str++) && len)
43 *bp++ = '0' + ((c & 0300)>>6);
44 *bp++ = '0' + ((c & 0070)>>3);
45 *bp++ = '0' + ((c & 0007)>>0);
53 if (c || len <1) len = -1;
62 void qword_addhex(char **bpp, int *lp, char *buf, int blen)
73 while (blen && len >= 2) {
74 unsigned char c = *buf++;
75 *bp++ = '0' + ((c&0xf0)>>4) + (c>=0xa0)*('a'-'9'-1);
76 *bp++ = '0' + (c&0x0f) + ((c&0x0f)>=0x0a)*('a'-'9'-1);
81 if (blen || len<1) len = -1;
90 static char qword_buf[8192];
91 void qword_print(FILE *f, char *str)
94 int len = sizeof(qword_buf);
95 qword_add(&bp, &len, str);
96 fwrite(qword_buf, bp-qword_buf, 1, f);
99 void qword_printhex(FILE *f, char *str, int slen)
101 char *bp = qword_buf;
102 int len = sizeof(qword_buf);
103 qword_addhex(&bp, &len, str, slen);
104 fwrite(qword_buf, bp-qword_buf, 1, f);
107 void qword_printint(FILE *f, int num)
109 fprintf(f, "%d ", num);
112 int qword_eol(FILE *f)
120 #define isodigit(c) (isdigit(c) && c <= '7')
121 int qword_get(char **bpp, char *dest, int bufsize)
123 /* return bytes copied, or -1 on error */
127 while (*bp == ' ') bp++;
129 if (bp[0] == '\\' && bp[1] == 'x') {
132 while (isxdigit(bp[0]) && isxdigit(bp[1]) && len < bufsize) {
133 int byte = isdigit(*bp) ? *bp-'0' : toupper(*bp)-'A'+10;
136 byte |= isdigit(*bp) ? *bp-'0' : toupper(*bp)-'A'+10;
142 /* text with \nnn octal quoting */
143 while (*bp != ' ' && *bp != '\n' && *bp && len < bufsize-1) {
145 isodigit(bp[1]) && (bp[1] <= '3') &&
148 int byte = (*++bp -'0');
150 byte = (byte << 3) | (*bp++ - '0');
151 byte = (byte << 3) | (*bp++ - '0');
161 if (*bp != ' ' && *bp != '\n' && *bp != '\0')
163 while (*bp == ' ') bp++;
169 int qword_get_int(char **bpp, int *anint)
174 int len = qword_get(bpp, buf, 50);
175 if (len < 0) return -1;
176 if (len ==0) return -1;
177 rv = strtol(buf, &ep, 0);
183 int readline(int fd, char **buf, int *lenp)
185 /* read a line into *buf, which is malloced *len long
186 * realloc if needed until we find a \n
187 * nul out the \n and return
188 * 0 of eof, 1 of success
193 char *b = malloc(128);
199 len = read(fd, *buf, len);
202 while ((*buf)[len-1] != '\n') {
203 /* now the less common case. There was no newline,
204 * so we have to keep reading after re-alloc
209 new = realloc(*buf, *lenp);
213 nl = read(fd, *buf + len, *lenp - len);
218 (*buf)[len-1] = '\0';
223 /* Check if we should use the new caching interface
224 * This succeeds iff the "nfsd" filesystem is mounted on
228 check_new_cache(void)
231 return (stat("/proc/fs/nfs/filehandle", &stb) == 0) ||
232 (stat("/proc/fs/nfsd/filehandle", &stb) == 0);
236 /* flush the kNFSd caches.
237 * Set the flush time to the mtime of _PATH_ETAB or
239 * the caches to flush are:
240 * auth.unix.ip nfsd.export nfsd.fh
244 cache_flush(int force)
251 /* Note: the order of these caches is important.
252 * They need to be flushed in dependancy order. So
253 * a cache that references items in another cache,
254 * as nfsd.fh entries reference items in nfsd.export,
255 * must be flushed before the cache that it references.
257 static char *cachelist[] = {
266 stat(_PATH_ETAB, &stb) != 0 ||
268 stb.st_mtime = time(0);
270 sprintf(stime, "%ld\n", stb.st_mtime);
271 for (c=0; cachelist[c]; c++) {
273 sprintf(path, "/proc/net/rpc/%s/flush", cachelist[c]);
274 fd = open(path, O_RDWR);
276 write(fd, stime, strlen(stime));