summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGianluca Guida <glguida@gmail.com>2005-05-25 01:59:48 +0000
committerGianluca Guida <glguida@gmail.com>2005-05-25 01:59:48 +0000
commitc0351921ad4ad4b4a69a2b29ed6fc289d97392db (patch)
treeface8d7ad8468cbd5289447c87270083b667a2e1
parent25364edf1efa3f73a2c7a1cc35b700d9778d9faa (diff)
added mkdir and rmdir support
-rw-r--r--ChangeLog16
-rw-r--r--netfs.c75
-rw-r--r--node.c42
-rw-r--r--node.h8
4 files changed, 136 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index f12367c..83bc13a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2005-05-25 Gianluca Guida <glguida@gmail.com>
+
+ * CAVEAT: New file.
+ * README: Rewritten.
+
+ * netfs.c (netfs_attempt_unlink): Use fshelp_checkdirmod
+ instead of fshelp_access.
+ (netfs_attempt_mkdir): Implemented.
+ (netfs_attempt_rmdir): Likewise.
+ (netfs_attempt_create_file_reduced): Likewise.
+ Fixed typo in a comment.
+ * node.c (node_dir_remove): New function.
+ (node_dir_create): Likewise.
+ * node.h (node_dir_create): New declaration.
+ (node_dir_remove): Likewise.
+
2005-05-24 Gianluca Guida <glguida@gmail.com>
* netfs.c (netfs_attempt_unlink): Implemented.
diff --git a/netfs.c b/netfs.c
index 2f80c13..024a097 100644
--- a/netfs.c
+++ b/netfs.c
@@ -235,10 +235,18 @@ netfs_attempt_unlink (struct iouser *user, struct node *dir,
char *name)
{
error_t err = 0;
+ mach_port_t p;
+ struct stat statbuf;
node_update (dir);
- err = fshelp_access (&dir->nn_stat, S_IWRITE, user);
+ err = node_lookup_file (dir, name, 0, &p, &statbuf);
+ if (err)
+ return err;
+
+ port_dealloc (p);
+
+ err = fshelp_checkdirmod (&dir->nn_stat, &statbuf, user);
if (err)
return err;
@@ -263,7 +271,46 @@ error_t
netfs_attempt_mkdir (struct iouser *user, struct node *dir,
char *name, mode_t mode)
{
- return EOPNOTSUPP;
+ error_t err = 0;
+ mach_port_t p;
+ struct stat statbuf;
+
+ node_update (dir);
+
+ err = fshelp_checkdirmod (&dir->nn_stat, 0, 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;
+ }
+
+ err = node_dir_create (dir, name, mode);
+ if (err)
+ goto exit;
+
+ err = node_lookup_file (dir, name, 0, &p, &statbuf);
+ if (err)
+ {
+ node_dir_remove (dir, name);
+ goto exit;
+ }
+
+ err = file_chown (p, user->uids->ids[0], user->gids->ids[0]);
+ if (err)
+ {
+ port_dealloc (p);
+ node_dir_remove (dir, name);
+ goto exit;
+ }
+
+ port_dealloc (p);
+
+ exit:
+ return err;
}
/* Attempt to remove directory named NAME in DIR (which is locked) for
@@ -272,7 +319,25 @@ error_t
netfs_attempt_rmdir (struct iouser *user,
struct node *dir, char *name)
{
- return EOPNOTSUPP;
+ error_t err = 0;
+ mach_port_t p;
+ struct stat statbuf;
+
+ node_update (dir);
+
+ err = node_lookup_file (dir, name, 0, &p, &statbuf);
+ if (err)
+ return err;
+
+ port_dealloc (p);
+
+ err = fshelp_checkdirmod (&dir->nn_stat, &statbuf, user);
+ if (err)
+ return err;
+
+ err = node_dir_remove (dir, name);
+
+ return err;
}
/* Create a link in DIR with name NAME to FILE for USER. Note that
@@ -320,11 +385,11 @@ netfs_attempt_create_file_reduced (struct iouser *user, struct node *dir,
node_update (dir);
- err = fshelp_access (&dir->nn_stat, S_IWRITE, user);
+ err = fshelp_checkdirmod (&dir->nn_stat, 0, user);
if (err)
goto exit;
- /* Special case for no UID processes (like login shell) */
+ /* Special case for no UID processes (like login shell). */
if ((!user->uids->ids) || (!user->uids->ids))
{
err = EACCES;
diff --git a/node.c b/node.c
index 976d5d1..c96737d 100644
--- a/node.c
+++ b/node.c
@@ -183,6 +183,48 @@ node_update (node_t *node)
return err;
}
+/* Remove all directory named NAME beneath DIR on all underlying filesystems.
+ Fails if we cannot remove all the directories. */
+error_t
+node_dir_remove (node_t *dir, char *name)
+{
+ error_t err = 0;
+
+ node_ulfs_iterate_reverse_unlocked (dir)
+ {
+ if (!port_valid (node_ulfs->port))
+ continue;
+
+ err = dir_rmdir (node_ulfs->port, name);
+
+ if ((err) && (err != ENOENT))
+ break;
+ }
+
+ return err;
+}
+
+/* Create a directory named NAME beneath DIR on the first (writable) underlying
+ filesystem. */
+error_t
+node_dir_create (node_t *dir, char *name, mode_t mode)
+{
+ error_t err = 0;
+
+ node_ulfs_iterate_unlocked (dir)
+ {
+ if (!port_valid (node_ulfs->port))
+ continue;
+
+ err = dir_mkdir (node_ulfs->port, name, mode);
+
+ if ((!err) || (err == EEXIST) || (err == ENOTDIR))
+ break;
+ }
+
+ return err;
+}
+
/* Remove all files named NAME beneath DIR on the underlying filesystems
with FLAGS as openflags. */
error_t
diff --git a/node.h b/node.h
index e647ce0..41ae43a 100644
--- a/node.h
+++ b/node.h
@@ -80,6 +80,14 @@ void node_destroy (node_t *node);
which must be locked, are uptodate. */
error_t node_update (node_t *node);
+/* Create a directory named NAME beneath DIR on all the (writable) underlying
+ filesystems. */
+error_t node_dir_create (node_t *dir, char *name, mode_t mode);
+
+/* Remove all directory named NAME beneath DIR on all underlying filesystems.
+ Fails if we cannot remove all the directories. */
+error_t node_dir_remove (node_t *dir, char *name);
+
/* 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);