summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil Brown <neilb@cse.unsw.edu.au>2002-10-11 05:40:19 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2002-10-11 05:40:19 -0700
commit5ce8b167dae710a36cf8ca0aacc456e7f4cb1818 (patch)
treef4bddf26f591f80c443886db22aa75951137d69b
parent11644e2effeabe4333397d9822a4009624c068ca (diff)
[PATCH] kNFSd: Implement get_word to help in parsing cache updates
get_word understands both \x and \012 quoting styles.
-rw-r--r--include/linux/sunrpc/cache.h1
-rw-r--r--net/sunrpc/cache.c61
2 files changed, 62 insertions, 0 deletions
diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
index 7d9f0bc0f906..8b06312e499a 100644
--- a/include/linux/sunrpc/cache.h
+++ b/include/linux/sunrpc/cache.h
@@ -273,5 +273,6 @@ extern void cache_drop(struct cache_detail *detail);
extern void add_word(char **bpp, int *lp, char *str);
extern void add_hex(char **bpp, int *lp, char *buf, int blen);
+extern int get_word(char **bpp, char *dest, int bufsize);
#endif /* _LINUX_SUNRPC_CACHE_H_ */
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index ec6b28cbc4de..d401cf6bea94 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -19,6 +19,7 @@
#include <linux/kmod.h>
#include <linux/list.h>
#include <linux/module.h>
+#include <linux/ctype.h>
#include <asm/uaccess.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
@@ -864,3 +865,63 @@ static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h)
wake_up(&queue_wait);
return 0;
}
+
+/*
+ * parse a message from user-space and pass it
+ * to an appropriate cache
+ * Messages are, like requests, separated into fields by
+ * spaces and dequotes as \xHEXSTRING or embedded \nnn octal
+ *
+ * Message is
+ * reply cachename expiry key ... content....
+ *
+ * key and content are both parsed by cache
+ */
+
+#define isodigit(c) (isdigit(c) && c <= '7')
+int get_word(char **bpp, char *dest, int bufsize)
+{
+ /* return bytes copied, or -1 on error */
+ char *bp = *bpp;
+ int len = 0;
+
+ while (*bp == ' ') bp++;
+
+ if (bp[0] == '\\' && bp[1] == 'x') {
+ /* HEX STRING */
+ bp += 2;
+ while (isxdigit(bp[0]) && isxdigit(bp[1]) && len < bufsize) {
+ int byte = isdigit(*bp) ? *bp-'0' : toupper(*bp)-'A'+10;
+ bp++;
+ byte <<= 4;
+ byte |= isdigit(*bp) ? *bp-'0' : toupper(*bp)-'A'+10;
+ *dest++ = byte;
+ bp++;
+ len++;
+ }
+ } else {
+ /* text with \nnn octal quoting */
+ while (*bp != ' ' && *bp && len < bufsize-1) {
+ if (*bp == '\\' &&
+ isodigit(bp[1]) && (bp[1] <= '3') &&
+ isodigit(bp[2]) &&
+ isodigit(bp[3])) {
+ int byte = (*++bp -'0');
+ bp++;
+ byte = (byte << 3) | (*bp++ - '0');
+ byte = (byte << 3) | (*bp++ - '0');
+ *dest++ = byte;
+ len++;
+ } else {
+ *dest++ = *bp++;
+ len++;
+ }
+ }
+ *dest = '\0';
+ }
+
+ *bpp = bp;
+ if (*bp == ' ' || *bp == '\n' || *bp == '\0')
+ return len;
+ return -1;
+}