summaryrefslogtreecommitdiff
path: root/node.c
diff options
context:
space:
mode:
Diffstat (limited to 'node.c')
-rw-r--r--node.c1860
1 files changed, 865 insertions, 995 deletions
diff --git a/node.c b/node.c
index a452571ff..866bd1977 100644
--- a/node.c
+++ b/node.c
@@ -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 */
+
+/*---------------------------------------------------------------------------*/