[AVFS] Inode problem and own release
Ralf Hoffmann <[email protected]> Tue, 29 Mar 2005 23:33:56 +0200
| Newsgroups | gmane.comp.file-systems.avfs.user |
|---|---|
| Message-ID | <[email protected]> |
Hi,
I thought about the inode problem I mentioned previously but I didn't
came up with a solution. The calculation in src/state.c:297
buf->ino = (int) stf + st_paramhash(sf->stent->param);
results in 0 but because stf is NULL and sf->stent->param is the empty
string (for /#avfsstat/cache) I think changing the hash function
wouldn't help much. I currently prefer to take additional information
into account. For example sf->stent->ent->name is a good candidate which
is the last path component. More expensive is of course to use the whole
path for the hash by accessing sf->stent->ent->parent...
In any case access to struct entry is necessary which is a private
struct in namespace.c. I can think of two solutions: move the struct
definition to namespace.h or add a wrapper function to return the name
(or full path name).
A new inode calculation could be:
buf->ino = (int) stf + st_paramhash(sf->stent->param) + st_paramhash(
sf->stent->ent->name);
and wrapping the whole expression in a new function to avoid inode
number 0 and 1.
What do you think about this?
I'm planning the next release of my file manager and want to provide a
patched avfs version. I attached the patch I want to use which differs
from the previous version only by setting the version to 0.9.4 so I can
require this version in my configure script. Is this okay with you?
Best Regards,
Ralf Hoffmann
--
Homepage: http://www.boomerangsworld.de
E-Mail: Ralf Hoffmann <[email protected]>
english or german
avfs-cvs-patch3.diff
(text/x-patch, 12.2 KB)
diff -purN avfs-cvs/configure.in avfs-cvs-my/configure.in
--- avfs-cvs/configure.in 2004-01-09 13:21:53.000000000 +0100
+++ avfs-cvs-my/configure.in 2005-03-29 22:58:26.000000000 +0200
@@ -20,7 +20,7 @@ if test "$validstring" = invalid; then
AC_MSG_ERROR([type 'make realclean' before running configure])
fi
-VERSION=0.9.3
+VERSION=0.9.4
AC_SUBST(VERSION)
os=`uname -s`
diff -purN avfs-cvs/include/version.h avfs-cvs-my/include/version.h
--- avfs-cvs/include/version.h 2002-01-09 10:49:20.000000000 +0100
+++ avfs-cvs-my/include/version.h 2005-03-29 23:06:47.000000000 +0200
@@ -6,4 +6,4 @@
See the file COPYING.
*/
-#define AV_VER 93
+#define AV_VER 94
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-14 00:17:18.000000000 +0100
@@ -195,27 +195,6 @@ avoff_t av_fd_lseek(int fd, avoff_t offs
return res;
}
-static void avdirent_escape_magic(struct avdirent *buf)
-{
- char *newname;
- char *src;
- char *dst;
-
- if(strchr(buf->name, AVFS_SEP_CHAR) == NULL)
- return;
-
- newname = av_malloc(strlen(buf->name) * 2 + 1);
- dst = newname;
- for(src = buf->name; *src != '\0'; src++) {
- *dst++ = *src;
- if(*src == AVFS_SEP_CHAR)
- *dst++ = AVFS_SEP_CHAR;
- }
- *dst = '\0';
- av_free(buf->name);
- buf->name = newname;
-}
-
int av_fd_readdir(int fd, struct avdirent *buf, avoff_t *posp)
{
int res;
@@ -230,8 +209,6 @@ int av_fd_readdir(int fd, struct avdiren
res = avfs->readdir(vf, buf);
AVFS_UNLOCK(avfs);
- if(res > 0)
- avdirent_escape_magic(buf);
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-03-04 13:02:15.000000000 +0100
@@ -12,6 +12,7 @@
#include "version.h"
#include "local.h"
#include "mod_static.h"
+#include "operutil.h"
#include <stdio.h>
#include <ctype.h>
@@ -39,6 +40,7 @@ struct parse_state {
int resolvelast;
int nextseg;
int linkctr;
+ int first_seg; /* true if no segment was analysed, see segment_len() comment */
};
static int copyrightstat_get(struct entry *ent, const char *param, char **retp)
@@ -213,6 +215,28 @@ void av_add_avfs(struct avfs *newavfs)
AV_UNLOCK(avfs_lock);
}
+static int av_copy_parsestate(struct parse_state *ps, struct parse_state *destps)
+{
+ destps->linkctr = ps->linkctr;
+ destps->nextseg = ps->nextseg;
+ destps->resolvelast = ps->resolvelast;
+ destps->islink = ps->islink;
+
+ if(ps->path)
+ destps->path = av_strdup(ps->path);
+ else
+ destps->path = NULL;
+
+ destps->first_seg = ps->first_seg;
+
+ if(ps->prevseg)
+ destps->prevseg = av_strdup(ps->prevseg);
+ else
+ destps->prevseg = NULL;
+
+ av_copy_ventry(ps->ve, &(destps->ve));
+ return 0;
+}
static void set_prevseg(struct parse_state *ps, const char *name)
{
@@ -475,36 +499,30 @@ static int lookup_avfs(struct parse_stat
return res;
}
-static void preprocess_name(char *name)
-{
- char *s, *d;
-
- for(s = name, d = name; *s; s++, d++) {
- if(s[0] == AVFS_SEP_CHAR && s[1] == AVFS_SEP_CHAR)
- s++;
- *d = *s;
- }
- *d = '\0';
-}
-
-static int lookup_segment(struct parse_state *ps)
+static int lookup_segment(struct parse_state *ps, int noavfs)
{
int res;
char *name = ps->path;
ventry *ve = ps->ve;
- if(name[0] == AVFS_SEP_CHAR && name[1] != AVFS_SEP_CHAR)
- res = lookup_avfs(ps, name+1);
+ /* only enter next avfs hierarchie if the magic char is not the
+ very first char (first_seg) and we really want this action
+ (noavfs needed by segment_islocal() test */
+
+ if((name[0] == AVFS_SEP_CHAR) && (noavfs == 0) && (ps->first_seg == 0))
+ res = lookup_avfs(ps, name+1);
else {
+ /* reset first_seg as we now process a path segment and from now on
+ the next magic char is always the magic char and not from a local
+ filename */
+ ps->first_seg = 0;
+
for(;*name && *name == AV_DIR_SEP_CHAR; name++);
set_prevseg(ps, name);
if((ve->mnt->avfs->flags & AVF_NEEDSLASH) != 0)
name = ps->path;
- if(ve->mnt->base != NULL)
- preprocess_name(name);
-
if(name[0] != '\0')
res = lookup_virtual(ps, name);
else
@@ -514,28 +532,98 @@ static int lookup_segment(struct parse_s
return res;
}
-static unsigned int segment_len(struct parse_state *ps)
+static int segment_islocal(struct parse_state *ps, unsigned int seglen )
{
- const char *s = ps->path;
- unsigned int seglen;
+ int islocal = 0;
+ char c;
+ struct parse_state tempps;
+ int f;
- if(s[0] == AVFS_SEP_CHAR && s[1] != AVFS_SEP_CHAR)
+ /* we will copy the whole parse_state and try to find a local entry
+ if open succeed there is a local file and we can return true */
+
+ av_copy_parsestate( ps, &tempps );
+
+ tempps.nextseg = seglen;
+ c = tempps.path[seglen];
+ tempps.path[seglen] = '\0';
+
+ /* we force lookup_segment() to not enter any avfs hierarchie */
+ lookup_segment(&tempps, 1);
+ f = av_fd_open_entry(tempps.ve, AVO_RDONLY, 0);
+ av_free_ventry(tempps.ve);
+ av_free(tempps.path);
+ av_free(tempps.prevseg);
+ if ( f >= 0 ) {
+ islocal = 1;
+ av_fd_close(f);
+ }
+ return islocal;
+}
+
+static unsigned int segment_len(struct parse_state *ps, int ignoreMagic)
+{
+ const char *s = ps->path,
+ *first_s = ps->path;
+ unsigned int seglen, orig_seglen;
+ int found_magic = 0, search_avfs_key = 0;
+
+ /* this function will find the next segment len by also checking for local files
+ with magic chars inside the filename
+ two cases:
+ 1.magic at the beginning:
+ in this case we are searching for an avfs key (#utar, #ugz...)
+ so we will stop at the next magic char or dir separator
+ except when this magic char is the very first character
+ where it makes no sense to accept this as an avfs key
+ (imagine open("#utar"))
+ For this case there is a new flag first_seg which takes
+ care of this
+ 2.Otherwise we are searching for the longest path segment
+ starting at the next dir separator skipping any magic char
+ we stop after first local hit
+ If no local file was found we return whole segment len to be able
+ to open new files with magic chars
+ If no magic char was found or we are forced to ignore it
+ we immediately return the whole path segment without any checking
+ */
+
+ if(s[0] == AVFS_SEP_CHAR) {
s++;
- else while(*s == AV_DIR_SEP_CHAR)
+ if(ps->first_seg == 0)
+ search_avfs_key = 1;
+ } else while(*s == AV_DIR_SEP_CHAR)
s++;
while(*s && *s != AV_DIR_SEP_CHAR) {
- if(s[0] == AVFS_SEP_CHAR) {
- if(s[1] == AVFS_SEP_CHAR)
- s++;
- else
- break;
+ if(*s == AVFS_SEP_CHAR) {
+ if(found_magic == 0) {
+ first_s = s;
+ }
+ found_magic++;
}
s++;
}
seglen = s - ps->path;
- return seglen;
+ if((ignoreMagic == 1) || (found_magic == 0)) return seglen;
+
+ /* a magic char was already found so first_s is correct */
+ if(search_avfs_key == 1)
+ return (first_s - ps->path);
+
+ orig_seglen = seglen;
+ /* found magic char so check for existing local file */
+ while(seglen > 0) {
+ if(segment_islocal(ps, seglen) == 1)
+ break;
+ for(seglen = seglen - 1;
+ (seglen > 0) && ( ps->path[seglen] != AVFS_SEP_CHAR );
+ seglen--);
+ }
+
+ if(seglen > 0) return seglen;
+ else return orig_seglen;
}
static int is_last(struct parse_state *ps, unsigned int seglen)
@@ -561,7 +649,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 +676,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 +685,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,26 +695,27 @@ static int follow_link(struct parse_stat
return res;
}
-static int parse_path(struct parse_state *ps)
+static int parse_path(struct parse_state *ps, int force_localfile)
{
int res = 0;
int numseg = 0;
ps->prevseg = av_strdup("");
-
+ ps->first_seg = 1;
while(ps->path[0]) {
unsigned int seglen;
int lastseg;
char c;
- seglen = segment_len(ps);
+ seglen = segment_len(ps, force_localfile);
+
lastseg = is_last(ps, seglen);
ps->nextseg = seglen;
c = ps->path[seglen];
ps->path[seglen] = '\0';
ps->islink = 0;
- res = lookup_segment(ps);
+ res = lookup_segment(ps,0);
if(res < 0)
break;
@@ -650,7 +740,6 @@ static int parse_path(struct parse_state
return res;
}
-
int av_get_ventry(const char *path, int resolvelast, ventry **resp)
{
int res;
@@ -673,7 +762,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;
@@ -768,8 +873,7 @@ static int ipath_len(const char *s)
{
int cnt;
- for(cnt = 0; *s; s++, cnt++)
- if(*s == AVFS_SEP_CHAR) cnt++;
+ for(cnt = 0; *s; s++, cnt++);
return cnt;
}
@@ -778,8 +882,6 @@ static void ipath_copy(char *dst, const
{
for(; *src; dst++, src++) {
*dst = *src;
- if(*src == AVFS_SEP_CHAR)
- *++dst = AVFS_SEP_CHAR;
}
*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-10 20:45:59.000000000 +0100
@@ -671,3 +671,45 @@ 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;
+}