summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGianluca Guida <glguida@gmail.com>2005-05-24 22:41:38 +0000
committerGianluca Guida <glguida@gmail.com>2005-05-24 22:41:38 +0000
commit459df2f3cf215a8712f55280e0617189c45ff518 (patch)
tree1707e71574d90ae862058c7926c6ccfb9d4fe9d8
parent023b8ad08b52ce938ab84db8052b4ce940cd0e8a (diff)
added file creation and unlinking
-rw-r--r--ChangeLog16
-rw-r--r--netfs.c230
-rw-r--r--node.c433
-rw-r--r--node.h9
-rw-r--r--options.c2
5 files changed, 447 insertions, 243 deletions
diff --git a/ChangeLog b/ChangeLog
index e9ff7a9..ac17c7b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2005-05-24 Gianluca Guida <glguida@gmail.com>
+
+ * netfs.c (netfs_attempt_unlink): Implemented.
+ (netfs_attempt_create_file_reduced): New function.
+ (netfs_S_dir_lookup): Initialized variable "error".
+ Added support for file creation.
+ (netfs_attempt_lookup_improved): Changed instruction flow,
+ return on error not continue on non-error.
+ Check user permission to open file before returning port.
+ * node.c (node_create, node_update, node_lookup_file, node_ulfs_free)
+ (node_ulfs_init, node_entries_get, node_create_root, node_init_root):
+ Changed instruction flow, return on error not continue on non-error.
+ (node_unlink_file): New function.
+ * node.h (node_unlink_file): New declaration.
+ (node_ulfs_iterate_reverse_unlocked): New macro.
+
2005-01-31 Gianluca Guida <glguida@gmail.com>
* stow.c (stow_diradd): Handle --stow argument with missing /
diff --git a/netfs.c b/netfs.c
index 729cca4..2f80c13 100644
--- a/netfs.c
+++ b/netfs.c
@@ -1,5 +1,5 @@
/* Hurd unionfs
- Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
Written by Moritz Schulte <moritz@duesseldorf.ccc.de>.
This program is free software; you can redistribute it and/or
@@ -234,7 +234,17 @@ error_t
netfs_attempt_unlink (struct iouser *user, struct node *dir,
char *name)
{
- return EOPNOTSUPP;
+ error_t err = 0;
+
+ node_update (dir);
+
+ err = fshelp_access (&dir->nn_stat, S_IWRITE, user);
+ if (err)
+ return err;
+
+ err = node_unlink_file (dir, name);
+
+ return err;
}
/* Attempt to rename the directory FROMDIR to TODIR. Note that neither
@@ -298,6 +308,77 @@ netfs_attempt_create_file (struct iouser *user, struct node *dir,
return EOPNOTSUPP;
}
+/* We use this local interface to attempt_create file since we are
+ using our own netfs_S_dir_lookup. */
+error_t
+netfs_attempt_create_file_reduced (struct iouser *user, struct node *dir,
+ char *name, mode_t mode, int flags)
+{
+ mach_port_t p;
+ error_t err;
+ struct stat statbuf;
+
+ node_update (dir);
+
+ err = fshelp_access (&dir->nn_stat, S_IWRITE, user);
+ if (err)
+ goto exit;
+
+ /* Special case for no UID processes (like login shell) */
+ if ((!user->uids->ids) || (!user->uids->ids))
+ {
+ err = EACCES;
+ goto exit;
+ }
+
+ mutex_unlock (&dir->lock);
+ err = node_lookup_file (dir, name, flags | O_CREAT,
+ &p, &statbuf);
+ mutex_lock (&dir->lock);
+
+ if (err)
+ goto exit;
+
+ err = file_chmod (p, mode);
+ if (err)
+ {
+ port_dealloc (p);
+ node_unlink_file (dir, name);
+ goto exit;
+ }
+
+ err = file_chown (p, user->uids->ids[0], user->gids->ids[0]);
+ if (err)
+ {
+ port_dealloc (p);
+ node_unlink_file (dir, name);
+ goto exit;
+ }
+
+ err = io_stat (p, &statbuf);
+
+ /* Check file permissions. */
+ if (! err && (flags & O_READ))
+ err = fshelp_access (&statbuf, S_IREAD, user);
+ if (! err && (flags & O_WRITE))
+ err = fshelp_access (&statbuf, S_IWRITE, user);
+ if (! err && (flags & O_EXEC))
+ err = fshelp_access (&statbuf, S_IEXEC, user);
+
+ if (err)
+ {
+ port_dealloc (p);
+ node_unlink_file (dir, name);
+ goto exit;
+ }
+
+ port_dealloc (p);
+
+ exit:
+ mutex_unlock (&dir->lock);
+ return err;
+}
+
/* Read the contents of locked node NP (a symlink), for USER, into
BUF. */
error_t
@@ -389,26 +470,35 @@ netfs_attempt_lookup_improved (struct iouser *user, struct node *dir,
mutex_lock (&dir->nn->lnode->lock);
err = fshelp_access (&dir->nn_stat, S_IEXEC, user);
- if ((! err) && (! *name || ! strcmp (name, ".")))
+ if (err)
+ goto exit;
+
+
+ if (! *name || ! strcmp (name, "."))
{
+
/* The same node is wanted. */
*np = dir;
netfs_nref (*np);
+
}
- else if ((! err) && (! strcmp (name, "..")))
+ else if (! strcmp (name, ".."))
{
+
/* We have to get the according light node first. */
lnode_t *lnode = dir->nn->lnode;
node_t *node;
err = ncache_node_lookup (lnode->dir, &node);
- if (! err)
- {
- *np = node;
- }
+ if (err)
+ goto exit;
+
+ *np = node;
+
}
- else if (! err)
+ else
{
+
lnode_t *dir_lnode = dir->nn->lnode;
struct stat statbuf;
lnode_t *lnode = NULL;
@@ -421,13 +511,18 @@ netfs_attempt_lookup_improved (struct iouser *user, struct node *dir,
/* We have to unlock this node while doing lookups. */
mutex_unlock (&dir_lnode->lock);
mutex_unlock (&dir->lock);
- if (! err)
- err = node_lookup_file (dir, name, flags & ~O_NOLINK,
- &p, &statbuf);
+
+ err = node_lookup_file (dir, name, flags & ~(O_NOLINK|O_CREAT),
+ &p, &statbuf);
+
mutex_lock (&dir->lock);
mutex_lock (&dir_lnode->lock);
- if ((! err) && S_ISDIR (statbuf.st_mode))
+
+ if (err)
+ goto exit;
+
+ if (S_ISDIR (statbuf.st_mode))
{
node_t *node;
@@ -441,54 +536,70 @@ netfs_attempt_lookup_improved (struct iouser *user, struct node *dir,
if (err == ENOENT)
{
/* It does not exist, we have to create it. */
-
err = lnode_create (name, &lnode);
- if (! err)
- lnode_install (dir_lnode, lnode);
+ if (err)
+ goto exit;
+
+ lnode_install (dir_lnode, lnode);
}
+
+ /* Now we have a light node. */
+ err = ncache_node_lookup (lnode, &node);
+
+ /* This unlocks the node for us. */
+ lnode_ref_remove (lnode);
- if (! err)
- /* Now we have a light node. */
- err = ncache_node_lookup (lnode, &node);
-
- if (lnode)
- /* This unlocks the node for us. */
- lnode_ref_remove (lnode);
-
- if (! err)
- {
- /* Got the node. */
- *np = node;
- }
+ if (err)
+ goto exit;
+
+ /* Got the node. */
+ *np = node;
+
}
- else if (! err)
+ else
{
/* The found node is not a directory. */
+ mach_port_t p_restricted;
+
if (! lastcomp)
{
/* We have not reached the last path component yet. */
port_dealloc (p);
err = ENOTDIR;
+ goto exit;
}
- if (! err)
- {
- mach_port_t p_restricted;
- /* A file node is successfully looked up. */
- err = io_restrict_auth (p, &p_restricted,
- user->uids->ids, user->uids->num,
- user->gids->ids, user->gids->num);
+ /* Check file permissions. */
+ if (! err && (flags & O_READ))
+ err = fshelp_access (&statbuf, S_IREAD, user);
+ if (! err && (flags & O_WRITE))
+ err = fshelp_access (&statbuf, S_IWRITE, user);
+ if (! err && (flags & O_EXEC))
+ err = fshelp_access (&statbuf, S_IEXEC, user);
+
+ if (err)
+ {
port_dealloc (p);
- if (! err)
- {
- /* Successfully restricted. */
- *port = p_restricted;
- *port_type = MACH_MSG_TYPE_MOVE_SEND;
- }
+ goto exit;
}
+
+
+ /* A file node is successfully looked up. */
+ err = io_restrict_auth (p, &p_restricted,
+ user->uids->ids, user->uids->num,
+ user->gids->ids, user->gids->num);
+ port_dealloc (p);
+
+ if (err)
+ goto exit;
+
+ /* Successfully restricted. */
+ *port = p_restricted;
+ *port_type = MACH_MSG_TYPE_MOVE_SEND;
}
}
-
+
+ exit:
if (err)
*np = NULL;
@@ -531,7 +642,7 @@ netfs_S_dir_lookup (struct protid *diruser,
int nsymlinks = 0;
struct node *dnp, *np;
char *nextname;
- error_t error;
+ error_t error = 0;
struct protid *newpi;
struct iouser *user;
@@ -633,34 +744,37 @@ netfs_S_dir_lookup (struct protid *diruser,
else
/* Attempt a lookup on the next pathname component. */
error = netfs_attempt_lookup_improved (diruser->user, dnp,
- filename, &np, flags, lastcomp,
+ filename, &np,
+ flags, lastcomp,
retry_port, retry_port_type);
-
+
/* At this point, DNP is unlocked */
-
+
/* Implement O_EXCL flag here */
if (lastcomp && create && excl && !error && np)
error = EEXIST;
-
+
/* Create the new node if necessary */
if (lastcomp && create && error == ENOENT)
{
mode &= ~(S_IFMT | S_ISPARE | S_ISVTX);
mode |= S_IFREG;
mutex_lock (&dnp->lock);
- /* FIXME, new interface needed! */
- error = netfs_attempt_create_file (diruser->user, dnp,
- filename, mode, &np);
-
- /* If someone has already created the file (between our lookup
- and this create) then we just got EEXIST. If we are
- EXCL, that's fine; otherwise, we have to retry the lookup. */
- if (error == EEXIST && !excl)
+
+ error = netfs_attempt_create_file_reduced (diruser->user, dnp,
+ filename, mode, flags);
+
+ /* We retry lookup in two cases:
+ - we created the file and we have to get a valid port;
+ - someone has already created the file (between our lookup
+ and this create) then we just got EEXIST. If we are EXCL,
+ that's fine; otherwise, we have to retry the lookup. */
+ if ((!error) || (error == EEXIST && !excl))
{
mutex_lock (&dnp->lock);
goto retry_lookup;
}
-
+
newnode = 1;
}
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);
diff --git a/node.h b/node.h
index 4d30417..e647ce0 100644
--- a/node.h
+++ b/node.h
@@ -80,6 +80,10 @@ void node_destroy (node_t *node);
which must be locked, are uptodate. */
error_t node_update (node_t *node);
+/* 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);
+
/* Lookup a file named NAME beneath DIR on the underlying filesystems
with FLAGS as openflags. Return the first port successfully looked
up in *PORT and according stat information in *STAT. */
@@ -115,4 +119,9 @@ error_t node_init_root (node_t *node);
node_ulfs < (node)->nn->ulfs + (node)->nn->ulfs_num; \
node_ulfs++)
+#define node_ulfs_iterate_reverse_unlocked(node) \
+ for (node_ulfs_t *node_ulfs = (node)->nn->ulfs + (node)->nn->ulfs_num - 1;\
+ node_ulfs >= (node)->nn->ulfs; \
+ node_ulfs--)
+
#endif
diff --git a/options.c b/options.c
index 28a68bf..d14b3ef 100644
--- a/options.c
+++ b/options.c
@@ -113,8 +113,6 @@ argp_parse_common_options (int key, char *arg, struct argp_state *state)
case OPT_UNDERLYING: /* --underlying */
case ARGP_KEY_ARG:
- fprintf (stderr, "adding %s\n", arg);
-
if (ulfs_remove)
{
err = ulfs_unregister (arg);