summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergiu Ivanov <unlimitedscolobb@gmail.com>2008-10-17 20:56:13 +0300
committerSergiu Ivanov <unlimitedscolobb@gmail.com>2008-10-17 20:56:13 +0300
commit38387c44b0b5bb172b4bd9b7d3469e928fb7abfa (patch)
treef7f12f6e656a0fdba8ae5790e58b16264a8893eb
parentd423d38a81328723675049349993737b1a95ec16 (diff)
Implemented the traversal of the static translator stack.
trace_find can now traverse the translator stack, stop at the necessary translator and return a port to it.
-rw-r--r--trace.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/trace.c b/trace.c
index a9415322e..829cc7504 100644
--- a/trace.c
+++ b/trace.c
@@ -48,5 +48,167 @@ trace_find
mach_port_t * port
)
{
+ error_t err = 0;
+
+ /*Identity information about the current process*/
+ uid_t * uids;
+ size_t nuids;
+
+ gid_t * gids;
+ size_t ngids;
+
+ /*The name and arguments of the translator being passed now*/
+ char * argz = NULL;
+ size_t argz_len = 0;
+
+ /*The current working directory*/
+ char * cwd = NULL;
+
+ /*The port to the directory containing the file pointed to by `underlying`*/
+ file_t dir;
+
+ /*The unauthenticated version of `dir`*/
+ file_t unauth_dir;
+
+ /*The control port of the current translator*/
+ fsys_t fsys;
+
+ /*The port to the translator we are currently looking at*/
+ mach_port_t node = underlying;
+
+ /*The retry name and retry type returned by fsys_getroot*/
+ string_t retry_name;
+ retry_type retry;
+
+ /*Finalizes the execution of this function*/
+ void
+ finalize(void)
+ {
+ /*If there is a working directory, free it*/
+ if(cwd)
+ free(cwd);
+
+ /*If the ports to the directory exist*/
+ if(dir)
+ PORT_DEALLOC(dir);
+ }/*finalize*/
+
+ /*Obtain the current working directory*/
+ cwd = getcwd(NULL, 0);
+ if(!cwd)
+ {
+ LOG_MSG("trace_find: Could not obtain cwd.");
+ return EINVAL;
+ }
+ LOG_MSG("trace_find: cwd: '%s'", cwd);
+
+ /*Open a port to this directory*/
+ dir = file_name_lookup(cwd, 0, 0);
+ if(!dir)
+ {
+ finalize();
+ return ENOENT;
+ }
+
+ /*Try to get the number of effective UIDs*/
+ nuids = geteuids(0, 0);
+ if(nuids < 0)
+ {
+ finalize();
+ return EINVAL;
+ }
+
+ /*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)
+ {
+ finalize();
+ return EINVAL;
+ }
+
+ /*Try to get the number of effective GIDs*/
+ ngids = getgroups(0, 0);
+ if(ngids < 0)
+ {
+ finalize();
+ return EINVAL;
+ }
+
+ /*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)
+ {
+ finalize();
+ return EINVAL;
+ }
+
+ /*Obtain the unauthenticated version of `dir`*/
+ err = io_restrict_auth(dir, &unauth_dir, 0, 0, 0, 0);
+ if(err)
+ {
+ finalize();
+ return err;
+ }
+
+ /*Go up the translator stack*/
+ for(; !err;)
+ {
+ /*retreive the name and options of the current translator*/
+ err = file_get_fs_options(node, &argz, &argz_len);
+ if(err)
+ break;
+
+ LOG_MSG("trace_find: Obtained translator '%s'", argz);
+
+ if(strcmp(argz, name) == 0)
+ {
+ LOG_MSG("trace_find: Match. Stopping here.");
+ break;
+ }
+
+ /*try to fetch the control port for this translator*/
+ err = file_get_translator_cntl(node, &fsys);
+ LOG_MSG("trace_find: err = %d", (int)err);
+ if(err)
+ break;
+
+ LOG_MSG("trace_find: Translator control port: %lu", (unsigned long)fsys);
+
+ /*fetch the root of the translator*/
+ err = fsys_getroot
+ (
+ fsys, unauth_dir, MACH_MSG_TYPE_COPY_SEND,
+ uids, nuids, gids, ngids,
+ flags | O_NOTRANS, &retry, retry_name, &node
+ );
+
+ LOG_MSG("trace_find: Translator root: %lu", (unsigned long)node);
+
+ /*TODO: Remove this debug output.*/
+ /*char buf[256];
+ char * _buf = buf;
+ size_t len = 256;
+ io_read(node, &_buf, &len, 0, len);
+ LOG_MSG("trace_find: Read: '%s'", buf);*/
+ }
+
+ /*If the error occurred (most probably) because of the fact that we
+ have reached the top of the translator stack*/
+ if((err == EMACH_SEND_INVALID_DEST) || (err == ENXIO))
+ /*this is OK*/
+ err = 0;
+
+ /*Return the port to read from*/
+ *port = node;
+
+ /*Return the result of operations*/
+ finalize();
+ return err;
}/*trace_find*/
/*----------------------------------------------------------------------------*/