summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergiu Ivanov <unlimitedscolobb@gmail.com>2008-07-22 18:10:44 +0300
committerSergiu Ivanov <unlimitedscolobb@gmail.com>2008-07-22 18:10:44 +0300
commit13fa6563250dcd4b2d1a54f15aba1bb7d8aace28 (patch)
treef70c733622bd20dada164bf6b072c4bfb7bc22e4
parentef6b6263abd1d58ebefe3c8b751c9148459c9638 (diff)
Added the possibility to propagate translators onto directories. Fixed bugs.
Now the user can enter directories using the following command: cd dir,,x All files in this directory will then be implicitly translated by translator 'x'; in other words, if there is a file 'file' in directory 'dir', after executing the command mentioned above, and after running cat file the user will obtain the content of 'file' translated by 'x'. Also fixed several rather serious bugs in lookup of file names of the type 'file,,x'.
-rw-r--r--lnode.c4
-rw-r--r--lnode.h8
-rw-r--r--node.c229
-rw-r--r--node.h29
-rw-r--r--nsmux.c465
5 files changed, 546 insertions, 189 deletions
diff --git a/lnode.c b/lnode.c
index 406b7b4f5..aed83a0f5 100644
--- a/lnode.c
+++ b/lnode.c
@@ -138,6 +138,10 @@ lnode_destroy
/*Destroy the name of the node*/
free(node->name);
+ /*If there is a list of translators*/
+ if(node->trans)
+ free(node->trans);
+
/*Destroy the node itself*/
free(node);
}/*lnode_destroy*/
diff --git a/lnode.h b/lnode.h
index 9ca1ef2c5..674102523 100644
--- a/lnode.h
+++ b/lnode.h
@@ -32,6 +32,14 @@
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
+/*--------Macros--------------------------------------------------------------*/
+/*The possible flags in an lnode*/
+#define FLAG_LNODE_DIR 0x00000001 /*the lnode is a directory*/
+#define FLAG_LNODE_TRANSLATED 0x00000002 /*all appropriate translators
+ have already been set on this node*/
+/*----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------*/
/*A candy synonym for the fundamental libnetfs node*/
typedef struct node node_t;
/*----------------------------------------------------------------------------*/
diff --git a/node.c b/node.c
index a622db2bd..a37803e15 100644
--- a/node.c
+++ b/node.c
@@ -32,12 +32,14 @@
#include <sys/stat.h>
#include <sys/mman.h>
#include <stdio.h>
+#include <argz.h>
/*----------------------------------------------------------------------------*/
#include "debug.h"
#include "node.h"
#include "options.h"
#include "lib.h"
#include "nsmux.h"
+#include "ncache.h"
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
@@ -111,7 +113,16 @@ node_destroy
assert(!np->nn->ncache_next || !np->nn->ncache_prev);
/*Destroy the port to the underlying filesystem allocated to the node*/
- PORT_DEALLOC(np->nn->port);
+ if(np->nn->port != MACH_PORT_NULL)
+ PORT_DEALLOC(np->nn->port);
+
+ /*If the given node is not the root node and there are translators
+ to kill*/
+ if(np->nn->lnode->dir && np->nn->lnode->trans)
+ {
+ /*kill all translators on the underlying nodes*/
+ node_kill_all_translators(np);
+ }
/*Lock the lnode corresponding to the current node*/
mutex_lock(&np->nn->lnode->lock);
@@ -621,3 +632,219 @@ node_unlink_file
return err;
}/*node_unlink_file*/
/*----------------------------------------------------------------------------*/
+/*Sets the given translator on the supplied 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_set_translator
+ (
+ node_t * dir,
+ node_t * node,
+ const char * trans /*set this on `name`*/
+ )
+ {
+ error_t err;
+
+ /*A port for opened to the file*/
+ mach_port_t p;
+
+ /*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 control port for the active translator*/
+ mach_port_t active_control;
+
+ /*Opens a port to the file at the request of fshelp_start_translator*/
+ error_t
+ open_port
+ (
+ int flags,
+ mach_port_t * underlying,
+ mach_msg_type_name_t * underlying_type,
+ task_t task,
+ void * cookie /*some additional information, not used here*/
+ )
+ {
+ /*Lookup the file we are working with*/
+ p = file_name_lookup_under
+ (dir->nn->port, node->nn->lnode->name, flags, 0);
+ if(p == MACH_PORT_NULL)
+ return errno;
+
+ /*Store the result in the parameters*/
+ *underlying = p;
+ *underlying_type = MACH_MSG_TYPE_COPY_SEND;
+
+ /*Here everything is OK*/
+ return 0;
+ }/*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 a copy (possibly extended) of the name*/
+ ext = put_in_hurd(trans);
+ if(!ext)
+ return ENOMEM;
+
+ /*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, NULL, 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
+ );
+ if(err)
+ return err;
+
+ /*Deallocate the port we have just opened*/
+ PORT_DEALLOC(p);
+
+ /*Everything is OK here*/
+ return 0;
+ }/*node_set_translator*/
+/*----------------------------------------------------------------------------*/
+/*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
+ )
+ {
+ /*Lookup the file*/
+ mach_port_t p =
+ file_name_lookup_under(dir->nn->port, node->nn->lnode->name, O_NOTRANS, 0);
+
+ /*Remove a translator from the node*/
+ error_t err = file_set_translator
+ (
+ p, FS_TRANS_SET, FS_TRANS_SET, 0, NULL, 0,
+ MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND
+ );
+
+ /*Close the port*/
+ PORT_DEALLOC(p);
+
+ /*Return the result of removing the translator*/
+ return err;
+ }/*node_kill_translator*/
+/*----------------------------------------------------------------------------*/
+/*Kills all translators on the nodes belonging to the given directory*/
+void
+node_kill_all_translators
+ (
+ node_t * node
+ )
+ {
+ /*Goes through all children of the given node recursively*/
+ void
+ traverse_children_r
+ (
+ node_t * dir,
+ node_t * np,
+ size_t ntrans /*the number of translators to remove from all nodes*/
+ )
+ {
+ int i;
+
+ /*A child of the current node*/
+ lnode_t * ln = np->nn->lnode;
+
+ /*If the current node is not a directory*/
+ if(!(ln->flags & FLAG_LNODE_DIR))
+ {
+ /*remove the required number of translators from the current node*/
+ for(i = 0; i < ntrans + ln->ntrans; ++i)
+ node_kill_translator(dir, np);
+ }
+ else
+ /*Go through the list of entries belonging to this directory*/
+ for(ln = ln->entries; ln; ln = ln->next)
+ {
+ /*die, if there is no node corresponding to the current child*/
+ /*This is abnormal, because lnodes should normally go away shortly
+ after the destruction of correpsonding nodes*/
+ assert(ln->node);
+
+ /*kill translators for this node*/
+ traverse_children_r(np, ln->node, ntrans + ln->ntrans);
+ }
+
+ /*Obtain a pointer to the lnode corresponding to np*/
+ ln = np->nn->lnode;
+
+ /*Destroy the list of translators*/
+ if(ln->trans)
+ free(ln->trans);
+
+ /*No more translators on this node*/
+ ln->trans = NULL;
+ ln->ntrans = ln->translen = 0;
+
+ /*There are no translators on this node*/
+ ln->flags &= ~FLAG_LNODE_TRANSLATED;
+ }/*traverse_children_r*/
+
+ /*Obtain the pointer to the parent node of the current node*/
+ node_t * dnp;
+ ncache_node_lookup(node->nn->lnode->dir, &dnp);
+
+ /*Kill all translators on the current node*/
+ traverse_children_r(dnp, node, node->nn->lnode->ntrans);
+
+ /*Unlock the parent node*/
+ mutex_unlock(&dnp->lock);
+ }/*node_kill_all_translators*/
+/*----------------------------------------------------------------------------*/
diff --git a/node.h b/node.h
index 584aa9f3d..72c244e8c 100644
--- a/node.h
+++ b/node.h
@@ -165,4 +165,33 @@ node_unlink_file
char * name
);
/*----------------------------------------------------------------------------*/
+/*Sets the given translator on the supplied 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_set_translator
+ (
+ node_t * dir,
+ node_t * node,
+ const char * trans /*set this on `name`*/
+ );
+/*----------------------------------------------------------------------------*/
+/*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_all_translators
+ (
+ node_t * node
+ );
+/*----------------------------------------------------------------------------*/
#endif /*__NODE_H__*/
diff --git a/nsmux.c b/nsmux.c
index d7f89002c..d512d7722 100644
--- a/nsmux.c
+++ b/nsmux.c
@@ -31,7 +31,6 @@
/*----------------------------------------------------------------------------*/
#include <error.h>
#include <argp.h>
-#include <argz.h>
#include <hurd/netfs.h>
#include <fcntl.h>
/*----------------------------------------------------------------------------*/
@@ -41,13 +40,6 @@
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
-/*--------Macros--------------------------------------------------------------*/
-/*The state modes use in open*/
-#define OPENONLY_STATE_MODES (O_CREAT | O_EXCL | O_NOLINK | O_NOTRANS \
- | O_NONBLOCK)
-/*----------------------------------------------------------------------------*/
-
-/*----------------------------------------------------------------------------*/
/*--------Global Variables----------------------------------------------------*/
/*The name of the server*/
char * netfs_server_name = "nsmux";
@@ -520,6 +512,7 @@ netfs_attempt_lookup
LOG_MSG("netfs_attempt_lookup: '%s'", name);
error_t err = 0;
+ int i = 0;
/*If we are asked to fetch the current directory*/
if(strcmp(name, ".") == 0)
@@ -564,10 +557,32 @@ netfs_attempt_lookup
/*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)
{
@@ -625,6 +640,9 @@ netfs_attempt_lookup
{
/*do not set the port*/
p = MACH_PORT_NULL;
+
+ /*remember we do not have a directory*/
+ isdir = 0;
}
else
{
@@ -634,6 +652,9 @@ netfs_attempt_lookup
{
return EBADF; /*not enough rights?*/
}
+
+ /*we have a directory here*/
+ isdir = 1;
}
/*Try to find an lnode called `name` under the lnode corresponding to `dir`*/
@@ -653,28 +674,13 @@ netfs_attempt_lookup
/*install the new lnode into the directory*/
lnode_install(dir->nn->lnode, lnode);
}
- else
- {
- /*TODO: Remove the code from here and put it into the caller block,
- so that we can decide there whether to remove translators and
- *which* ones to remove*/
-
- /*free the list of translators associated with this node, if
- such a list exists*/
- if(lnode->trans)
- {
- free(lnode->trans);
- lnode->trans = NULL;
- lnode->ntrans = lnode->translen = 0;
- }
- }
-
+
/*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 the lookup in the cache failed*/
if(err)
{
@@ -686,6 +692,12 @@ netfs_attempt_lookup
/*Store the port in the node*/
(*node)->nn->port = p;
+ /*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)
@@ -701,12 +713,6 @@ netfs_attempt_lookup
return 0;
}/*lookup*/
- /*The position of ',,' in the name*/
- char * sep;
-
- /*A pointer for various operations on strings*/
- char * str;
-
/*While pairs of commas can still be found in the name*/
for(sep = strstr(name, ",,"); sep; sep = strstr(sep, ",,"))
{
@@ -760,58 +766,219 @@ netfs_attempt_lookup
/*duplicate the part of the name containing the list of translators
and store the copy in the lnode*/
- lnode->trans = strdup(sep);
- if(!lnode->trans)
+ trans = strdup(sep);
+ if(!trans)
{
finalize();
return err;
}
- /*free the copy of the name*/
- /*we've just copied the pointer, so don't free it*/
- /*free(name_cpy);*/
-
/*obtain a pointer to the beginning of the list of translators*/
- str = lnode->trans;
+ str = trans;
- /*used to process escaped commas*/
- /*char * p;*/
+ /*a pointer for removal of extra commas*/
+ char * p;
/*Go through the list of translators*/
- for(lnode->ntrans = 0; *str; ++str)
+ for(translen = ntrans = 0; *str; ++str)
{
- /*Commas are not allowed in translator names*/
-#if 0
- /*If we are now situated at an escaped comma*/
- if((*str == '\\') && (str[1] == ','))
- {
- /*shift everything left in the string to remove the escaping backslash*/
- for(p = str; *p; *p = p[1], ++p);
-
- /*count a single character and step forward*/
- ++lnode->translen;
- continue;
- }
-#endif
-
/*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*/
- ++lnode->ntrans;
+ ++ntrans;
}
/*take the current character into account*/
- ++lnode->translen;
+ ++translen;
}
/*take into consideration the last element in the list,
which does not end in a comma and the corresponding terminal 0*/
- ++lnode->ntrans;
- ++lnode->translen;
+ ++ntrans;
+ ++translen;
+
+ /*If there are no translators set upon the current node*/
+ if(!lnode->trans)
+ {
+ /*copy the list of translators we have just built in the lnode*/
+ lnode->trans = trans;
+ lnode->ntrans = ntrans;
+ lnode->translen = translen;
+
+ /*If the node has already been fully translated before and it's
+ not a directory*/
+ /*We don't need to set the whole collection of translators,
+ both inherited and the ones in lnode->trans. The latter
+ are only necessary. Directories, on the other hand, cannot
+ bear translators on them.*/
+ if
+ (
+ (lnode->flags & FLAG_LNODE_TRANSLATED)
+ && !(lnode->flags & FLAG_LNODE_DIR)
+ )
+ {
+ /*Go through the list of translators*/
+ for(str = trans, i = 0; i < ntrans; ++i)
+ {
+ /*set the translator specified in the current component*/
+ err = node_set_translator(dir, *node, str);
+ if(err)
+ {
+ finalize();
+ return 0; /*TODO: A better way to fight errors here*/
+ }
+
+ /*skip the current component*/
+ str += strlen(str) + 1;
+ }
+
+ /*we don't own the list of translators any more*/
+ trans = NULL;
+ ntrans = 0;
+ translen = 0;
+
+ /*here the lookup is successful*/
+ err = 0;
+ finalize();
+ return err;
+ }
+
+ /*we don't own the list of translators any more*/
+ trans = NULL;
+ ntrans = 0;
+ translen = 0;
+ }
+ else
+ {
+ /*If the current node is not a directory*/
+ if(!isdir)
+ {
+ /*obtain the minimal of the lengths of the lists of translators*/
+ size_t minlen =
+ (translen < lnode->translen) ? (translen) : (lnode->translen);
+
+ /*the number of similar translators*/
+ size_t similar = 0;
+
+ /*the current position in the list*/
+ size_t i;
+
+ /*Go through the lists of translators*/
+ for(i = 0; i < minlen; ++i)
+ {
+ /*If the current characters are different, stop here*/
+ if(trans[i] != lnode->trans[i])
+ break;
+
+ /*If the current character marks the end of a translator name*/
+ if(trans[i] == 0)
+ /*one more matching translator*/
+ ++similar;
+ }
+
+ /*While all not matching translators have not been removed*/
+ size_t j;
+ for(j = 0; j < lnode->ntrans - similar; ++j)
+ {
+ /*remove one more translator*/
+ err = node_kill_translator(dir, *node);
+ if(err)
+ {
+ finalize();
+ return err;
+ }
+ }
+
+ /*obtain the pointer to the first not matching position*/
+ str = trans + i;
+
+ /*seek to the beginning of the current translator name*/
+ for(; (str > trans) && *str; --str);
+
+ /*While the required new translators have not been set*/
+ for(i = 0; i < ntrans - similar; ++i)
+ {
+ /*set the current translator on the file*/
+ err = node_set_translator(dir, *node, str);
+ if(err)
+ {
+ finalize();
+ return err;
+ }
+
+ /*skip the current translator*/
+ str += strlen(str) + 1;
+ }
+ }
+ /*We have looked up a directory*/
+ else
+ {
+ /*If the length of the lists of translators are the same*/
+ if((lnode->translen = translen) && (lnode->ntrans == ntrans))
+ {
+ /*check each character of the list of translators*/
+ int i;
+ for(i = 0; (i < translen) && (lnode->trans[i] == trans[i]); ++i);
+
+ /*If the lists coincide*/
+ if(i == translen)
+ {
+ /*the lookup has finished successfully here*/
+ err = 0;
+ finalize();
+ return err;
+ }
+ }
+
+ /*unlock the directory in which we are at the moment*/
+ mutex_unlock(&dir->lock);
+
+ /*kill all translators on all children of this node*/
+ node_kill_all_translators(*node);
+
+ /*lock the directory back*/
+ mutex_lock(&dir->lock);
+ }
+
+ /*destroy the list of translators in the current node*/
+ free(lnode->trans);
+
+ /*put the new list in the node*/
+ lnode->trans = trans;
+ lnode->ntrans = ntrans;
+ lnode->translen = translen;
+
+ /*all required translators have been already applied on this node*/
+ /*lnode->flags |= FLAG_LNODE_TRANSLATED;*/
+
+ /*we don't own the list of translators any more*/
+ trans = NULL;
+
+ /*the lookup is already finished here*/
+ err = 0;
+ finalize();
+ return err;
+ }
}
/*The control sequence ',,' has not been found*/
else
@@ -823,14 +990,51 @@ netfs_attempt_lookup
finalize();
return err;
}
+
+ /*If there are some translators set on this file*/
+ if(lnode->trans)
+ {
+ /*unlock the directory*/
+ mutex_unlock(&dir->lock);
+
+ /*kill all translators on this node*/
+ node_kill_all_translators(*node);
+
+ /*lock the directory again*/
+ mutex_lock(&dir->lock);
+
+ /*all translators have been succesfully set here*/
+ /*lnode->flags |= FLAG_LNODE_TRANSLATED;*/
+
+ /*the lookup has finished successfully here*/
+ /*The translators inherited from parents survive throughout
+ the previous loop*/
+ err = 0;
+ finalize();
+ return err;
+ }
}
- /*The list of translators inherited from its ancestors*/
- char * trans;
-
- /*the number of translators*/
- size_t ntrans;
-
+ /*If we have a directory*/
+ if(isdir)
+ {
+ /*FIXME: It means we've got a directory, and no translators are set on
+ directories. The point is that nsmux should mainly handle libtrivs-based
+ translators, which should not operate on directories.*/
+ err = 0;
+ finalize();
+ return err;
+ }
+
+ /*If the current node has already been successfully translated*/
+ if(lnode->flags & FLAG_LNODE_TRANSLATED)
+ {
+ /*no additional translators must set on this file*/
+ err = 0;
+ finalize();
+ return err;
+ }
+
/*Obtain the list of inherited translators*/
err = lnode_list_translators(lnode, &trans, &ntrans);
if(err)
@@ -847,139 +1051,24 @@ netfs_attempt_lookup
return 0;
}
- int i;
-
- /*If there is a port open for the current node*/
- if((*node)->nn->port != MACH_PORT_NULL)
- {
- /*close the port, since we will open it when starting translators*/
- PORT_DEALLOC((*node)->nn->port);
- }
-
- /*Opens a port to the file at the request of fshelp_start_translator*/
- error_t
- open_port
- (
- int flags,
- mach_port_t * underlying,
- mach_msg_type_name_t * underlying_type,
- task_t task,
- void * cookie /*some additional information, not used here*/
- )
- {
- /*Lookup the file we are working with*/
- p = file_name_lookup_under
- (dir->nn->port, (*node)->nn->lnode->name, flags, 0);
- if(p == MACH_PORT_NULL)
- return errno;
-
- /*Store the result in the parameters*/
- *underlying = p;
- *underlying_type = MACH_MSG_TYPE_COPY_SEND;
-
- /*Here everything is OK*/
- return 0;
- }/*open_port*/
-
- /*Adds a "/hurd/" at the beginning of the translator name, if required*/
- char *
- put_in_hurd
- (
- 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/");
- strcpy(full + 6, name);
- full[6 + len] = 0;
-
- /*Return the full path*/
- return full;
- }/*put_in_hurd*/
-
- /*A copy (possibly extended) of the name of the translator*/
- char * ext;
-
- /*The length of the current component in the list of translators*/
- size_t complen;
-
- /*The holders of argz-transformed translator name and arguments*/
- char * argz = NULL;
- size_t argz_len = 0;
-
- /*The control port for the active translator*/
- mach_port_t active_control;
-
/*Go through the list of translators*/
for(str = trans, i = 0; i < ntrans; ++i)
{
- /*obtain the length of the current component*/
- complen = strlen(str);
-
- /*obtain a copy (possibly extended) of the name*/
- ext = put_in_hurd(str);
- if(!ext)
- {
- err = ENOMEM;
- finalize();
- return err;
- }
-
- /*TODO: Better argument-parsing?*/
-
- /*obtain the argz version of str*/
- err = argz_create_sep(ext, ' ', &argz, &argz_len);
+ /*set the translator specified in the current component*/
+ err = node_set_translator(dir, *node, str);
if(err)
{
finalize();
- return err;
+ return 0; /*TODO: A better way to fight errors here*/
}
-
- /*start the translator*/
- err = fshelp_start_translator
- (
- open_port, NULL, argz, argz, argz_len,
- 60000,/*this is the default in settrans*/
- &active_control
- );
- if(err)
- {
- finalize();
- 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
- );
- if(err)
- {
- finalize();
- return err;
- }
-
- /*deallocate the port we have just opened*/
- PORT_DEALLOC(p);
-
+
/*skip the current component*/
- str += complen + 1;
+ str += strlen(str) + 1;
}
+ /*All translators have been succesfully set on this node*/
+ lnode->flags |= FLAG_LNODE_TRANSLATED;
+
/*Everything OK here*/
finalize();
return err;