Re: [AVFS] ~/.avfs and symlinks
Ralf Hoffmann <[email protected]> Tue, 07 Mar 2006 23:01:08 +0100
| Newsgroups | gmane.comp.file-systems.avfs.user |
|---|---|
| Message-ID | <[email protected]> |
Hi, On 2006-03-06 12:08, Miklos Szeredi wrote: >> I'm not sure what will happen if someone does a chroot to the avfs >> mountpoint. In this case the symlink rewriting could be wrong again. > > Yes, that is also a problematic case. > > Attached the symlink transformation in sshfs. sshfs.base_path is the > path within the remote filesystem which is mounted. For example if > you mount 'user@host:/', then base path is '/', if you mount > 'user@host:/foo' then the base path is '/foo'. If you mount > 'user@host:', then the base path is '.' (which means the home > directory), in this case the transformation doesn't work. Is this code GPL'd? I used the code to modify the readlink function, see the attached patch. I still have some questions: Is it possible to add a mount option or something to switch the symlink rewriting on or off? I think we don't need to take care of the mount point since it looks like fuse passes the path without the mount point. But you are the export in fuse, are my changes in transform_symlink okay? > newlink = malloc(dotdots * 3 + l ? strlen(l) : 1 + 10); There is a bug in the malloc argument: the expression is equal to (dotdots * 3 + l) ? strlen(l) : (l + 10) which is not correct, it should be dotdots * 3 + (*l ? strlen(l) : 1) + 10 Best Regards, Ralf Hoffmann -- Homepage: http://www.boomerangsworld.de E-Mail: Ralf Hoffmann <[email protected]> english or german
avfsd.diff
(text/x-patch, 2.5 KB)
diff --git a/fuse/avfsd.c b/fuse/avfsd.c
index bbadd6f..3a644ea 100644
--- a/fuse/avfsd.c
+++ b/fuse/avfsd.c
@@ -1,6 +1,7 @@
/*
FUSE: Filesystem in Userspace
Copyright (C) 2001 Miklos Szeredi ([email protected])
+ Copyright (C) 2006 Ralf Hoffmann ([email protected])
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
@@ -16,6 +17,7 @@
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
+#include <avfs.h>
struct fuse *fuse;
@@ -34,6 +36,72 @@ static int avfsd_getattr(const char *pat
return 0;
}
+static int count_components(const char *p)
+{
+ int ctr;
+
+ for (; *p == '/'; p++);
+ for (ctr = 0; *p; ctr++) {
+ for (; *p && *p != '/'; p++);
+ for (; *p == '/'; p++);
+ }
+ return ctr;
+}
+
+static void strip_common(const char **sp, const char **tp)
+{
+ const char *s = *sp;
+ const char *t = *tp;
+ do {
+ for (; *s == '/'; s++);
+ for (; *t == '/'; t++);
+ *tp = t;
+ *sp = s;
+ for (; *s == *t && *s && *s != '/'; s++, t++);
+ } while ((*s == *t && *s) || (!*s && *t == '/') || (*s == '/' && !*t));
+}
+
+static void transform_symlink(const char *path, const char *linkdest, char **linkp)
+{
+ const char *l = linkdest;
+ char *newlink;
+ char *s;
+ int dotdots;
+ int i;
+
+ if (linkp == NULL)
+ return;
+
+ *linkp = NULL;
+
+ if (l[0] != '/' || path[0] != '/')
+ return;
+
+ strip_common(&l, &path);
+
+ dotdots = count_components(path);
+ if (!dotdots)
+ return;
+ dotdots--;
+
+ newlink = malloc(dotdots * 3 + (*l ? strlen(l) : 1) + 10);
+ if (!newlink) {
+ av_log(AVLOG_ERROR, "readlink: memory allocation failed");
+ exit(1);
+ }
+ for (s = newlink, i = 0; i < dotdots; i++, s += 3)
+ strcpy(s, "../");
+
+ if (l[0])
+ strcpy(s, l);
+ else if (!dotdots)
+ strcpy(s, ".");
+ else
+ s[0] = '\0';
+
+ *linkp = newlink;
+}
+
static int avfsd_readlink(const char *path, char *buf, size_t size)
{
int res;
@@ -43,6 +111,18 @@ static int avfsd_readlink(const char *pa
return -errno;
buf[res] = '\0';
+
+ if (buf[0] == '/') {
+ char *rel_link = NULL;
+
+ transform_symlink(path, buf, &rel_link);
+ if (rel_link != NULL) {
+ strncpy(buf, rel_link, size - 1);
+ buf[size - 1] = '\0';
+ free(rel_link);
+ }
+ }
+
return 0;
}