From 68b83a4181d3cbc87b015def11ca7bfacf424865 Mon Sep 17 00:00:00 2001 From: szaka Date: Sat, 12 Apr 2008 14:05:43 +0000 Subject: [PATCH] fix: FUSE limited the total file system depth to 4095 characters and gave "No such file or directory" errors (Miklos Szeredi, Szabolcs Szakacsits) --- libfuse-lite/fuse.c | 55 ++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/libfuse-lite/fuse.c b/libfuse-lite/fuse.c index 1eeed443..9e850743 100644 --- a/libfuse-lite/fuse.c +++ b/libfuse-lite/fuse.c @@ -28,7 +28,6 @@ #include #include -#define FUSE_MAX_PATH 4096 #define FUSE_DEFAULT_INTR_SIGNAL SIGUSR1 #define FUSE_UNKNOWN_INO 0xffffffff @@ -302,14 +301,28 @@ static struct node *find_node(struct fuse *f, fuse_ino_t parent, return node; } -static char *add_name(char *buf, char *s, const char *name) +static char *add_name(char **buf, unsigned *bufsize, char *s, const char *name) { size_t len = strlen(name); - s -= len; - if (s <= buf) { - fprintf(stderr, "fuse: path too long: ...%s\n", s + len); - return NULL; + + if (s - len <= *buf) { + unsigned pathlen = *bufsize - (s - *buf); + unsigned newbufsize = *bufsize; + char *newbuf; + + while (newbufsize < pathlen + len + 1) + newbufsize *= 2; + + newbuf = realloc(*buf, newbufsize); + if (newbuf == NULL) + return NULL; + + *buf = newbuf; + s = newbuf + newbufsize - pathlen; + memmove(s, newbuf + *bufsize - pathlen, pathlen); + *bufsize = newbufsize; } + s -= len; strncpy(s, name, len); s--; *s = '/'; @@ -319,16 +332,22 @@ static char *add_name(char *buf, char *s, const char *name) static char *get_path_name(struct fuse *f, fuse_ino_t nodeid, const char *name) { - char buf[FUSE_MAX_PATH]; - char *s = buf + FUSE_MAX_PATH - 1; + unsigned bufsize = 256; + char *buf; + char *s; struct node *node; + buf = malloc(bufsize); + if (buf == NULL) + return NULL; + + s = buf + bufsize - 1; *s = '\0'; if (name != NULL) { - s = add_name(buf, s, name); + s = add_name(&buf, &bufsize, s, name); if (s == NULL) - return NULL; + goto out_free; } pthread_mutex_lock(&f->lock); @@ -339,18 +358,24 @@ static char *get_path_name(struct fuse *f, fuse_ino_t nodeid, const char *name) break; } - s = add_name(buf, s, node->name); + s = add_name(&buf, &bufsize, s, node->name); if (s == NULL) break; } pthread_mutex_unlock(&f->lock); if (node == NULL || s == NULL) - return NULL; - else if (*s == '\0') - return strdup("/"); + goto out_free; + + if (s[0]) + memmove(buf, s, bufsize - (s - buf)); else - return strdup(s); + strcpy(buf, "/"); + return buf; + +out_free: + free(buf); + return NULL; } static char *get_path(struct fuse *f, fuse_ino_t nodeid)