diff options
author | Gianluca Guida <glguida@gmail.com> | 2005-05-25 01:59:48 +0000 |
---|---|---|
committer | Gianluca Guida <glguida@gmail.com> | 2005-05-25 01:59:48 +0000 |
commit | c0351921ad4ad4b4a69a2b29ed6fc289d97392db (patch) | |
tree | face8d7ad8468cbd5289447c87270083b667a2e1 | |
parent | 25364edf1efa3f73a2c7a1cc35b700d9778d9faa (diff) |
added mkdir and rmdir support
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | netfs.c | 75 | ||||
-rw-r--r-- | node.c | 42 | ||||
-rw-r--r-- | node.h | 8 |
4 files changed, 136 insertions, 5 deletions
@@ -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. @@ -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; @@ -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 @@ -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); |