Re: [AVFS] Problems with fork, Questions about avfs
Ralf Hoffmann <[email protected]> Tue, 08 Feb 2005 23:01:28 +0100 (CET)
| Newsgroups | gmane.comp.file-systems.avfs.user |
|---|---|
| Message-ID | <[email protected]> |
Hi,
I attached a patch which fixes some of the problems I mentioned. I
describe my changes below.
On 17-Jan-2005 Miklos Szeredi wrote:
>> not a real problem. But there is no virt_remove function. I know it
>> is
>> only a wrapper for unlink/rmdir but according to the man-page the
>> remove
>> function is mentioned in ANSI C, POSIX and other standards so it is
>> perhaps a good idea to implement it.
>
> It's easy to implement:
>
> int virt_remove(const char *path)
> {
> struct stat buf;
> virt_stat(path, &buf);
> if (S_ISDIR(buf.st_mode))
> return virt_rmdir(path);
> else
> return virt_unlink(path);
> }
I have added this to virtual.c (but by using lstat instead of stat).
> It's not designed to be fork safe unfortunately. So if it works it's
> purely by chance.
Okay, good to know. I have some ideas to solve this or atleast
workaround but I don't need this currently.
>> Then there is serious problem with the character # inside filenames.
>
> Hmm. In theory it should work. If it doesn't thats a bug.
The problem was that preprocess_name is only called for non-local files
in lookup_segment but escape_magic is called for every file in
av_fd_readdir.
Anyway I don't like the method to escape the magic character. The user
would need to enter double "#" to add a single "#" to the filename.
I came up with a different solution. In parse_path I firstly ignore the
magic character for each segment and test for a local file. If this
fails it is repeated with the magic character taken into account.
With this solution it is possible to access any local file while still
be able to access most virtual files (filenames in archives with the
magic character are not accessable but they are not accessable at all
without avfs on the other hand :-) ).
A possible solution could be the use of the stat function of the
corresponding avfs struct but this could slowdown the parse_path
operation.
>> A function "isLocal()" would really help me as I use the filecontent
>> for
>> filetype recognition and it is not always a good idea to read the
>> files
>> in virtual directories (slow ftp or ssh). This way I can skip such
>> files.
>
> Something like this should work:
>
> int is_local(const char *path)
> {
[snip}
> }
Okay, I also added this function to virtual.c
I hope you can find some time to look at my changes and tell me your
thoughts about it.
Thanks.
Best Regards,
Ralf Hoffmann
--
Homepage: http://www.boomerangsworld.de
E-Mail: Ralf Hoffmann <[email protected]>
english or german
avfs-cvs-patch1.diff
(application/octet-stream, 9.2 KB)
diff -purN avfs-cvs/autogen.sh avfs-cvs-my/autogen.sh
--- avfs-cvs/autogen.sh 1970-01-01 01:00:00.000000000 +0100
+++ avfs-cvs-my/autogen.sh 2005-01-18 08:30:37.000000000 +0100
@@ -0,0 +1,5 @@
+#! /bin/sh
+
+aclocal -I macros
+autoheader
+autoconf
diff -purN avfs-cvs/include/virtual.h avfs-cvs-my/include/virtual.h
--- avfs-cvs/include/virtual.h 2004-01-05 13:46:49.000000000 +0100
+++ avfs-cvs-my/include/virtual.h 2005-02-06 13:23:25.000000000 +0100
@@ -52,4 +52,7 @@ int virt_closedir (DIR *dirp
struct dirent *virt_readdir (DIR *dirp);
void virt_rewinddir (DIR *dirp);
+int virt_remove (const char *path);
+int virt_islocal (const char *path);
+
#endif /* _VIRTUAL_H */
diff -purN avfs-cvs/src/fdops.c avfs-cvs-my/src/fdops.c
--- avfs-cvs/src/fdops.c 2001-11-05 13:31:29.000000000 +0100
+++ avfs-cvs-my/src/fdops.c 2005-02-08 20:47:20.000000000 +0100
@@ -195,6 +195,7 @@ avoff_t av_fd_lseek(int fd, avoff_t offs
return res;
}
+#ifdef ESCAPE_MAGIC
static void avdirent_escape_magic(struct avdirent *buf)
{
char *newname;
@@ -215,6 +216,7 @@ static void avdirent_escape_magic(struct
av_free(buf->name);
buf->name = newname;
}
+#endif
int av_fd_readdir(int fd, struct avdirent *buf, avoff_t *posp)
{
@@ -230,8 +232,10 @@ int av_fd_readdir(int fd, struct avdiren
res = avfs->readdir(vf, buf);
AVFS_UNLOCK(avfs);
+#ifdef ESCAPE_MAGIC
if(res > 0)
- avdirent_escape_magic(buf);
+ avdirent_escape_magic(buf);
+#endif
put_file(vf);
}
diff -purN avfs-cvs/src/parse.c avfs-cvs-my/src/parse.c
--- avfs-cvs/src/parse.c 2001-05-17 18:16:03.000000000 +0200
+++ avfs-cvs-my/src/parse.c 2005-02-08 20:48:54.000000000 +0100
@@ -475,6 +475,7 @@ static int lookup_avfs(struct parse_stat
return res;
}
+#ifdef ESCAPE_MAGIC
static void preprocess_name(char *name)
{
char *s, *d;
@@ -486,6 +487,7 @@ static void preprocess_name(char *name)
}
*d = '\0';
}
+#endif
static int lookup_segment(struct parse_state *ps)
{
@@ -493,8 +495,13 @@ static int lookup_segment(struct parse_s
char *name = ps->path;
ventry *ve = ps->ve;
+#ifdef ESCAPE_MAGIC
if(name[0] == AVFS_SEP_CHAR && name[1] != AVFS_SEP_CHAR)
res = lookup_avfs(ps, name+1);
+#else
+ if(name[0] == AVFS_SEP_CHAR)
+ res = lookup_avfs(ps, name+1);
+#endif
else {
for(;*name && *name == AV_DIR_SEP_CHAR; name++);
set_prevseg(ps, name);
@@ -502,8 +509,10 @@ static int lookup_segment(struct parse_s
if((ve->mnt->avfs->flags & AVF_NEEDSLASH) != 0)
name = ps->path;
- if(ve->mnt->base != NULL)
- preprocess_name(name);
+#ifdef ESCAPE_MAGIC
+ /* if(ve->mnt->base != NULL) */
+ preprocess_name(name);
+#endif
if(name[0] != '\0')
res = lookup_virtual(ps, name);
@@ -514,22 +523,31 @@ static int lookup_segment(struct parse_s
return res;
}
-static unsigned int segment_len(struct parse_state *ps)
+static unsigned int segment_len(struct parse_state *ps, int ignoreMagic)
{
const char *s = ps->path;
unsigned int seglen;
+#ifdef ESCAPE_MAGIC
if(s[0] == AVFS_SEP_CHAR && s[1] != AVFS_SEP_CHAR)
s++;
else while(*s == AV_DIR_SEP_CHAR)
s++;
+#else
+ if(s[0] == AVFS_SEP_CHAR)
+ s++;
+ else while(*s == AV_DIR_SEP_CHAR)
+ s++;
+#endif
while(*s && *s != AV_DIR_SEP_CHAR) {
if(s[0] == AVFS_SEP_CHAR) {
+#ifdef ESCAPE_MAGIC
if(s[1] == AVFS_SEP_CHAR)
s++;
else
- break;
+#endif
+ if ( ! ignoreMagic ) break;
}
s++;
}
@@ -561,7 +579,7 @@ static struct avfs *get_local_avfs()
return localavfs;
}
-static int parse_path(struct parse_state *ps);
+static int parse_path(struct parse_state *ps, int force_localfile);
static int follow_link(struct parse_state *ps)
{
@@ -588,7 +606,7 @@ static int follow_link(struct parse_stat
res = lookup_virtual(&linkps, NULL);
if(res == 0)
- res = parse_path(&linkps);
+ res = parse_path(&linkps, 0);
}
else {
av_free_ventry(ps->ve);
@@ -597,8 +615,9 @@ static int follow_link(struct parse_stat
linkps.ve->mnt = new_mount(NULL, get_local_avfs(), NULL);
linkps.ve->data = av_strdup("");
- res = parse_path(&linkps);
+ res = parse_path(&linkps, 0);
}
+
av_free(buf);
ps->ve = linkps.ve;
@@ -606,19 +625,76 @@ static int follow_link(struct parse_stat
return res;
}
-static int parse_path(struct parse_state *ps)
+#define TMPBUFFER_SIZE 1024
+
+static int parse_path(struct parse_state *ps, int force_localfile)
{
int res = 0;
int numseg = 0;
-
+ struct stat stbuf;
+ char tmpbuffer[TMPBUFFER_SIZE];
+
ps->prevseg = av_strdup("");
-
while(ps->path[0]) {
unsigned int seglen;
int lastseg;
char c;
- seglen = segment_len(ps);
+ if ( ( ps->ve->mnt->base == NULL ) && ( ps->ve->data != NULL ) ) {
+ /* still on local filesystem
+ now check if next segment is also local by firstly ingoring
+ the magic char */
+ /* POSSIBLE IMPROVEMENT: duplicate path at the beginning
+ and only set each seglen to 0 so there is no need to
+ strcat
+ But the current solution doesn't need to copy anything if
+ the path doesn't contain magic characters */
+ char *allocstr, *usestr, *tstr;
+ int tl, found_magic;
+
+ seglen = segment_len( ps, 1 );
+ c = ps->path[seglen];
+ ps->path[seglen] = '\0';
+
+ /* try to find the magic char in segment */
+ tstr = ps->path;
+ for ( found_magic = 0; *tstr != '\0'; tstr++ ) {
+ if ( *tstr == AVFS_SEP_CHAR ) {
+ found_magic = 1;
+ break;
+ }
+ }
+ if ( found_magic == 1 ) {
+ /* found so cat previous path and segment and
+ test for local file */
+
+ tl = strlen( (char*)ps->ve->data ) + strlen( ps->path );
+
+ allocstr = NULL;
+ if ( tl < TMPBUFFER_SIZE ) usestr = tmpbuffer;
+ else usestr = allocstr = av_malloc( tl + 1 );
+
+ if ( usestr != NULL ) {
+ strcpy( usestr, (char*)ps->ve->data );
+ strcat( usestr, ps->path );
+
+ ps->path[seglen] = c;
+ if ( lstat( usestr, &stbuf ) != 0 ) {
+ /* no such local file so try again without
+ ignoring magic char (unless localfile is
+ forced) */
+ seglen = segment_len( ps, force_localfile );
+ }
+ if ( allocstr != NULL ) av_free( allocstr );
+ } else {
+ ps->path[seglen] = c;
+ seglen = segment_len( ps, force_localfile ); /* fallback for failed malloc */
+ }
+ } else {
+ ps->path[seglen] = c;
+ }
+ } else seglen = segment_len( ps, force_localfile ); /* fallback for files outside local fs */
+
lastseg = is_last(ps, seglen);
ps->nextseg = seglen;
c = ps->path[seglen];
@@ -649,7 +725,7 @@ static int parse_path(struct parse_state
return res;
}
-
+#undef TMPBUFFER_SIZE
int av_get_ventry(const char *path, int resolvelast, ventry **resp)
{
@@ -673,7 +749,23 @@ int av_get_ventry(const char *path, int
ps.ve->mnt = new_mount(NULL, get_local_avfs(), NULL);
ps.ve->data = av_strdup("");
- res = parse_path(&ps);
+ res = parse_path(&ps, 0);
+
+ /* no ventry so force localfile to be able to create files with
+ the magic character inside filename */
+ if ( res < 0 ) {
+ av_free(copypath);
+ copypath = av_strdup(path);
+ av_free_ventry(ps.ve);
+ ps.path = copypath;
+ ps.resolvelast = resolvelast;
+ ps.linkctr = 10;
+ AV_NEW(ps.ve);
+ ps.ve->mnt = new_mount(NULL, get_local_avfs(), NULL);
+ ps.ve->data = av_strdup("");
+ res = parse_path(&ps, 1);
+ }
+
if(res < 0) {
av_free_ventry(ps.ve);
*resp = NULL;
@@ -769,7 +861,11 @@ static int ipath_len(const char *s)
int cnt;
for(cnt = 0; *s; s++, cnt++)
+#ifdef ESCAPE_MAGIC
if(*s == AVFS_SEP_CHAR) cnt++;
+#else
+ ;
+#endif
return cnt;
}
@@ -778,8 +874,10 @@ static void ipath_copy(char *dst, const
{
for(; *src; dst++, src++) {
*dst = *src;
+#ifdef ESCAPE_MAGIC
if(*src == AVFS_SEP_CHAR)
*++dst = AVFS_SEP_CHAR;
+#endif
}
*dst = '\0';
}
diff -purN avfs-cvs/src/virtual.c avfs-cvs-my/src/virtual.c
--- avfs-cvs/src/virtual.c 2004-01-05 13:46:49.000000000 +0100
+++ avfs-cvs-my/src/virtual.c 2005-02-06 13:33:58.000000000 +0100
@@ -671,3 +671,43 @@ int virt_link(const char *path, const ch
errno = errno_save;
return 0;
}
+
+int virt_remove(const char *path)
+{
+ struct stat stbuf;
+
+ if ( path != NULL ) {
+ if ( virt_lstat( path, &stbuf ) == 0 ) {
+ if ( S_ISDIR( stbuf.st_mode ) ) {
+ return virt_rmdir( path );
+ } else {
+ return virt_unlink( path );
+ }
+ }
+ }
+
+ errno = EFAULT;
+ return -1;
+}
+
+int virt_islocal(const char *path)
+{
+ int res;
+ ventry *ve;
+ int errno_save = errno;
+ int erg = 0;
+
+ res = av_get_ventry(path, 0, &ve);
+ if(res == 0) {
+ if ( ve->mnt->base == NULL ) erg = 1;
+ else erg = 0;
+ av_free_ventry(ve);
+ }
+ if(res < 0) {
+ errno = -res;
+ return -1;
+ }
+
+ errno = errno_save;
+ return erg;
+}