fix: FUSE limited the total file system depth to 4095 characters and gave

"No such file or directory" errors (Miklos Szeredi, Szabolcs Szakacsits)
master
szaka 2008-04-12 14:05:43 +00:00
parent 46b3ebbb16
commit 68b83a4181
1 changed files with 40 additions and 15 deletions

View File

@ -28,7 +28,6 @@
#include <sys/uio.h>
#include <sys/time.h>
#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)