summaryrefslogtreecommitdiff
path: root/node.c
diff options
context:
space:
mode:
Diffstat (limited to 'node.c')
-rw-r--r--node.c433
1 files changed, 250 insertions, 183 deletions
diff --git a/node.c b/node.c
index 5ea698a..976d5d1 100644
--- a/node.c
+++ b/node.c
@@ -1,5 +1,5 @@
/* Hurd unionfs
- Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2005 Free Software Foundation, Inc.
Written by Moritz Schulte <moritz@duesseldorf.ccc.de>.
This program is free software; you can redistribute it and/or
@@ -52,33 +52,36 @@ node_create (lnode_t *lnode, node_t **node)
debug_msg ("node_create for lnode: %s", lnode->name);
if (! netnode_new)
- err = ENOMEM;
- else
{
- node_new = netfs_make_node (netnode_new);
- if (! node_new)
- {
- err = ENOMEM;
- free (netnode_new);
- }
- else
- {
- node_new->nn->ulfs = NULL;
- err = node_ulfs_init (node_new);
- if (err)
- node_destroy (node_new);
- else
- {
- lnode->node = node_new;
- lnode_ref_add (lnode);
- node_new->nn->lnode = lnode;
- node_new->nn->flags = 0;
- node_new->nn->ncache_next = NULL;
- node_new->nn->ncache_prev = NULL;
- *node = node_new;
- }
- }
+ err = ENOMEM;
+ return err;
}
+
+ node_new = netfs_make_node (netnode_new);
+ if (! node_new)
+ {
+ err = ENOMEM;
+ free (netnode_new);
+ return err;
+ }
+
+ node_new->nn->ulfs = NULL;
+
+ err = node_ulfs_init (node_new);
+ if (err)
+ {
+ node_destroy (node_new);
+ return err;
+ }
+
+ lnode->node = node_new;
+ lnode_ref_add (lnode);
+ node_new->nn->lnode = lnode;
+ node_new->nn->flags = 0;
+ node_new->nn->ncache_next = NULL;
+ node_new->nn->ncache_prev = NULL;
+ *node = node_new;
+
return err;
}
@@ -105,58 +108,103 @@ node_update (node_t *node)
error_t err = 0;
char *path;
+ node_ulfs_t *root_ulfs;
+ struct stat stat;
+ file_t port;
+ int i = 0;
+
debug_msg ("node_update for lnode: %s", node->nn->lnode->name);
- if (! node_is_root (node))
+ if (node_is_root (node))
+ return err;
+
+ mutex_lock (&netfs_root_node->lock);
+
+ err = lnode_path_construct (node->nn->lnode, &path);
+ if (err)
+ {
+ mutex_unlock (&netfs_root_node->lock);
+ return err;
+ }
+
+ root_ulfs = netfs_root_node->nn->ulfs;
+
+ node_ulfs_iterate_unlocked (node)
{
- mutex_lock (&netfs_root_node->lock);
- err = lnode_path_construct (node->nn->lnode, &path);
- if (! err)
+
+ if (node_ulfs->flags & FLAG_NODE_ULFS_FIXED)
{
- node_ulfs_t *root_ulfs;
- struct stat stat;
- file_t port;
- int i = 0;
-
- root_ulfs = netfs_root_node->nn->ulfs;
- node_ulfs_iterate_unlocked (node)
- {
- if (! (node_ulfs->flags & FLAG_NODE_ULFS_FIXED))
- {
- /* We really have to update the port. */
- if (port_valid (node_ulfs->port))
- port_dealloc (node_ulfs->port);
- err = file_lookup ((root_ulfs + i)->port, path,
- O_READ | O_NOTRANS, O_NOTRANS,
- 0, &port, &stat);
- if (! err)
- {
- if (stat.st_ino == underlying_node_stat.st_ino
- && stat.st_fsid == underlying_node_stat.st_fsid)
- /* It's OUR root node. */
- err = ELOOP;
- else
- {
- port_dealloc (port);
- err = file_lookup ((root_ulfs + i)->port, path,
- O_READ, 0, 0, &port, &stat);
- }
- }
-
- if (err)
- {
- port = MACH_PORT_NULL;
- err = 0;
- }
- node_ulfs->port = port;
- }
- i++;
- }
- free (path);
- node->nn->flags |= FLAG_NODE_ULFS_UPTODATE;
+ i++;
+ continue;
}
- mutex_unlock (&netfs_root_node->lock);
+
+ /* We really have to update the port. */
+ if (port_valid (node_ulfs->port))
+ port_dealloc (node_ulfs->port);
+
+ err = file_lookup ((root_ulfs + i)->port, path,
+ O_READ | O_NOTRANS, O_NOTRANS,
+ 0, &port, &stat);
+
+ if (err)
+ {
+ node_ulfs->port = MACH_PORT_NULL;
+ err = 0;
+ i++;
+ continue;
+ }
+
+ if (stat.st_ino == underlying_node_stat.st_ino
+ && stat.st_fsid == underlying_node_stat.st_fsid)
+ /* It's OUR root node. */
+ err = ELOOP;
+ else
+ {
+ port_dealloc (port);
+ err = file_lookup ((root_ulfs + i)->port, path,
+ O_READ, 0, 0, &port, &stat);
+ }
+
+ if (err)
+ {
+ port = MACH_PORT_NULL;
+ err = 0;
+ }
+ node_ulfs->port = port;
+
+ i++;
+ }
+
+ free (path);
+ node->nn->flags |= FLAG_NODE_ULFS_UPTODATE;
+
+ mutex_unlock (&netfs_root_node->lock);
+
+ return err;
+}
+
+/* Remove all files named NAME beneath DIR on the underlying filesystems
+ with FLAGS as openflags. */
+error_t
+node_unlink_file (node_t *dir, char *name)
+{
+ error_t err = 0;
+
+ /* Using reverse iteration still have issues. Infact, we could be
+ deleting a file in some underlying filesystem, and keeping those
+ after the first occurring error.
+ FIXME: Check BEFORE starting deletion. */
+
+ node_ulfs_iterate_reverse_unlocked (dir)
+ {
+
+ if (!port_valid (node_ulfs->port))
+ continue;
+
+ err = dir_unlink (node_ulfs->port, name);
+
}
+ err = 0;
return err;
}
@@ -173,31 +221,38 @@ node_lookup_file (node_t *dir, char *name, int flags,
node_ulfs_iterate_unlocked (dir)
{
- if (err == ENOENT && port_valid (node_ulfs->port))
+
+ if (err != ENOENT)
+ break;
+
+ if (!port_valid (node_ulfs->port))
+ continue;
+
+ err = file_lookup (node_ulfs->port, name,
+ flags | O_NOTRANS, O_NOTRANS,
+ 0, &p, &stat);
+ if (err)
+ continue;
+
+ if (stat.st_ino == underlying_node_stat.st_ino
+ && stat.st_fsid == underlying_node_stat.st_fsid)
+ /* It's OUR root node. */
+ err = ELOOP;
+ else
+ /* stat.st_mode & S_ITRANS */
{
+ port_dealloc (p);
err = file_lookup (node_ulfs->port, name,
- flags | O_NOTRANS, O_NOTRANS,
- 0, &p, &stat);
- if (! err)
- {
- if (stat.st_ino == underlying_node_stat.st_ino
- && stat.st_fsid == underlying_node_stat.st_fsid)
- /* It's OUR root node. */
- err = ELOOP;
- else if (1) //stat.st_mode & S_ITRANS)
- {
- port_dealloc (p);
- err = file_lookup (node_ulfs->port, name,
- flags, 0, 0, &p, &stat);
- }
- }
+ flags, 0, 0, &p, &stat);
}
}
+
if (! err)
{
*s = stat;
*port = p;
}
+
return err;
}
@@ -206,10 +261,14 @@ node_lookup_file (node_t *dir, char *name, int flags,
void
node_ulfs_free (node_t *node)
{
+
node_ulfs_iterate_unlocked (node)
- if (port_valid (node_ulfs->port)
- && node_ulfs->port != underlying_node)
- port_dealloc (node_ulfs->port);
+ {
+ if (port_valid (node_ulfs->port)
+ && node_ulfs->port != underlying_node)
+ port_dealloc (node_ulfs->port);
+ }
+
free (node->nn->ulfs);
}
@@ -223,20 +282,21 @@ node_ulfs_init (node_t *node)
ulfs_new = malloc (ulfs_num * sizeof (node_ulfs_t));
if (! ulfs_new)
- err = ENOMEM;
- else
{
- if (node->nn->ulfs)
- node_ulfs_free (node);
+ err = ENOMEM;
+ return err;
+ }
- node->nn->ulfs = ulfs_new;
- node->nn->ulfs_num = ulfs_num;
+ if (node->nn->ulfs)
+ node_ulfs_free (node);
+
+ node->nn->ulfs = ulfs_new;
+ node->nn->ulfs_num = ulfs_num;
- node_ulfs_iterate_unlocked (node)
- {
- node_ulfs->flags = 0;
- node_ulfs->port = port_null;
- }
+ node_ulfs_iterate_unlocked (node)
+ {
+ node_ulfs->flags = 0;
+ node_ulfs->port = port_null;
}
return err;
@@ -258,8 +318,13 @@ node_entries_get (node_t *node, node_dirent_t **dirents)
one. */
error_t node_dirent_add (char *name, ino_t fileno, int type)
{
- node_dirent_t *node_dirent;
error_t e = 0;
+ node_dirent_t *node_dirent;
+ node_dirent_t *node_dirent_new;
+ struct dirent *dirent_new;
+ int name_len = strlen (name);
+ int size = DIRENT_LEN (name_len);
+
for (node_dirent = node_dirent_list;
node_dirent && strcmp (node_dirent->dirent->d_name, name);
@@ -271,64 +336,59 @@ node_entries_get (node_t *node, node_dirent_t **dirents)
node_dirent->dirent->d_fileno = fileno;
node_dirent->dirent->d_type = type;
+ return e;
}
- else
+
+ /* Create new entry. */
+
+ node_dirent_new = malloc (sizeof (node_dirent_t));
+ if (!node_dirent_new)
+ {
+ e = ENOMEM;
+ return e;
+ }
+
+ dirent_new = malloc (size);
+ if (!dirent_new)
{
- /* Create new entry. */
-
- node_dirent_t *node_dirent_new;
-
- node_dirent_new = malloc (sizeof (node_dirent_t));
- if (node_dirent_new)
- {
- int name_len = strlen (name);
- int size = DIRENT_LEN (name_len);
- struct dirent *dirent_new;
-
- dirent_new = malloc (size);
- if (dirent_new)
- {
- /* Fill dirent. */
- dirent_new->d_fileno = fileno;
- dirent_new->d_type = type;
- dirent_new->d_reclen = size;
- strcpy ((char *) dirent_new + DIRENT_NAME_OFFS, name);
-
- /* Add dirent to the list. */
- node_dirent_new->dirent = dirent_new;
- node_dirent_new->next = node_dirent_list;
- node_dirent_list = node_dirent_new;
- }
- else
- {
- free (node_dirent_new);
- e = ENOMEM;
- }
- }
- else
- e = ENOMEM;
+ free (node_dirent_new);
+ e = ENOMEM;
+ return e;
}
+
+ /* Fill dirent. */
+ dirent_new->d_fileno = fileno;
+ dirent_new->d_type = type;
+ dirent_new->d_reclen = size;
+ strcpy ((char *) dirent_new + DIRENT_NAME_OFFS, name);
+
+ /* Add dirent to the list. */
+ node_dirent_new->dirent = dirent_new;
+ node_dirent_new->next = node_dirent_list;
+ node_dirent_list = node_dirent_new;
+
return e;
}
node_ulfs_iterate_unlocked(node)
{
- if (port_valid (node_ulfs->port))
- {
- err = dir_entries_get (node_ulfs->port, &dirent_data,
- &dirent_data_size, &dirent_list);
- if (! err)
- {
- for (dirent = dirent_list; (! err) && *dirent; dirent++)
- if (strcmp ((*dirent)->d_name, ".")
- && strcmp ((*dirent)->d_name, ".."))
- err = node_dirent_add ((*dirent)->d_name,
- (*dirent)->d_fileno,
- (*dirent)->d_type);
- free (dirent_list);
- munmap (dirent_data, dirent_data_size);
- }
- }
+ if (!port_valid (node_ulfs->port))
+ continue;
+
+ err = dir_entries_get (node_ulfs->port, &dirent_data,
+ &dirent_data_size, &dirent_list);
+ if (err)
+ continue;
+
+ for (dirent = dirent_list; (! err) && *dirent; dirent++)
+ if (strcmp ((*dirent)->d_name, ".")
+ && strcmp ((*dirent)->d_name, ".."))
+ err = node_dirent_add ((*dirent)->d_name,
+ (*dirent)->d_fileno,
+ (*dirent)->d_type);
+
+ free (dirent_list);
+ munmap (dirent_data, dirent_data_size);
}
if (err)
@@ -363,17 +423,18 @@ node_create_root (node_t **root_node)
error_t err = 0;
err = lnode_create (NULL, &lnode);
- if (! err)
+ if (err)
+ return err;
+
+ err = node_create (lnode, &node);
+ if (err)
{
- err = node_create (lnode, &node);
- if (err)
- lnode_destroy (lnode);
- else
- mutex_unlock (&lnode->lock);
+ lnode_destroy (lnode);
+ return err;
}
- if (! err)
- *root_node = node;
+ mutex_unlock (&lnode->lock);
+ *root_node = node;
return err;
}
@@ -383,36 +444,42 @@ error_t
node_init_root (node_t *node)
{
error_t err;
+ ulfs_t *ulfs;
+ int i = 0;
mutex_lock (&ulfs_lock);
err = node_ulfs_init (node);
- if (! err)
+ if (err)
+ {
+ mutex_unlock (&ulfs_lock);
+ return err;
+ }
+
+ node_ulfs_iterate_unlocked (node)
{
- ulfs_t *ulfs;
- int i = 0;
- node_ulfs_iterate_unlocked (node)
+ if (err)
+ break;
+
+ err = ulfs_get_num (i, &ulfs);
+ if (err)
+ break;
+
+ if (ulfs->path)
+ node_ulfs->port = file_name_lookup (ulfs->path,
+ O_READ | O_DIRECTORY, 0);
+ else
+ node_ulfs->port = underlying_node;
+
+ if (! port_valid (node_ulfs->port))
{
- if (! err)
- err = ulfs_get_num (i, &ulfs);
- if (! err)
- {
- if (ulfs->path)
- node_ulfs->port = file_name_lookup (ulfs->path,
- O_READ | O_DIRECTORY, 0);
- else
- node_ulfs->port = underlying_node;
-
- if (! port_valid (node_ulfs->port))
- err = errno;
- else
- {
- node_ulfs->flags |= FLAG_NODE_ULFS_FIXED;
- i++;
- }
- }
+ err = errno;
+ break;
}
+
+ node_ulfs->flags |= FLAG_NODE_ULFS_FIXED;
+ i++;
}
mutex_unlock (&ulfs_lock);