1
1

Use GList to store directory content in vfs_s_inode.

Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
Signed-off-by: Slava Zanko <slavazanko@gmail.com>
Этот коммит содержится в:
Andrew Borodin 2011-03-28 15:17:45 +03:00
родитель 401aaa5014
Коммит 519246eccd
2 изменённых файлов: 83 добавлений и 78 удалений

Просмотреть файл

@ -61,7 +61,7 @@
struct dirhandle
{
struct vfs_s_entry *cur;
GList *cur;
struct vfs_s_inode *dir;
};
@ -72,33 +72,43 @@ static volatile int total_inodes = 0, total_entries = 0;
/*** file scope functions ************************************************************************/
/* --------------------------------------------------------------------------------------------- */
static int
vfs_s_entry_compare (const void *a, const void *b)
{
const struct vfs_s_entry *e = (const struct vfs_s_entry *) a;
const char *name = (const char *) b;
return strcmp (e->name, name);
}
/* --------------------------------------------------------------------------------------------- */
static void
vfs_s_free_inode (struct vfs_class *me, struct vfs_s_inode *ino)
{
if (!ino)
if (ino == NULL)
vfs_die ("Don't pass NULL to me");
/* ==0 can happen if freshly created entry is deleted */
if (ino->st.st_nlink <= 1)
if (ino->st.st_nlink > 1)
{
while (ino->subdir)
{
vfs_s_free_entry (me, ino->subdir);
}
CALL (free_inode) (me, ino);
g_free (ino->linkname);
if (ino->localname)
{
unlink (ino->localname);
g_free (ino->localname);
}
total_inodes--;
ino->super->ino_usage--;
g_free (ino);
}
else
ino->st.st_nlink--;
return;
}
while (ino->subdir != NULL)
vfs_s_free_entry (me, (struct vfs_s_entry *) ino->subdir->data);
CALL (free_inode) (me, ino);
g_free (ino->linkname);
if (ino->localname != NULL)
{
unlink (ino->localname);
g_free (ino->localname);
}
total_inodes--;
ino->super->ino_usage--;
g_free (ino);
}
/* --------------------------------------------------------------------------------------------- */
@ -108,14 +118,16 @@ static struct vfs_s_entry *
vfs_s_automake (struct vfs_class *me, struct vfs_s_inode *dir, char *path, int flags)
{
struct vfs_s_entry *res;
char *sep = strchr (path, PATH_SEP);
char *sep;
sep = strchr (path, PATH_SEP);
if (sep != NULL)
*sep = '\0';
if (sep)
*sep = 0;
res = vfs_s_generate_entry (me, path, dir, flags & FL_MKDIR ? (0777 | S_IFDIR) : 0777);
vfs_s_insert_entry (me, dir, res);
if (sep)
if (sep != NULL)
*sep = PATH_SEP;
return res;
@ -179,36 +191,46 @@ vfs_s_find_entry_tree (struct vfs_class *me, struct vfs_s_inode *root,
/* canonicalize as well, but don't remove '../' from path */
custom_canonicalize_pathname (path, CANON_PATH_ALL & (~CANON_PATH_REMDOUBLEDOTS));
while (root)
while (root != NULL)
{
GList *iter;
while (*path == PATH_SEP) /* Strip leading '/' */
path++;
if (!path[0])
if (path[0] == '\0')
{
g_free (pathref);
return ent;
}
for (pseg = 0; path[pseg] && path[pseg] != PATH_SEP; pseg++);
for (pseg = 0; path[pseg] != '\0' && path[pseg] != PATH_SEP; pseg++)
;
for (ent = root->subdir; ent != NULL; ent = ent->next)
if (strlen (ent->name) == pseg && (!strncmp (ent->name, path, pseg)))
for (iter = root->subdir; iter != NULL; iter = g_list_next (iter))
{
ent = (struct vfs_s_entry *) iter->data;
if (strlen (ent->name) == pseg && strncmp (ent->name, path, pseg) == 0)
/* FOUND! */
break;
}
if (!ent && (flags & (FL_MKFILE | FL_MKDIR)))
ent = iter != NULL ? (struct vfs_s_entry *) iter->data : NULL;
if (ent == NULL && (flags & (FL_MKFILE | FL_MKDIR)) != 0)
ent = vfs_s_automake (me, root, path, flags);
if (!ent)
if (ent == NULL)
{
me->verrno = ENOENT;
goto cleanup;
}
path += pseg;
/* here we must follow leading directories always;
only the actual file is optional */
ent = vfs_s_resolve_symlink (me, ent, strchr (path, PATH_SEP) ? LINK_FOLLOW : follow);
if (!ent)
ent = vfs_s_resolve_symlink (me, ent,
strchr (path, PATH_SEP) != NULL ? LINK_FOLLOW : follow);
if (ent == NULL)
goto cleanup;
root = ent->ino;
}
@ -251,6 +273,7 @@ vfs_s_find_entry_linear (struct vfs_class *me, struct vfs_s_inode *root,
struct vfs_s_entry *ent = NULL;
char *const path = g_strdup (a_path);
struct vfs_s_entry *retval = NULL;
GList *iter;
if (root->super->root != root)
vfs_die ("We have to use _real_ root. Always. Sorry.");
@ -258,24 +281,23 @@ vfs_s_find_entry_linear (struct vfs_class *me, struct vfs_s_inode *root,
/* canonicalize as well, but don't remove '../' from path */
custom_canonicalize_pathname (path, CANON_PATH_ALL & (~CANON_PATH_REMDOUBLEDOTS));
if (!(flags & FL_DIR))
if ((flags & FL_DIR) == 0)
{
char *dirname, *name, *save;
struct vfs_s_inode *ino;
split_dir_name (me, path, &dirname, &name, &save);
ino = vfs_s_find_inode (me, root->super, dirname, follow, flags | FL_DIR);
if (save)
if (save != NULL)
*save = PATH_SEP;
retval = vfs_s_find_entry_tree (me, ino, name, follow, flags);
g_free (path);
return retval;
}
for (ent = root->subdir; ent != NULL; ent = ent->next)
if (!strcmp (ent->name, path))
break;
iter = g_list_find_custom (root->subdir, path, (GCompareFunc) vfs_s_entry_compare);
ent = iter != NULL ? (struct vfs_s_entry *) iter->data : NULL;
if (ent && (!(MEDATA->dir_uptodate) (me, ent->ino)))
if (ent != NULL && !MEDATA->dir_uptodate (me, ent->ino))
{
#if 1
vfs_print_message (_("Directory cache expired for %s"), path);
@ -284,25 +306,25 @@ vfs_s_find_entry_linear (struct vfs_class *me, struct vfs_s_inode *root,
ent = NULL;
}
if (!ent)
if (ent == NULL)
{
struct vfs_s_inode *ino;
ino = vfs_s_new_inode (me, root->super, vfs_s_default_stat (me, S_IFDIR | 0755));
ent = vfs_s_new_entry (me, path, ino);
if ((MEDATA->dir_load) (me, ino, path) == -1)
if (MEDATA->dir_load (me, ino, path) == -1)
{
vfs_s_free_entry (me, ent);
g_free (path);
return NULL;
}
vfs_s_insert_entry (me, root, ent);
for (ent = root->subdir; ent != NULL; ent = ent->next)
if (!strcmp (ent->name, path))
break;
iter = g_list_find_custom (root->subdir, path, (GCompareFunc) vfs_s_entry_compare);
ent = iter != NULL ? (struct vfs_s_entry *) iter->data : NULL;
}
if (!ent)
if (ent == NULL)
vfs_die ("find_linear: success but directory is not there\n");
#if 0
@ -343,7 +365,7 @@ vfs_s_insert_super (struct vfs_class *me, struct vfs_s_super *super)
static void
vfs_s_free_super (struct vfs_class *me, struct vfs_s_super *super)
{
if (super->root)
if (super->root != NULL)
{
vfs_s_free_inode (me, super->root);
super->root = NULL;
@ -419,14 +441,14 @@ vfs_s_opendir (struct vfs_class *me, const char *dirname)
struct dirhandle *info;
dir = vfs_s_inode_from_path (me, dirname, FL_DIR | FL_FOLLOW);
if (!dir)
if (dir == NULL)
return NULL;
if (!S_ISDIR (dir->st.st_mode))
ERRNOR (ENOTDIR, NULL);
dir->st.st_nlink++;
#if 0
if (!dir->subdir) /* This can actually happen if we allow empty directories */
if (dir->subdir == NULL) /* This can actually happen if we allow empty directories */
ERRNOR (EAGAIN, NULL);
#endif
info = g_new (struct dirhandle, 1);
@ -443,21 +465,19 @@ vfs_s_readdir (void *data)
{
static union vfs_dirent dir;
struct dirhandle *info = (struct dirhandle *) data;
const char *name;
if (!(info->cur))
if (info->cur == NULL || info->cur->data == NULL)
return NULL;
if (info->cur->name)
{
g_strlcpy (dir.dent.d_name, info->cur->name, MC_MAXPATHLEN);
}
name = ((struct vfs_s_entry *) info->cur->data)->name;
if (name != NULL)
g_strlcpy (dir.dent.d_name, name, MC_MAXPATHLEN);
else
{
vfs_die ("Null in structure-cannot happen");
}
compute_namelen (&dir.dent);
info->cur = info->cur->next;
info->cur = g_list_next (info->cur);
return (void *) &dir;
}
@ -898,9 +918,7 @@ vfs_s_new_entry (struct vfs_class *me, const char *name, struct vfs_s_inode *ino
entry = g_new0 (struct vfs_s_entry, 1);
total_entries++;
if (name)
entry->name = g_strdup (name);
entry->name = g_strdup (name);
entry->ino = inode;
entry->ino->ent = entry;
CALL (init_entry) (me, entry);
@ -914,22 +932,16 @@ vfs_s_new_entry (struct vfs_class *me, const char *name, struct vfs_s_inode *ino
void
vfs_s_free_entry (struct vfs_class *me, struct vfs_s_entry *ent)
{
if (ent->prevp)
{
/* It is possible that we are deleting freshly created entry */
*ent->prevp = ent->next;
if (ent->next)
ent->next->prevp = ent->prevp;
}
if (ent->dir != NULL)
ent->dir->subdir = g_list_remove (ent->dir->subdir, ent);
g_free (ent->name);
ent->name = NULL;
/* ent->name = NULL; */
if (ent->ino)
if (ent->ino != NULL)
{
ent->ino->ent = NULL;
vfs_s_free_inode (me, ent->ino);
ent->ino = NULL;
}
total_entries--;
@ -941,18 +953,12 @@ vfs_s_free_entry (struct vfs_class *me, struct vfs_s_entry *ent)
void
vfs_s_insert_entry (struct vfs_class *me, struct vfs_s_inode *dir, struct vfs_s_entry *ent)
{
struct vfs_s_entry **ep;
(void) me;
for (ep = &dir->subdir; *ep != NULL; ep = &((*ep)->next))
;
ent->prevp = ep;
ent->next = NULL;
ent->dir = dir;
*ep = ent;
ent->ino->st.st_nlink++;
dir->subdir = g_list_append (dir->subdir, ent);
}
/* --------------------------------------------------------------------------------------------- */

Просмотреть файл

@ -130,7 +130,6 @@ struct vfs_s_super
*/
struct vfs_s_entry
{
struct vfs_s_entry **prevp, *next; /* Pointers in the entry list */
struct vfs_s_inode *dir; /* Directory we are in, i.e. our parent */
char *name; /* Name of this entry */
struct vfs_s_inode *ino; /* ... and its inode */
@ -143,7 +142,7 @@ struct vfs_s_inode
struct vfs_s_entry *ent; /* Our entry in the parent directory -
use only for directories because they
cannot be hardlinked */
struct vfs_s_entry *subdir; /* If this is a directory, its entry */
GList *subdir; /* If this is a directory, its entry. List of vfs_s_entry */
struct stat st; /* Parameters of this inode */
char *linkname; /* Symlink's contents */
char *localname; /* Filename of local file, if we have one */