diff options
author | Sergiu Ivanov <unlimitedscolobb@gmail.com> | 2008-11-21 23:54:40 +0200 |
---|---|---|
committer | Sergiu Ivanov <unlimitedscolobb@gmail.com> | 2008-11-21 23:54:40 +0200 |
commit | a54273639f6afd659c15326cb997922fcecfe89a (patch) | |
tree | 3f240fed8fcfd7f14cbc5b7d059f48f6eb9707cb | |
parent | 59f4d4d2b67028c01f41ea0de0f12934b4fad07b (diff) |
Moved the code to GCS
Now the code is (hopefully) compliant with GNU Coding Standards.
-rw-r--r-- | debug.h | 51 | ||||
-rw-r--r-- | lib.c | 371 | ||||
-rw-r--r-- | lib.h | 95 | ||||
-rw-r--r-- | lnode.c | 759 | ||||
-rw-r--r-- | lnode.h | 242 | ||||
-rw-r--r-- | ncache.c | 364 | ||||
-rw-r--r-- | ncache.h | 122 | ||||
-rw-r--r-- | node.c | 1860 | ||||
-rw-r--r-- | node.h | 280 | ||||
-rw-r--r-- | nsmux.c | 2792 | ||||
-rw-r--r-- | nsmux.h | 414 | ||||
-rw-r--r-- | options.c | 346 | ||||
-rw-r--r-- | options.h | 34 |
13 files changed, 3569 insertions, 4161 deletions
@@ -1,10 +1,10 @@ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*debug.h*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Simple facilities for debugging messages*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Copyright (C) 2001, 2002, 2005, 2008 Free Software Foundation, Inc. Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. @@ -22,39 +22,38 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #ifndef __DEBUG_H__ #define __DEBUG_H__ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #include <stdio.h> -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Macros--------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Macros-------------------------------------------------------------*/ /*Print debug messages here*/ #define DEBUG_OUTPUT "/var/log/nsmux.dbg" -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #ifdef DEBUG - /*Initializes the log*/ -# define INIT_LOG() nsmux_dbg = fopen(DEBUG_OUTPUT, "wt") - /*Closes the log*/ +/*Initializes the log */ +# define INIT_LOG() nsmux_dbg = fopen(DEBUG_OUTPUT, "wt") +/*Closes the log */ # define CLOSE_LOG() fclose(nsmux_dbg) - /*Prints a debug message and flushes the debug output*/ -# define LOG_MSG(fmt, args...) {fprintf(nsmux_dbg, fmt"\n", ##args);\ - fflush(nsmux_dbg);} +/*Prints a debug message and flushes the debug output */ +# define LOG_MSG(fmt, args...) {fprintf(nsmux_dbg, fmt"\n", ##args);\ + fflush(nsmux_dbg);} #else - /*Remove requests for debugging output*/ -# define INIT_LOG() -# define CLOSE_LOG() -# define LOG_MSG(fmt, args...) +/*Remove requests for debugging output */ +# define INIT_LOG() +# define CLOSE_LOG() +# define LOG_MSG(fmt, args...) #endif /*DEBUG*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Global Variables----------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Global Variables---------------------------------------------------*/ /*The file to write debugging info to*/ -extern FILE * nsmux_dbg; -/*----------------------------------------------------------------------------*/ - +extern FILE *nsmux_dbg; +/*---------------------------------------------------------------------------*/ #endif /*__DEBUG_H__*/ @@ -1,10 +1,10 @@ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*lib.h*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Basic routines for filesystem manipulations*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Copyright (C) 2001, 2002, 2005, 2008 Free Software Foundation, Inc. Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. @@ -22,198 +22,195 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #define _GNU_SOURCE 1 -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #include <sys/mman.h> #include <fcntl.h> #include <hurd/fshelp.h> -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #include "lib.h" #include "debug.h" -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Functions-----------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Functions----------------------------------------------------------*/ /*Fetches directory entries for `dir`*/ -error_t -dir_entries_get - ( - file_t dir, - char ** dirent_data, /*the list of directory entries as returned - by dir_readdir*/ - size_t * dirent_data_size, /*the size of `dirent_data`*/ - struct dirent *** dirent_list /*the array of pointers to beginnings of - dirents in dirent_data*/ - ) - { - error_t err = 0; - - /*The data (array of dirents(?)) returned by dir_readdir*/ - char * data; - - /*The size of `data`*/ - size_t data_size; - - /*The number of entries in `data`*/ - int entries_num; - - /*Try to read the contents of the specified directory*/ - err = dir_readdir(dir, &data, &data_size, 0, -1, 0, &entries_num); - if(err) - return err; - - /*Create a new list of dirents*/ - struct dirent ** list; - - /*Allocate the memory for the list of dirents and for the - finalizing element*/ - list = malloc(sizeof(struct dirent *) * (entries_num + 1)); - - /*If memory allocation has failed*/ - if(!list) - { - /*free the result of dir_readdir*/ - munmap(data, data_size); - - /*return the corresponding error*/ - return ENOMEM; - } - - /*The current directory entry*/ - struct dirent * dp; - - int i; - - /*Go through every element of the list of dirents*/ - for - ( - i = 0, dp = (struct dirent *)data; - i < entries_num; - ++i, dp = (struct dirent *)((char *)dp + dp->d_reclen)) - /*copy the current value into the list*/ - *(list + i) = dp; - - /*Nullify the last element of the list*/ - *(list + i) = NULL; - - /*Copy the required values in the parameters*/ - *dirent_data = data; - *dirent_data_size = data_size; - *dirent_list = list; - - /*Return success*/ - return err; - }/*dir_entries_get*/ -/*----------------------------------------------------------------------------*/ +error_t dir_entries_get (file_t dir, + char **dirent_data, /*the list of directory + entries as returned by + dir_readdir */ + size_t * dirent_data_size,/*the size of + `dirent_data` */ + struct dirent ***dirent_list/*the array of + pointers to + beginnings of + dirents in + dirent_data */ + ) +{ + error_t err = 0; + + /*The data (array of dirents(?)) returned by dir_readdir */ + char *data; + + /*The size of `data` */ + size_t data_size; + + /*The number of entries in `data` */ + int entries_num; + + /*Try to read the contents of the specified directory */ + err = dir_readdir (dir, &data, &data_size, 0, -1, 0, &entries_num); + if (err) + return err; + + /*Create a new list of dirents */ + struct dirent **list; + + /*Allocate the memory for the list of dirents and for the + finalizing element */ + list = malloc (sizeof (struct dirent *) * (entries_num + 1)); + + /*If memory allocation has failed */ + if (!list) + { + /*free the result of dir_readdir */ + munmap (data, data_size); + + /*return the corresponding error */ + return ENOMEM; + } + + /*The current directory entry */ + struct dirent *dp; + + int i; + + /*Go through every element of the list of dirents */ + for + (i = 0, dp = (struct dirent *) data; + i < entries_num; + ++i, dp = (struct dirent *) ((char *) dp + dp->d_reclen)) + /*copy the current value into the list */ + *(list + i) = dp; + + /*Nullify the last element of the list */ + *(list + i) = NULL; + + /*Copy the required values in the parameters */ + *dirent_data = data; + *dirent_data_size = data_size; + *dirent_list = list; + + /*Return success */ + return err; +} /*dir_entries_get */ + +/*---------------------------------------------------------------------------*/ /*Lookup `name` under `dir` (or cwd, if `dir` is invalid)*/ -error_t -file_lookup - ( - file_t dir, - char * name, - int flags0, /*try to open with these flags first*/ - int flags1, /*try to open with these flags, if `flags0` fail*/ - int mode, /*if the file is to be created, create it with this mode*/ - file_t * port, /*store the port to the looked up file here*/ - io_statbuf_t * stat /*store the stat information here*/ - ) +error_t file_lookup (file_t dir, char *name, + int flags0, /*try to open with these flags first */ + int flags1, /*try to open with these flags, if + `flags0` fail */ + int mode, /*if the file is to be created, create + it with this mode */ + file_t * port, /*store the port to the looked up + file here */ + io_statbuf_t * stat /*store the stat information here */ + ) +{ + error_t err = 0; + + /*The port to the looked up file */ + file_t p; + + /*The stat information about the looked up file */ + io_statbuf_t s; + + /*Performs a lookup under 'dir' or in cwd, if `dir` is invalid */ + file_t do_file_lookup (file_t dir, char *name, /*lookup this file */ + int flags, /*lookup the file with these flags */ + int mode /*if a new file is to be + created, create it with this + mode */ + ) + { + /*The result of lookup */ + file_t p; + + /*If `dir` is a valid port */ + if (dir != MACH_PORT_NULL) + /*try to lookup `name` under `dir` */ + p = file_name_lookup_under (dir, name, flags, mode); + else + /*lookup `name` under current cwd */ + p = file_name_lookup (name, flags, mode); + + /*Return the result of the lookup */ + return p; + } /*do_file_lookup */ + + /*Lookup `name` under the suggested `dir` */ + p = do_file_lookup (dir, name, flags0, mode); + + /*If the lookup failed */ + if (p == MACH_PORT_NULL) + /*try to lookup for `name` using alternative flags `flags1` */ + p = do_file_lookup (dir, name, flags1, mode); + + /*If the port is valid */ + if (p != MACH_PORT_NULL) + { + /*If stat information is required */ + if (stat) { - error_t err = 0; - - /*The port to the looked up file*/ - file_t p; - - /*The stat information about the looked up file*/ - io_statbuf_t s; - - /*Performs a lookup under 'dir' or in cwd, if `dir` is invalid*/ - file_t - do_file_lookup - ( - file_t dir, - char * name, /*lookup this file*/ - int flags, /*lookup the file with these flags*/ - int mode /*if a new file is to be created, create it with this mode*/ - ) - { - /*The result of lookup*/ - file_t p; - - /*If `dir` is a valid port*/ - if(dir != MACH_PORT_NULL) - /*try to lookup `name` under `dir`*/ - p = file_name_lookup_under(dir, name, flags, mode); - else - /*lookup `name` under current cwd*/ - p = file_name_lookup(name, flags, mode); - - /*Return the result of the lookup*/ - return p; - }/*do_file_lookup*/ - - /*Lookup `name` under the suggested `dir`*/ - p = do_file_lookup(dir, name, flags0, mode); - - /*If the lookup failed*/ - if(p == MACH_PORT_NULL) - /*try to lookup for `name` using alternative flags `flags1`*/ - p = do_file_lookup(dir, name, flags1, mode); - - /*If the port is valid*/ - if(p != MACH_PORT_NULL) - { - /*If stat information is required*/ - if(stat) - { - /*obtain stat information for `p`*/ - err = io_stat(p, &s); - if(err) - PORT_DEALLOC(p); - } - } - else - /*copy `errno` into `err`*/ - err = errno; - - /*If no errors have happened during lookup*/ - if(!err) - { - /*copy the resulting port into *`port`*/ - *port = p; - - /*fill in the receiver for stat information, if requried*/ - if(stat) - *stat = s; - } - - /*Return the result of performing operations*/ - return err; - }/*file_lookup*/ -/*----------------------------------------------------------------------------*/ -/*Checks whether `user` has the right to open the node described by `stat` with - `flags`*/ + /*obtain stat information for `p` */ + err = io_stat (p, &s); + if (err) + PORT_DEALLOC (p); + } + } + else + /*copy `errno` into `err` */ + err = errno; + + /*If no errors have happened during lookup */ + if (!err) + { + /*copy the resulting port into *`port` */ + *port = p; + + /*fill in the receiver for stat information, if requried */ + if (stat) + *stat = s; + } + + /*Return the result of performing operations */ + return err; +} /*file_lookup */ + +/*---------------------------------------------------------------------------*/ +/*Checks whether `user` has the right to open the node described by + `stat` with `flags`*/ error_t -check_open_permissions - ( - struct iouser * user, - io_statbuf_t * stat, - int flags - ) - { - error_t err = 0; - - /*Cheks user's permissions*/ - if(flags & O_READ) - err = fshelp_access(stat, S_IREAD, user); - if(!err && (flags & O_WRITE)) - err = fshelp_access(stat, S_IWRITE, user); - if(!err && (flags & O_EXEC)) - err = fshelp_access(stat, S_IEXEC, user); - - /*Return the result of the check*/ - return err; - }/*check_open_permissions*/ -/*----------------------------------------------------------------------------*/ + check_open_permissions + (struct iouser * user, io_statbuf_t * stat, int flags) +{ + error_t err = 0; + + /*Cheks user's permissions */ + if (flags & O_READ) + err = fshelp_access (stat, S_IREAD, user); + if (!err && (flags & O_WRITE)) + err = fshelp_access (stat, S_IWRITE, user); + if (!err && (flags & O_EXEC)) + err = fshelp_access (stat, S_IEXEC, user); + + /*Return the result of the check */ + return err; +} /*check_open_permissions */ + +/*---------------------------------------------------------------------------*/ @@ -1,10 +1,10 @@ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*lib.h*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Declarations of basic routines for filesystem manipulations*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Copyright (C) 2001, 2002, 2005, 2008 Free Software Foundation, Inc. Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. @@ -22,72 +22,69 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #ifndef __LIB_H__ #define __LIB_H__ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #define __USE_FILE_OFFSET64 -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #include <hurd.h> #include <dirent.h> #include <stddef.h> #include <hurd/iohelp.h> -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Macros--------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Macros-------------------------------------------------------------*/ /*Alignment of directory entries*/ #define DIRENT_ALIGN 4 -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*The offset of the directory name in the directory entry structure*/ #define DIRENT_NAME_OFFS offsetof(struct dirent, d_name) -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Computes the length of the structure before the name + the name + 0, - all padded to DIRENT_ALIGN*/ + all padded to DIRENT_ALIGN*/ #define DIRENT_LEN(name_len)\ ((DIRENT_NAME_OFFS + (name_len) + 1 + DIRENT_ALIGN - 1) &\ ~(DIRENT_ALIGN - 1)) -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Deallocate the given port for the current task*/ #define PORT_DEALLOC(p) (mach_port_deallocate(mach_task_self(), (p))) -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Functions-----------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Functions----------------------------------------------------------*/ /*Fetches directory entries for `dir`*/ -error_t -dir_entries_get - ( - file_t dir, - char ** dirent_data, /*the list of directory entries as returned - by dir_readdir*/ - size_t * dirent_data_size, /*the size of `dirent_data`*/ - struct dirent *** dirent_list /*the array of pointers to beginnings of - dirents in dirent_data*/ - ); -/*----------------------------------------------------------------------------*/ +error_t dir_entries_get (file_t dir, + char **dirent_data, /*the list of directory + entries as returned by + dir_readdir */ + size_t * dirent_data_size,/*the size of + `dirent_data` */ + struct dirent ***dirent_list/*the array of + pointers to + beginnings of + dirents in + dirent_data */ + ); +/*---------------------------------------------------------------------------*/ /*Lookup `name` under `dir` (or cwd, if `dir` is invalid)*/ +error_t file_lookup (file_t dir, char *name, + int flags0, /*try to open with these flags first */ + int flags1, /*try to open with these flags, if + `flags0` fail */ + int mode, /*if the file is to be created, create + it with this mode */ + file_t * port, /*store the port to the looked up + file here */ + io_statbuf_t * stat /*store the stat information here */ + ); +/*---------------------------------------------------------------------------*/ +/*Checks whether `user` has the right to open the node described by + `stat` with `flags`*/ error_t -file_lookup - ( - file_t dir, - char * name, - int flags0, /*try to open with these flags first*/ - int flags1, /*try to open with these flags, if `flags0` fail*/ - int mode, /*if the file is to be created, create it with this mode*/ - file_t * port, /*store the port to the looked up file here*/ - io_statbuf_t * stat /*store the stat information here*/ - ); -/*----------------------------------------------------------------------------*/ -/*Checks whether `user` has the right to open the node described by `stat` with - `flags`*/ -error_t -check_open_permissions - ( - struct iouser * user, - io_statbuf_t * stat, - int flags - ); -/*----------------------------------------------------------------------------*/ + check_open_permissions + (struct iouser *user, io_statbuf_t * stat, int flags); +/*---------------------------------------------------------------------------*/ #endif /*__LIB_H__*/ @@ -1,10 +1,10 @@ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*lnode.c*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Implementation of policies of management of 'light nodes'*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Copyright (C) 2001, 2002, 2005, 2008 Free Software Foundation, Inc. Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. @@ -22,407 +22,376 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #define _GNU_SOURCE -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #include "lnode.h" #include "debug.h" #include "node.h" -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Functions-----------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Functions----------------------------------------------------------*/ /*Adds a reference to the `lnode` (which must be locked)*/ -void -lnode_ref_add - ( - lnode_t * node - ) - { - /*Increment the number of references*/ - ++node->references; - }/*lnode_ref_add*/ -/*----------------------------------------------------------------------------*/ -/*Removes a reference from `node` (which must be locked). If that was the last - reference, destroy the node*/ -void -lnode_ref_remove - ( - lnode_t * node - ) - { - /*Fail if the node is not referenced by anybody*/ - assert(node->references); - - /*Decrement the number of references to `node`*/ - --node->references; - - /*If there are no references remaining*/ - if(node->references == 0) - { - /*uninstall the node from the directory it is in and destroy it*/ - lnode_uninstall(node); - lnode_destroy(node); - } - else - /*simply unlock the node*/ - mutex_unlock(&node->lock); - }/*lnode_ref_remove*/ -/*----------------------------------------------------------------------------*/ +void lnode_ref_add (lnode_t * node) +{ + /*Increment the number of references */ + ++node->references; +} /*lnode_ref_add */ + +/*---------------------------------------------------------------------------*/ +/*Removes a reference from `node` (which must be locked). If that was + the last reference, destroy the node*/ +void lnode_ref_remove (lnode_t * node) +{ + /*Fail if the node is not referenced by anybody */ + assert (node->references); + + /*Decrement the number of references to `node` */ + --node->references; + + /*If there are no references remaining */ + if (node->references == 0) + { + /*uninstall the node from the directory it is in and destroy it */ + lnode_uninstall (node); + lnode_destroy (node); + } + else + /*simply unlock the node */ + mutex_unlock (&node->lock); +} /*lnode_ref_remove */ + +/*---------------------------------------------------------------------------*/ /*Creates a new lnode with `name`; the new node is locked and contains - a single reference*/ -error_t -lnode_create - ( - char * name, - lnode_t ** node /*put the result here*/ - ) + a single reference*/ +error_t lnode_create (char *name, lnode_t ** node) +{ + /*Allocate the memory for the node */ + lnode_t *node_new = malloc (sizeof (lnode_t)); + + /*If the memory has not been allocated */ + if (!node_new) + { + /*stop */ + return ENOMEM; + } + + /*The copy of the name */ + char *name_cp = NULL; + + /*If the name exists */ + if (name) + { + /*duplicate it */ + name_cp = strdup (name); + + /*If the name has not been duplicated */ + if (!name_cp) { - /*Allocate the memory for the node*/ - lnode_t * node_new = malloc(sizeof(lnode_t)); - - /*If the memory has not been allocated*/ - if(!node_new) - { - /*stop*/ - return ENOMEM; - } - - /*The copy of the name*/ - char * name_cp = NULL; - - /*If the name exists*/ - if(name) - { - /*duplicate it*/ - name_cp = strdup(name); - - /*If the name has not been duplicated*/ - if(!name_cp) - { - /*free the node*/ - free(node_new); - - /*stop*/ - return ENOMEM; - } - } - - /*Setup the new node*/ - memset(node_new, 0, sizeof(lnode_t)); - node_new->name = name_cp; - node_new->name_len = (name_cp) ? (strlen(name_cp)) : (0); - - /*Setup one reference to this lnode*/ - node_new->references = 1; - - /*Initialize the mutex and acquire a lock on this lnode*/ - mutex_init(&node_new->lock); - mutex_lock(&node_new->lock); - - /*Store the result in the second parameter*/ - *node = node_new; - - /*Return success*/ - return 0; - }/*lnode_create*/ -/*----------------------------------------------------------------------------*/ + /*free the node */ + free (node_new); + + /*stop */ + return ENOMEM; + } + } + + /*Setup the new node */ + memset (node_new, 0, sizeof (lnode_t)); + node_new->name = name_cp; + node_new->name_len = (name_cp) ? (strlen (name_cp)) : (0); + + /*Setup one reference to this lnode */ + node_new->references = 1; + + /*Initialize the mutex and acquire a lock on this lnode */ + mutex_init (&node_new->lock); + mutex_lock (&node_new->lock); + + /*Store the result in the second parameter */ + *node = node_new; + + /*Return success */ + return 0; +} /*lnode_create */ + +/*---------------------------------------------------------------------------*/ /*Destroys the given lnode*/ -void -lnode_destroy - ( - lnode_t * node /*destroy this*/ - ) - { - /*Destroy the name of the node*/ - free(node->name); - - /*While the list of proxies has not been freed*/ - node_list_t p; - for(p = node->proxies; p;) - { - /*shift the pointer to the head of the list forward*/ - node->proxies = node->proxies->next; - - /*drop the current cell in the list*/ - free(p); - - /*store the current proxy*/ - p = node->proxies; - } - - /*Destroy the node itself*/ - free(node); - }/*lnode_destroy*/ -/*----------------------------------------------------------------------------*/ -/*Constructs the full path for the given lnode and stores the result both in - the parameter and inside the lnode (the same string, actually)*/ -error_t -lnode_path_construct - ( - lnode_t * node, - char ** path /*store the path here*/ - ) +void lnode_destroy (lnode_t * node) +{ + /*Destroy the name of the node */ + free (node->name); + + /*While the list of proxies has not been freed */ + node_list_t p; + for (p = node->proxies; p;) + { + /*shift the pointer to the head of the list forward */ + node->proxies = node->proxies->next; + + /*drop the current cell in the list */ + free (p); + + /*store the current proxy */ + p = node->proxies; + } + + /*Destroy the node itself */ + free (node); +} /*lnode_destroy */ + +/*---------------------------------------------------------------------------*/ +/*Constructs the full path for the given lnode and stores the result + both in the parameter and inside the lnode (the same string, + actually)*/ +error_t lnode_path_construct (lnode_t * node, char **path) +{ + error_t err = 0; + + /*The final path */ + char *p; + + /*The final length of the path */ + int p_len = 0; + + /*A temporary pointer to an lnode */ + lnode_t *n; + + /*While the root node of the proxy filesystem has not been reached */ + for (n = node; n && n->dir; n = n->dir) + /*add the length of the name of `n` to `p_len` make some space for + the delimiter '/', if we are not approaching the root node */ + /*p_len += n->name_len + ((n->dir->dir) ? (1) : (0)); */ + /*There is some path to our root node, so we will anyway have to + add a '/' */ + p_len += n->name_len + 1; + + /*Include the space for the path to the root node of the proxy + (n is now the root of the filesystem) */ + p_len += strlen (n->path) + 1; + + /*Try to allocate the space for the string */ + p = malloc (p_len * sizeof (char)); + if (!p) + err = ENOMEM; + /*If memory allocation has been successful */ + else + { + /*put a terminal 0 at the end of the path */ + p[--p_len] = 0; + + /*While the root node of the proxy filesystem has not been reached */ + for (n = node; n && n->dir; n = n->dir) { - error_t err = 0; - - /*The final path*/ - char * p; - - /*The final length of the path*/ - int p_len = 0; - - /*A temporary pointer to an lnode*/ - lnode_t * n; - - /*While the root node of the proxy filesystem has not been reached*/ - for(n = node; n && n->dir; n = n->dir) - /*add the length of the name of `n` to `p_len` make some space for - the delimiter '/', if we are not approaching the root node*/ - /*p_len += n->name_len + ((n->dir->dir) ? (1) : (0));*/ - /*There is some path to our root node, so we will anyway have to - add a '/'*/ - p_len += n->name_len + 1; - - /*Include the space for the path to the root node of the proxy - (n is now the root of the filesystem)*/ - p_len += strlen(n->path) + 1; - - /*Try to allocate the space for the string*/ - p = malloc(p_len * sizeof(char)); - if(!p) - err = ENOMEM; - /*If memory allocation has been successful*/ - else - { - /*put a terminal 0 at the end of the path*/ - p[--p_len] = 0; - - /*While the root node of the proxy filesystem has not been reached*/ - for(n = node; n && n->dir; n = n->dir) - { - /*compute the position where the name of `n` is to be inserted*/ - p_len -= n->name_len; - - /*copy the name of the node into the path (omit the terminal 0)*/ - strncpy(p + p_len, n->name, n->name_len); - - /*If we are not at the root node of the proxy filesystem, add the - separator*/ - /*if(n->dir->dir) - p[--p_len] = '/';*/ - /*we anyway have to add the separator slash*/ - p[--p_len] = '/'; - } - - /*put the path to the root node at the beginning of the first path - (n is at the root now)*/ - strncpy(p, n->path, strlen(n->path)); - - /*destroy the former path in lnode, if it exists*/ - if(node->path) - free(node->path); - - /*store the new path inside the lnode*/ - node->path = p; - - /*store the path in the parameter*/ - if(path) - *path = p; - } - - /*Return the result of operations*/ - return err; - }/*lnode_path_construct*/ -/*----------------------------------------------------------------------------*/ + /*compute the position where the name of `n` is to be inserted */ + p_len -= n->name_len; + + /*copy the name of the node into the path (omit the terminal 0) */ + strncpy (p + p_len, n->name, n->name_len); + + /*If we are not at the root node of the proxy filesystem, add the + separator */ + /*if(n->dir->dir) + p[--p_len] = '/'; */ + /*we anyway have to add the separator slash */ + p[--p_len] = '/'; + } + + /*put the path to the root node at the beginning of the first path + (n is at the root now) */ + strncpy (p, n->path, strlen (n->path)); + + /*destroy the former path in lnode, if it exists */ + if (node->path) + free (node->path); + + /*store the new path inside the lnode */ + node->path = p; + + /*store the path in the parameter */ + if (path) + *path = p; + } + + /*Return the result of operations */ + return err; +} /*lnode_path_construct */ + +/*---------------------------------------------------------------------------*/ /*Gets a light node by its name, locks it and increments its refcount*/ -error_t -lnode_get - ( - lnode_t * dir, /*search here*/ - char * name, /*search for this name*/ - lnode_t ** node /*put the result here*/ - ) - { - error_t err = 0; - - /*The pointer to the required lnode*/ - lnode_t * n; - - /*Find `name` among the names of entries in `dir`*/ - for(n = dir->entries; n && (strcmp(n->name, name) != 0); n = n->next); - - /*If the search has been successful*/ - if(n) - { - /*lock the node*/ - mutex_lock(&n->lock); - - /*increment the refcount of the found lnode*/ - lnode_ref_add(n); - - /*put a pointer to `n` into the parameter*/ - *node = n; - } - else - err = ENOENT; - - /*Return the result of operations*/ - return err; - }/*lnode_get*/ -/*----------------------------------------------------------------------------*/ -/*Install the lnode into the lnode tree: add a reference to `dir` (which must - be locked)*/ -void -lnode_install - ( - lnode_t * dir, /*install here*/ - lnode_t * node /*install this*/ - ) - { - /*Install `node` into the list of entries in `dir`*/ - node->next = dir->entries; - node->prevp = &dir->entries; /*this node is the first on the list*/ - if(dir->entries) - dir->entries->prevp = &node->next; /*here `prevp` gets the value - corresponding to its meaning*/ - dir->entries = node; - - /*Add a new reference to dir*/ - lnode_ref_add(dir); - - /*Setup the `dir` link in node*/ - node->dir = dir; - }/*lnode_install*/ -/*----------------------------------------------------------------------------*/ -/*Unistall the node from the node tree; remove a reference from the lnode - containing `node`*/ -void -lnode_uninstall - ( - lnode_t * node - ) - { - /*Remove a reference from the parent*/ - lnode_ref_remove(node->dir); - - /*Make the next pointer in the previous element point to the element, - which follows `node`*/ - *node->prevp = node->next; - - /*If the current node is not the last one, connect the list after removal - of the current node*/ - if(node->next) - node->next->prevp = &node->next; - }/*lnode_uninstall*/ -/*----------------------------------------------------------------------------*/ -/*Makes the specified lnode aware of another proxy. Both `node` and `proxy` - must be locked*/ -error_t -lnode_add_proxy - ( - lnode_t * node, - node_t * proxy - ) - { - /*TODO: Make the list of proxies finite*/ - - /*Create an new cell in the list of proxies*/ - node_list_t p = malloc(sizeof(node_list_t)); - if(!p) - return ENOMEM; - - /*If the supplied node references an lnode already - (this should always happen, though)*/ - if(proxy->nn->lnode) - /*remove the reference held by the node to that lnode*/ - lnode_ref_remove(proxy->nn->lnode); - - /*Connect the proxy to the lnode*/ - proxy->nn->lnode = node; - - /*Store the pointer to the proxy in the new cell*/ - p->node = proxy; - - /*Add the new cell to the list of proxies*/ - p->next = node->proxies; - node->proxies = p; - - /*Count a new reference to this lnode*/ - lnode_ref_add(node); - - /*Everything is OK here*/ - return 0; - }/*lnode_add_proxy*/ -/*----------------------------------------------------------------------------*/ +error_t lnode_get (lnode_t * dir, /*search here */ + char *name, /*search for this name */ + lnode_t ** node /*put the result here */ + ) +{ + error_t err = 0; + + /*The pointer to the required lnode */ + lnode_t *n; + + /*Find `name` among the names of entries in `dir` */ + for (n = dir->entries; n && (strcmp (n->name, name) != 0); n = n->next); + + /*If the search has been successful */ + if (n) + { + /*lock the node */ + mutex_lock (&n->lock); + + /*increment the refcount of the found lnode */ + lnode_ref_add (n); + + /*put a pointer to `n` into the parameter */ + *node = n; + } + else + err = ENOENT; + + /*Return the result of operations */ + return err; +} /*lnode_get */ + +/*---------------------------------------------------------------------------*/ +/*Install the lnode into the lnode tree: add a reference to `dir` + (which must be locked)*/ +void lnode_install (lnode_t * dir, /*install here */ + lnode_t * node /*install this */ + ) +{ + /*Install `node` into the list of entries in `dir` */ + node->next = dir->entries; + node->prevp = &dir->entries; /*this node is the first on the list */ + if (dir->entries) + dir->entries->prevp = &node->next; /*here `prevp` gets the value + corresponding to its meaning */ + dir->entries = node; + + /*Add a new reference to dir */ + lnode_ref_add (dir); + + /*Setup the `dir` link in node */ + node->dir = dir; +} /*lnode_install */ + +/*---------------------------------------------------------------------------*/ +/*Unistall the node from the node tree; remove a reference from the + lnode containing `node`*/ +void lnode_uninstall (lnode_t * node) +{ + /*Remove a reference from the parent */ + lnode_ref_remove (node->dir); + + /*Make the next pointer in the previous element point to the element, + which follows `node` */ + *node->prevp = node->next; + + /*If the current node is not the last one, connect the list after removal + of the current node */ + if (node->next) + node->next->prevp = &node->next; +} /*lnode_uninstall */ + +/*---------------------------------------------------------------------------*/ +/*Makes the specified lnode aware of another proxy. Both `node` and + `proxy` must be locked*/ +error_t lnode_add_proxy (lnode_t * node, node_t * proxy) +{ + /*TODO: Make the list of proxies finite */ + + /*Create an new cell in the list of proxies */ + node_list_t p = malloc (sizeof (node_list_t)); + if (!p) + return ENOMEM; + + /*If the supplied node references an lnode already + (this should always happen, though) */ + if (proxy->nn->lnode) + /*remove the reference held by the node to that lnode */ + lnode_ref_remove (proxy->nn->lnode); + + /*Connect the proxy to the lnode */ + proxy->nn->lnode = node; + + /*Store the pointer to the proxy in the new cell */ + p->node = proxy; + + /*Add the new cell to the list of proxies */ + p->next = node->proxies; + node->proxies = p; + + /*Count a new reference to this lnode */ + lnode_ref_add (node); + + /*Everything is OK here */ + return 0; +} /*lnode_add_proxy */ + +/*---------------------------------------------------------------------------*/ /*Removes the specified proxy from the list of proxies of the supplied lnode. - `proxy` must not be locked*/ -void -lnode_remove_proxy - ( - lnode_t * node, - node_t * proxy - ) - { - /*A pointer to a cell in the list of proxies*/ - node_list_t p; - - /*Lock the lnode*/ - mutex_lock(&node->lock); - - /*If the first cell in the list contains a reference to `proxy`*/ - if(node->proxies->node == proxy) - { - /*store a pointer to the head of the list*/ - p = node->proxies; - - /*shift the head of the list forward*/ - node->proxies = node->proxies->next; - - /*destroy the former head*/ - free(p); - - /*remove a reference from the supplied lnode*/ - lnode_ref_remove(node); - - /*stop right here*/ - mutex_unlock(&node->lock); - return; - } - - /*Another pointer to a cell in the list*/ - node_list_t q; - - /*Go through the list of proxy nodes of the given lnode*/ - for(p = node->proxies; p->next; p = p->next) - { - /*If the next cell does not contain a reference to the same node, - as specified in the parameter, skip this entry*/ - if(p->next->node != proxy) - continue; - - /*store a copy of the next element*/ - q = p->next; - - /*unregister the next element from the list*/ - p->next = q->next; - - /*remove the unregistered element*/ - free(q); - - /*stop looping*/ - break; - } - - /*Remove a reference from the supplied lnode*/ - lnode_ref_remove(node); - - - /*Unlock the node*/ - mutex_unlock(&node->lock); - - return; - }/*lnode_remove_proxy*/ -/*----------------------------------------------------------------------------*/ + `proxy` must not be locked*/ +void lnode_remove_proxy (lnode_t * node, node_t * proxy) +{ + /*A pointer to a cell in the list of proxies */ + node_list_t p; + + /*Lock the lnode */ + mutex_lock (&node->lock); + + /*If the first cell in the list contains a reference to `proxy` */ + if (node->proxies->node == proxy) + { + /*store a pointer to the head of the list */ + p = node->proxies; + + /*shift the head of the list forward */ + node->proxies = node->proxies->next; + + /*destroy the former head */ + free (p); + + /*remove a reference from the supplied lnode */ + lnode_ref_remove (node); + + /*stop right here */ + mutex_unlock (&node->lock); + return; + } + + /*Another pointer to a cell in the list */ + node_list_t q; + + /*Go through the list of proxy nodes of the given lnode */ + for (p = node->proxies; p->next; p = p->next) + { + /*If the next cell does not contain a reference to the same node, + as specified in the parameter, skip this entry */ + if (p->next->node != proxy) + continue; + + /*store a copy of the next element */ + q = p->next; + + /*unregister the next element from the list */ + p->next = q->next; + + /*remove the unregistered element */ + free (q); + + /*stop looping */ + break; + } + + /*Remove a reference from the supplied lnode */ + lnode_ref_remove (node); + + + /*Unlock the node */ + mutex_unlock (&node->lock); + + return; +} /*lnode_remove_proxy */ + +/*---------------------------------------------------------------------------*/ @@ -1,10 +1,10 @@ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*lnode.h*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Management of cheap 'light nodes'*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Copyright (C) 2001, 2002, 2005, 2008 Free Software Foundation, Inc. Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. @@ -22,164 +22,122 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #ifndef __LNODE_H__ #define __LNODE_H__ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #include <error.h> #include <hurd/netfs.h> -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Macros--------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Macros-------------------------------------------------------------*/ /*The possible flags in an lnode*/ -#define FLAG_LNODE_DIR 0x00000001 /*the lnode is a directory*/ -/*----------------------------------------------------------------------------*/ +#define FLAG_LNODE_DIR 0x00000001 /*the lnode is a directory */ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Types---------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Types--------------------------------------------------------------*/ /*A candy synonym for the fundamental libnetfs node*/ typedef struct node node_t; -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*A list of lnodes*/ struct node_element - { - /*the node associated with the current entry*/ - node_t * node; - - /*the next element in the list*/ - struct node_element * next; - };/*struct node_element*/ -/*----------------------------------------------------------------------------*/ -typedef struct node_element * node_list_t; -/*----------------------------------------------------------------------------*/ +{ + /*the node associated with the current entry */ + node_t *node; + + /*the next element in the list */ + struct node_element *next; +}; /*struct node_element */ +/*---------------------------------------------------------------------------*/ +typedef struct node_element *node_list_t; +/*---------------------------------------------------------------------------*/ /*The light node*/ struct lnode - { - /*the name of the lnode*/ - char * name; - - /*the length of the name; `name` does not change, and this value is used - quite often, therefore calculate it just once*/ - size_t name_len; - - /*the full path to the lnode*/ - char * path; - - /*the associated flags*/ - int flags; - - /*the number of references to this lnode*/ - int references; - - /*the reference to the real netfs node*/ - node_t * node; - - /*the references to the proxy nodes of this lnode; - lnodes do not hold references to */ - node_list_t proxies; - - /*the next lnode and the pointer to this lnode from the previous one*/ - struct lnode * next, **prevp; - - /*the lnode (directory) in which this node is contained*/ - struct lnode * dir; - - /*the beginning of the list of entries contained in this lnode (directory)*/ - struct lnode * entries; - - /*the lock, protecting this lnode*/ - struct mutex lock; - };/*struct lnode*/ -/*----------------------------------------------------------------------------*/ +{ + /*the name of the lnode */ + char *name; + + /*the length of the name; `name` does not change, and this value is used + quite often, therefore calculate it just once */ + size_t name_len; + + /*the full path to the lnode */ + char *path; + + /*the associated flags */ + int flags; + + /*the number of references to this lnode */ + int references; + + /*the reference to the real netfs node */ + node_t *node; + + /*the references to the proxy nodes of this lnode; + lnodes do not hold references to */ + node_list_t proxies; + + /*the next lnode and the pointer to this lnode from the previous one */ + struct lnode *next, **prevp; + + /*the lnode (directory) in which this node is contained */ + struct lnode *dir; + + /*the beginning of the list of entries contained in this lnode (directory) */ + struct lnode *entries; + + /*the lock, protecting this lnode */ + struct mutex lock; +}; /*struct lnode */ +/*---------------------------------------------------------------------------*/ typedef struct lnode lnode_t; -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/ -/*--------Functions-----------------------------------------------------------*/ +/*--------Functions----------------------------------------------------------*/ /*Adds a reference to the `lnode` (which must be locked)*/ -void -lnode_ref_add - ( - lnode_t * node - ); -/*----------------------------------------------------------------------------*/ -/*Removes a reference from `node` (which must be locked). If that was the last - reference, destroy the node*/ -void -lnode_ref_remove - ( - lnode_t * node - ); -/*----------------------------------------------------------------------------*/ +void lnode_ref_add (lnode_t * node); +/*---------------------------------------------------------------------------*/ +/*Removes a reference from `node` (which must be locked). If that was + the last reference, destroy the node*/ +void lnode_ref_remove (lnode_t * node); +/*---------------------------------------------------------------------------*/ /*Creates a new lnode with `name`; the new node is locked and contains - a single reference*/ -error_t -lnode_create - ( - char * name, - lnode_t ** node /*put the result here*/ - ); -/*----------------------------------------------------------------------------*/ + a single reference*/ +error_t lnode_create (char *name, lnode_t ** node); +/*---------------------------------------------------------------------------*/ /*Destroys the given lnode*/ -void -lnode_destroy - ( - lnode_t * node /*destroy this*/ - ); -/*----------------------------------------------------------------------------*/ -/*Constructs the full path for the given lnode and stores the result both in - the parameter and inside the lnode (the same string, actually)*/ -error_t -lnode_path_construct - ( - lnode_t * node, - char ** path /*store the path here*/ - ); -/*----------------------------------------------------------------------------*/ +void lnode_destroy (lnode_t * node); +/*---------------------------------------------------------------------------*/ +/*Constructs the full path for the given lnode and stores the result + both in the parameter and inside the lnode (the same string, + actually)*/ +error_t lnode_path_construct (lnode_t * node, char **path); +/*---------------------------------------------------------------------------*/ /*Gets a light node by its name, locks it and increments its refcount*/ -error_t -lnode_get - ( - lnode_t * dir, /*search here*/ - char * name, /*search for this name*/ - lnode_t ** node /*put the result here*/ - ); -/*----------------------------------------------------------------------------*/ -/*Install the lnode into the lnode tree: add a reference to `dir` (which must - be locked)*/ -void -lnode_install - ( - lnode_t * dir, /*install here*/ - lnode_t * node /*install this*/ - ); -/*----------------------------------------------------------------------------*/ +error_t lnode_get (lnode_t * dir, /*search here */ + char *name, /*search for this name */ + lnode_t ** node /*put the result here */ + ); +/*---------------------------------------------------------------------------*/ +/*Install the lnode into the lnode tree: add a reference to `dir` + (which must be locked)*/ +void lnode_install (lnode_t * dir, /*install here */ + lnode_t * node /*install this */ + ); +/*---------------------------------------------------------------------------*/ /*Unistall the node from the node tree; remove a reference from the lnode*/ -void -lnode_uninstall - ( - lnode_t * node - ); -/*----------------------------------------------------------------------------*/ -/*Makes the specified lnode aware of another proxy. Both `node` and `proxy` - must be locked*/ -error_t -lnode_add_proxy - ( - lnode_t * node, - node_t * proxy - ); -/*----------------------------------------------------------------------------*/ -/*Removes the specified proxy from the list of proxies of the supplied lnode. - `proxy` must not be locked*/ -void -lnode_remove_proxy - ( - lnode_t * node, - node_t * proxy - ); -/*----------------------------------------------------------------------------*/ +void lnode_uninstall (lnode_t * node); +/*---------------------------------------------------------------------------*/ +/*Makes the specified lnode aware of another proxy. Both `node` and + `proxy` must be locked*/ +error_t lnode_add_proxy (lnode_t * node, node_t * proxy); +/*---------------------------------------------------------------------------*/ +/*Removes the specified proxy from the list of proxies of the supplied + lnode. `proxy` must not be locked*/ +void lnode_remove_proxy (lnode_t * node, node_t * proxy); +/*---------------------------------------------------------------------------*/ #endif /*__LNODE_H__*/ - @@ -1,10 +1,10 @@ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*ncache.h*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*The implementation of the cache of nodes*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Copyright (C) 2001, 2002, 2005, 2008 Free Software Foundation, Inc. Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. @@ -22,191 +22,184 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #define _GNU_SOURCE 1 -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #include "ncache.h" -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Global Variables----------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Global Variables---------------------------------------------------*/ /*The global cache chain*/ ncache_t ncache; -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Cache size (may be overwritten by the user)*/ /*int ncache_size = NCACHE_SIZE;*/ -/*Our cache is not really a cache now (actually, it has never been one). Its - main task now will be to maintain additional references to shadow nodes, - which are still in use by some clients and which could possibly go away if - nobody maintained references to them explicitly.*/ -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Functions-----------------------------------------------------------*/ +/*Our cache is not really a cache now (actually, it has never been + one). Its main task now will be to maintain additional references to + shadow nodes, which are still in use by some clients and which could + possibly go away if nobody maintained references to them + explicitly.*/ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/*--------Functions----------------------------------------------------------*/ /*Initializes the node cache*/ -void -ncache_init - ( - /*int size_max*/ - void - ) - { - /*Reset the LRU and MRU ends of the list*/ - ncache.mru = ncache.lru = NULL; - - /*Set the maximal size according to the parameter*/ - /*ncache.size_max = size_max;*/ - - /*The cache is empty so far; remark that*/ - ncache.size_current = 0; - - /*Init the lock*/ - mutex_init(&ncache.lock); - }/*ncache_init*/ -/*----------------------------------------------------------------------------*/ -/*Looks up the lnode and stores the result in `node`; creates a new entry - in the cache if the lookup fails*/ -error_t -ncache_node_lookup - ( - lnode_t * lnode, /*search for this*/ - node_t ** node /*put the result here*/ - ) - { - error_t err = 0; - - /*Obtain the pointer to the node corresponding to `lnode`*/ - node_t * n = lnode->node; - - /*If a node has already been created for the given lnode*/ - if(n != NULL) - { - /*count a new reference to 'n'*/ - netfs_nref(n); - } - else - { - /*create a new node for the given lnode and store the result in `n`*/ - err = node_create(lnode, &n); - } - - /*If no errors have occurred during the previous operations*/ - if(!err) - { - /*lock the mutex in the looked up node*/ - mutex_lock(&n->lock); - - /*store the lookup result in `node`*/ - *node = n; - } - - /*Return the result of operations*/ - return err; - }/*ncache_node_lookup*/ -/*----------------------------------------------------------------------------*/ -/*Removes the given node from the cache. Does not release the reference held - by the cache (for some further finalization actions on the node)*/ +void ncache_init (void) +{ + /*Reset the LRU and MRU ends of the list */ + ncache.mru = ncache.lru = NULL; + + /*Set the maximal size according to the parameter */ + /*ncache.size_max = size_max; */ + + /*The cache is empty so far; remark that */ + ncache.size_current = 0; + + /*Init the lock */ + mutex_init (&ncache.lock); +} /*ncache_init */ + +/*---------------------------------------------------------------------------*/ +/*Looks up the lnode and stores the result in `node`; creates a new + entry in the cache if the lookup fails*/ +error_t ncache_node_lookup (lnode_t * lnode, /*search for this */ + node_t ** node /*put the result here */ + ) +{ + error_t err = 0; + + /*Obtain the pointer to the node corresponding to `lnode` */ + node_t *n = lnode->node; + + /*If a node has already been created for the given lnode */ + if (n != NULL) + { + /*count a new reference to 'n' */ + netfs_nref (n); + } + else + { + /*create a new node for the given lnode and store the result in `n` */ + err = node_create (lnode, &n); + } + + /*If no errors have occurred during the previous operations */ + if (!err) + { + /*lock the mutex in the looked up node */ + mutex_lock (&n->lock); + + /*store the lookup result in `node` */ + *node = n; + } + + /*Return the result of operations */ + return err; +} /*ncache_node_lookup */ + +/*---------------------------------------------------------------------------*/ +/*Removes the given node from the cache. Does not release the + reference held by the cache (for some further finalization actions + on the node)*/ /*Nodes will NOT be removed from the cache automatically*/ -void -ncache_node_remove - ( - node_t * node - ) - { - /*Obtain the pointer to the netnode (this contains the information - specific of us)*/ - struct netnode * nn = node->nn; - - /*If there exists a successor of this node in the cache chain*/ - if(nn->ncache_next) - /*remove the reference in the successor*/ - nn->ncache_next->nn->ncache_prev = nn->ncache_prev; - /*If there exists a predecessor of this node in the cache chain*/ - if(nn->ncache_prev) - /*remove the reference in the predecessor*/ - nn->ncache_prev->nn->ncache_next = nn->ncache_next; - - /*If the node was located at the MRU end of the list*/ - if(ncache.mru == node) - /*shift the MRU end to the next node*/ - ncache.mru = nn->ncache_next; - /*If the node was located at the LRU end of the list*/ - if(ncache.lru == node) - /*shift the LRU end to the previous node*/ - ncache.lru = nn->ncache_prev; - - /*Invalidate the references inside the node*/ - nn->ncache_next = nn->ncache_prev = NULL; - - /*Count the removal of a node*/ - --ncache.size_current; - }/*ncache_node_remove*/ -/*----------------------------------------------------------------------------*/ +void ncache_node_remove (node_t * node) +{ + /*Obtain the pointer to the netnode (this contains the information + specific of us) */ + struct netnode *nn = node->nn; + + /*If there exists a successor of this node in the cache chain */ + if (nn->ncache_next) + /*remove the reference in the successor */ + nn->ncache_next->nn->ncache_prev = nn->ncache_prev; + /*If there exists a predecessor of this node in the cache chain */ + if (nn->ncache_prev) + /*remove the reference in the predecessor */ + nn->ncache_prev->nn->ncache_next = nn->ncache_next; + + /*If the node was located at the MRU end of the list */ + if (ncache.mru == node) + /*shift the MRU end to the next node */ + ncache.mru = nn->ncache_next; + /*If the node was located at the LRU end of the list */ + if (ncache.lru == node) + /*shift the LRU end to the previous node */ + ncache.lru = nn->ncache_prev; + + /*Invalidate the references inside the node */ + nn->ncache_next = nn->ncache_prev = NULL; + + /*Count the removal of a node */ + --ncache.size_current; +} /*ncache_node_remove */ + +/*---------------------------------------------------------------------------*/ /*Resets the node cache*/ /*No references to nodes are released*/ void -ncache_reset(void) - { - /*The node being currently removed from the cache*/ - node_t * node; - - /*Acquire a lock on the cache*/ - mutex_lock(&ncache.lock); - - /*Release the whole cache chain*/ - for(node = ncache.mru; node != NULL; ncache_node_remove(node), node = ncache.mru); - - /*Release the lock*/ - mutex_unlock(&ncache.lock); - }/*ncache_reset*/ -/*----------------------------------------------------------------------------*/ +ncache_reset (void) +{ + /*The node being currently removed from the cache */ + node_t *node; + + /*Acquire a lock on the cache */ + mutex_lock (&ncache.lock); + + /*Release the whole cache chain */ + for (node = ncache.mru; node != NULL; + ncache_node_remove (node), node = ncache.mru); + + /*Release the lock */ + mutex_unlock (&ncache.lock); +} /*ncache_reset */ + +/*---------------------------------------------------------------------------*/ /*Adds the given node to the cache*/ -void -ncache_node_add - ( - node_t * node /*the node to add*/ - ) +void ncache_node_add (node_t * node) +{ + /*Acquire a lock on the cache */ + mutex_lock (&ncache.lock); + + /*If there already are some nodes in the cache already */ + if (ncache.size_current > 0) + { + /*If the node to be added is not at the MRU end already */ + if (ncache.mru != node) { - /*Acquire a lock on the cache*/ - mutex_lock(&ncache.lock); - - /*If there already are some nodes in the cache already*/ - if(ncache.size_current > 0) - { - /*If the node to be added is not at the MRU end already*/ - if(ncache.mru != node) - { - /*If the node is correctly integrated in the cache*/ - if((node->nn->ncache_next != NULL) && (node->nn->ncache_prev != NULL)) - /*remove the old entry*/ - ncache_node_remove(node); - else - /*add a new reference to the node*/ - netfs_nref(node); - - /*put the node at the MRU end of the cache chain*/ - node->nn->ncache_next = ncache.mru; - node->nn->ncache_prev = NULL; - - /*setup the pointer in the old MRU end, if it exists*/ - if(ncache.mru != NULL) - ncache.mru->nn->ncache_prev = node; - - /*setup the LRU end of the cache chain, if it did not exist previously*/ - if(ncache.lru == NULL) - ncache.lru = node; - - /*shift the MRU end to the new node*/ - ncache.mru = node; - - /*count the addition*/ - ++ncache.size_current; - } - } - - /*While the size of the cache is exceeding the maximal size*/ + /*If the node is correctly integrated in the cache */ + if ((node->nn->ncache_next != NULL) + && (node->nn->ncache_prev != NULL)) + /*remove the old entry */ + ncache_node_remove (node); + else + /*add a new reference to the node */ + netfs_nref (node); + + /*put the node at the MRU end of the cache chain */ + node->nn->ncache_next = ncache.mru; + node->nn->ncache_prev = NULL; + + /*setup the pointer in the old MRU end, if it exists */ + if (ncache.mru != NULL) + ncache.mru->nn->ncache_prev = node; + + /*setup the LRU end of the cache chain, if it did not exist + previously */ + if (ncache.lru == NULL) + ncache.lru = node; + + /*shift the MRU end to the new node */ + ncache.mru = node; + + /*count the addition */ + ++ncache.size_current; + } + } + + /*While the size of the cache is exceeding the maximal size */ /* node_t * old_lru; for ( @@ -215,14 +208,15 @@ ncache_node_add old_lru = ncache.lru ) {*/ - /*remove the current LRU end of the list from the cache*/ - /*ncache_node_remove(old_lru);*/ - - /*release the reference to the node owned by this thread*/ - /*netfs_nrele(old_lru); - }*/ - - /*Release the lock on the cache*/ - mutex_unlock(&ncache.lock); - }/*ncache_node_add*/ -/*----------------------------------------------------------------------------*/ + /*remove the current LRU end of the list from the cache */ + /*ncache_node_remove(old_lru); */ + + /*release the reference to the node owned by this thread */ + /*netfs_nrele(old_lru); + } */ + + /*Release the lock on the cache */ + mutex_unlock (&ncache.lock); +} /*ncache_node_add */ + +/*---------------------------------------------------------------------------*/ @@ -1,10 +1,10 @@ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*ncache.h*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*The cache of nodes*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Copyright (C) 2001, 2002, 2005, 2008 Free Software Foundation, Inc. Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. @@ -22,94 +22,78 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #ifndef __NCACHE_H__ #define __NCACHE_H__ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #include <error.h> #include <hurd/netfs.h> -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #include "node.h" -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Macros--------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Macros-------------------------------------------------------------*/ /*The default maximal cache size*/ /*#define NCACHE_SIZE 256*/ /*SEE ALSO the comment in ncache.c*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Types---------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Types--------------------------------------------------------------*/ /*A cache chain*/ struct ncache - { - /*the MRU end of the cache chain*/ - node_t * mru; - - /*the LRU end of the cache chain*/ - node_t * lru; - - /*the maximal number of nodes to cache*/ - /*int size_max;*/ - /*SEE ALSO the comment in ncache.c*/ - - /*the current length of the cache chain*/ - int size_current; - - /*a lock*/ - struct mutex lock; - };/*struct ncache*/ -/*----------------------------------------------------------------------------*/ +{ + /*the MRU end of the cache chain */ + node_t *mru; + + /*the LRU end of the cache chain */ + node_t *lru; + + /*the maximal number of nodes to cache */ + /*int size_max; */ + /*SEE ALSO the comment in ncache.c */ + + /*the current length of the cache chain */ + int size_current; + + /*a lock */ + struct mutex lock; +}; /*struct ncache */ +/*---------------------------------------------------------------------------*/ typedef struct ncache ncache_t; -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Global Variables----------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Global Variables---------------------------------------------------*/ /*The cache size (may be overwritten by the user)*/ /*extern int cache_size;*/ /*SEE ALSO the comment in ncache.c*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/ -/*--------Functions-----------------------------------------------------------*/ +/*--------Functions----------------------------------------------------------*/ /*Initializes the node cache*/ -void -ncache_init - ( - /*int size_max*/ - void - ); -/*----------------------------------------------------------------------------*/ -/*Looks up the lnode and stores the result in `node`; creates a new entry - in the cache if the lookup fails*/ -error_t -ncache_node_lookup - ( - lnode_t * lnode, /*search for this*/ - node_t ** node /*put the result here*/ - ); -/*----------------------------------------------------------------------------*/ -/*Removes the given node from the cache. Does not release the reference held - by the cache (for some further finalization actions on the node)*/ +void ncache_init (void); +/*---------------------------------------------------------------------------*/ +/*Looks up the lnode and stores the result in `node`; creates a new + entry in the cache if the lookup fails*/ +error_t ncache_node_lookup (lnode_t * lnode, /*search for this */ + node_t ** node /*put the result here */ + ); +/*---------------------------------------------------------------------------*/ +/*Removes the given node from the cache. Does not release the + reference held by the cache (for some further finalization actions + on the node)*/ /*Nodes will NOT be removed from the cache automatically*/ -void -ncache_node_remove - ( - node_t * node - ); -/*----------------------------------------------------------------------------*/ +void ncache_node_remove (node_t * node); +/*---------------------------------------------------------------------------*/ /*Resets the node cache*/ /*No references to nodes are released*/ -void -ncache_reset(void); -/*----------------------------------------------------------------------------*/ +void ncache_reset (void); +/*---------------------------------------------------------------------------*/ /*Adds the given node to the cache*/ -void -ncache_node_add - ( - node_t * node /*the node to add*/ - ); -/*----------------------------------------------------------------------------*/ +void ncache_node_add (node_t * node); +/*---------------------------------------------------------------------------*/ #endif /*__NCACHE_H__*/ @@ -1,10 +1,10 @@ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*node.c*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Implementation of node management strategies*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Copyright (C) 2001, 2002, 2005, 2008 Free Software Foundation, Inc. Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. @@ -22,11 +22,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #define _GNU_SOURCE 1 -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #include <stdlib.h> #include <fcntl.h> #include <sys/stat.h> @@ -34,1018 +34,888 @@ #include <stdio.h> #include <argz.h> #include <hurd/fsys.h> -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #include "debug.h" #include "node.h" #include "options.h" #include "lib.h" #include "nsmux.h" #include "ncache.h" -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Global Variables----------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Global Variables---------------------------------------------------*/ /*The lock protecting the underlying filesystem*/ struct mutex ulfs_lock = MUTEX_INITIALIZER; -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Functions-----------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Functions----------------------------------------------------------*/ /*Derives a new node from `lnode` and adds a reference to `lnode`*/ -error_t -node_create - ( - lnode_t * lnode, - node_t ** node /*store the result here*/ - ) +error_t node_create (lnode_t * lnode, node_t ** node) +{ + error_t err = 0; + + /*Create a new netnode */ + netnode_t *netnode_new = malloc (sizeof (netnode_t)); + + /*Reset the memory allocated for the new netnode (just in case :-) ) */ + memset (netnode_new, 0, sizeof (netnode_t)); + + /*If the memory could not be allocated */ + if (netnode_new == NULL) + err = ENOMEM; + else + { + /*create a new node from the netnode */ + node_t *node_new = netfs_make_node (netnode_new); + + /*If the creation failed */ + if (node_new == NULL) { - error_t err = 0; - - /*Create a new netnode*/ - netnode_t * netnode_new = malloc(sizeof(netnode_t)); - - /*Reset the memory allocated for the new netnode (just in case :-) )*/ - memset(netnode_new, 0, sizeof(netnode_t)); - - /*If the memory could not be allocated*/ - if(netnode_new == NULL) - err = ENOMEM; - else - { - /*create a new node from the netnode*/ - node_t * node_new = netfs_make_node(netnode_new); - - /*If the creation failed*/ - if(node_new == NULL) - { - /*set the error code*/ - err = ENOMEM; - - /*destroy the netnode created above*/ - free(netnode_new); - - /*stop*/ - return err; - } - - /*link the lnode to the new node*/ - lnode->node = node_new; - - /*setup the references in the newly created node*/ - node_new->nn->lnode = lnode; - lnode_ref_add(lnode); - - /*setup the information in the netnode*/ - node_new->nn->flags = 0; - node_new->nn->ncache_next = node_new->nn->ncache_prev = NULL; - - /*initialize the list of translators*/ - node_new->nn->trans = NULL; - node_new->nn->ntrans = node_new->nn->translen = 0; - - /*store the result of creation in the second parameter*/ - *node = node_new; - } - - /*Return the result of operations*/ - return err; - }/*node_create*/ -/*----------------------------------------------------------------------------*/ + /*set the error code */ + err = ENOMEM; + + /*destroy the netnode created above */ + free (netnode_new); + + /*stop */ + return err; + } + + /*link the lnode to the new node */ + lnode->node = node_new; + + /*setup the references in the newly created node */ + node_new->nn->lnode = lnode; + lnode_ref_add (lnode); + + /*setup the information in the netnode */ + node_new->nn->flags = 0; + node_new->nn->ncache_next = node_new->nn->ncache_prev = NULL; + + /*initialize the list of translators */ + node_new->nn->trans = NULL; + node_new->nn->ntrans = node_new->nn->translen = 0; + + /*store the result of creation in the second parameter */ + *node = node_new; + } + + /*Return the result of operations */ + return err; +} /*node_create */ + +/*---------------------------------------------------------------------------*/ /*Derives a new proxy from `lnode`*/ -error_t -node_create_proxy - ( - lnode_t * lnode, - node_t ** node /*store the result here*/ - ) +error_t node_create_proxy (lnode_t * lnode, node_t ** node) +{ + error_t err = 0; + + /*Create a new netnode */ + netnode_t *netnode_new = malloc (sizeof (netnode_t)); + + /*Reset the memory allocated for the new netnode. We do this here + since lnode_add_proxy will try to reference the `lnode` in this + netnode and will do bad writes to memory. */ + memset (netnode_new, 0, sizeof (netnode_t)); + + /*If the memory could not be allocated */ + if (netnode_new == NULL) + err = ENOMEM; + else + { + /*create a new node from the netnode */ + node_t *node_new = netfs_make_node (netnode_new); + + /*If the creation failed */ + if (node_new == NULL) { - error_t err = 0; - - /*Create a new netnode*/ - netnode_t * netnode_new = malloc(sizeof(netnode_t)); - - /*Reset the memory allocated for the new netnode. We do this here - since lnode_add_proxy will try to reference the `lnode` in this netnode - and will do bad writes to memory.*/ - memset(netnode_new, 0, sizeof(netnode_t)); - - /*If the memory could not be allocated*/ - if(netnode_new == NULL) - err = ENOMEM; - else - { - /*create a new node from the netnode*/ - node_t * node_new = netfs_make_node(netnode_new); - - /*If the creation failed*/ - if(node_new == NULL) - { - /*set the error code*/ - err = ENOMEM; - - /*destroy the netnode created above*/ - free(netnode_new); - - /*stop*/ - return err; - } - - /*add this new node to the list of proxies of `lnode`*/ - lnode_add_proxy(lnode, node_new); - - /*setup the information in the netnode*/ - node_new->nn->flags = 0; - node_new->nn->ncache_next = node_new->nn->ncache_prev = NULL; - - /*initialize the list of translators*/ - node_new->nn->trans = NULL; - node_new->nn->ntrans = node_new->nn->translen = 0; - - /*store the result of creation in the second parameter*/ - *node = node_new; - } - - /*Return the result of operations*/ - return err; - }/*node_create_proxy*/ -/*----------------------------------------------------------------------------*/ + /*set the error code */ + err = ENOMEM; + + /*destroy the netnode created above */ + free (netnode_new); + + /*stop */ + return err; + } + + /*add this new node to the list of proxies of `lnode` */ + lnode_add_proxy (lnode, node_new); + + /*setup the information in the netnode */ + node_new->nn->flags = 0; + node_new->nn->ncache_next = node_new->nn->ncache_prev = NULL; + + /*initialize the list of translators */ + node_new->nn->trans = NULL; + node_new->nn->ntrans = node_new->nn->translen = 0; + + /*store the result of creation in the second parameter */ + *node = node_new; + } + + /*Return the result of operations */ + return err; +} /*node_create_proxy */ + +/*---------------------------------------------------------------------------*/ /*Destroys the specified node and removes a light reference from the - associated light node*/ -void -node_destroy - ( - node_t * np - ) - { - /*Die if the node does not belong to node cache*/ - assert(!np->nn->ncache_next || !np->nn->ncache_prev); - - /*Destroy the port to the underlying filesystem allocated to the node*/ - if(np->nn->port != MACH_PORT_NULL) - PORT_DEALLOC(np->nn->port); - - /*If there are translators to kill*/ - if(np->nn->lnode->dir && np->nn->trans) - { - /*kill all translators on the underlying nodes*/ - node_kill_translators(np); - } - - /*Lock the lnode corresponding to the current node*/ - mutex_lock(&np->nn->lnode->lock); - - /*If the node to be destroyed is a real netfs node*/ - if(np->nn->lnode->node == np) - /*orphan the light node*/ - np->nn->lnode->node = NULL; - else - /*remove a reference to this node from the list of proxies*/ - lnode_remove_proxy(np->nn->lnode, np); - - /*Remove a reference from the lnode*/ - lnode_ref_remove(np->nn->lnode); - - /*Free the netnode and the node itself*/ - free(np->nn); - free(np); - }/*node_destroy*/ -/*----------------------------------------------------------------------------*/ + associated light node*/ +void node_destroy (node_t * np) +{ + /*Die if the node does not belong to node cache */ + assert (!np->nn->ncache_next || !np->nn->ncache_prev); + + /*Destroy the port to the underlying filesystem allocated to the node */ + if (np->nn->port != MACH_PORT_NULL) + PORT_DEALLOC (np->nn->port); + + /*If there are translators to kill */ + if (np->nn->lnode->dir && np->nn->trans) + { + /*kill all translators on the underlying nodes */ + node_kill_translators (np); + } + + /*Lock the lnode corresponding to the current node */ + mutex_lock (&np->nn->lnode->lock); + + /*If the node to be destroyed is a real netfs node */ + if (np->nn->lnode->node == np) + /*orphan the light node */ + np->nn->lnode->node = NULL; + else + /*remove a reference to this node from the list of proxies */ + lnode_remove_proxy (np->nn->lnode, np); + + /*Remove a reference from the lnode */ + lnode_ref_remove (np->nn->lnode); + + /*Free the netnode and the node itself */ + free (np->nn); + free (np); +} /*node_destroy */ + +/*---------------------------------------------------------------------------*/ /*Creates the root node and the corresponding lnode*/ -error_t -node_create_root - ( - node_t ** root_node /*store the result here*/ - ) - { - /*Try to create a new lnode*/ - lnode_t * lnode; - error_t err = lnode_create(NULL, &lnode); - - /*Stop, if the creation failed*/ - if(err) - return err; - - /*Try to derive the node corresponding to `lnode`*/ - node_t * node; - err = node_create(lnode, &node); - - /*If the operation failed*/ - if(err) - { - /*destroy the created lnode*/ - lnode_destroy(lnode); - - /*stop*/ - return err; - } - - /*Release the lock on the lnode*/ - mutex_unlock(&lnode->lock); - - /*Store the result in the parameter*/ - *root_node = node; - - /*Return the result*/ - return err; - }/*node_create_root*/ -/*----------------------------------------------------------------------------*/ +error_t node_create_root (node_t ** root_node) +{ + /*Try to create a new lnode */ + lnode_t *lnode; + error_t err = lnode_create (NULL, &lnode); + + /*Stop, if the creation failed */ + if (err) + return err; + + /*Try to derive the node corresponding to `lnode` */ + node_t *node; + err = node_create (lnode, &node); + + /*If the operation failed */ + if (err) + { + /*destroy the created lnode */ + lnode_destroy (lnode); + + /*stop */ + return err; + } + + /*Release the lock on the lnode */ + mutex_unlock (&lnode->lock); + + /*Store the result in the parameter */ + *root_node = node; + + /*Return the result */ + return err; +} /*node_create_root */ + +/*---------------------------------------------------------------------------*/ /*Initializes the port to the underlying filesystem for the root node*/ -error_t -node_init_root - ( - node_t * node /*the root node*/ - ) +error_t node_init_root (node_t * node /*the root node */ + ) +{ + error_t err = 0; + + /*Acquire a lock for operations on the underlying filesystem */ + mutex_lock (&ulfs_lock); + + /*Open the port to the directory specified in `dir` */ + node->nn->port = file_name_lookup (dir, O_READ | O_DIRECTORY, 0); + + /*If the directory could not be opened */ + if (node->nn->port == MACH_PORT_NULL) + { + /*set the error code accordingly */ + err = errno; + LOG_MSG ("node_init_root: Could not open the port for %s.", dir); + + /*release the lock and stop */ + mutex_unlock (&ulfs_lock); + return err; + } + + LOG_MSG ("node_init_root: Port for %s opened successfully.", dir); + LOG_MSG ("\tPort: 0x%lX", (unsigned long) node->nn->port); + + /*Stat the root node */ + err = io_stat (node->nn->port, &node->nn_stat); + if (err) + { + /*deallocate the port */ + PORT_DEALLOC (node->nn->port); + + LOG_MSG ("node_init_root: Could not stat the root node."); + + /*unlock the mutex and exit */ + mutex_unlock (&ulfs_lock); + return err; + } + + /*Set the path to the corresponding lnode to `dir` */ + node->nn->lnode->path = strdup (dir); + if (!node->nn->lnode->path) + { + /*deallocate the port */ + PORT_DEALLOC (node->nn->port); + + /*unlock the mutex */ + mutex_unlock (&ulfs_lock); + + LOG_MSG ("node_init_root: Could not strdup the directory."); + return ENOMEM; + } + + /*The current position in dir */ + char *p = dir + strlen (dir); + + /*Go through the path from end to beginning */ + for (; p >= dir; --p) + { + /*If the current character is a '/' */ + if (*p == '/') { - error_t err = 0; - - /*Acquire a lock for operations on the underlying filesystem*/ - mutex_lock(&ulfs_lock); - - /*Open the port to the directory specified in `dir`*/ - node->nn->port = file_name_lookup(dir, O_READ | O_DIRECTORY, 0); - - /*If the directory could not be opened*/ - if(node->nn->port == MACH_PORT_NULL) - { - /*set the error code accordingly*/ - err = errno; - LOG_MSG("node_init_root: Could not open the port for %s.", dir); - - /*release the lock and stop*/ - mutex_unlock(&ulfs_lock); - return err; - } - - LOG_MSG("node_init_root: Port for %s opened successfully.", dir); - LOG_MSG("\tPort: 0x%lX", (unsigned long)node->nn->port); - - /*Stat the root node*/ - err = io_stat(node->nn->port, &node->nn_stat); - if(err) - { - /*deallocate the port*/ - PORT_DEALLOC(node->nn->port); - - LOG_MSG("node_init_root: Could not stat the root node."); - - /*unlock the mutex and exit*/ - mutex_unlock(&ulfs_lock); - return err; - } - - /*Set the path to the corresponding lnode to `dir`*/ - node->nn->lnode->path = strdup(dir); - if(!node->nn->lnode->path) - { - /*deallocate the port*/ - PORT_DEALLOC(node->nn->port); - - /*unlock the mutex*/ - mutex_unlock(&ulfs_lock); - - LOG_MSG("node_init_root: Could not strdup the directory."); - return ENOMEM; - } - - /*The current position in dir*/ - char * p = dir + strlen(dir); - - /*Go through the path from end to beginning*/ - for(; p >= dir; --p) - { - /*If the current character is a '/'*/ - if(*p == '/') - { - /*If p is not the first character*/ - if(p > dir) - { - /*if this slash is escaped, skip it*/ - if(*(p - 1) == '\\') - continue; - } - - /*advance the pointer to the first character after the slash*/ - ++p; - - /*stop*/ - break; - } - } - - LOG_MSG("node_init_root: The name of root node is %s.", p); - - /*Set the name of the lnode to the last element in the path to dir*/ - node->nn->lnode->name = strdup(p); - /*If the name of the node could not be duplicated*/ - if(!node->nn->lnode->name) - { - /*free the name of the path to the node and deallocate teh port*/ - free(node->nn->lnode->path); - PORT_DEALLOC(node->nn->port); - - /*unlock the mutex*/ - mutex_unlock(&ulfs_lock); - - LOG_MSG("node_init_root: Could not strdup the name of the root node."); - return ENOMEM; - } - - /*Compute the length of the name of the root node*/ - node->nn->lnode->name_len = strlen(p); - - /*Release the lock for operations on the undelying filesystem*/ - mutex_unlock(&ulfs_lock); - - /*Return the result of operations*/ - return err; - }/*node_init_root*/ -/*----------------------------------------------------------------------------*/ + /*If p is not the first character */ + if (p > dir) + { + /*if this slash is escaped, skip it */ + if (*(p - 1) == '\\') + continue; + } + + /*advance the pointer to the first character after the slash */ + ++p; + + /*stop */ + break; + } + } + + LOG_MSG ("node_init_root: The name of root node is %s.", p); + + /*Set the name of the lnode to the last element in the path to dir */ + node->nn->lnode->name = strdup (p); + /*If the name of the node could not be duplicated */ + if (!node->nn->lnode->name) + { + /*free the name of the path to the node and deallocate teh port */ + free (node->nn->lnode->path); + PORT_DEALLOC (node->nn->port); + + /*unlock the mutex */ + mutex_unlock (&ulfs_lock); + + LOG_MSG ("node_init_root: Could not strdup the name of the root node."); + return ENOMEM; + } + + /*Compute the length of the name of the root node */ + node->nn->lnode->name_len = strlen (p); + + /*Release the lock for operations on the undelying filesystem */ + mutex_unlock (&ulfs_lock); + + /*Return the result of operations */ + return err; +} /*node_init_root */ + +/*---------------------------------------------------------------------------*/ /*Frees a list of dirents*/ -void -node_entries_free - ( - node_dirent_t * dirents /*free this*/ - ) - { - /*The current and the next elements*/ - node_dirent_t * dirent, * dirent_next; - - /*Go through all elements of the list*/ - for(dirent = dirents; dirent; dirent = dirent_next) - { - /*store the next element*/ - dirent_next = dirent->next; - - /*free the dirent stored in the current element of the list*/ - free(dirent->dirent); - - /*free the current element*/ - free(dirent); - } - }/*node_entries_free*/ -/*----------------------------------------------------------------------------*/ +void node_entries_free (node_dirent_t * dirents) +{ + /*The current and the next elements */ + node_dirent_t *dirent, *dirent_next; + + /*Go through all elements of the list */ + for (dirent = dirents; dirent; dirent = dirent_next) + { + /*store the next element */ + dirent_next = dirent->next; + + /*free the dirent stored in the current element of the list */ + free (dirent->dirent); + + /*free the current element */ + free (dirent); + } +} /*node_entries_free */ + +/*---------------------------------------------------------------------------*/ /*Reads the directory entries from `node`, which must be locked*/ -error_t -node_entries_get - ( - node_t * node, - node_dirent_t ** dirents /*store the result here*/ - ) +error_t node_entries_get (node_t * node, node_dirent_t ** dirents) +{ + error_t err = 0; + + /*The list of dirents */ + struct dirent **dirent_list, **dirent; + + /*The head of the list of dirents */ + node_dirent_t *node_dirent_list = NULL; + + /*The size of the array of pointers to dirent */ + size_t dirent_data_size; + + /*The array of dirents */ + char *dirent_data; + + /*Obtain the directory entries for the given node */ + err = dir_entries_get + (node->nn->port, &dirent_data, &dirent_data_size, &dirent_list); + if (err) + { + return err; + } + + /*The new entry in the list */ + node_dirent_t *node_dirent_new; + + /*The new dirent */ + struct dirent *dirent_new; + + /*LOG_MSG("node_entries_get: Getting entries for %p", node); */ + + /*The name of the current dirent */ + char *name; + + /*The length of the current name */ + size_t name_len; + + /*The size of the current dirent */ + size_t size; + + /*Go through all elements of the list of pointers to dirent */ + for (dirent = dirent_list; *dirent; ++dirent) + { + /*obtain the name of the current dirent */ + name = &((*dirent)->d_name[0]); + + /*If the current dirent is either '.' or '..', skip it */ + if ((strcmp (name, ".") == 0) || (strcmp (name, "..") == 0)) + continue; + + /*obtain the length of the current name */ + name_len = strlen (name); + + /*obtain the length of the current dirent */ + size = DIRENT_LEN (name_len); + + /*create a new list element */ + node_dirent_new = malloc (sizeof (node_dirent_t)); + if (!node_dirent_new) { - error_t err = 0; - - /*The list of dirents*/ - struct dirent ** dirent_list, **dirent; - - /*The head of the list of dirents*/ - node_dirent_t * node_dirent_list = NULL; - - /*The size of the array of pointers to dirent*/ - size_t dirent_data_size; - - /*The array of dirents*/ - char * dirent_data; - - /*Obtain the directory entries for the given node*/ - err = dir_entries_get - (node->nn->port, &dirent_data, &dirent_data_size, &dirent_list); - if(err) - { - return err; - } - - /*The new entry in the list*/ - node_dirent_t * node_dirent_new; - - /*The new dirent*/ - struct dirent * dirent_new; - - /*LOG_MSG("node_entries_get: Getting entries for %p", node);*/ - - /*The name of the current dirent*/ - char * name; - - /*The length of the current name*/ - size_t name_len; - - /*The size of the current dirent*/ - size_t size; - - /*Go through all elements of the list of pointers to dirent*/ - for(dirent = dirent_list; *dirent; ++dirent) - { - /*obtain the name of the current dirent*/ - name = &((*dirent)->d_name[0]); - - /*If the current dirent is either '.' or '..', skip it*/ - if((strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) - continue; - - /*obtain the length of the current name*/ - name_len = strlen(name); - - /*obtain the length of the current dirent*/ - size = DIRENT_LEN(name_len); - - /*create a new list element*/ - node_dirent_new = malloc(sizeof(node_dirent_t)); - if(!node_dirent_new) - { - err = ENOMEM; - break; - } - - /*create a new dirent*/ - dirent_new = malloc(size); - if(!dirent_new) - { - free(node_dirent_new); - err = ENOMEM; - break; - } - - /*fill the dirent with information*/ - dirent_new->d_ino = (*dirent)->d_ino; - dirent_new->d_type = (*dirent)->d_type; - dirent_new->d_reclen = size; - strcpy((char *)dirent_new + DIRENT_NAME_OFFS, name); - - /*add the dirent to the list*/ - node_dirent_new->dirent = dirent_new; - node_dirent_new->next = node_dirent_list; - node_dirent_list = node_dirent_new; - } - - /*If something went wrong in the loop*/ - if(err) - /*free the list of dirents*/ - node_entries_free(node_dirent_list); - else - /*store the list of dirents in the second parameter*/ - *dirents = node_dirent_list; - - /*Free the list of pointers to dirent*/ - free(dirent_list); - - /*Free the results of listing the dirents*/ - munmap(dirent_data, dirent_data_size); - - /*Return the result of operations*/ - return err; - }/*node_entries_get*/ -/*----------------------------------------------------------------------------*/ -/*Makes sure that all ports to the underlying filesystem of `node` are up to - date*/ -error_t -node_update - ( - node_t * node - ) + err = ENOMEM; + break; + } + + /*create a new dirent */ + dirent_new = malloc (size); + if (!dirent_new) { - error_t err = 0; - - /*The full path to this node*/ - char * path; - - /*Stat information for `node`*/ - io_statbuf_t stat; - - /*The port to the file corresponding to `node`*/ - file_t port; - - /*If the specified node is the root node or if it must not be updated*/ - if(NODE_IS_ROOT(node) || (node->nn->flags & FLAG_NODE_ULFS_FIXED)) - /*do nothing*/ - return err; /*return 0; actually*/ - - /*Gain exclusive access to the root node of the filesystem*/ - mutex_lock(&netfs_root_node->lock); - - /*Construct the full path to `node`*/ - err = lnode_path_construct(node->nn->lnode, &path); - if(err) - { - mutex_unlock(&netfs_root_node->lock); - return err; - } - - /*Deallocate `node`'s port to the underlying filesystem*/ - if(node->nn->port) - PORT_DEALLOC(node->nn->port); - - /*Try to lookup the file for `node` in its untranslated version*/ - err = file_lookup - ( - netfs_root_node->nn->port, path, O_READ | O_NOTRANS, O_NOTRANS, - 0, &port, &stat - ); - if(err) - { - node->nn->port = MACH_PORT_NULL; - err = 0; /*failure (?)*/ - return err; - } - - /*If the node looked up is actually the root node of the proxy filesystem*/ - if - ( - (stat.st_ino == underlying_node_stat.st_ino) - && (stat.st_fsid == underlying_node_stat.st_fsid) - ) - /*set `err` accordingly*/ - err = ELOOP; - else - { - /*deallocate the obtained port*/ - PORT_DEALLOC(port); - - /*obtain the translated version of the required node*/ - err = file_lookup - (netfs_root_node->nn->port, path, O_READ, 0, 0, &port, &stat); - } - - /*If there have been errors*/ - if(err) - /*reset the port*/ - port = MACH_PORT_NULL; - - /*Store the port in the node*/ - node->nn->port = port; - - /*Remove the flag about the invalidity of the current node and set the - flag that the node is up-to-date*/ - node->nn->flags &= ~FLAG_NODE_INVALIDATE; - node->nn->flags |= FLAG_NODE_ULFS_UPTODATE; - - /*Release the lock on the root node of proxy filesystem*/ - mutex_unlock(&netfs_root_node->lock); - - /*Return the result of operations*/ - return err; - }/*node_update*/ -/*----------------------------------------------------------------------------*/ + free (node_dirent_new); + err = ENOMEM; + break; + } + + /*fill the dirent with information */ + dirent_new->d_ino = (*dirent)->d_ino; + dirent_new->d_type = (*dirent)->d_type; + dirent_new->d_reclen = size; + strcpy ((char *) dirent_new + DIRENT_NAME_OFFS, name); + + /*add the dirent to the list */ + node_dirent_new->dirent = dirent_new; + node_dirent_new->next = node_dirent_list; + node_dirent_list = node_dirent_new; + } + + /*If something went wrong in the loop */ + if (err) + /*free the list of dirents */ + node_entries_free (node_dirent_list); + else + /*store the list of dirents in the second parameter */ + *dirents = node_dirent_list; + + /*Free the list of pointers to dirent */ + free (dirent_list); + + /*Free the results of listing the dirents */ + munmap (dirent_data, dirent_data_size); + + /*Return the result of operations */ + return err; +} /*node_entries_get */ + +/*---------------------------------------------------------------------------*/ +/*Makes sure that all ports to the underlying filesystem of `node` are + up to date*/ +error_t node_update (node_t * node) +{ + error_t err = 0; + + /*The full path to this node */ + char *path; + + /*Stat information for `node` */ + io_statbuf_t stat; + + /*The port to the file corresponding to `node` */ + file_t port; + + /*If the specified node is the root node or if it must not be updated */ + if (NODE_IS_ROOT (node) || (node->nn->flags & FLAG_NODE_ULFS_FIXED)) + /*do nothing */ + return err; /*return 0; actually */ + + /*Gain exclusive access to the root node of the filesystem */ + mutex_lock (&netfs_root_node->lock); + + /*Construct the full path to `node` */ + err = lnode_path_construct (node->nn->lnode, &path); + if (err) + { + mutex_unlock (&netfs_root_node->lock); + return err; + } + + /*Deallocate `node`'s port to the underlying filesystem */ + if (node->nn->port) + PORT_DEALLOC (node->nn->port); + + /*Try to lookup the file for `node` in its untranslated version */ + err = file_lookup + (netfs_root_node->nn->port, path, O_READ | O_NOTRANS, O_NOTRANS, + 0, &port, &stat); + if (err) + { + node->nn->port = MACH_PORT_NULL; + err = 0; /*failure (?) */ + return err; + } + + /*If the node looked up is actually the root node of the proxy filesystem */ + if ((stat.st_ino == underlying_node_stat.st_ino) + && (stat.st_fsid == underlying_node_stat.st_fsid)) + /*set `err` accordingly */ + err = ELOOP; + else + { + /*deallocate the obtained port */ + PORT_DEALLOC (port); + + /*obtain the translated version of the required node */ + err = file_lookup + (netfs_root_node->nn->port, path, O_READ, 0, 0, &port, &stat); + } + + /*If there have been errors */ + if (err) + /*reset the port */ + port = MACH_PORT_NULL; + + /*Store the port in the node */ + node->nn->port = port; + + /*Remove the flag about the invalidity of the current node and set the + flag that the node is up-to-date */ + node->nn->flags &= ~FLAG_NODE_INVALIDATE; + node->nn->flags |= FLAG_NODE_ULFS_UPTODATE; + + /*Release the lock on the root node of proxy filesystem */ + mutex_unlock (&netfs_root_node->lock); + + /*Return the result of operations */ + return err; +} /*node_update */ + +/*---------------------------------------------------------------------------*/ /*Computes the size of the given directory*/ -error_t -node_get_size - ( - node_t * dir, - OFFSET_T * off - ) - { - error_t err = 0; - - /*The final size*/ - size_t size = 0; - - /*The number of directory entries*/ - /*int count = 0;*/ - - /*The the node in the directory entries list from which we start counting*/ - /*node_dirent_t * dirent_start = NULL;*/ - - /*The currently analyzed dirent*/ - node_dirent_t * dirent_current = NULL; - - /*The pointer to the beginning of the list of dirents*/ - node_dirent_t * dirent_list = NULL; - - /*The first entry we have to analyze*/ - /*int first_entry = 2;*/ - - /*Takes into consideration the name of the current dirent*/ - void - bump_size - ( - const char * name - ) - { - /*Increment the current size by the size of the current dirent*/ - size += DIRENT_LEN(strlen(name)); - - /*Count the current dirent*/ - /*++count;*/ - }/*bump_size*/ - - /*Obtain the list of entries in the current directory*/ - err = node_entries_get(dir, &dirent_list); - if(err) - return err; - - /*Obtain the pointer to the dirent which has the number first_entry*/ - /*Actually, the first element of the list*/ - /*This code is included in unionfs, but it's completely useless here*/ - /*for - ( - dirent_start = dirent_list, count = 2; - dirent_start && count < first_entry; - dirent_start = dirent_start->next, ++count - );*/ - - /*Reset the count*/ - /*count = 0;*/ - - /*Make space for '.' and '..' entries*/ - /*This code is included in unionfs, but it's completely useless here*/ - /*if(first_entry == 0) - bump_size("."); - if(first_entry <= 1) - bump_size("..");*/ - - /*See how much space is required for the node*/ - for - ( - dirent_current = dirent_list/*dirent_start*/; dirent_current; - dirent_current = dirent_current->next - ) - bump_size(dirent_current->dirent->d_name); - - /*Free the list of dirents*/ - node_entries_free(dirent_list); - - /*Return the size*/ - *off = size; - return 0; - }/*node_get_size*/ -/*----------------------------------------------------------------------------*/ +error_t node_get_size (node_t * dir, OFFSET_T * off) +{ + error_t err = 0; + + /*The final size */ + size_t size = 0; + + /*The number of directory entries */ + /*int count = 0; */ + + /*The the node in the directory entries list from which we start counting */ + /*node_dirent_t * dirent_start = NULL; */ + + /*The currently analyzed dirent */ + node_dirent_t *dirent_current = NULL; + + /*The pointer to the beginning of the list of dirents */ + node_dirent_t *dirent_list = NULL; + + /*The first entry we have to analyze */ + /*int first_entry = 2; */ + + /*Takes into consideration the name of the current dirent */ + void bump_size (const char *name) + { + /*Increment the current size by the size of the current dirent */ + size += DIRENT_LEN (strlen (name)); + + /*Count the current dirent */ + /*++count; */ + } /*bump_size */ + + /*Obtain the list of entries in the current directory */ + err = node_entries_get (dir, &dirent_list); + if (err) + return err; + + /*Obtain the pointer to the dirent which has the number first_entry */ + /*Actually, the first element of the list */ + /*This code is included in unionfs, but it's completely useless here */ + /*for + ( + dirent_start = dirent_list, count = 2; + dirent_start && count < first_entry; + dirent_start = dirent_start->next, ++count + ); */ + + /*Reset the count */ + /*count = 0; */ + + /*Make space for '.' and '..' entries */ + /*This code is included in unionfs, but it's completely useless here */ + /*if(first_entry == 0) + bump_size("."); + if(first_entry <= 1) + bump_size(".."); */ + + /*See how much space is required for the node */ + for (dirent_current = dirent_list /*dirent_start */ ; dirent_current; + dirent_current = dirent_current->next) + bump_size (dirent_current->dirent->d_name); + + /*Free the list of dirents */ + node_entries_free (dirent_list); + + /*Return the size */ + *off = size; + return 0; +} /*node_get_size */ + +/*---------------------------------------------------------------------------*/ /*Remove the file called `name` under `dir`*/ -error_t -node_unlink_file - ( - node_t * dir, - char * name - ) - { - error_t err = 0; - - /*The port to the file which will be unlinked*/ - mach_port_t p; - - /*Stat information about the file which will be unlinked*/ - io_statbuf_t stat; - - /*If port corresponding to `dir` is invalid*/ - if(dir->nn->port == MACH_PORT_NULL) - /*stop with an error*/ - return ENOENT; /*FIXME: Is the return value indeed meaningful here?*/ - - /*Attempt to lookup the specified file*/ - err = file_lookup(dir->nn->port, name, O_NOTRANS, O_NOTRANS, 0, &p, &stat); - if(err) - return err; - - /*Deallocate the obtained port*/ - PORT_DEALLOC(p); - - /*Unlink file `name` under `dir`*/ - err = dir_unlink(dir->nn->port, name); - if(err) - return err; - - return err; - }/*node_unlink_file*/ -/*----------------------------------------------------------------------------*/ +error_t node_unlink_file (node_t * dir, char *name) +{ + error_t err = 0; + + /*The port to the file which will be unlinked */ + mach_port_t p; + + /*Stat information about the file which will be unlinked */ + io_statbuf_t stat; + + /*If port corresponding to `dir` is invalid */ + if (dir->nn->port == MACH_PORT_NULL) + /*stop with an error */ + return ENOENT; /*FIXME: Is the return value indeed meaningful here? */ + + /*Attempt to lookup the specified file */ + err = file_lookup (dir->nn->port, name, O_NOTRANS, O_NOTRANS, 0, &p, &stat); + if (err) + return err; + + /*Deallocate the obtained port */ + PORT_DEALLOC (p); + + /*Unlink file `name` under `dir` */ + err = dir_unlink (dir->nn->port, name); + if (err) + return err; + + return err; +} /*node_unlink_file */ + +/*---------------------------------------------------------------------------*/ /*Sets the given translators on the specified node*/ -error_t -node_set_translators - ( - struct protid * diruser, - node_t * np, - char * trans, /*set these on `node`*/ - size_t ntrans, - int flags, - mach_port_t * port - ) - { - error_t err; - mach_port_t p; - - /*An unauthenticated port to the directory containing `np`*/ - mach_port_t unauth_dir; - - /*A copy (possibly extended) of the name of the translator*/ - char * ext; - - /*The holders of argz-transformed translator name and arguments*/ - char * argz = NULL; - size_t argz_len = 0; - - /*The pointer to the name of the translator we are going to start now*/ - char * str; - - /*The index of the translator in the list of strings*/ - size_t idx; - - /*The control port for the active translator*/ - mach_port_t active_control; - - /*A new element in the list of control ports*/ - port_el_t * p_el; - - /*A copy of the user information, supplied in `user`*/ - struct iouser * user; - - /*A protid for the supplied node*/ - struct protid * newpi; - - /*Identity information about the current process (for fsys_getroot)*/ - uid_t * uids; - size_t nuids; - - gid_t * gids; - size_t ngids; - - /*The retry information returned by fsys_getroot*/ - string_t retry_name; - mach_port_t retry_port; - - /*Try to get the number of effective UIDs*/ - nuids = geteuids(0, 0); - if(nuids < 0) - return EPERM; - - /*Allocate some memory for the UIDs on the stack*/ - uids = alloca(nuids * sizeof(uid_t)); - - /*Fetch the UIDs themselves*/ - nuids = geteuids(nuids, uids); - if(nuids < 0) - return EPERM; - - /*Try to get the number of effective GIDs*/ - ngids = getgroups(0, 0); - if(ngids < 0) - return EPERM; - - /*Allocate some memory for the GIDs on the stack*/ - gids = alloca(ngids * sizeof(gid_t)); - - /*Fetch the GIDs themselves*/ - ngids = getgroups(ngids, gids); - if(ngids < 0) - return EPERM; - - /*Opens the port on which to set the new translator*/ - error_t - open_port - ( - int flags, - mach_port_t * underlying, - mach_msg_type_name_t * underlying_type, - task_t task, - void * cookie /*if 0, open the port to the node; otherwise get the port - of the topmost translator on the node*/ - ) - { - /*No errors at first*/ - err = 0; - - /*If a port to the node is wanted*/ - if((int)cookie == 0) - { - /*check, whether the user has the permissions to open this node*/ - err = check_open_permissions(diruser->user, &np->nn_stat, flags); - if(err) - return err; - - /*duplicate the supplied user*/ - err = iohelp_dup_iouser(&user, diruser->user); - if(err) - return err; - - /*create a protid for this node*/ - newpi = netfs_make_protid - (netfs_make_peropen(np, flags, diruser->po), user); - if(!newpi) - { - iohelp_free_iouser(user); - return errno; - } - LOG_MSG("node_set_translators.open_port: PASSED"); - - /*obtain the resulting port right and set its type appropriately*/ - *underlying = p = ports_get_send_right(newpi); - *underlying_type = MACH_MSG_TYPE_COPY_SEND; - - LOG_MSG("node_set_translators.open_port: %ld", (long)*underlying); - - /*drop our reference to the port*/ - ports_port_deref(newpi); - } - /*We are not setting the first translator, this one is not required - to sit on the node itself*/ - else - /*in the previous iteration of the loop fsys_getroot gave us the port - to the toplevel translator on the current node, namely `p`; this is - what is required of us now*/ - { - *underlying = p; - *underlying_type = MACH_MSG_TYPE_COPY_SEND; - } - - /*Return the result of operations (everything should be okay here)*/ - return err; - }/*open_port*/ - - /*Adds a "/hurd/" at the beginning of the translator name, if required*/ - char * - put_in_hurd - ( - const char * name - ) - { - /*If the path to the translator is absolute, return a copy of the name*/ - /*TODO: A better decision technique on whether we have to add the prefix*/ - if(name[0] == '/') - return strdup(name); - - /*Compute the length of the name*/ - size_t len = strlen(name); - - /*Try to allocate new memory*/ - char * full = malloc(6/*strlen("/hurd/")*/ + len + 1); - if(!full) - return NULL; - - /*Construct the name*/ - strcpy(full, "/hurd/"); - /*LOG_MSG("node_set_translator: %s", full);*/ - strcpy(full + 6, name); - /*LOG_MSG("node_set_translator: %s", full);*/ - full[6 + len] = 0; - /*LOG_MSG("node_set_translator: %s", full);*/ - - /*Return the full path*/ - return full; - }/*put_in_hurd*/ - - /*Obtain the unauthenticated port to the directory*/ - err = io_restrict_auth(diruser->po->np->nn->port, &unauth_dir, 0, 0, 0, 0); - if(err) - return err; - - /*While all translators have not been looked through*/ - for(str = trans, idx = 0; idx < ntrans; ++idx) - { - /*obtain a copy (possibly extended) of the name*/ - ext = put_in_hurd(str); - if(!ext) - return ENOMEM; - - /*move str to the next translator in the list*/ - str += strlen(str) + 1; - - /*TODO: Better argument-parsing?*/ - - /*obtain the argz version of str*/ - err = argz_create_sep(ext, ' ', &argz, &argz_len); - if(err) - return err; - - /*start the translator*/ - err = fshelp_start_translator - ( - open_port, (void *)((idx == 0) ? 0 : 1), argz, argz, argz_len, - 60000,/*this is the default in settrans*/ - &active_control - ); - if(err) - return err; - - /*attempt to set a translator on the port opened by the previous call*/ - err = file_set_translator - ( - p, 0, FS_TRANS_SET, 0, argz, argz_len, - active_control, MACH_MSG_TYPE_COPY_SEND - ); - /*close the port we have just opened*/ - PORT_DEALLOC(p); - - /*stop, if the attempt to set the translator failed*/ - if(err) - return err; - - /*allocate a new element for the current control port*/ - p_el = malloc(sizeof(struct port_el)); - if(!p_el) - return ENOMEM; - - /*store the current control port in the new cell*/ - p_el->p = active_control; - - /*add the new control port to the list*/ - p_el->next = np->nn->cntl_ports; - np->nn->cntl_ports = p_el; - - /*obtain the port to the top of the newly-set translator*/ - err = fsys_getroot - ( - active_control, unauth_dir, MACH_MSG_TYPE_COPY_SEND, - uids, nuids, gids, ngids, - flags, &retry_port, retry_name, &p - ); - if(err) - return err; - } - - /*Return the port*/ - *port = p; - - /*Everything is OK here*/ - return 0; - }/*node_set_translators*/ -/*----------------------------------------------------------------------------*/ -/*Kill the topmost translator for this node*/ -/*This function will normally be called from netfs_attempt_lookup, therefore - it's better that the caller should provide the parent node for `node`.*/ -/*This is the code for the wrong version of nsmux.*/ -error_t -node_kill_translator - ( - node_t * dir, - node_t * node - ) - { - error_t err = 0; - - /*Lookup the file*/ - mach_port_t p = - file_name_lookup_under - (dir->nn->port, node->nn->lnode->name, /*O_NOTRANS*/0, 0); - if(!p) - return errno; - - /*Remove a translator from the node*/ -/*This code was taken from the code of settrans and works only when there is - only one translator in the stack (not including the ext2fs, for example). - For this code to work the O_NOTRANS is required in the lookup.*/ - /*error_t err = file_set_translator - ( - p, FS_TRANS_SET, FS_TRANS_SET, 0, NULL, 0, - MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND - );*/ - - /*Obtain the control port of the filesystem to which file `name` belongs*/ - fsys_t fsys; - err = file_getcontrol(p, &fsys); - - char * argz = NULL; - size_t argz_len = 0; - err = file_get_fs_options(p, &argz, &argz_len); - - /*Close the port*/ - PORT_DEALLOC(p); - - /*If the control port of the filesystem could not be fetched, stop*/ - if(err) - return err; - - /*Ask the translator to go away*/ - err = fsys_goaway(fsys, 0); - - /*If the translator is busy*/ - if(err) - /*force the translator to go away*/ - err = fsys_goaway(fsys, FSYS_GOAWAY_FORCE); - - /*Deallocate the control port*/ - PORT_DEALLOC(fsys); - - /*Return the result of removing the translator*/ +error_t node_set_translators (struct protid * diruser, node_t * np, + char *trans, /*set these on `node` */ + size_t ntrans, int flags, mach_port_t * port) +{ + error_t err; + mach_port_t p; + + /*An unauthenticated port to the directory containing `np` */ + mach_port_t unauth_dir; + + /*A copy (possibly extended) of the name of the translator */ + char *ext; + + /*The holders of argz-transformed translator name and arguments */ + char *argz = NULL; + size_t argz_len = 0; + + /*The pointer to the name of the translator we are going to start now */ + char *str; + + /*The index of the translator in the list of strings */ + size_t idx; + + /*The control port for the active translator */ + mach_port_t active_control; + + /*A new element in the list of control ports */ + port_el_t *p_el; + + /*A copy of the user information, supplied in `user` */ + struct iouser *user; + + /*A protid for the supplied node */ + struct protid *newpi; + + /*Identity information about the current process (for fsys_getroot) */ + uid_t *uids; + size_t nuids; + + gid_t *gids; + size_t ngids; + + /*The retry information returned by fsys_getroot */ + string_t retry_name; + mach_port_t retry_port; + + /*Try to get the number of effective UIDs */ + nuids = geteuids (0, 0); + if (nuids < 0) + return EPERM; + + /*Allocate some memory for the UIDs on the stack */ + uids = alloca (nuids * sizeof (uid_t)); + + /*Fetch the UIDs themselves */ + nuids = geteuids (nuids, uids); + if (nuids < 0) + return EPERM; + + /*Try to get the number of effective GIDs */ + ngids = getgroups (0, 0); + if (ngids < 0) + return EPERM; + + /*Allocate some memory for the GIDs on the stack */ + gids = alloca (ngids * sizeof (gid_t)); + + /*Fetch the GIDs themselves */ + ngids = getgroups (ngids, gids); + if (ngids < 0) + return EPERM; + + /*Opens the port on which to set the new translator */ + error_t open_port (int flags, mach_port_t * underlying, + mach_msg_type_name_t * underlying_type, task_t task, + void *cookie /*if 0, open the port to the node; + otherwise get the port of the + topmost translator on the node */ + ) + { + /*No errors at first */ + err = 0; + + /*If a port to the node is wanted */ + if ((int) cookie == 0) + { + /*check, whether the user has the permissions to open this node */ + err = check_open_permissions (diruser->user, &np->nn_stat, flags); + if (err) + return err; + + /*duplicate the supplied user */ + err = iohelp_dup_iouser (&user, diruser->user); + if (err) + return err; + + /*create a protid for this node */ + newpi = netfs_make_protid + (netfs_make_peropen (np, flags, diruser->po), user); + if (!newpi) + { + iohelp_free_iouser (user); + return errno; + } + LOG_MSG ("node_set_translators.open_port: PASSED"); + + /*obtain the resulting port right and set its type appropriately */ + *underlying = p = ports_get_send_right (newpi); + *underlying_type = MACH_MSG_TYPE_COPY_SEND; + + LOG_MSG ("node_set_translators.open_port: %ld", (long) *underlying); + + /*drop our reference to the port */ + ports_port_deref (newpi); + } + /*We are not setting the first translator, this one is not required + to sit on the node itself */ + else + /*in the previous iteration of the loop fsys_getroot gave us the port + to the toplevel translator on the current node, namely `p`; this is + what is required of us now */ + { + *underlying = p; + *underlying_type = MACH_MSG_TYPE_COPY_SEND; + } + + /*Return the result of operations (everything should be okay here) */ + return err; + } /*open_port */ + + /*Adds a "/hurd/" at the beginning of the translator name, if required */ + char *put_in_hurd (const char *name) + { + /*If the path to the translator is absolute, return a copy of the name */ + /*TODO: A better decision technique on whether we have to add the prefix */ + if (name[0] == '/') + return strdup (name); + + /*Compute the length of the name */ + size_t len = strlen (name); + + /*Try to allocate new memory */ + char *full = malloc (6 /*strlen("/hurd/") */ + len + 1); + if (!full) + return NULL; + + /*Construct the name */ + strcpy (full, "/hurd/"); + /*LOG_MSG("node_set_translator: %s", full); */ + strcpy (full + 6, name); + /*LOG_MSG("node_set_translator: %s", full); */ + full[6 + len] = 0; + /*LOG_MSG("node_set_translator: %s", full); */ + + /*Return the full path */ + return full; + } /*put_in_hurd */ + + /*Obtain the unauthenticated port to the directory */ + err = io_restrict_auth (diruser->po->np->nn->port, &unauth_dir, 0, 0, 0, 0); + if (err) + return err; + + /*While all translators have not been looked through */ + for (str = trans, idx = 0; idx < ntrans; ++idx) + { + /*obtain a copy (possibly extended) of the name */ + ext = put_in_hurd (str); + if (!ext) + return ENOMEM; + + /*move str to the next translator in the list */ + str += strlen (str) + 1; + + /*TODO: Better argument-parsing? */ + + /*obtain the argz version of str */ + err = argz_create_sep (ext, ' ', &argz, &argz_len); + if (err) return err; - }/*node_kill_translator*/ -/*----------------------------------------------------------------------------*/ + + /*start the translator */ + err = fshelp_start_translator (open_port, (void *) ((idx == 0) ? 0 : 1), + argz, argz, argz_len, + 60000, /*this is the default in settrans*/ + &active_control); + if (err) + return err; + + /*attempt to set a translator on the port opened by the previous call */ + err = file_set_translator + (p, 0, FS_TRANS_SET, 0, argz, argz_len, + active_control, MACH_MSG_TYPE_COPY_SEND); + /*close the port we have just opened */ + PORT_DEALLOC (p); + + /*stop, if the attempt to set the translator failed */ + if (err) + return err; + + /*allocate a new element for the current control port */ + p_el = malloc (sizeof (struct port_el)); + if (!p_el) + return ENOMEM; + + /*store the current control port in the new cell */ + p_el->p = active_control; + + /*add the new control port to the list */ + p_el->next = np->nn->cntl_ports; + np->nn->cntl_ports = p_el; + + /*obtain the port to the top of the newly-set translator */ + err = fsys_getroot + (active_control, unauth_dir, MACH_MSG_TYPE_COPY_SEND, + uids, nuids, gids, ngids, flags, &retry_port, retry_name, &p); + if (err) + return err; + } + + /*Return the port */ + *port = p; + + /*Everything is OK here */ + return 0; +} /*node_set_translators */ + +/*---------------------------------------------------------------------------*/ /*Kills all translators on the nodes belonging to the given directory*/ -void -node_kill_translators - ( - node_t * node - ) - { - /*If the node has no translators*/ - if(node->nn->trans == NULL) - /*nothing to do*/ - return; - - error_t err = 0; - - /*The current element in the port list*/ - port_el_t * p_el; - - /*While the list of control ports is not empty*/ - for(p_el = node->nn->cntl_ports; p_el; p_el = node->nn->cntl_ports) - { - /*kill the current translator*/ - err = fsys_goaway(p_el->p, 0); - - /*If the translator says it is busy, force it to go away*/ - if(err == EBUSY) - err = fsys_goaway(p_el->p, FSYS_GOAWAY_FORCE); - - /*move the beginning of the list of control ports forward*/ - node->nn->cntl_ports = p_el->next; - - /*destroy the current cell in the list of ports*/ - free(p_el); - } - }/*node_kill_translators*/ -/*----------------------------------------------------------------------------*/ +void node_kill_translators (node_t * node) +{ + /*If the node has no translators */ + if (node->nn->trans == NULL) + /*nothing to do */ + return; + + error_t err = 0; + + /*The current element in the port list */ + port_el_t *p_el; + + /*While the list of control ports is not empty */ + for (p_el = node->nn->cntl_ports; p_el; p_el = node->nn->cntl_ports) + { + /*kill the current translator */ + err = fsys_goaway (p_el->p, 0); + + /*If the translator says it is busy, force it to go away */ + if (err == EBUSY) + err = fsys_goaway (p_el->p, FSYS_GOAWAY_FORCE); + + /*move the beginning of the list of control ports forward */ + node->nn->cntl_ports = p_el->next; + + /*destroy the current cell in the list of ports */ + free (p_el); + } +} /*node_kill_translators */ + +/*---------------------------------------------------------------------------*/ @@ -1,10 +1,10 @@ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*node.h*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Node management. Also see lnode.h*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Copyright (C) 2001, 2002, 2005, 2008 Free Software Foundation, Inc. Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. @@ -22,212 +22,152 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #ifndef __NODE_H__ #define __NODE_H__ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #include <error.h> #include <sys/stat.h> #include <hurd/netfs.h> -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #include "lnode.h" -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Macros--------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Macros-------------------------------------------------------------*/ /*Checks whether the give node is the root of the proxy filesystem*/ #define NODE_IS_ROOT(n) (((n)->nn->lnode->dir) ? (0) : (1)) -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Node flags*/ -#define FLAG_NODE_ULFS_FIXED 0x00000001 /*this node should not be updated*/ -#define FLAG_NODE_INVALIDATE 0x00000002 /*this node must be updated*/ -#define FLAG_NODE_ULFS_UPTODATE 0x00000004 /*this node has just been updated*/ -/*----------------------------------------------------------------------------*/ +#define FLAG_NODE_ULFS_FIXED 0x00000001 /*this node should not be updated */ +#define FLAG_NODE_INVALIDATE 0x00000002 /*this node must be updated */ +#define FLAG_NODE_ULFS_UPTODATE 0x00000004 /*this node has just been updated */ +/*---------------------------------------------------------------------------*/ /*The type of offset corresponding to the current platform*/ #ifdef __USE_FILE_OFFSET64 # define OFFSET_T __off64_t #else # define OFFSET_T __off_t #endif /*__USE_FILE_OFFSET64*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Types---------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Types--------------------------------------------------------------*/ /*A list element containing a port*/ struct port_el - { - /*the port*/ - mach_port_t p; - - /*the next element in the list*/ - struct port_el * next; - };/*struct port_el*/ -/*----------------------------------------------------------------------------*/ +{ + /*the port */ + mach_port_t p; + + /*the next element in the list */ + struct port_el *next; +}; /*struct port_el */ +/*---------------------------------------------------------------------------*/ typedef struct port_el port_el_t; -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*The user-defined node for libnetfs*/ struct netnode - { - /*the reference to the corresponding light node*/ - lnode_t * lnode; - - /*the flags associated with this node*/ - int flags; - - /*a port to the underlying filesystem*/ - file_t port; - - /*the port to the untranslated version of the node*/ - file_t port_notrans; - - /*the malloced set of translators which have to be stacked upon this node - and upon its children; the corresponding translators will have to decide - on their own whether to accept directories or not*/ - char * trans; - - /*the number of translators listed in `translators`*/ - size_t ntrans; - - /*the length of the list of translators (in bytes)*/ - size_t translen; - - /*the list of control ports to the translators being set on this node*/ - port_el_t * cntl_ports; - - /*the neighbouring entries in the cache*/ - node_t * ncache_prev, * ncache_next; - };/*struct netnode*/ -/*----------------------------------------------------------------------------*/ +{ + /*the reference to the corresponding light node */ + lnode_t *lnode; + + /*the flags associated with this node */ + int flags; + + /*a port to the underlying filesystem */ + file_t port; + + /*the port to the untranslated version of the node */ + file_t port_notrans; + + /*the malloced set of translators which have to be stacked upon this node + and upon its children; the corresponding translators will have to decide + on their own whether to accept directories or not */ + char *trans; + + /*the number of translators listed in `translators` */ + size_t ntrans; + + /*the length of the list of translators (in bytes) */ + size_t translen; + + /*the list of control ports to the translators being set on this node */ + port_el_t *cntl_ports; + + /*the neighbouring entries in the cache */ + node_t *ncache_prev, *ncache_next; +}; /*struct netnode */ +/*---------------------------------------------------------------------------*/ typedef struct netnode netnode_t; -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*A list element containing directory entry*/ struct node_dirent - { - /*the directory entry*/ - struct dirent * dirent; - - /*the next element*/ - struct node_dirent * next; - };/*struct node_dirent*/ -/*----------------------------------------------------------------------------*/ +{ + /*the directory entry */ + struct dirent *dirent; + + /*the next element */ + struct node_dirent *next; +}; /*struct node_dirent */ +/*---------------------------------------------------------------------------*/ typedef struct node_dirent node_dirent_t; -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Global Variables----------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Global Variables---------------------------------------------------*/ /*The lock protecting the underlying filesystem*/ extern struct mutex ulfs_lock; -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/ -/*--------Functions-----------------------------------------------------------*/ +/*--------Functions----------------------------------------------------------*/ /*Derives a new node from `lnode` and adds a reference to `lnode`*/ -error_t -node_create - ( - lnode_t * lnode, - node_t ** node /*store the result here*/ - ); -/*----------------------------------------------------------------------------*/ +error_t node_create (lnode_t * lnode, node_t ** node); +/*---------------------------------------------------------------------------*/ /*Derives a new proxy from `lnode`*/ -error_t -node_create_proxy - ( - lnode_t * lnode, - node_t ** node /*store the result here*/ - ); -/*----------------------------------------------------------------------------*/ +error_t node_create_proxy (lnode_t * lnode, node_t ** node); +/*---------------------------------------------------------------------------*/ /*Destroys the specified node and removes a light reference from the - associated light node*/ -void -node_destroy - ( - node_t * np - ); -/*----------------------------------------------------------------------------*/ + associated light node*/ +void node_destroy (node_t * np); +/*---------------------------------------------------------------------------*/ /*Creates the root node and the corresponding lnode*/ -error_t -node_create_root - ( - node_t ** root_node /*store the result here*/ - ); -/*----------------------------------------------------------------------------*/ +error_t node_create_root (node_t ** root_node); +/*---------------------------------------------------------------------------*/ /*Initializes the port to the underlying filesystem for the root node*/ -error_t -node_init_root - ( - node_t * node /*the root node*/ - ); -/*----------------------------------------------------------------------------*/ +error_t node_init_root (node_t * node); +/*---------------------------------------------------------------------------*/ /*Frees a list of dirents*/ -void -node_entries_free - ( - node_dirent_t * dirents /*free this*/ - ); -/*----------------------------------------------------------------------------*/ +void node_entries_free (node_dirent_t * dirents); +/*---------------------------------------------------------------------------*/ /*Reads the directory entries from `node`, which must be locked*/ -error_t -node_entries_get - ( - node_t * node, - node_dirent_t ** dirents /*store the result here*/ - ); -/*----------------------------------------------------------------------------*/ -/*Makes sure that all ports to the underlying filesystem of `node` are up to - date*/ -error_t -node_update - ( - node_t * node - ); -/*----------------------------------------------------------------------------*/ +error_t node_entries_get (node_t * node, node_dirent_t ** dirents); +/*---------------------------------------------------------------------------*/ +/*Makes sure that all ports to the underlying filesystem of `node` are + up to date*/ +error_t node_update (node_t * node); +/*---------------------------------------------------------------------------*/ /*Computes the size of the given directory*/ -error_t -node_get_size - ( - node_t * dir, - OFFSET_T * off - ); -/*----------------------------------------------------------------------------*/ +error_t node_get_size (node_t * dir, OFFSET_T * off); +/*---------------------------------------------------------------------------*/ /*Remove the file called `name` under `dir`*/ -error_t -node_unlink_file - ( - node_t * dir, - char * name - ); -/*----------------------------------------------------------------------------*/ -/*Sets the given translators on the specified node and returns the port to - the topmost one opened as `flags` require*/ -error_t -node_set_translators - ( - struct protid * diruser, - node_t * np, - char * trans, /*set these on `node`*/ - size_t ntrans, - int flags, - mach_port_t * port - ); -/*----------------------------------------------------------------------------*/ +error_t node_unlink_file (node_t * dir, char *name); +/*---------------------------------------------------------------------------*/ +/*Sets the given translators on the specified node and returns the + port to the topmost one opened as `flags` require*/ +error_t node_set_translators (struct protid *diruser, node_t * np, + char *trans, /*set these on `node` */ + size_t ntrans, int flags, mach_port_t * port); +/*---------------------------------------------------------------------------*/ /*Kill the topmost translator for this node*/ -/*This function will normally be called from netfs_attempt_lookup, therefore - it's better that the caller should provide the parent node for `node`.*/ -error_t -node_kill_translator - ( - node_t * dir, - node_t * node - ); -/*----------------------------------------------------------------------------*/ -/*Kills all translators on the current node or on all underlying nodes it the - current node is a directory*/ -void -node_kill_translators - ( - node_t * node - ); -/*----------------------------------------------------------------------------*/ +/*This function will normally be called from netfs_attempt_lookup, + therefore it's better that the caller should provide the parent node + for `node`.*/ +error_t node_kill_translator (node_t * dir, node_t * node); +/*---------------------------------------------------------------------------*/ +/*Kills all translators on the current node or on all underlying nodes + it the current node is a directory*/ +void node_kill_translators (node_t * node); +/*---------------------------------------------------------------------------*/ #endif /*__NODE_H__*/ @@ -1,10 +1,10 @@ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*nsmux.c*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*The filesystem proxy for namespace-based translator selection.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Copyright (C) 2001, 2002, 2005, 2008 Free Software Foundation, Inc. Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. @@ -22,938 +22,882 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #define _GNU_SOURCE 1 -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #include "nsmux.h" -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #include <error.h> #include <argp.h> #include <hurd/netfs.h> #include <fcntl.h> #include <hurd/paths.h> -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #include "debug.h" #include "options.h" #include "ncache.h" -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Global Variables----------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Global Variables---------------------------------------------------*/ /*The name of the server*/ -char * netfs_server_name = "nsmux"; -/*----------------------------------------------------------------------------*/ +char *netfs_server_name = "nsmux"; +/*---------------------------------------------------------------------------*/ /*The version of the server*/ -char * netfs_server_version = "0.0"; -/*----------------------------------------------------------------------------*/ +char *netfs_server_version = "0.0"; +/*---------------------------------------------------------------------------*/ /*The maximal length of a chain of symbolic links*/ int netfs_maxsymlinks = 12; -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*A port to the underlying node*/ mach_port_t underlying_node; -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Status information for the underlying node*/ io_statbuf_t underlying_node_stat; -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Mapped time used for updating node information*/ -volatile struct mapped_time_value * maptime; -/*----------------------------------------------------------------------------*/ +volatile struct mapped_time_value *maptime; +/*---------------------------------------------------------------------------*/ /*The filesystem ID*/ pid_t fsid; -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*The file to print debug messages to*/ -FILE * nsmux_dbg; -/*----------------------------------------------------------------------------*/ +FILE *nsmux_dbg; +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Functions-----------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Functions----------------------------------------------------------*/ /*Attempts to create a file named `name` in `dir` for `user` with mode `mode`*/ error_t -netfs_attempt_create_file - ( - struct iouser * user, - struct node * dir, - char * name, - mode_t mode, - struct node ** node - ) - { - LOG_MSG("netfs_attempt_create_file"); - - /*Unlock `dir` and say that we can do nothing else here*/ - mutex_unlock(&dir->lock); - return EOPNOTSUPP; - }/*netfs_attempt_create_file*/ -/*----------------------------------------------------------------------------*/ -/*Return an error if the process of opening a file should not be allowed - to complete because of insufficient permissions*/ + netfs_attempt_create_file + (struct iouser *user, + struct node *dir, char *name, mode_t mode, struct node **node) +{ + LOG_MSG ("netfs_attempt_create_file"); + + /*Unlock `dir` and say that we can do nothing else here */ + mutex_unlock (&dir->lock); + return EOPNOTSUPP; +} /*netfs_attempt_create_file */ + +/*---------------------------------------------------------------------------*/ +/*Return an error if the process of opening a file should not be + allowed to complete because of insufficient permissions*/ error_t -netfs_check_open_permissions - ( - struct iouser * user, - struct node * np, - int flags, - int newnode - ) - { - LOG_MSG("netfs_check_open_permissions: '%s'", np->nn->lnode->name); + netfs_check_open_permissions + (struct iouser * user, struct node * np, int flags, int newnode) +{ + LOG_MSG ("netfs_check_open_permissions: '%s'", np->nn->lnode->name); + + /*Cheks user's permissions and return the result */ + return check_open_permissions (user, &np->nn_stat, flags); +} /*netfs_check_open_permissions */ - /*Cheks user's permissions and return the result*/ - return check_open_permissions(user, &np->nn_stat, flags); - }/*netfs_check_open_permissions*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Attempts an utimes call for the user `cred` on node `node`*/ error_t -netfs_attempt_utimes - ( - struct iouser * cred, - struct node * node, - struct timespec * atime, - struct timespec * mtime - ) - { - LOG_MSG("netfs_attempt_utimes"); - - error_t err = 0; - - /*See what information is to be updated*/ - int flags = TOUCH_CTIME; - - /*Check if the user is indeed the owner of the node*/ - err = fshelp_isowner(&node->nn_stat, cred); - - /*If the user is allowed to do utimes*/ - if(!err) - { - /*If atime is to be updated*/ - if(atime) - /*update the atime*/ - node->nn_stat.st_atim = *atime; - else - /*the current time will be set as the atime*/ - flags |= TOUCH_ATIME; - - /*If mtime is to be updated*/ - if(mtime) - /*update the mtime*/ - node->nn_stat.st_mtim = *mtime; - else - /*the current time will be set as mtime*/ - flags |= TOUCH_MTIME; - - /*touch the file*/ - fshelp_touch(&node->nn_stat, flags, maptime); - } - - /*Return the result of operations*/ - return err; - }/*netfs_attempt_utimes*/ -/*----------------------------------------------------------------------------*/ + netfs_attempt_utimes + (struct iouser * cred, + struct node * node, struct timespec * atime, struct timespec * mtime) +{ + LOG_MSG ("netfs_attempt_utimes"); + + error_t err = 0; + + /*See what information is to be updated */ + int flags = TOUCH_CTIME; + + /*Check if the user is indeed the owner of the node */ + err = fshelp_isowner (&node->nn_stat, cred); + + /*If the user is allowed to do utimes */ + if (!err) + { + /*If atime is to be updated */ + if (atime) + /*update the atime */ + node->nn_stat.st_atim = *atime; + else + /*the current time will be set as the atime */ + flags |= TOUCH_ATIME; + + /*If mtime is to be updated */ + if (mtime) + /*update the mtime */ + node->nn_stat.st_mtim = *mtime; + else + /*the current time will be set as mtime */ + flags |= TOUCH_MTIME; + + /*touch the file */ + fshelp_touch (&node->nn_stat, flags, maptime); + } + + /*Return the result of operations */ + return err; +} /*netfs_attempt_utimes */ + +/*---------------------------------------------------------------------------*/ /*Returns the valid access types for file `node` and user `cred`*/ error_t -netfs_report_access - ( - struct iouser * cred, - struct node * np, - int * types - ) - { - LOG_MSG("netfs_report_access"); - - /*No access at first*/ - *types = 0; - - /*Check the access and set the required bits*/ - if(fshelp_access(&np->nn_stat, S_IREAD, cred) == 0) - *types |= O_READ; - if(fshelp_access(&np->nn_stat, S_IWRITE, cred) == 0) - *types |= O_WRITE; - if(fshelp_access(&np->nn_stat, S_IEXEC, cred) == 0) - *types |= O_EXEC; - - /*Everything OK*/ - return 0; - }/*netfs_report_access*/ -/*----------------------------------------------------------------------------*/ + netfs_report_access (struct iouser * cred, struct node * np, int *types) +{ + LOG_MSG ("netfs_report_access"); + + /*No access at first */ + *types = 0; + + /*Check the access and set the required bits */ + if (fshelp_access (&np->nn_stat, S_IREAD, cred) == 0) + *types |= O_READ; + if (fshelp_access (&np->nn_stat, S_IWRITE, cred) == 0) + *types |= O_WRITE; + if (fshelp_access (&np->nn_stat, S_IEXEC, cred) == 0) + *types |= O_EXEC; + + /*Everything OK */ + return 0; +} /*netfs_report_access */ + +/*---------------------------------------------------------------------------*/ /*Validates the stat data for the node*/ -error_t -netfs_validate_stat - ( - struct node * np, - struct iouser * cred - ) +error_t netfs_validate_stat (struct node * np, struct iouser * cred) +{ + LOG_MSG ("netfs_validate_stat: '%s'", (np ? np->nn->lnode->name : "")); + + error_t err = 0; + + /*If we are not at the root */ + if (np != netfs_root_node) + { + /*If the node is not surely up-to-date */ + if (!(np->nn->flags & FLAG_NODE_ULFS_UPTODATE)) { - LOG_MSG("netfs_validate_stat: '%s'", (np ? np->nn->lnode->name : "")); + /*update it */ + err = node_update (np); + } - error_t err = 0; - - /*If we are not at the root*/ - if(np != netfs_root_node) - { - /*If the node is not surely up-to-date*/ - if(!(np->nn->flags & FLAG_NODE_ULFS_UPTODATE)) - { - /*update it*/ - err = node_update(np); - } - - /*If no errors have yet occurred*/ - if(!err) - { - /*If the port to the file corresponding to `np` is valid*/ - if(np->nn->port != MACH_PORT_NULL) - { - /*We have a directory here (normally, only they maintain an open port). - Generally, our only concern is to maintain an open port in this case*/ - - /*attempt to stat this file*/ - err = io_stat(np->nn->port, &np->nn_stat); - - if(S_ISDIR(np->nn_stat.st_mode)) - LOG_MSG("\tIs a directory"); - - /*If stat information has been successfully obtained for the file*/ - if(!err) - /*duplicate the st_mode field of stat structure*/ - np->nn_translated = np->nn_stat.st_mode; - } - else - { - /*We, most probably, have something which is not a directory. Therefore - we will open the port and close it after the stat, so that additional - resources are not consumed.*/ - - /*the parent node of the current node*/ - node_t * dnp; - - /*obtain the parent node of the the current node*/ - err = ncache_node_lookup(np->nn->lnode->dir, &dnp); - - /*the lookup should never fail here*/ - assert(!err); - - /*open a port to the file we are interested in*/ - mach_port_t p = file_name_lookup_under - (dnp->nn->port, np->nn->lnode->name, 0, 0); - - /*put `dnp` back, since we don't need it any more*/ - netfs_nput(dnp); - - if(!p) - return EBADF; - - /*try to stat the node*/ - err = io_stat(p, &np->nn_stat); - - /*deallocate the port*/ - PORT_DEALLOC(p); - } - } - } - /*If we are at the root*/ - else - /*put the size of the node into the stat structure belonging to `np`*/ - node_get_size(np, (OFFSET_T *)&np->nn_stat.st_size); + /*If no errors have yet occurred */ + if (!err) + { + /*If the port to the file corresponding to `np` is valid */ + if (np->nn->port != MACH_PORT_NULL) + { + /*We have a directory here (normally, only they maintain an open port). + Generally, our only concern is to maintain an open port in this case */ - /*Return the result of operations*/ - return err; - }/*netfs_validate_stat*/ -/*----------------------------------------------------------------------------*/ + /*attempt to stat this file */ + err = io_stat (np->nn->port, &np->nn_stat); + + if (S_ISDIR (np->nn_stat.st_mode)) + LOG_MSG ("\tIs a directory"); + + /*If stat information has been successfully obtained for the file */ + if (!err) + /*duplicate the st_mode field of stat structure */ + np->nn_translated = np->nn_stat.st_mode; + } + else + { + /*We, most probably, have something which is not a directory. Therefore + we will open the port and close it after the stat, so that additional + resources are not consumed. */ + + /*the parent node of the current node */ + node_t *dnp; + + /*obtain the parent node of the the current node */ + err = ncache_node_lookup (np->nn->lnode->dir, &dnp); + + /*the lookup should never fail here */ + assert (!err); + + /*open a port to the file we are interested in */ + mach_port_t p = file_name_lookup_under + (dnp->nn->port, np->nn->lnode->name, 0, 0); + + /*put `dnp` back, since we don't need it any more */ + netfs_nput (dnp); + + if (!p) + return EBADF; + + /*try to stat the node */ + err = io_stat (p, &np->nn_stat); + + /*deallocate the port */ + PORT_DEALLOC (p); + } + } + } + /*If we are at the root */ + else + /*put the size of the node into the stat structure belonging to `np` */ + node_get_size (np, (OFFSET_T *) & np->nn_stat.st_size); + + /*Return the result of operations */ + return err; +} /*netfs_validate_stat */ + +/*---------------------------------------------------------------------------*/ /*Syncs `node` completely to disk*/ error_t -netfs_attempt_sync - ( - struct iouser * cred, - struct node * node, - int wait - ) - { - LOG_MSG("netfs_attempt_sync"); + netfs_attempt_sync (struct iouser * cred, struct node * node, int wait) +{ + LOG_MSG ("netfs_attempt_sync"); + + /*Operation is not supported */ + return EOPNOTSUPP; +} /*netfs_attempt_sync */ - /*Operation is not supported*/ - return EOPNOTSUPP; - }/*netfs_attempt_sync*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Fetches a directory*/ error_t -netfs_get_dirents - ( - struct iouser * cred, - struct node * dir, - int first_entry, - int num_entries, - char ** data, - mach_msg_type_number_t * data_len, - vm_size_t max_data_len, - int * data_entries - ) - { - LOG_MSG("netfs_get_dirents: '%s'", dir->nn->lnode->name); - - error_t err; - - /*Two pointers required for processing the list of dirents*/ - node_dirent_t * dirent_start, * dirent_current; - - /*The pointer to the beginning of the list of dirents*/ - node_dirent_t * dirent_list = NULL; - - /*The size of the current dirent*/ - size_t size = 0; - - /*The number of dirents added*/ - int count = 0; - - /*The dereferenced value of parameter `data`*/ - char * data_p; - - /*Takes into account the size of the given dirent*/ - int - bump_size - ( - const char * name - ) - { - /*If the required number of entries has not been listed yet*/ - if((num_entries == -1) || (count < num_entries)) - { - /*take the current size and take into account the length of the name*/ - size_t new_size = size + DIRENT_LEN(strlen(name)); - - /*If there is a limit for the received size and it has been exceeded*/ - if((max_data_len > 0) && (new_size > max_data_len)) - /*a new dirent cannot be added*/ - return 0; - - /*memorize the new size*/ - size = new_size; - - /*increase the number of dirents added*/ - ++count; - - /*everything is OK*/ - return 1; - } - else - { - /*dirents cannot be added*/ - return 0; - } - }/*bump_size*/ - - /*Adds a dirent to the list of dirents*/ - int - add_dirent - ( - const char * name, - ino_t ino, - int type - ) - { - /*If the required number of dirents has not been listed yet*/ - if((num_entries == -1) || (count < num_entries)) - { - /*create a new dirent*/ - struct dirent hdr; - - /*obtain the length of the name*/ - size_t name_len = strlen(name); - - /*compute the full size of the dirent*/ - size_t sz = DIRENT_LEN(name_len); - - /*If there is no room for this dirent*/ - if(sz > size) - /*stop*/ - return 0; - else - /*take into account the fact that a new dirent has just been added*/ - size -= sz; - - /*setup the dirent*/ - hdr.d_ino = ino; - hdr.d_reclen = sz; - hdr.d_type = type; - hdr.d_namlen = name_len; - - /*The following two lines of code reflect the old layout of - dirents in the memory. Now libnetfs expects the layout - identical to the layout provided by dir_readdir (see dir_entries_get)*/ - - /*copy the header of the dirent into the final block of dirents*/ - memcpy(data_p, &hdr, DIRENT_NAME_OFFS); - - /*copy the name of the dirent into the block of dirents*/ - strcpy(data_p + DIRENT_NAME_OFFS, name); - - /*This line is commented for the same reason as the two specifically - commented lines above.*/ - /*move the current pointer in the block of dirents*/ - data_p += sz; - - /*count the new dirent*/ - ++count; - - /*everything was OK, so say it*/ - return 1; - } - else - /*no [new] dirents allowed*/ - return 0; - }/*add_dirent*/ - - /*List the dirents for node `dir`*/ - err = node_entries_get(dir, &dirent_list); - - /*If listing was successful*/ - if(!err) - { - /*find the entry whose number is `first_entry`*/ - for - ( - dirent_start = dirent_list, count = 2; - dirent_start && (count < first_entry); - dirent_start = dirent_start->next, ++count - ); - - /*reset number of dirents added so far*/ - count = 0; - - /*make space for entries '.' and '..', if required*/ - if(first_entry == 0) - bump_size("."); - if(first_entry <= 1) - bump_size(".."); - - /*Go through all dirents*/ - for - ( - dirent_current = dirent_start; - dirent_current; - dirent_current = dirent_current->next - ) - /*If another dirent cannot be added succesfully*/ - if(bump_size(dirent_current->dirent->d_name) == 0) - /*stop here*/ - break; - - /*allocate the required space for dirents*/ - *data = mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANON, 0, 0); - - /*check if any error occurred*/ - err = ((void *)*data == MAP_FAILED) ? (errno) : (0); - } - - /*If no errors have occurred so far*/ - if(!err) - { - /*obtain the pointer to the beginning of the block of dirents*/ - data_p = *data; - - /*fill the parameters with useful values*/ - *data_len = size; - *data_entries = count; - - /*reset the number of dirents added*/ - count = 0; - - /*add entries '.' and '..', if required*/ - if(first_entry == 0) - add_dirent(".", 2, DT_DIR); - if(first_entry <= 1) - add_dirent("..", 2, DT_DIR); - - /*Follow the list of dirents beginning with dirents_start*/ - for - ( - dirent_current = dirent_start; dirent_current; - dirent_current = dirent_current->next - ) - /*If the addition of the current dirent fails*/ - if - ( - add_dirent - (dirent_current->dirent->d_name, dirent_current->dirent->d_fileno, - dirent_current->dirent->d_type) == 0 - ) - /*stop adding dirents*/ - break; - } - - /*If the list of dirents has been allocated, free it*/ - if(dirent_list) - node_entries_free(dirent_list); - - /*The directory has been read right now, modify the access time*/ - fshelp_touch(&dir->nn_stat, TOUCH_ATIME, maptime); - - /*Return the result of listing the dirents*/ - return err; - }/*netfs_get_dirents*/ -/*----------------------------------------------------------------------------*/ + netfs_get_dirents + (struct iouser * cred, + struct node * dir, + int first_entry, + int num_entries, + char **data, + mach_msg_type_number_t * data_len, + vm_size_t max_data_len, int *data_entries) +{ + LOG_MSG ("netfs_get_dirents: '%s'", dir->nn->lnode->name); + + error_t err; + + /*Two pointers required for processing the list of dirents */ + node_dirent_t *dirent_start, *dirent_current; + + /*The pointer to the beginning of the list of dirents */ + node_dirent_t *dirent_list = NULL; + + /*The size of the current dirent */ + size_t size = 0; + + /*The number of dirents added */ + int count = 0; + + /*The dereferenced value of parameter `data` */ + char *data_p; + + /*Takes into account the size of the given dirent */ + int bump_size (const char *name) + { + /*If the required number of entries has not been listed yet */ + if ((num_entries == -1) || (count < num_entries)) + { + /*take the current size and take into account the length of the name */ + size_t new_size = size + DIRENT_LEN (strlen (name)); + + /*If there is a limit for the received size and it has been exceeded */ + if ((max_data_len > 0) && (new_size > max_data_len)) + /*a new dirent cannot be added */ + return 0; + + /*memorize the new size */ + size = new_size; + + /*increase the number of dirents added */ + ++count; + + /*everything is OK */ + return 1; + } + else + { + /*dirents cannot be added */ + return 0; + } + } /*bump_size */ + + /*Adds a dirent to the list of dirents */ + int add_dirent (const char *name, ino_t ino, int type) + { + /*If the required number of dirents has not been listed yet */ + if ((num_entries == -1) || (count < num_entries)) + { + /*create a new dirent */ + struct dirent hdr; + + /*obtain the length of the name */ + size_t name_len = strlen (name); + + /*compute the full size of the dirent */ + size_t sz = DIRENT_LEN (name_len); + + /*If there is no room for this dirent */ + if (sz > size) + /*stop */ + return 0; + else + /*take into account the fact that a new dirent has just been added */ + size -= sz; + + /*setup the dirent */ + hdr.d_ino = ino; + hdr.d_reclen = sz; + hdr.d_type = type; + hdr.d_namlen = name_len; + + /*The following two lines of code reflect the old layout of + dirents in the memory. Now libnetfs expects the layout + identical to the layout provided by dir_readdir + see dir_entries_get) */ + + /*copy the header of the dirent into the final block of dirents */ + memcpy (data_p, &hdr, DIRENT_NAME_OFFS); + + /*copy the name of the dirent into the block of dirents */ + strcpy (data_p + DIRENT_NAME_OFFS, name); + + /*This line is commented for the same reason as the two specifically + commented lines above. */ + /*move the current pointer in the block of dirents */ + data_p += sz; + + /*count the new dirent */ + ++count; + + /*everything was OK, so say it */ + return 1; + } + else + /*no [new] dirents allowed */ + return 0; + } /*add_dirent */ + + /*List the dirents for node `dir` */ + err = node_entries_get (dir, &dirent_list); + + /*If listing was successful */ + if (!err) + { + /*find the entry whose number is `first_entry` */ + for + (dirent_start = dirent_list, count = 2; + dirent_start && (count < first_entry); + dirent_start = dirent_start->next, ++count); + + /*reset number of dirents added so far */ + count = 0; + + /*make space for entries '.' and '..', if required */ + if (first_entry == 0) + bump_size ("."); + if (first_entry <= 1) + bump_size (".."); + + /*Go through all dirents */ + for + (dirent_current = dirent_start; + dirent_current; dirent_current = dirent_current->next) + /*If another dirent cannot be added succesfully */ + if (bump_size (dirent_current->dirent->d_name) == 0) + /*stop here */ + break; + + /*allocate the required space for dirents */ + *data = mmap (0, size, PROT_READ | PROT_WRITE, MAP_ANON, 0, 0); + + /*check if any error occurred */ + err = ((void *) *data == MAP_FAILED) ? (errno) : (0); + } + + /*If no errors have occurred so far */ + if (!err) + { + /*obtain the pointer to the beginning of the block of dirents */ + data_p = *data; + + /*fill the parameters with useful values */ + *data_len = size; + *data_entries = count; + + /*reset the number of dirents added */ + count = 0; + + /*add entries '.' and '..', if required */ + if (first_entry == 0) + add_dirent (".", 2, DT_DIR); + if (first_entry <= 1) + add_dirent ("..", 2, DT_DIR); + + /*Follow the list of dirents beginning with dirents_start */ + for + (dirent_current = dirent_start; dirent_current; + dirent_current = dirent_current->next) + /*If the addition of the current dirent fails */ + if (add_dirent + (dirent_current->dirent->d_name, dirent_current->dirent->d_fileno, + dirent_current->dirent->d_type) == 0) + /*stop adding dirents */ + break; + } + + /*If the list of dirents has been allocated, free it */ + if (dirent_list) + node_entries_free (dirent_list); + + /*The directory has been read right now, modify the access time */ + fshelp_touch (&dir->nn_stat, TOUCH_ATIME, maptime); + + /*Return the result of listing the dirents */ + return err; +} /*netfs_get_dirents */ + +/*---------------------------------------------------------------------------*/ /*Looks up `name` under `dir` for `user`*/ error_t -netfs_attempt_lookup - ( - struct iouser * user, - struct node * dir, - char * name, - struct node ** node - ) - { - LOG_MSG("netfs_attempt_lookup"); - - /*We should never get here. In any case, we do not want to do this type - of lookup, netfs_attempt_lookup_improved is what we want*/ - return EOPNOTSUPP; - }/*netfs_attempt_lookup*/ -/*----------------------------------------------------------------------------*/ -/*Performs an advanced lookup of file `name` under `dir`. If the lookup of the - last component of the path is requested (`lastcomp` is 1), it is not a - directory and no translators are required (`name` does not contain ',,'), the - function will simply open the required file and return the port in `file`. In - other cases it will create a proxy node and return it in `node`.*/ + netfs_attempt_lookup + (struct iouser * user, struct node * dir, char *name, struct node ** node) +{ + LOG_MSG ("netfs_attempt_lookup"); + + /*We should never get here. In any case, we do not want to do this type + of lookup, netfs_attempt_lookup_improved is what we want */ + return EOPNOTSUPP; +} /*netfs_attempt_lookup */ + +/*---------------------------------------------------------------------------*/ +/*Performs an advanced lookup of file `name` under `dir`. If the + lookup of the last component of the path is requested (`lastcomp` is + 1), it is not a directory and no translators are required (`name` + does not contain ',,' ), the function will simply open the required + file and return the port in `file`. In other cases it will create a + proxy node and return it in `node`.*/ error_t -netfs_attempt_lookup_improved - ( - struct iouser * user, - struct node * dir, - char * name, - int flags, - int lastcomp, - node_t ** node, - file_t * file - ) + netfs_attempt_lookup_improved + (struct iouser * user, + struct node * dir, + char *name, int flags, int lastcomp, node_t ** node, file_t * file) +{ + LOG_MSG ("netfs_attempt_lookup_improved: '%s'", name); + + error_t err = 0; + + /*If we are asked to fetch the current directory */ + if (strcmp (name, ".") == 0) + { + /*validate the stat information for `dir` */ + err = netfs_validate_stat (dir, user); + if (err) { - LOG_MSG("netfs_attempt_lookup_improved: '%s'", name); + mutex_unlock (&dir->lock); + return err; + } - error_t err = 0; - - /*If we are asked to fetch the current directory*/ - if(strcmp(name, ".") == 0) - { - /*validate the stat information for `dir`*/ - err = netfs_validate_stat(dir, user); - if(err) - { - mutex_unlock(&dir->lock); - return err; - } - - /*If `dir` is not a directory, actually*/ - if(!S_ISDIR(dir->nn_stat.st_mode)) - { - /*unlock the directory and stop right here*/ - mutex_unlock(&dir->lock); - return ENOTDIR; - } - - /*add a reference to `dir` and put it into `node`*/ - netfs_nref(dir); - *node = dir; - - /*everything is OK*/ - return 0; - } - /*If we are asked to fetch the parent directory*/ - else if(strcmp(name, "..") == 0) - { - /*validate the stat information for `dir`*/ - err = netfs_validate_stat(dir, user); - if(err) - { - mutex_unlock(&dir->lock); - return err; - } - - /*If `dir` is not a directory, actually*/ - if(!S_ISDIR(dir->nn_stat.st_mode)) - { - /*unlock the directory and stop right here*/ - mutex_unlock(&dir->lock); - return ENOTDIR; - } - - /*If the supplied node is not root*/ - if(dir->nn->lnode->dir) - { - /*The node corresponding to the parent directory must exist here*/ - assert(dir->nn->lnode->dir->node); - - /*put the parent node of `dir` into the result*/ - err = ncache_node_lookup(dir->nn->lnode->dir, node); - } - /*The supplied node is root*/ - else - { - /*this node is not included into our filesystem*/ - err = ENOENT; - *node = NULL; - } - - /*unlock the directory*/ - mutex_unlock(&dir->lock); - - /*stop here*/ - return err; - } + /*If `dir` is not a directory, actually */ + if (!S_ISDIR (dir->nn_stat.st_mode)) + { + /*unlock the directory and stop right here */ + mutex_unlock (&dir->lock); + return ENOTDIR; + } - /*The port to the requested file*/ - mach_port_t p; - - /*The port to the untranslated version of the requested file*/ - mach_port_t p_notrans; - - /*The lnode corresponding to the entry we are supposed to fetch*/ - lnode_t * lnode; - - /*The position of ',,' in the name*/ - char * sep; - - /*A pointer for various operations on strings*/ - char * str; - - /*A list of translators*/ - char * trans = NULL; - - /*The number of translators in the list*/ - size_t ntrans; - - /*The length of the list of translators*/ - size_t translen; - - /*Is the looked up file a directory*/ - int isdir; - - /*Finalizes the execution of this function*/ - void - finalize(void) - { - /*Free the list of translators, if it has been allocated*/ - if(trans) - free(trans); - - /*If some errors have occurred*/ - if(err) - { - /*the user should receive nothing*/ - *node = NULL; - - /*If there is some port, free it*/ - if(p != MACH_PORT_NULL) - PORT_DEALLOC(p); - if(p_notrans != MACH_PORT_NULL) - PORT_DEALLOC(p_notrans); - } - /*If there is a node to return*/ - if(*node) - { - /*unlock the node*/ - mutex_unlock(&(*node)->lock); - - /*add the node to the cache*/ - ncache_node_add(*node); - } - - /*Unlock the mutexes in `dir`*/ - mutex_unlock(&dir->nn->lnode->lock); - mutex_unlock(&dir->lock); - }/*finalize*/ - - /*Performs a usual lookup*/ - error_t - lookup - ( - char * name, /*lookup this*/ - int flags, /*lookup `name` in the this way*/ - int proxy /*should a proxy node be created*/ - ) - { - /*Try to lookup the given file in the underlying directory*/ - p = file_name_lookup_under(dir->nn->port, name, 0, 0); - - /*If the lookup failed*/ - if(p == MACH_PORT_NULL) - /*no such entry*/ - return ENOENT; - - /*Obtain the stat information about the file*/ - io_statbuf_t stat; - err = io_stat(p, &stat); - - /*Deallocate the obtained port*/ - PORT_DEALLOC(p); - - /*If this file is not a directory*/ - if(err || !S_ISDIR(stat.st_mode)) - { - /*lookup the required file with the supplied flags*/ - p = file_name_lookup_under(dir->nn->port, name, flags, 0); - if(p == MACH_PORT_NULL) - return EBADF; - - /*obtain the untranslated version of the file, too (for filters)*/ - p_notrans = file_name_lookup_under - (dir->nn->port, name, O_NOTRANS, 0); - if(p_notrans == MACH_PORT_NULL) - return EBADF; - - /*remember we do not have a directory*/ - isdir = 0; - - /*If a proxy node is not required*/ - if(!proxy) - /*stop here, we want only the port to the file*/ - return 0; - } - else - { - /*lookup the port with the right to read the contents of the directory*/ - p = file_name_lookup_under - (dir->nn->port, name, flags | O_READ | O_DIRECTORY, 0); - if(p == MACH_PORT_NULL) - return EBADF; /*not enough rights?*/ - - /*obtain the untranslated version of the file, too (for filters)*/ - p_notrans = file_name_lookup_under - (dir->nn->port, name, O_NOTRANS, 0); - if(p_notrans == MACH_PORT_NULL) - return EBADF; - - /*we have a directory here*/ - isdir = 1; - } - - /*Try to find an lnode called `name` under the lnode corresponding to `dir`*/ - err = lnode_get(dir->nn->lnode, name, &lnode); - - /*If such an entry does not exist*/ - if(err == ENOENT) - { - /*create a new lnode with the supplied name*/ - err = lnode_create(name, &lnode); - if(err) - { - finalize(); - return err; - } - - /*install the new lnode into the directory*/ - lnode_install(dir->nn->lnode, lnode); - } - - /*If we are to create a proxy node*/ - if(proxy) - /*create a proxy node from the given lnode*/ - err = node_create_proxy(lnode, node); - /*If we don't need proxy nodes in this lookup*/ - else - { - /*obtain the node corresponding to this lnode*/ - err = ncache_node_lookup(lnode, node); - - /*remove an extra reference from the lnode*/ - lnode_ref_remove(lnode); - } - - /*If either the lookup in the cache or the creation of a proxy failed*/ - if(err) - { - /*stop*/ - mutex_unlock(&lnode->lock); - finalize(); - return err; - } - - /*Store the ports in the node*/ - (*node)->nn->port = p; - (*node)->nn->port_notrans = p_notrans; - - /*Fill in the flag about the node being a directory*/ - if(isdir) - lnode->flags |= FLAG_LNODE_DIR; - else - lnode->flags &= ~FLAG_LNODE_DIR; - - /*Construct the full path to the node*/ - err = lnode_path_construct(lnode, NULL); - if(err) - { - mutex_unlock(&lnode->lock); - finalize(); - return err; - } - - /*Unlock the lnode*/ - mutex_unlock(&lnode->lock); - - /*Now the node is up-to-date*/ - (*node)->nn->flags = FLAG_NODE_ULFS_UPTODATE; - - /*Everything OK here*/ - return 0; - }/*lookup*/ - - /*While pairs of commas can still be found in the name*/ - for(sep = strstr(name, ",,"); sep; sep = strstr(sep, ",,")) - { - /*If the separator is situated at the beginning, it is an error*/ - if(sep == name) - { - finalize(); - return ENOENT; - } - - /*If current pair of commas is not escaped*/ - if(*(sep + 2) != ',') - /*stop here, we've found what we needed*/ - break; - - /*remove the escaping ',' from the string*/ - for(str = ++sep; *str; str[-1] = *str, ++str); - str[-1] = 0; - - /*skip the current pair of commas*/ - ++sep; - } - - /*If the control sequence has been found*/ - if(sep) + /*add a reference to `dir` and put it into `node` */ + netfs_nref (dir); + *node = dir; + + /*everything is OK */ + return 0; + } + /*If we are asked to fetch the parent directory */ + else if (strcmp (name, "..") == 0) + { + /*validate the stat information for `dir` */ + err = netfs_validate_stat (dir, user); + if (err) + { + mutex_unlock (&dir->lock); + return err; + } + + /*If `dir` is not a directory, actually */ + if (!S_ISDIR (dir->nn_stat.st_mode)) + { + /*unlock the directory and stop right here */ + mutex_unlock (&dir->lock); + return ENOTDIR; + } + + /*If the supplied node is not root */ + if (dir->nn->lnode->dir) + { + /*The node corresponding to the parent directory must exist here */ + assert (dir->nn->lnode->dir->node); + + /*put the parent node of `dir` into the result */ + err = ncache_node_lookup (dir->nn->lnode->dir, node); + } + /*The supplied node is root */ + else + { + /*this node is not included into our filesystem */ + err = ENOENT; + *node = NULL; + } + + /*unlock the directory */ + mutex_unlock (&dir->lock); + + /*stop here */ + return err; + } + + /*The port to the requested file */ + mach_port_t p; + + /*The port to the untranslated version of the requested file */ + mach_port_t p_notrans; + + /*The lnode corresponding to the entry we are supposed to fetch */ + lnode_t *lnode; + + /*The position of ',,' in the name */ + char *sep; + + /*A pointer for various operations on strings */ + char *str; + + /*A list of translators */ + char *trans = NULL; + + /*The number of translators in the list */ + size_t ntrans; + + /*The length of the list of translators */ + size_t translen; + + /*Is the looked up file a directory */ + int isdir; + + /*Finalizes the execution of this function */ + void finalize (void) + { + /*Free the list of translators, if it has been allocated */ + if (trans) + free (trans); + + /*If some errors have occurred */ + if (err) + { + /*the user should receive nothing */ + *node = NULL; + + /*If there is some port, free it */ + if (p != MACH_PORT_NULL) + PORT_DEALLOC (p); + if (p_notrans != MACH_PORT_NULL) + PORT_DEALLOC (p_notrans); + } + /*If there is a node to return */ + if (*node) + { + /*unlock the node */ + mutex_unlock (&(*node)->lock); + + /*add the node to the cache */ + ncache_node_add (*node); + } + + /*Unlock the mutexes in `dir` */ + mutex_unlock (&dir->nn->lnode->lock); + mutex_unlock (&dir->lock); + } /*finalize */ + + /*Performs a usual lookup */ + error_t lookup (char *name, /*lookup this */ + int flags, /*lookup `name` in the this way */ + int proxy /*should a proxy node be created */ + ) + { + /*Try to lookup the given file in the underlying directory */ + p = file_name_lookup_under (dir->nn->port, name, 0, 0); + + /*If the lookup failed */ + if (p == MACH_PORT_NULL) + /*no such entry */ + return ENOENT; + + /*Obtain the stat information about the file */ + io_statbuf_t stat; + err = io_stat (p, &stat); + + /*Deallocate the obtained port */ + PORT_DEALLOC (p); + + /*If this file is not a directory */ + if (err || !S_ISDIR (stat.st_mode)) + { + /*lookup the required file with the supplied flags */ + p = file_name_lookup_under (dir->nn->port, name, flags, 0); + if (p == MACH_PORT_NULL) + return EBADF; + + /*obtain the untranslated version of the file, too (for filters) */ + p_notrans = file_name_lookup_under + (dir->nn->port, name, O_NOTRANS, 0); + if (p_notrans == MACH_PORT_NULL) + return EBADF; + + /*remember we do not have a directory */ + isdir = 0; + + /*If a proxy node is not required */ + if (!proxy) + /*stop here, we want only the port to the file */ + return 0; + } + else + { + /*lookup the port with the right to read the contents of the + directory */ + p = file_name_lookup_under + (dir->nn->port, name, flags | O_READ | O_DIRECTORY, 0); + if (p == MACH_PORT_NULL) + return EBADF; /*not enough rights? */ + + /*obtain the untranslated version of the file, too (for filters) */ + p_notrans = file_name_lookup_under + (dir->nn->port, name, O_NOTRANS, 0); + if (p_notrans == MACH_PORT_NULL) + return EBADF; + + /*we have a directory here */ + isdir = 1; + } + + /*Try to find an lnode called `name` under the lnode corresponding + to `dir` */ + err = lnode_get (dir->nn->lnode, name, &lnode); + + /*If such an entry does not exist */ + if (err == ENOENT) + { + /*create a new lnode with the supplied name */ + err = lnode_create (name, &lnode); + if (err) + { + finalize (); + return err; + } + + /*install the new lnode into the directory */ + lnode_install (dir->nn->lnode, lnode); + } + + /*If we are to create a proxy node */ + if (proxy) + /*create a proxy node from the given lnode */ + err = node_create_proxy (lnode, node); + /*If we don't need proxy nodes in this lookup */ + else + { + /*obtain the node corresponding to this lnode */ + err = ncache_node_lookup (lnode, node); + + /*remove an extra reference from the lnode */ + lnode_ref_remove (lnode); + } + + /*If either the lookup in the cache or the creation of a proxy failed */ + if (err) + { + /*stop */ + mutex_unlock (&lnode->lock); + finalize (); + return err; + } + + /*Store the ports in the node */ + (*node)->nn->port = p; + (*node)->nn->port_notrans = p_notrans; + + /*Fill in the flag about the node being a directory */ + if (isdir) + lnode->flags |= FLAG_LNODE_DIR; + else + lnode->flags &= ~FLAG_LNODE_DIR; + + /*Construct the full path to the node */ + err = lnode_path_construct (lnode, NULL); + if (err) + { + mutex_unlock (&lnode->lock); + finalize (); + return err; + } + + /*Unlock the lnode */ + mutex_unlock (&lnode->lock); + + /*Now the node is up-to-date */ + (*node)->nn->flags = FLAG_NODE_ULFS_UPTODATE; + + /*Everything OK here */ + return 0; + } /*lookup */ + + /*While pairs of commas can still be found in the name */ + for (sep = strstr (name, ",,"); sep; sep = strstr (sep, ",,")) + { + /*If the separator is situated at the beginning, it is an error */ + if (sep == name) + { + finalize (); + return ENOENT; + } + + /*If current pair of commas is not escaped */ + if (*(sep + 2) != ',') + /*stop here, we've found what we needed */ + break; + + /*remove the escaping ',' from the string */ + for (str = ++sep; *str; str[-1] = *str, ++str); + str[-1] = 0; + + /*skip the current pair of commas */ + ++sep; + } + + /*If the control sequence has been found */ + if (sep) + { + /*the name of the file to lookup */ + char *name_cpy; + + /*copy the name */ + /*just copy the pointer */ + name_cpy = /*strdup */ (name); + if (!name_cpy) + { + err = ENOMEM; + finalize (); + return err; + } + + /*move sep to name_cpy */ + sep = name_cpy + (sep - name); + + /*remove the separator from the string */ + *(sep++) = 0; + *(sep++) = 0; + + /*try to lookup the file with the specified name and create a proxy + node for it (since we need to start translators) */ + err = lookup (name_cpy, flags, 1); + + /*If the lookup failed */ + if (err) + { + /*say that the file has not been found */ + finalize (); + return ENOENT; + } + + /*duplicate the part of the name containing the list of translators + and store the copy in the lnode */ + trans = strdup (sep); + if (!trans) + { + finalize (); + return err; + } + + /*obtain a pointer to the beginning of the list of translators */ + str = trans; + + /*a pointer for removal of extra commas */ + char *p; + + /*Go through the list of translators */ + for (translen = ntrans = 0; *str; ++str) + { + /*If the current character is a comma */ + if (*str == ',') + { + /*While the next characters are commas, too */ + for (; str[1] == ',';) { - /*the name of the file to lookup*/ - char * name_cpy; - - /*copy the name*/ - /*just copy the pointer*/ - name_cpy = /*strdup*/(name); - if(!name_cpy) - { - err = ENOMEM; - finalize(); - return err; - } - - /*move sep to name_cpy*/ - sep = name_cpy + (sep - name); - - /*remove the separator from the string*/ - *(sep++) = 0; - *(sep++) = 0; - - /*try to lookup the file with the specified name and create a proxy - node for it (since we need to start translators)*/ - err = lookup(name_cpy, flags, 1); - - /*If the lookup failed*/ - if(err) - { - /*say that the file has not been found*/ - finalize(); - return ENOENT; - } - - /*duplicate the part of the name containing the list of translators - and store the copy in the lnode*/ - trans = strdup(sep); - if(!trans) - { - finalize(); - return err; - } - - /*obtain a pointer to the beginning of the list of translators*/ - str = trans; - - /*a pointer for removal of extra commas*/ - char * p; - - /*Go through the list of translators*/ - for(translen = ntrans = 0; *str; ++str) - { - /*If the current character is a comma*/ - if(*str == ',') - { - /*While the next characters are commas, too*/ - for(; str[1] == ',';) - { - /*shift the string leftwards*/ - for(p = str + 1; *p; p[-1] = *p, ++p); - p[-1] = 0; - } - - /*If the next character is the terminal 0*/ - if(!str[1]) - { - /*this comma is extra*/ - *str = 0; - break; - } - - /*make it a separator zero*/ - *str = 0; - - /*we have just finished going through a new component*/ - ++ntrans; - } - - /*take the current character into account*/ - ++translen; - } - - /*take into consideration the last element in the list, - which does not end in a comma and the corresponding terminal 0*/ - ++ntrans; - ++translen; - - /*copy the list of translators we have just built in the new proxy node*/ - (*node)->nn->trans = trans; - (*node)->nn->ntrans = ntrans; - (*node)->nn->translen = translen; - - /*we don't own the list of translators any more*/ - trans = NULL; - ntrans = 0; - translen = 0; + /*shift the string leftwards */ + for (p = str + 1; *p; p[-1] = *p, ++p); + p[-1] = 0; } - /*The control sequence ',,' has not been found*/ - else + + /*If the next character is the terminal 0 */ + if (!str[1]) { - /*simply lookup the provided name, without creating the proxy, if not - necessary (i.e. when the file is not a directory)*/ - err = lookup(name, flags, 0); - if(err) - { - finalize(); - return err; - } - - /*if we have looked up a regular file, store the port to it in *`file`*/ - if(!isdir) - *file = p; + /*this comma is extra */ + *str = 0; + break; } - - /*Everything OK here*/ - finalize(); - return err; - }/*netfs_attempt_lookup_improved*/ -/*----------------------------------------------------------------------------*/ + + /*make it a separator zero */ + *str = 0; + + /*we have just finished going through a new component */ + ++ntrans; + } + + /*take the current character into account */ + ++translen; + } + + /*take into consideration the last element in the list, + which does not end in a comma and the corresponding terminal 0 */ + ++ntrans; + ++translen; + + /*copy the list of translators we have just built in the new + proxy node */ + (*node)->nn->trans = trans; + (*node)->nn->ntrans = ntrans; + (*node)->nn->translen = translen; + + /*we don't own the list of translators any more */ + trans = NULL; + ntrans = 0; + translen = 0; + } + /*The control sequence ',,' has not been found */ + else + { + /*simply lookup the provided name, without creating the proxy, if not + necessary (i.e. when the file is not a directory) */ + err = lookup (name, flags, 0); + if (err) + { + finalize (); + return err; + } + + /*if we have looked up a regular file, store the port to it in *`file` */ + if (!isdir) + *file = p; + } + + /*Everything OK here */ + finalize (); + return err; +} /*netfs_attempt_lookup_improved */ + +/*---------------------------------------------------------------------------*/ /*Responds to the RPC dir_lookup*/ error_t -netfs_S_dir_lookup - ( - struct protid * diruser, - char * filename, - int flags, - mode_t mode, - retry_type * do_retry, - char * retry_name, - mach_port_t * retry_port, - mach_msg_type_number_t * retry_port_type - ) - { - LOG_MSG("netfs_S_dir_lookup: '%s'", filename); + netfs_S_dir_lookup + (struct protid * diruser, + char *filename, + int flags, + mode_t mode, + retry_type * do_retry, + char *retry_name, + mach_port_t * retry_port, mach_msg_type_number_t * retry_port_type) +{ + LOG_MSG ("netfs_S_dir_lookup: '%s'", filename); int create; /* true if O_CREAT flag set */ int excl; /* true if O_EXCL flag set */ @@ -967,15 +911,15 @@ netfs_S_dir_lookup struct protid *newpi; struct iouser *user; - /*The port to the file for the case when we don't need proxy nodes*/ - file_t file = MACH_PORT_NULL; - - /*The port to the same file with restricted rights*/ - file_t file_restricted = MACH_PORT_NULL; + /*The port to the file for the case when we don't need proxy nodes */ + file_t file = MACH_PORT_NULL; - /*The stat information about the node pointed at by `file` (for the case - when not proxy nodes are to be created)*/ - io_statbuf_t stat; + /*The port to the same file with restricted rights */ + file_t file_restricted = MACH_PORT_NULL; + + /*The stat information about the node pointed at by `file` (for the case + when not proxy nodes are to be created) */ + io_statbuf_t stat; if (!diruser) return EOPNOTSUPP; @@ -1044,7 +988,7 @@ netfs_S_dir_lookup *do_retry = FS_RETRY_REAUTH; *retry_port = diruser->po->shadow_root_parent; *retry_port_type = MACH_MSG_TYPE_COPY_SEND; - if (! lastcomp) + if (!lastcomp) strcpy (retry_name, nextname); error = 0; mutex_unlock (&dnp->lock); @@ -1072,38 +1016,40 @@ netfs_S_dir_lookup netfs_nref (np); } else + { + /* Attempt a lookup on the next pathname component. */ + /*error = netfs_attempt_lookup (diruser->user, dnp, filename, &np); */ + + /*attempt an improved lookup on the next pathname component */ + error = netfs_attempt_lookup_improved + (diruser->user, dnp, filename, flags, lastcomp, &np, &file); + + /*If no problems have occurred during the lookup and we do + not have O_EXCL */ + if (!error && !excl) + { + /*If a simple file has been looked up */ + if (file) + /*just return the port */ + goto justport; + + /*If a proxy for setting up translators has just been created */ + if (np->nn->trans) { - /* Attempt a lookup on the next pathname component. */ - /*error = netfs_attempt_lookup (diruser->user, dnp, filename, &np);*/ - - /*attempt an improved lookup on the next pathname component*/ - error = netfs_attempt_lookup_improved - (diruser->user, dnp, filename, flags, lastcomp, &np, &file); - - /*If no problems have occurred during the lookup and we do not have O_EXCL*/ - if(!error && !excl) - { - /*If a simple file has been looked up*/ - if(file) - /*just return the port*/ - goto justport; - - /*If a proxy for setting up translators has just been created*/ - if(np->nn->trans) - { - /*set the list of translators on this node*/ - node_set_translators - (diruser, np, np->nn->trans, np->nn->ntrans, flags, &file); - - /*lock the the node and add a new reference*/ - mutex_lock(&np->lock); - netfs_nref(np); - - /*return `file` as the resulting port*/ - goto justport; - } - } + /*set the list of translators on this node */ + node_set_translators + (diruser, np, np->nn->trans, np->nn->ntrans, flags, + &file); + + /*lock the the node and add a new reference */ + mutex_lock (&np->lock); + netfs_nref (np); + + /*return `file` as the resulting port */ + goto justport; } + } + } /* At this point, DNP is unlocked */ @@ -1152,61 +1098,61 @@ netfs_S_dir_lookup /* A callback function for short-circuited translators. S_ISLNK and S_IFSOCK are handled elsewhere. */ error_t short_circuited_callback1 (void *cookie1, void *cookie2, - uid_t *uid, gid_t *gid, - char **argz, size_t *argz_len) - { - struct node *np = cookie1; - error_t err; - - err = netfs_validate_stat (np, diruser->user); - if (err) - return err; - - switch (np->nn_translated & S_IFMT) - { - case S_IFCHR: - case S_IFBLK: - if (asprintf (argz, "%s%c%d%c%d", - (S_ISCHR (np->nn_translated) - ? _HURD_CHRDEV : _HURD_BLKDEV), - 0, major (np->nn_stat.st_rdev), - 0, minor (np->nn_stat.st_rdev)) < 0) - return ENOMEM; - *argz_len = strlen (*argz) + 1; - *argz_len += strlen (*argz + *argz_len) + 1; - *argz_len += strlen (*argz + *argz_len) + 1; - break; - case S_IFIFO: - if (asprintf (argz, "%s", _HURD_FIFO) < 0) - return ENOMEM; - *argz_len = strlen (*argz) + 1; - break; - default: - return ENOENT; - } - - *uid = np->nn_stat.st_uid; - *gid = np->nn_stat.st_gid; - - return 0; - } + uid_t * uid, gid_t * gid, + char **argz, size_t * argz_len) + { + struct node *np = cookie1; + error_t err; + + err = netfs_validate_stat (np, diruser->user); + if (err) + return err; + + switch (np->nn_translated & S_IFMT) + { + case S_IFCHR: + case S_IFBLK: + if (asprintf (argz, "%s%c%d%c%d", + (S_ISCHR (np->nn_translated) + ? _HURD_CHRDEV : _HURD_BLKDEV), + 0, major (np->nn_stat.st_rdev), + 0, minor (np->nn_stat.st_rdev)) < 0) + return ENOMEM; + *argz_len = strlen (*argz) + 1; + *argz_len += strlen (*argz + *argz_len) + 1; + *argz_len += strlen (*argz + *argz_len) + 1; + break; + case S_IFIFO: + if (asprintf (argz, "%s", _HURD_FIFO) < 0) + return ENOMEM; + *argz_len = strlen (*argz) + 1; + break; + default: + return ENOENT; + } + + *uid = np->nn_stat.st_uid; + *gid = np->nn_stat.st_gid; + + return 0; + } /* Create an unauthenticated port for DNP, and then unlock it. */ error = iohelp_create_empty_iouser (&user); - if (! error) + if (!error) { newpi = netfs_make_protid (netfs_make_peropen (dnp, 0, diruser->po), user); - if (! newpi) - { + if (!newpi) + { error = errno; iohelp_free_iouser (user); } } - if (! error) + if (!error) { dirport = ports_get_send_right (newpi); ports_port_deref (newpi); @@ -1216,12 +1162,12 @@ netfs_S_dir_lookup diruser->user, lastcomp ? flags : 0, ((np->nn_translated & S_IPTRANS) - ? _netfs_translator_callback1 - : short_circuited_callback1), + ? _netfs_translator_callback1 + : short_circuited_callback1), _netfs_translator_callback2, do_retry, retry_name, retry_port); /* fetch_root copies DIRPORT for success, so we always should - deallocate our send right. */ + deallocate our send right. */ mach_port_deallocate (mach_task_self (), dirport); } @@ -1238,15 +1184,16 @@ netfs_S_dir_lookup return error; } - /* ENOENT means there was a hiccup, and the translator vanished - while NP was unlocked inside fshelp_fetch_root; continue as normal. */ + /* ENOENT means there was a hiccup, and the translator + vanished while NP was unlocked inside fshelp_fetch_root; + continue as normal. */ error = 0; } - if (S_ISLNK (np->nn_translated) - && (!lastcomp - || mustbedir /* "foo/" must see that foo points to a dir */ - || !(flags & (O_NOLINK|O_NOTRANS)))) + /* "foo/" must see that foo points to a dir */ + if (S_ISLNK (np->nn_translated) && (!lastcomp || mustbedir + || !(flags & + (O_NOLINK | O_NOTRANS)))) { size_t nextnamelen, newnamelen, linklen; char *linkbuf; @@ -1271,8 +1218,7 @@ netfs_S_dir_lookup if (nextname) { linkbuf[linklen] = '/'; - memcpy (linkbuf + linklen + 1, nextname, - nextnamelen - 1); + memcpy (linkbuf + linklen + 1, nextname, nextnamelen - 1); } linkbuf[nextnamelen + linklen] = '\0'; @@ -1291,7 +1237,7 @@ netfs_S_dir_lookup lastcomp = 0; /* Symlinks to nonexistent files aren't allowed to cause - creation, so clear the flag here. */ + creation, so clear the flag here. */ create = 0; } netfs_nput (np); @@ -1316,7 +1262,7 @@ netfs_S_dir_lookup while (filename && *filename); /* At this point, NP is the node to return. */ - gotit: +gotit: if (mustbedir) { @@ -1327,8 +1273,7 @@ netfs_S_dir_lookup goto out; } } - error = netfs_check_open_permissions (diruser->user, np, - flags, newnode); + error = netfs_check_open_permissions (diruser->user, np, flags, newnode); if (error) goto out; @@ -1340,7 +1285,7 @@ netfs_S_dir_lookup newpi = netfs_make_protid (netfs_make_peropen (np, flags, diruser->po), user); - if (! newpi) + if (!newpi) { iohelp_free_iouser (user); error = errno; @@ -1350,553 +1295,472 @@ netfs_S_dir_lookup *retry_port = ports_get_right (newpi); ports_port_deref (newpi); + goto out; + + /*At this point, we have to return `file` as the resulting port */ +justport: + /*If a directory is definitely wanted */ + if (mustbedir) + { + /*stat the looked up file */ + error = io_stat (file, &stat); + if (error) goto out; - /*At this point, we have to return `file` as the resulting port*/ - justport: - /*If a directory is definitely wanted*/ - if(mustbedir) - { - /*stat the looked up file*/ - error = io_stat(file, &stat); - if(error) - goto out; - - /*If the file is not a directory*/ - if(!S_ISDIR(stat.st_mode)) - { - /*this is an error; stop here*/ - error = ENOTDIR; - goto out; - } - - } - - /*Check the user's open permissions for the specified port*/ - error = check_open_permissions(diruser->user, &stat, file); - if(error) - goto out; - - /*Restrict the port to the rights of the user*/ - error = io_restrict_auth - ( - file, &file_restricted, - diruser->user->uids->ids, diruser->user->uids->num, - diruser->user->gids->ids, diruser->user->gids->num - ); - if(error) - goto out; - - /*Put the resulting port in the corresponding receiver parameter*/ - *retry_port = file_restricted; - *retry_port_type = MACH_MSG_TYPE_MOVE_SEND; - - out: - if(error && (file != MACH_PORT_NULL)) - PORT_DEALLOC(file); + /*If the file is not a directory */ + if (!S_ISDIR (stat.st_mode)) + { + /*this is an error; stop here */ + error = ENOTDIR; + goto out; + } + + } + + /*Check the user's open permissions for the specified port */ + error = check_open_permissions (diruser->user, &stat, file); + if (error) + goto out; + + /*Restrict the port to the rights of the user */ + error = io_restrict_auth + (file, &file_restricted, + diruser->user->uids->ids, diruser->user->uids->num, + diruser->user->gids->ids, diruser->user->gids->num); + if (error) + goto out; + + /*Put the resulting port in the corresponding receiver parameter */ + *retry_port = file_restricted; + *retry_port_type = MACH_MSG_TYPE_MOVE_SEND; + +out: + if (error && (file != MACH_PORT_NULL)) + PORT_DEALLOC (file); if (np) netfs_nput (np); if (dnp) netfs_nrele (dnp); return error; - }/*netfs_S_dir_lookup*/ -/*----------------------------------------------------------------------------*/ +} /*netfs_S_dir_lookup */ + +/*---------------------------------------------------------------------------*/ /*Deletes `name` in `dir` for `user`*/ error_t -netfs_attempt_unlink - ( - struct iouser * user, - struct node * dir, - char * name - ) - { - LOG_MSG("netfs_attempt_unlink"); + netfs_attempt_unlink (struct iouser * user, struct node * dir, char *name) +{ + LOG_MSG ("netfs_attempt_unlink"); - return 0; - }/*netfs_attempt_unlink*/ -/*----------------------------------------------------------------------------*/ + return 0; +} /*netfs_attempt_unlink */ + +/*---------------------------------------------------------------------------*/ /*Attempts to rename `fromdir`/`fromname` to `todir`/`toname`*/ error_t -netfs_attempt_rename - ( - struct iouser * user, - struct node * fromdir, - char * fromname, - struct node * todir, - char * toname, - int excl - ) - { - LOG_MSG("netfs_attempt_rename"); - - /*Operation not supported*/ - return EOPNOTSUPP; - }/*netfs_attempt_rename*/ -/*----------------------------------------------------------------------------*/ + netfs_attempt_rename + (struct iouser * user, + struct node * fromdir, + char *fromname, struct node * todir, char *toname, int excl) +{ + LOG_MSG ("netfs_attempt_rename"); + + /*Operation not supported */ + return EOPNOTSUPP; +} /*netfs_attempt_rename */ + +/*---------------------------------------------------------------------------*/ /*Attempts to create a new directory*/ error_t -netfs_attempt_mkdir - ( - struct iouser * user, - struct node * dir, - char * name, - mode_t mode - ) - { - LOG_MSG("netfs_attempt_mkdir"); + netfs_attempt_mkdir + (struct iouser * user, struct node * dir, char *name, mode_t mode) +{ + LOG_MSG ("netfs_attempt_mkdir"); - return 0; - }/*netfs_attempt_mkdir*/ -/*----------------------------------------------------------------------------*/ + return 0; +} /*netfs_attempt_mkdir */ + +/*---------------------------------------------------------------------------*/ /*Attempts to remove directory `name` in `dir` for `user`*/ error_t -netfs_attempt_rmdir - ( - struct iouser * user, - struct node * dir, - char * name - ) - { - LOG_MSG("netfs_attempt_rmdir"); + netfs_attempt_rmdir (struct iouser * user, struct node * dir, char *name) +{ + LOG_MSG ("netfs_attempt_rmdir"); - return 0; - }/*netfs_attempt_rmdir*/ -/*----------------------------------------------------------------------------*/ + return 0; +} /*netfs_attempt_rmdir */ + +/*---------------------------------------------------------------------------*/ /*Attempts to change the mode of `node` for user `cred` to `uid`:`gid`*/ error_t -netfs_attempt_chown - ( - struct iouser * cred, - struct node * node, - uid_t uid, - uid_t gid - ) - { - LOG_MSG("netfs_attempt_chown"); + netfs_attempt_chown + (struct iouser * cred, struct node * node, uid_t uid, uid_t gid) +{ + LOG_MSG ("netfs_attempt_chown"); + + /*Operation is not supported */ + return EOPNOTSUPP; +} /*netfs_attempt_chown */ - /*Operation is not supported*/ - return EOPNOTSUPP; - }/*netfs_attempt_chown*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Attempts to change the author of `node` to `author`*/ error_t -netfs_attempt_chauthor - ( - struct iouser * cred, - struct node * node, - uid_t author - ) - { - LOG_MSG("netfs_attempt_chauthor"); + netfs_attempt_chauthor + (struct iouser * cred, struct node * node, uid_t author) +{ + LOG_MSG ("netfs_attempt_chauthor"); - /*Operation is not supported*/ - return EOPNOTSUPP; - }/*netfs_attempt_chauthor*/ -/*----------------------------------------------------------------------------*/ + /*Operation is not supported */ + return EOPNOTSUPP; +} /*netfs_attempt_chauthor */ + +/*---------------------------------------------------------------------------*/ /*Attempts to change the mode of `node` to `mode` for `cred`*/ error_t -netfs_attempt_chmod - ( - struct iouser * user, - struct node * node, - mode_t mode - ) - { - LOG_MSG("netfs_attempt_chmod"); + netfs_attempt_chmod (struct iouser * user, struct node * node, mode_t mode) +{ + LOG_MSG ("netfs_attempt_chmod"); - /*Operation is not supported*/ - return EOPNOTSUPP; - }/*netfs_attempt_chmod*/ -/*----------------------------------------------------------------------------*/ + /*Operation is not supported */ + return EOPNOTSUPP; +} /*netfs_attempt_chmod */ + +/*---------------------------------------------------------------------------*/ /*Attempts to turn `node` into a symlink targetting `name`*/ error_t -netfs_attempt_mksymlink - ( - struct iouser * cred, - struct node * node, - char * name - ) - { - LOG_MSG("netfs_attempt_mksymlink"); - - /*Operation is not supported*/ - return EOPNOTSUPP; - }/*netfs_attempt_mksymlink*/ -/*----------------------------------------------------------------------------*/ -/*Attempts to turn `node` into a device; type can be either S_IFBLK or S_IFCHR*/ + netfs_attempt_mksymlink + (struct iouser * cred, struct node * node, char *name) +{ + LOG_MSG ("netfs_attempt_mksymlink"); + + /*Operation is not supported */ + return EOPNOTSUPP; +} /*netfs_attempt_mksymlink */ + +/*---------------------------------------------------------------------------*/ +/*Attempts to turn `node` into a device; type can be either S_IFBLK or + S_IFCHR*/ error_t -netfs_attempt_mkdev - ( - struct iouser * cred, - struct node * node, - mode_t type, - dev_t indexes - ) - { - LOG_MSG("netfs_attempt_mkdev"); + netfs_attempt_mkdev + (struct iouser * cred, struct node * node, mode_t type, dev_t indexes) +{ + LOG_MSG ("netfs_attempt_mkdev"); - /*Operation is not supported*/ - return EOPNOTSUPP; - }/*netfs_attempt_mkdev*/ -/*----------------------------------------------------------------------------*/ + /*Operation is not supported */ + return EOPNOTSUPP; +} /*netfs_attempt_mkdev */ + +/*---------------------------------------------------------------------------*/ /*Attempts to set the passive translator record for `file` passing `argz`*/ error_t -netfs_set_translator - ( - struct iouser * cred, - struct node * node, - char * argz, - size_t arglen - ) - { - LOG_MSG("netfs_set_translator"); + netfs_set_translator + (struct iouser * cred, struct node * node, char *argz, size_t arglen) +{ + LOG_MSG ("netfs_set_translator"); + + /*Operation is not supported */ + return EOPNOTSUPP; +} /*netfs_set_translator */ - /*Operation is not supported*/ - return EOPNOTSUPP; - }/*netfs_set_translator */ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Attempts to call chflags for `node`*/ error_t -netfs_attempt_chflags - ( - struct iouser * cred, - struct node * node, - int flags - ) - { - LOG_MSG("netfs_attempt_chflags"); + netfs_attempt_chflags (struct iouser * cred, struct node * node, int flags) +{ + LOG_MSG ("netfs_attempt_chflags"); + + /*Operation is not supported */ + return EOPNOTSUPP; +} /*netfs_attempt_chflags */ - /*Operation is not supported*/ - return EOPNOTSUPP; - }/*netfs_attempt_chflags*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Attempts to set the size of file `node`*/ error_t -netfs_attempt_set_size - ( - struct iouser * cred, - struct node * node, - loff_t size - ) - { - LOG_MSG("netfs_attempt_set_size"); + netfs_attempt_set_size + (struct iouser * cred, struct node * node, loff_t size) +{ + LOG_MSG ("netfs_attempt_set_size"); + + /*Operation is not supported */ + return EOPNOTSUPP; +} /*netfs_attempt_set_size */ - /*Operation is not supported*/ - return EOPNOTSUPP; - }/*netfs_attempt_set_size*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Fetches the filesystem status information*/ error_t -netfs_attempt_statfs - ( - struct iouser * cred, - struct node * node, - fsys_statfsbuf_t * st - ) - { - LOG_MSG("netfs_attempt_statfs"); + netfs_attempt_statfs + (struct iouser * cred, struct node * node, fsys_statfsbuf_t * st) +{ + LOG_MSG ("netfs_attempt_statfs"); + + /*Operation is not supported */ + return EOPNOTSUPP; +} /*netfs_attempt_statfs */ - /*Operation is not supported*/ - return EOPNOTSUPP; - }/*netfs_attempt_statfs*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Syncs the filesystem*/ -error_t -netfs_attempt_syncfs - ( - struct iouser * cred, - int wait - ) - { - LOG_MSG("netfs_attempt_syncfs"); +error_t netfs_attempt_syncfs (struct iouser * cred, int wait) +{ + LOG_MSG ("netfs_attempt_syncfs"); - /*Everythin OK*/ - return 0; - }/*netfs_attempt_syncfs*/ -/*----------------------------------------------------------------------------*/ + /*Everythin OK */ + return 0; +} /*netfs_attempt_syncfs */ + +/*---------------------------------------------------------------------------*/ /*Creates a link in `dir` with `name` to `file`*/ error_t -netfs_attempt_link - ( - struct iouser * user, - struct node * dir, - struct node * file, - char * name, - int excl - ) - { - LOG_MSG("netfs_attempt_link"); + netfs_attempt_link + (struct iouser * user, + struct node * dir, struct node * file, char *name, int excl) +{ + LOG_MSG ("netfs_attempt_link"); - /*Operation not supported*/ - return EOPNOTSUPP; - }/*netfs_attempt_link*/ -/*----------------------------------------------------------------------------*/ + /*Operation not supported */ + return EOPNOTSUPP; +} /*netfs_attempt_link */ + +/*---------------------------------------------------------------------------*/ /*Attempts to create an anonymous file related to `dir` with `mode`*/ error_t -netfs_attempt_mkfile - ( - struct iouser * user, - struct node * dir, - mode_t mode, - struct node ** node - ) - { - LOG_MSG("netfs_attempt_mkfile"); + netfs_attempt_mkfile + (struct iouser * user, struct node * dir, mode_t mode, struct node ** node) +{ + LOG_MSG ("netfs_attempt_mkfile"); - /*Unlock the directory*/ - mutex_unlock(&dir->lock); + /*Unlock the directory */ + mutex_unlock (&dir->lock); - /*Operation not supported*/ - return EOPNOTSUPP; - }/*netfs_attempt_mkfile*/ -/*----------------------------------------------------------------------------*/ + /*Operation not supported */ + return EOPNOTSUPP; +} /*netfs_attempt_mkfile */ + +/*---------------------------------------------------------------------------*/ /*Reads the contents of symlink `node` into `buf`*/ error_t -netfs_attempt_readlink - ( - struct iouser * user, - struct node * node, - char * buf - ) - { - LOG_MSG("netfs_attempt_readlink"); + netfs_attempt_readlink (struct iouser * user, struct node * node, char *buf) +{ + LOG_MSG ("netfs_attempt_readlink"); - /*Operation not supported (why?..)*/ - return EOPNOTSUPP; - }/*netfs_attempt_readlink*/ -/*----------------------------------------------------------------------------*/ + /*Operation not supported (why?..) */ + return EOPNOTSUPP; +} /*netfs_attempt_readlink */ + +/*---------------------------------------------------------------------------*/ /*Reads from file `node` up to `len` bytes from `offset` into `data`*/ error_t -netfs_attempt_read - ( - struct iouser * cred, - struct node * np, - loff_t offset, - size_t * len, - void * data - ) - { - LOG_MSG("netfs_attempt_read"); - - error_t err = 0; - - /*Obtain a pointer to the first byte of the supplied buffer*/ - char * buf = data; - - /*Try to read the requested information from the file*/ - err = io_read(np->nn->port, &buf, len, offset, *len); - - /*If some data has been read successfully*/ - if(!err && (buf != data)) - { - /*copy the data from the buffer into which is has been read into the - supplied receiver*/ - memcpy(data, buf, *len); - - /*unmap the new buffer*/ - munmap(buf, *len); - } + netfs_attempt_read + (struct iouser * cred, + struct node * np, loff_t offset, size_t * len, void *data) +{ + LOG_MSG ("netfs_attempt_read"); - /*Return the result of reading*/ - return err; - }/*netfs_attempt_read*/ -/*----------------------------------------------------------------------------*/ + error_t err = 0; + + /*Obtain a pointer to the first byte of the supplied buffer */ + char *buf = data; + + /*Try to read the requested information from the file */ + err = io_read (np->nn->port, &buf, len, offset, *len); + + /*If some data has been read successfully */ + if (!err && (buf != data)) + { + /*copy the data from the buffer into which is has been read into the + supplied receiver */ + memcpy (data, buf, *len); + + /*unmap the new buffer */ + munmap (buf, *len); + } + + /*Return the result of reading */ + return err; +} /*netfs_attempt_read */ + +/*---------------------------------------------------------------------------*/ /*Writes to file `node` up to `len` bytes from offset from `data`*/ error_t -netfs_attempt_write - ( - struct iouser * cred, - struct node * node, - loff_t offset, - size_t * len, - void * data - ) - { - /*Write the supplied data into the file and return the result*/ - return io_write(node->nn->port, data, *len, offset, len); - }/*netfs_attempt_write*/ -/*----------------------------------------------------------------------------*/ + netfs_attempt_write + (struct iouser * cred, + struct node * node, loff_t offset, size_t * len, void *data) +{ + /*Write the supplied data into the file and return the result */ + return io_write (node->nn->port, data, *len, offset, len); +} /*netfs_attempt_write */ + +/*---------------------------------------------------------------------------*/ /*Frees all storage associated with the node*/ -void -netfs_node_norefs - ( - struct node * np - ) - { - /*Destroy the node*/ - node_destroy(np); - }/*netfs_node_norefs*/ -/*----------------------------------------------------------------------------*/ +void netfs_node_norefs (struct node *np) +{ + /*Destroy the node */ + node_destroy (np); +} /*netfs_node_norefs */ + +/*---------------------------------------------------------------------------*/ /*Implements file_get_translator_cntl as described in <hurd/fs.defs> - (according to diskfs_S_file_get_translator_cntl)*/ + (according to diskfs_S_file_get_translator_cntl)*/ kern_return_t -netfs_S_file_get_translator_cntl - ( - struct protid * user, - mach_port_t * cntl, - mach_msg_type_name_t * cntltype - ) - { - /*If the information about the user is missing*/ - if(!user) - return EOPNOTSUPP; - - error_t err = 0; - - /*Obtain the node for which we are called*/ - node_t * np = user->po->np; - - /*If the node is not the root node of nsmux*/ - if(np != netfs_root_node) - { - /*the control port to the translator sitting on the real node*/ - mach_port_t p; - - /*obtain the control port for the translator sitting on the real node; - provide the bottommost translator, so that the filter (and this is - most probably a request of such a translator) should be able to trace - the real translator stack*/ - err = file_get_translator_cntl(np->nn->port_notrans, &p); - if(err) - return err; - - /*set the parameters accordingly*/ - *cntltype = MACH_MSG_TYPE_MOVE_SEND; - *cntl = p; - - /*return the result of operations*/ - return err; - } - - /*Lock the node*/ - mutex_lock(&np->lock); - - /*Check if the user is the owner of this node*/ - err = fshelp_isowner(&np->nn_stat, user->user); - - /*If no errors have happened*/ - if(!err) - /*try to fetch the control port*/ - err = fshelp_fetch_control(&np->transbox, cntl); - - /*If no errors have occurred, but no port has been returned*/ - if(!err && (cntl == MACH_PORT_NULL)) - /*set the error accordingly*/ - err = ENXIO; - - /*If no errors have occurred so far*/ - if(!err) - /*set the control port type*/ - *cntltype = MACH_MSG_TYPE_MOVE_SEND; - - /*Unlock the node*/ - mutex_unlock(&np->lock); - - /*Return the result of operations*/ + netfs_S_file_get_translator_cntl + (struct protid *user, mach_port_t * cntl, mach_msg_type_name_t * cntltype) +{ + /*If the information about the user is missing */ + if (!user) + return EOPNOTSUPP; + + error_t err = 0; + + /*Obtain the node for which we are called */ + node_t *np = user->po->np; + + /*If the node is not the root node of nsmux */ + if (np != netfs_root_node) + { + /*the control port to the translator sitting on the real node */ + mach_port_t p; + + /*obtain the control port for the translator sitting on the real node; + provide the bottommost translator, so that the filter (and this is + most probably a request of such a translator) should be able to trace + the real translator stack */ + err = file_get_translator_cntl (np->nn->port_notrans, &p); + if (err) return err; - }/*netfs_S_file_get_translator_cntl*/ -/*----------------------------------------------------------------------------*/ + + /*set the parameters accordingly */ + *cntltype = MACH_MSG_TYPE_MOVE_SEND; + *cntl = p; + + /*return the result of operations */ + return err; + } + + /*Lock the node */ + mutex_lock (&np->lock); + + /*Check if the user is the owner of this node */ + err = fshelp_isowner (&np->nn_stat, user->user); + + /*If no errors have happened */ + if (!err) + /*try to fetch the control port */ + err = fshelp_fetch_control (&np->transbox, cntl); + + /*If no errors have occurred, but no port has been returned */ + if (!err && (cntl == MACH_PORT_NULL)) + /*set the error accordingly */ + err = ENXIO; + + /*If no errors have occurred so far */ + if (!err) + /*set the control port type */ + *cntltype = MACH_MSG_TYPE_MOVE_SEND; + + /*Unlock the node */ + mutex_unlock (&np->lock); + + /*Return the result of operations */ + return err; +} /*netfs_S_file_get_translator_cntl */ + +/*---------------------------------------------------------------------------*/ /*Entry point*/ -int -main - ( - int argc, - char ** argv - ) - { - /*Start logging*/ - INIT_LOG(); - LOG_MSG(">> Starting initialization..."); - - /*The port on which this translator will be set upon*/ - mach_port_t bootstrap_port; - - error_t err = 0; - - /*Parse the command line arguments*/ - argp_parse(&argp_startup, argc, argv, ARGP_IN_ORDER, 0, 0); - LOG_MSG("Command line arguments parsed."); - - /*Try to create the root node*/ - err = node_create_root(&netfs_root_node); - if(err) - error(EXIT_FAILURE, err, "Failed to create the root node"); - LOG_MSG("Root node created."); - - /*Obtain the bootstrap port*/ - task_get_bootstrap_port(mach_task_self(), &bootstrap_port); - - /*Initialize the translator*/ - netfs_init(); - - /*Obtain a port to the underlying node*/ - underlying_node = netfs_startup(bootstrap_port, O_READ); - LOG_MSG("netfs initialization complete."); - - /*Initialize the root node*/ - err = node_init_root(netfs_root_node); - if(err) - error(EXIT_FAILURE, err, "Failed to initialize the root node"); - LOG_MSG("Root node initialized."); - LOG_MSG("\tRoot node address: 0x%lX", (unsigned long)netfs_root_node); - - /*Map the time for updating node information*/ - err = maptime_map(0, 0, &maptime); - if(err) - error(EXIT_FAILURE, err, "Failed to map the time"); - LOG_MSG("Time mapped."); - - /*Initialize the cache with the required number of nodes*/ - ncache_init(/*ncache_size*/); - LOG_MSG("Cache initialized."); - - /*Obtain stat information about the underlying node*/ - err = io_stat(underlying_node, &underlying_node_stat); - if(err) - error(EXIT_FAILURE, err, - "Cannot obtain stat information about the underlying node"); - LOG_MSG("Stat information for undelying node obtained."); - - /*Obtain the ID of the current process*/ - fsid = getpid(); - - /*Setup the stat information for the root node*/ - netfs_root_node->nn_stat = underlying_node_stat; - - netfs_root_node->nn_stat.st_ino = NSMUX_ROOT_INODE; - netfs_root_node->nn_stat.st_fsid = fsid; - netfs_root_node->nn_stat.st_mode = S_IFDIR | (underlying_node_stat.st_mode - & ~S_IFMT & ~S_ITRANS); /*we are providing a translated directory*/ - - netfs_root_node->nn_translated = netfs_root_node->nn_stat.st_mode; - - /*If the underlying node is not a directory, enhance the permissions - of the root node of the proxy filesystem*/ - if(!S_ISDIR(underlying_node_stat.st_mode)) - { - /*can be read by owner*/ - if(underlying_node_stat.st_mode & S_IRUSR) - /*allow execution by the owner*/ - netfs_root_node->nn_stat.st_mode |= S_IXUSR; - /*can be read by group*/ - if(underlying_node_stat.st_mode & S_IRGRP) - /*allow execution by the group*/ - netfs_root_node->nn_stat.st_mode |= S_IXGRP; - /*can be read by others*/ - if(underlying_node_stat.st_mode & S_IROTH) - /*allow execution by the others*/ - netfs_root_node->nn_stat.st_mode |= S_IXOTH; - } - - /*Update the timestamps of the root node*/ - fshelp_touch - (&netfs_root_node->nn_stat, TOUCH_ATIME | TOUCH_MTIME | TOUCH_CTIME, - maptime); - - LOG_MSG(">> Initialization complete. Entering netfs server loop..."); - - /*Start serving clients*/ - for(;;) - netfs_server_loop(); - }/*main*/ -/*----------------------------------------------------------------------------*/ +int main (int argc, char **argv) +{ + /*Start logging */ + INIT_LOG (); + LOG_MSG (">> Starting initialization..."); + + /*The port on which this translator will be set upon */ + mach_port_t bootstrap_port; + + error_t err = 0; + + /*Parse the command line arguments */ + argp_parse (&argp_startup, argc, argv, ARGP_IN_ORDER, 0, 0); + LOG_MSG ("Command line arguments parsed."); + + /*Try to create the root node */ + err = node_create_root (&netfs_root_node); + if (err) + error (EXIT_FAILURE, err, "Failed to create the root node"); + LOG_MSG ("Root node created."); + + /*Obtain the bootstrap port */ + task_get_bootstrap_port (mach_task_self (), &bootstrap_port); + + /*Initialize the translator */ + netfs_init (); + + /*Obtain a port to the underlying node */ + underlying_node = netfs_startup (bootstrap_port, O_READ); + LOG_MSG ("netfs initialization complete."); + + /*Initialize the root node */ + err = node_init_root (netfs_root_node); + if (err) + error (EXIT_FAILURE, err, "Failed to initialize the root node"); + LOG_MSG ("Root node initialized."); + LOG_MSG ("\tRoot node address: 0x%lX", (unsigned long) netfs_root_node); + + /*Map the time for updating node information */ + err = maptime_map (0, 0, &maptime); + if (err) + error (EXIT_FAILURE, err, "Failed to map the time"); + LOG_MSG ("Time mapped."); + + /*Initialize the cache with the required number of nodes */ + ncache_init ( /*ncache_size */ ); + LOG_MSG ("Cache initialized."); + + /*Obtain stat information about the underlying node */ + err = io_stat (underlying_node, &underlying_node_stat); + if (err) + error (EXIT_FAILURE, err, + "Cannot obtain stat information about the underlying node"); + LOG_MSG ("Stat information for undelying node obtained."); + + /*Obtain the ID of the current process */ + fsid = getpid (); + + /*Setup the stat information for the root node */ + netfs_root_node->nn_stat = underlying_node_stat; + + netfs_root_node->nn_stat.st_ino = NSMUX_ROOT_INODE; + netfs_root_node->nn_stat.st_fsid = fsid; + /*we are providing a translated directory */ + netfs_root_node->nn_stat.st_mode = + S_IFDIR | (underlying_node_stat.st_mode & ~S_IFMT & ~S_ITRANS); + + netfs_root_node->nn_translated = netfs_root_node->nn_stat.st_mode; + + /*If the underlying node is not a directory, enhance the permissions + of the root node of the proxy filesystem */ + if (!S_ISDIR (underlying_node_stat.st_mode)) + { + /*can be read by owner */ + if (underlying_node_stat.st_mode & S_IRUSR) + /*allow execution by the owner */ + netfs_root_node->nn_stat.st_mode |= S_IXUSR; + /*can be read by group */ + if (underlying_node_stat.st_mode & S_IRGRP) + /*allow execution by the group */ + netfs_root_node->nn_stat.st_mode |= S_IXGRP; + /*can be read by others */ + if (underlying_node_stat.st_mode & S_IROTH) + /*allow execution by the others */ + netfs_root_node->nn_stat.st_mode |= S_IXOTH; + } + + /*Update the timestamps of the root node */ + fshelp_touch + (&netfs_root_node->nn_stat, TOUCH_ATIME | TOUCH_MTIME | TOUCH_CTIME, + maptime); + + LOG_MSG (">> Initialization complete. Entering netfs server loop..."); + + /*Start serving clients */ + for (;;) + netfs_server_loop (); +} /*main */ + +/*---------------------------------------------------------------------------*/ @@ -1,10 +1,10 @@ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*nsmux.h*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Definitions for filesystem proxy for namespace-based translator selection.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Copyright (C) 2001, 2002, 2005, 2008 Free Software Foundation, Inc. Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. @@ -22,10 +22,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #ifndef __NSMUX_H__ #define __NSMUX_H__ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #include <stddef.h> #include <stdlib.h> #include <cthreads.h> @@ -37,354 +37,206 @@ #include <sys/time.h> #include <hurd/ihash.h> #include <hurd/iohelp.h> -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #include "lib.h" #include "node.h" -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Macros--------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Macros-------------------------------------------------------------*/ /*The inode number for the root node*/ #define NSMUX_ROOT_INODE 1 -/*----------------------------------------------------------------------------*/ -/*The special flag character for creating proxy nodes*/ -#define LOOKUP_MAGIC_CHAR '\33' -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Bits that are turned off after open*/ #define OPENONLY_STATE_MODES (O_CREAT | O_EXCL | O_NOLINK | O_NOTRANS) -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Global Variables----------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Global Variables---------------------------------------------------*/ /*A mapped time value*/ /*Required for a very fast access to time*/ -extern volatile struct mapped_time_value * maptime; -/*----------------------------------------------------------------------------*/ +extern volatile struct mapped_time_value *maptime; +/*---------------------------------------------------------------------------*/ /*A port to the underlying node*/ extern mach_port_t underlying_node; -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*The stat information about the underlying node*/ extern io_statbuf_t underlying_node_stat; -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*The translator callbacks required by netfs_S_dir_lookup*/ fshelp_fetch_root_callback1_t _netfs_translator_callback1; fshelp_fetch_root_callback2_t _netfs_translator_callback2; -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Functions-----------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Functions----------------------------------------------------------*/ /*Attempts to create a file named `name` in `dir` for `user` with mode `mode`*/ error_t -netfs_attempt_create_file - ( - struct iouser * user, - struct node * dir, - char * name, - mode_t mode, - struct node ** node - ); -/*----------------------------------------------------------------------------*/ + netfs_attempt_create_file + (struct iouser *user, + struct node *dir, char *name, mode_t mode, struct node **node); +/*---------------------------------------------------------------------------*/ /*Returns an error if the process of opening a file should not be allowed to complete because of insufficient permissions*/ error_t -netfs_check_open_permissions - ( - struct iouser * user, - struct node * np, - int flags, - int newnode - ); -/*----------------------------------------------------------------------------*/ + netfs_check_open_permissions + (struct iouser *user, struct node *np, int flags, int newnode); +/*---------------------------------------------------------------------------*/ /*Attempts an utimes call for the user `cred` on node `node`*/ error_t -netfs_attempt_utimes - ( - struct iouser * cred, - struct node * node, - struct timespec * atime, - struct timespec * mtime - ); -/*----------------------------------------------------------------------------*/ + netfs_attempt_utimes + (struct iouser *cred, + struct node *node, struct timespec *atime, struct timespec *mtime); +/*---------------------------------------------------------------------------*/ /*Returns the valid access types for file `node` and user `cred`*/ error_t -netfs_report_access - ( - struct iouser * cred, - struct node * np, - int * types - ); -/*----------------------------------------------------------------------------*/ + netfs_report_access (struct iouser *cred, struct node *np, int *types); +/*---------------------------------------------------------------------------*/ /*Validates the stat data for the node*/ -error_t -netfs_validate_stat - ( - struct node * np, - struct iouser * cred - ); -/*----------------------------------------------------------------------------*/ +error_t netfs_validate_stat (struct node *np, struct iouser *cred); +/*---------------------------------------------------------------------------*/ /*Syncs `node` completely to disk*/ -error_t -netfs_attempt_sync - ( - struct iouser * cred, - struct node * node, - int wait - ); -/*----------------------------------------------------------------------------*/ +error_t netfs_attempt_sync (struct iouser *cred, struct node *node, int wait); +/*---------------------------------------------------------------------------*/ /*Fetches a directory*/ error_t -netfs_get_dirents - ( - struct iouser * cred, - struct node * dir, - int first_entry, - int num_entries, - char ** data, - mach_msg_type_number_t * data_len, - vm_size_t max_data_len, - int * data_entries - ); -/*----------------------------------------------------------------------------*/ + netfs_get_dirents + (struct iouser *cred, + struct node *dir, + int first_entry, + int num_entries, + char **data, + mach_msg_type_number_t * data_len, + vm_size_t max_data_len, int *data_entries); +/*---------------------------------------------------------------------------*/ /*Looks up `name` under `dir` for `user`*/ error_t -netfs_attempt_lookup - ( - struct iouser * user, - struct node * dir, - char * name, - struct node ** node - ); -/*----------------------------------------------------------------------------*/ -/*Performs an advanced lookup of file `name` under `dir`. If the lookup of the - last component of the path is requested (`lastcomp` is 1), it is not a - directory and no translators are required (`name` does not contain ',,'), the - function will simply open the required file and return the port in `file`. In - other cases it will create a proxy node and return it in `node`.*/ -error_t -netfs_attempt_lookup_improved - ( - struct iouser * user, - struct node * dir, - char * name, - int flags, - int lastcomp, - node_t ** node, - file_t * file - ); -/*----------------------------------------------------------------------------*/ + netfs_attempt_lookup + (struct iouser *user, struct node *dir, char *name, struct node **node); +/*---------------------------------------------------------------------------*/ +/*Performs an advanced lookup of file `name` under `dir`. If the + lookup of the last component of the path is requested (`lastcomp` is + 1), it is not a directory and no translators are required (`name` + does not contain ',,'), the function will simply open the required + file and return the port in `file`. In other cases it will create a + proxy node and return it in `node`.*/ +error_t + netfs_attempt_lookup_improved + (struct iouser *user, + struct node *dir, + char *name, int flags, int lastcomp, node_t ** node, file_t * file); +/*---------------------------------------------------------------------------*/ /*Responds to the RPC dir_lookup*/ error_t -netfs_S_dir_lookup - ( - struct protid * diruser, - char * filename, - int flags, - mode_t mode, - retry_type * do_retry, - char * retry_name, - mach_port_t * retry_port, - mach_msg_type_number_t * retry_port_type - ); -/*----------------------------------------------------------------------------*/ + netfs_S_dir_lookup + (struct protid *diruser, + char *filename, + int flags, + mode_t mode, + retry_type * do_retry, + char *retry_name, + mach_port_t * retry_port, mach_msg_type_number_t * retry_port_type); +/*---------------------------------------------------------------------------*/ /*Deletes `name` in `dir` for `user`*/ error_t -netfs_attempt_unlink - ( - struct iouser * user, - struct node * dir, - char * name - ); -/*----------------------------------------------------------------------------*/ + netfs_attempt_unlink (struct iouser *user, struct node *dir, char *name); +/*---------------------------------------------------------------------------*/ /*Attempts to rename `fromdir`/`fromname` to `todir`/`toname`*/ error_t -netfs_attempt_rename - ( - struct iouser * user, - struct node * fromdir, - char * fromname, - struct node * todir, - char * toname, - int excl - ); -/*----------------------------------------------------------------------------*/ + netfs_attempt_rename + (struct iouser *user, + struct node *fromdir, + char *fromname, struct node *todir, char *toname, int excl); +/*---------------------------------------------------------------------------*/ /*Attempts to create a new directory*/ error_t -netfs_attempt_mkdir - ( - struct iouser * user, - struct node * dir, - char * name, - mode_t mode - ); -/*----------------------------------------------------------------------------*/ + netfs_attempt_mkdir + (struct iouser *user, struct node *dir, char *name, mode_t mode); +/*---------------------------------------------------------------------------*/ /*Attempts to remove directory `name` in `dir` for `user`*/ error_t -netfs_attempt_rmdir - ( - struct iouser * user, - struct node * dir, - char * name - ); -/*----------------------------------------------------------------------------*/ + netfs_attempt_rmdir (struct iouser *user, struct node *dir, char *name); +/*---------------------------------------------------------------------------*/ /*Attempts to change the owner of `node` for user `cred` to `uid`:`gid`*/ error_t -netfs_attempt_chown - ( - struct iouser * cred, - struct node * node, - uid_t uid, - uid_t gid - ); -/*----------------------------------------------------------------------------*/ + netfs_attempt_chown + (struct iouser *cred, struct node *node, uid_t uid, uid_t gid); +/*---------------------------------------------------------------------------*/ /*Attempts to change the author of `node` to `author`*/ error_t -netfs_attempt_chauthor - ( - struct iouser * cred, - struct node * node, - uid_t author - ); -/*----------------------------------------------------------------------------*/ + netfs_attempt_chauthor + (struct iouser *cred, struct node *node, uid_t author); +/*---------------------------------------------------------------------------*/ /*Attempts to change the mode of `node` to `mode` for `cred`*/ error_t -netfs_attempt_chmod - ( - struct iouser * user, - struct node * node, - mode_t mode - ); -/*----------------------------------------------------------------------------*/ + netfs_attempt_chmod (struct iouser *user, struct node *node, mode_t mode); +/*---------------------------------------------------------------------------*/ /*Attempts to turn `node` into a symlink targetting `name`*/ error_t -netfs_attempt_mksymlink - ( - struct iouser * cred, - struct node * node, - char * name - ); -/*----------------------------------------------------------------------------*/ + netfs_attempt_mksymlink + (struct iouser *cred, struct node *node, char *name); +/*---------------------------------------------------------------------------*/ /*Attempts to turn `node` into a device; type can be either S_IFBLK or S_IFCHR*/ error_t -netfs_attempt_mkdev - ( - struct iouser * cred, - struct node * node, - mode_t type, - dev_t indexes - ); -/*----------------------------------------------------------------------------*/ + netfs_attempt_mkdev + (struct iouser *cred, struct node *node, mode_t type, dev_t indexes); +/*---------------------------------------------------------------------------*/ /*Attempts to set the passive translator record for `file` passing `argz`*/ error_t -netfs_set_translator - ( - struct iouser * cred, - struct node * node, - char * argz, - size_t arglen - ); -/*----------------------------------------------------------------------------*/ + netfs_set_translator + (struct iouser *cred, struct node *node, char *argz, size_t arglen); +/*---------------------------------------------------------------------------*/ /*Attempts to call chflags for `node`*/ error_t -netfs_attempt_chflags - ( - struct iouser * cred, - struct node * node, - int flags - ); -/*----------------------------------------------------------------------------*/ + netfs_attempt_chflags (struct iouser *cred, struct node *node, int flags); +/*---------------------------------------------------------------------------*/ /*Attempts to set the size of file `node`*/ error_t -netfs_attempt_set_size - ( - struct iouser * cred, - struct node * node, - loff_t size - ); -/*----------------------------------------------------------------------------*/ + netfs_attempt_set_size + (struct iouser *cred, struct node *node, loff_t size); +/*---------------------------------------------------------------------------*/ /*Fetches the filesystem status information*/ error_t -netfs_attempt_statfs - ( - struct iouser * cred, - struct node * node, - fsys_statfsbuf_t * st - ); -/*----------------------------------------------------------------------------*/ + netfs_attempt_statfs + (struct iouser *cred, struct node *node, fsys_statfsbuf_t * st); +/*---------------------------------------------------------------------------*/ /*Syncs the filesystem*/ -error_t -netfs_attempt_syncfs - ( - struct iouser * cred, - int wait - ); -/*----------------------------------------------------------------------------*/ +error_t netfs_attempt_syncfs (struct iouser *cred, int wait); +/*---------------------------------------------------------------------------*/ /*Creates a link in `dir` with `name` to `file`*/ error_t -netfs_attempt_link - ( - struct iouser * user, - struct node * dir, - struct node * file, - char * name, - int excl - ); -/*----------------------------------------------------------------------------*/ + netfs_attempt_link + (struct iouser *user, + struct node *dir, struct node *file, char *name, int excl); +/*---------------------------------------------------------------------------*/ /*Attempts to create an anonymous file related to `dir` with `mode`*/ error_t -netfs_attempt_mkfile - ( - struct iouser * user, - struct node * dir, - mode_t mode, - struct node ** node - ); -/*----------------------------------------------------------------------------*/ + netfs_attempt_mkfile + (struct iouser *user, struct node *dir, mode_t mode, struct node **node); +/*---------------------------------------------------------------------------*/ /*Reads the contents of symlink `node` into `buf`*/ error_t -netfs_attempt_readlink - ( - struct iouser * user, - struct node * node, - char * buf - ); -/*----------------------------------------------------------------------------*/ + netfs_attempt_readlink (struct iouser *user, struct node *node, char *buf); +/*---------------------------------------------------------------------------*/ /*Reads from file `node` up to `len` bytes from `offset` into `data`*/ error_t -netfs_attempt_read - ( - struct iouser * cred, - struct node * np, - loff_t offset, - size_t * len, - void * data - ); -/*----------------------------------------------------------------------------*/ + netfs_attempt_read + (struct iouser *cred, + struct node *np, loff_t offset, size_t * len, void *data); +/*---------------------------------------------------------------------------*/ /*Writes to file `node` up to `len` bytes from offset from `data`*/ error_t -netfs_attempt_write - ( - struct iouser * cred, - struct node * node, - loff_t offset, - size_t * len, - void * data - ); -/*----------------------------------------------------------------------------*/ + netfs_attempt_write + (struct iouser *cred, + struct node *node, loff_t offset, size_t * len, void *data); +/*---------------------------------------------------------------------------*/ /*Frees all storage associated with the node*/ -void -netfs_node_norefs - ( - struct node * np - ); -/*----------------------------------------------------------------------------*/ +void netfs_node_norefs (struct node *np); +/*---------------------------------------------------------------------------*/ /*Implements file_get_translator_cntl as described in <hurd/fs.defs> - (according to diskfs_S_file_get_translator_cntl)*/ + (according to diskfs_S_file_get_translator_cntl)*/ kern_return_t -netfs_S_file_get_translator_cntl - ( - struct protid * user, - mach_port_t * cntl, - mach_msg_type_name_t * cntltype - ); -/*----------------------------------------------------------------------------*/ + netfs_S_file_get_translator_cntl + (struct protid *user, mach_port_t * cntl, mach_msg_type_name_t * cntltype); +/*---------------------------------------------------------------------------*/ #endif /*__NSMUX_H__*/ @@ -1,10 +1,10 @@ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*options.h*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Definitions for parsing the command line switches*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Copyright (C) 2001, 2002, 2005, 2008 Free Software Foundation, Inc. Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. @@ -22,222 +22,206 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #define _GNU_SOURCE 1 -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #include <argp.h> #include <error.h> -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #include "debug.h" #include "options.h" #include "ncache.h" #include "node.h" -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Macros--------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Macros-------------------------------------------------------------*/ /*Short documentation for argp*/ #define ARGS_DOC "DIR" -#define DOC "Provides namespace-based translator selection."\ +#define DOC "Provides namespace-based translator selection."\ " You can dynamically obtain the file 'file' translated by translator"\ " 'x' using the syntax: 'file,,x'." -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Forward Declarations------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Forward Declarations-----------------------------------------------*/ /*Argp parser function for the common options*/ static -error_t -argp_parse_common_options - ( - int key, - char * arg, - struct argp_state * state - ); -/*----------------------------------------------------------------------------*/ + error_t + argp_parse_common_options (int key, char *arg, struct argp_state *state); +/*---------------------------------------------------------------------------*/ /*Argp parser function for the startup options*/ static -error_t -argp_parse_startup_options - ( - int key, - char * arg, - struct argp_state * state - ); -/*----------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------*/ -/*--------Global Variables----------------------------------------------------*/ + error_t + argp_parse_startup_options (int key, char *arg, struct argp_state *state); +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/*--------Global Variables---------------------------------------------------*/ /*This variable is set to a non-zero value after the parsing of starup options is finished*/ /*Whenever the argument parser is later called to modify the options of the root node will be initialized accordingly directly by the parser*/ static int parsing_startup_options_finished; -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Argp options common to both the runtime and the startup parser*/ -static const struct argp_option argp_common_options[] = - { - /*{OPT_LONG_CACHE_SIZE, OPT_CACHE_SIZE, "SIZE", 0, - "The maximal number of nodes in the node cache"}*/ - {0} - }; -/*----------------------------------------------------------------------------*/ +static const struct argp_option argp_common_options[] = { + /*{OPT_LONG_CACHE_SIZE, OPT_CACHE_SIZE, "SIZE", 0, + "The maximal number of nodes in the node cache"} */ + {0} +}; + +/*---------------------------------------------------------------------------*/ /*Argp options only meaningful for startup parsing*/ -static const struct argp_option argp_startup_options[] = - { - {0} - }; -/*----------------------------------------------------------------------------*/ +static const struct argp_option argp_startup_options[] = { + {0} +}; + +/*---------------------------------------------------------------------------*/ /*Argp parser for only the common options*/ static const struct argp argp_parser_common_options = - {argp_common_options, argp_parse_common_options, 0, 0, 0}; -/*----------------------------------------------------------------------------*/ + { argp_common_options, argp_parse_common_options, 0, 0, 0 }; +/*---------------------------------------------------------------------------*/ /*Argp parser for only the startup options*/ static const struct argp argp_parser_startup_options = - {argp_startup_options, argp_parse_startup_options, 0, 0, 0}; -/*----------------------------------------------------------------------------*/ + { argp_startup_options, argp_parse_startup_options, 0, 0, 0 }; +/*---------------------------------------------------------------------------*/ /*The list of children parsers for runtime arguments*/ -static const struct argp_child argp_children_runtime[] = - { - {&argp_parser_common_options}, - {&netfs_std_runtime_argp}, - {0} - }; -/*----------------------------------------------------------------------------*/ +static const struct argp_child argp_children_runtime[] = { + {&argp_parser_common_options}, + {&netfs_std_runtime_argp}, + {0} +}; + +/*---------------------------------------------------------------------------*/ /*The list of children parsers for startup arguments*/ -static const struct argp_child argp_children_startup[] = - { - {&argp_parser_startup_options}, - {&argp_parser_common_options}, - {&netfs_std_startup_argp}, - {0} - }; -/*----------------------------------------------------------------------------*/ +static const struct argp_child argp_children_startup[] = { + {&argp_parser_startup_options}, + {&argp_parser_common_options}, + {&netfs_std_startup_argp}, + {0} +}; + +/*---------------------------------------------------------------------------*/ /*The version of the server for argp*/ -const char * argp_program_version = "0.0"; -/*----------------------------------------------------------------------------*/ +const char *argp_program_version = "0.0"; +/*---------------------------------------------------------------------------*/ /*The arpg parser for runtime arguments*/ -struct argp argp_runtime = - {0, 0, 0, 0, argp_children_runtime}; -/*----------------------------------------------------------------------------*/ +struct argp argp_runtime = { 0, 0, 0, 0, argp_children_runtime }; + +/*---------------------------------------------------------------------------*/ /*The argp parser for startup arguments*/ -struct argp argp_startup = - {0, 0, ARGS_DOC, DOC, argp_children_startup}; -/*----------------------------------------------------------------------------*/ +struct argp argp_startup = { 0, 0, ARGS_DOC, DOC, argp_children_startup }; + +/*---------------------------------------------------------------------------*/ /*The directory to mirror*/ -char * dir = NULL; -/*----------------------------------------------------------------------------*/ +char *dir = NULL; +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Functions-----------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Functions----------------------------------------------------------*/ /*Argp parser function for the common options*/ static -error_t -argp_parse_common_options - ( - int key, - char * arg, - struct argp_state * state - ) - { - error_t err = 0; - - /*Go through the possible options*/ - switch(key) - { - /*case OPT_CACHE_SIZE: - {*/ - /*store the new cache-size*/ - /*ncache_size = strtol(arg, NULL, 10); - - break; - }*/ - case ARGP_KEY_ARG: /*the directory to mirror*/ - { - /*try to duplicate the directory name*/ - dir = strdup(arg); - if(!dir) - error(EXIT_FAILURE, ENOMEM, "argp_parse_common_options: " - "Could not strdup the directory"); - - /*fill all trailing spaces with 0*/ - int i = strlen(dir) - 1; - /*for(i = strlen(dir) - 1; (i >= 0) && (dir[i] == ' '); dir[i--] = 0);*/ - /*the original filename may contain spaces*/ - - /*If the last non blank symbol is a '/' and it's not the only one*/ - if((dir[i] == '/') && (i != 0)) - /*put 0 instead*/ - dir[i] = 0; - - LOG_MSG("argp_parse_common_options: Mirroring the directory %s.", dir); - - break; - } - case ARGP_KEY_END: - { - /*If parsing of startup options has not finished*/ - if(!parsing_startup_options_finished) - { - /*reset the cache*/ - ncache_reset(); - - /*If the directory has not been specified*/ - if(!dir) - { - /*assume the directory to be the home directory*/ - ; - - /*FIXME: The default directory is /var/tmp*/ - dir = "/var/tmp"; - } - - /*set the flag that the startup options have already been parsed*/ - parsing_startup_options_finished = 1; - } - else - { + error_t + argp_parse_common_options (int key, char *arg, struct argp_state *state) +{ + error_t err = 0; + + /*Go through the possible options */ + switch (key) + { + /*case OPT_CACHE_SIZE: + { */ + /*store the new cache-size */ + /*ncache_size = strtol(arg, NULL, 10); + + break; + } */ + case ARGP_KEY_ARG: /*the directory to mirror */ + { + /*try to duplicate the directory name */ + dir = strdup (arg); + if (!dir) + error (EXIT_FAILURE, ENOMEM, "argp_parse_common_options: " + "Could not strdup the directory"); + + /*fill all trailing spaces with 0 */ + int i = strlen (dir) - 1; + /*for(i = strlen(dir) - 1; (i >= 0) && (dir[i] == ' '); + dir[i--] = 0); */ + /*the original filename may contain spaces */ + + /*If the last non blank symbol is a '/' and it's not the only one */ + if ((dir[i] == '/') && (i != 0)) + /*put 0 instead */ + dir[i] = 0; + + LOG_MSG ("argp_parse_common_options: Mirroring the directory %s.", + dir); + + break; + } + case ARGP_KEY_END: + { + /*If parsing of startup options has not finished */ + if (!parsing_startup_options_finished) + { + /*reset the cache */ + ncache_reset (); + + /*If the directory has not been specified */ + if (!dir) + { + /*assume the directory to be the home directory */ + ; + + /*FIXME: The default directory is /var/tmp */ + dir = "/var/tmp"; + } + + /*set the flag that the startup options have already been parsed */ + parsing_startup_options_finished = 1; + } + else + { /*TODO: Take care of runtime calls modifying the property*/ - } - } - /*If the option could not be recognized*/ - default: - { - /*set the error code*/ - err = ARGP_ERR_UNKNOWN; - } - } - - /*Return the result*/ - return err; - }/*argp_parse_common_options*/ -/*----------------------------------------------------------------------------*/ + } + } + /*If the option could not be recognized */ + default: + { + /*set the error code */ + err = ARGP_ERR_UNKNOWN; + } + } + + /*Return the result */ + return err; +} /*argp_parse_common_options */ + +/*---------------------------------------------------------------------------*/ /*Argp parser function for the startup options*/ static -error_t -argp_parse_startup_options - ( - int key, - char * arg, - struct argp_state * state - ) - { - /*Do nothing in a beautiful way*/ - error_t err = 0; - - switch(key) - { - default: - { - err = ARGP_ERR_UNKNOWN; - - break; - } - } - - return err; - }/*argp_parse_startup_options*/ -/*----------------------------------------------------------------------------*/ + error_t + argp_parse_startup_options (int key, char *arg, struct argp_state *state) +{ + /*Do nothing in a beautiful way */ + error_t err = 0; + + switch (key) + { + default: + { + err = ARGP_ERR_UNKNOWN; + + break; + } + } + + return err; +} /*argp_parse_startup_options */ + +/*---------------------------------------------------------------------------*/ @@ -1,10 +1,10 @@ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*options.h*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Declarations for parsing the command line switches*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Based on the code of unionfs translator.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Copyright (C) 2001, 2002, 2005, 2008 Free Software Foundation, Inc. Written by Sergiu Ivanov <unlimitedscolobb@gmail.com>. @@ -22,34 +22,34 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.*/ -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ #ifndef __OPTIONS_H__ #define __OPTIONS_H__ -/*----------------------------------------------------------------------------*/ -/*--------Macros--------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Macros-------------------------------------------------------------*/ /*The possible short options*/ #define OPT_CACHE_SIZE 'c' -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*The corresponding long options*/ #define OPT_LONG_CACHE_SIZE "cache-size" -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*Makes a long option out of option name*/ #define OPT_LONG(o) "--"o -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -/*----------------------------------------------------------------------------*/ -/*--------Global Variables----------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/*--------Global Variables---------------------------------------------------*/ /*The argp parser for startup arguments*/ extern struct argp argp_startup; -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*The argp parser for rutime arguments*/ extern struct argp argp_runtime; -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*The number of nodes in cache (see ncache.{c,h})*/ extern int ncache_size; -/*----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ /*The directory to mirror*/ -extern char * dir; -/*----------------------------------------------------------------------------*/ +extern char *dir; +/*---------------------------------------------------------------------------*/ #endif /*__OPTIONS_H__*/ |