diff options
Diffstat (limited to 'libtreefs/dir-lookup.c')
-rw-r--r-- | libtreefs/dir-lookup.c | 313 |
1 files changed, 0 insertions, 313 deletions
diff --git a/libtreefs/dir-lookup.c b/libtreefs/dir-lookup.c deleted file mode 100644 index 33fefe69..00000000 --- a/libtreefs/dir-lookup.c +++ /dev/null @@ -1,313 +0,0 @@ -/* Default treefs_s_dir_lookup hook - - Copyright (C) 1992, 1993, 1994, 1995, 1998 Free Software Foundation, Inc. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include <fcntl.h> -#include <string.h> - -#include <hurd/fsys.h> - -#include "treefs.h" -#include "treefs-s-hooks.h" - -/* Default dir_lookup hook. This code was originally copied from diskfs. */ -error_t -_treefs_s_dir_lookup (struct treefs_handle *h, - char *path, int flags, mode_t mode, - enum retry_type *retry, char *retry_name, - file_t *result, mach_msg_type_name_t *result_type) -{ - struct treefs_node *dir; - struct treefs_node *node; - unsigned symlink_expansions = 0; - error_t err = 0; - char *path_buf = 0; - int path_buf_len = 0; - int lastcomp = 0; - int mustbedir = 0; - - flags &= O_HURD; - mode &= ~S_IFMT; - - /* Skip leading slashes */ - while (path[0] == '/') - path++; - - *result_type = MACH_MSG_TYPE_MAKE_SEND; - *retry = FS_RETRY_NORMAL; - retry_name[0] = '\0'; - - if (path[0] == '\0') - { - /* Set things up in the state expected by the code from gotit: on. */ - dir = 0; - node = h->po->node; - pthread_mutex_lock (&node->lock); - treefs_node_ref (node); - goto gotit; - } - - dir = h->po->node; - pthread_mutex_lock (&dir->lock); - node = 0; - - treefs_node_ref (dir); /* acquire a ref for later node_release */ - - do - { - char *nextname; - - assert_backtrace (!lastcomp); - - /* Find the name of the next pathname component */ - nextname = index (path, '/'); - - if (nextname) - { - *nextname++ = '\0'; - while (*nextname == '/') - nextname++; - if (*nextname == '\0') - { - /* These are the rules for filenames ending in /. */ - nextname = 0; - lastcomp = 1; - mustbedir = 1; - - } - else - lastcomp = 0; - } - else - lastcomp = 1; - - node = 0; - - /* Lookup the next pathname component. */ - if (!lastcomp) - err = treefs_dir_lookup (dir, path, h->auth, 0, 0, &node); - else - /* ... and in this case, the last. Note that the S_IFREG only - applies in the case of O_CREAT, which is turned off for - directories anyway. */ - err = - treefs_dir_lookup (dir, path, h->auth, flags, mode | S_IFREG, &node); - - /* If we get an error we're done */ - if (err == EAGAIN) - { - if (h->po->parent_port != MACH_PORT_NULL) - { - *retry = FS_RETRY_REAUTH; - *result = h->po->parent_port; - *result_type = MACH_MSG_TYPE_COPY_SEND; - if (!lastcomp) - strcpy (retry_name, nextname); - err = 0; - goto out; - } - else - /* The global filesystem root... .. == . */ - { - err = 0; - node = dir; - treefs_node_ref (node); - } - } - - if (err) - goto out; - - /* If this is translated, start the translator (if necessary) - and return. */ - /* The check for `node != dir' simplifies this code a great - deal. Such a translator should already have been started, - so there's no lossage in doing it this way. */ - if ((!lastcomp || !(flags & O_NOTRANS)) - && node != dir) - { - file_t dir_port = MACH_PORT_NULL, child_fsys; - - /* Be very careful not to hold an inode lock while fetching - a translator lock and vice versa. */ - - pthread_mutex_unlock (&node->lock); - pthread_mutex_unlock (&dir->lock); - - do - { - err = - treefs_node_get_active_trans (node, dir, h->po->parent_port, - &dir_port, &child_fsys); - if (err == 0 && child_fsys != MACH_PORT_NULL) - { - err = - fsys_getroot (child_fsys, dir_port, - MACH_MSG_TYPE_COPY_SEND, - h->auth->uids, h->auth->nuids, - h->auth->gids, h->auth->ngids, - lastcomp ? flags : 0, - retry, retry_name, result); - /* If we got MACH_SEND_INVALID_DEST or MIG_SERVER_DIED, then - the server is dead. Zero out the old control port and try - everything again. */ - if (err == MACH_SEND_INVALID_DEST || err == EMIG_SERVER_DIED) - treefs_node_drop_active_trans (node, child_fsys); - } - } - while (err == MACH_SEND_INVALID_DEST || err == EMIG_SERVER_DIED); - - if (err || child_fsys) - { - /* We're done; return to the user. If there are more - components after this name, be sure to append them to the - user's retry path. */ - if (!err && !lastcomp) - { - strcat (retry_name, "/"); - strcat (retry_name, nextname); - } - - *result_type = MACH_MSG_TYPE_MOVE_SEND; - - treefs_node_unref (dir); - treefs_node_unref (node); - if (dir_port) - mach_port_deallocate (mach_task_self (), dir_port); - - return err; - } - - /* We're here if we tried the translator check, and it - failed. Lock everything back, and make sure we do it - in the right order. */ - if (strcmp (path, "..") != 0) - { - if (pthread_mutex_trylock (&dir->lock)) - { - pthread_mutex_unlock (&node->lock); - pthread_mutex_lock (&dir->lock); - pthread_mutex_lock (&node->lock); - } - } - else - pthread_mutex_lock (&dir->lock); - } - - if (treefs_node_type (node) == S_IFLNK - && !(lastcomp && (flags & (O_NOLINK|O_NOTRANS)))) - /* Handle symlink interpretation */ - { - unsigned nextname_len = nextname ? strlen (nextname) + 1 : 0; - /* max space we currently have for the sym link */ - unsigned sym_len = path_buf_len - nextname_len - 1; - - if (symlink_expansions++ > node->fsys->max_symlinks) - { - err = ELOOP; - goto out; - } - - err = treefs_node_get_symlink (node, path_buf, &sym_len); - if (err == E2BIG) - /* Symlink contents + extra path won't fit in our buffer, so - reallocate it and try again. */ - { - path_buf_len = sym_len + nextname_len + 1 + 1; - path_buf = alloca (path_buf_len); - err = treefs_node_get_symlink (node, path_buf, &sym_len); - } - if (err) - goto out; - - if (nextname) - { - path_buf[sym_len] = '/'; - bcopy (nextname, path_buf + sym_len + 1, nextname_len - 1); - } - if (mustbedir) - { - path_buf[nextnamelen + sym_len] = '/'; - path_buf[nextnamelen + sym_len + 1] = '\0'; - } - else - path_buf[nextname_len + sym_len] = '\0'; - - if (path_buf[0] == '/') - { - /* Punt to the caller. */ - *retry = FS_RETRY_MAGICAL; - *result = MACH_PORT_NULL; - strcpy (retry_name, path_buf); - goto out; - } - - path = path_buf; - mustbedir = 0; - if (lastcomp) - { - lastcomp = 0; - /* Symlinks to nonexistent files aren't allowed to cause - creation, so clear the flag here. */ - flags &= ~O_CREAT; - } - treefs_node_release (node); - node = 0; - } - else - { - /* Handle normal nodes */ - path = nextname; - if (node == dir) - treefs_node_unref (dir); - else - treefs_node_release (dir); - if (!lastcomp) - { - dir = node; - node = 0; - } - else - dir = 0; - } - } while (path && *path); - - gotit: - /* At this point, node is the node to return. */ - - if (mustbedir && !treefs_node_isdir (node)) - err = ENOTDIR; - if (err) - goto out; - - err = treefs_node_create_right (node, flags, h->po->parent_port, h->auth, - result); - - out: - if (node) - { - if (dir == node) - treefs_node_unref (node); - else - treefs_node_release (node); - } - if (dir) - treefs_node_release (dir); - return err; -} |