summaryrefslogtreecommitdiff
path: root/hostmux/mux.c
diff options
context:
space:
mode:
Diffstat (limited to 'hostmux/mux.c')
-rw-r--r--hostmux/mux.c401
1 files changed, 0 insertions, 401 deletions
diff --git a/hostmux/mux.c b/hostmux/mux.c
deleted file mode 100644
index cba29126..00000000
--- a/hostmux/mux.c
+++ /dev/null
@@ -1,401 +0,0 @@
-/* Root hostmux node
-
- Copyright (C) 1997 Free Software Foundation, Inc.
- Written by Miles Bader <miles@gnu.ai.mit.edu>
- 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */
-
-#include <stddef.h>
-#include <string.h>
-#include <dirent.h>
-#include <netdb.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-
-#include "hostmux.h"
-
-error_t create_host_node (struct hostmux *mux, struct hostmux_name *name,
- struct node **node);
-
-/* Returned directory entries are aligned to blocks this many bytes long.
- Must be a power of two. */
-#define DIRENT_ALIGN 4
-#define DIRENT_NAME_OFFS offsetof (struct dirent, d_name)
-
-/* Length is structure before the name + the name + '\0', all
- padded to a four-byte alignment. */
-#define DIRENT_LEN(name_len) \
- ((DIRENT_NAME_OFFS + (name_len) + 1 + (DIRENT_ALIGN - 1)) \
- & ~(DIRENT_ALIGN - 1))
-
-static error_t lookup_host (struct hostmux *mux, const char *host,
- struct node **node); /* fwd decl */
-
-/* [root] Directory operations. */
-
-/* Lookup NAME in DIR for USER; set *NODE to the found name upon return. If
- the name was not found, then return ENOENT. On any error, clear *NODE.
- (*NODE, if found, should be locked, this call should unlock DIR no matter
- what.) */
-error_t
-netfs_attempt_lookup (struct iouser *user, struct node *dir,
- char *name, struct node **node)
-{
- error_t err;
-
- if (dir->nn->name)
- err = ENOTDIR;
- else
- err = lookup_host (dir->nn->mux, name, node);
-
- touch (dir, TOUCH_ATIME);
-
- mutex_unlock (&dir->lock);
-
- if (! err)
- mutex_lock (&(*node)->lock);
-
- return err;
-}
-
-/* Implement the netfs_get_directs callback as described in
- <hurd/netfs.h>. */
-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)
-{
- error_t err;
- int count;
- size_t size = 0; /* Total size of our return block. */
- struct hostmux_name *first_name, *nm;
-
- if (dir->nn->name)
- return ENOTDIR;
-
- rwlock_reader_lock (&dir->nn->mux->names_lock);
-
- /* Find the first entry. */
- for (first_name = dir->nn->mux->names;
- first_name && first_entry > 0;
- first_name = first_name->next)
- if (first_name->node)
- first_entry--;
-
- /* See how much space we need for the result. */
- for (nm = first_name, count = 0;
- nm && (num_entries == -1 || count < num_entries);
- nm = nm->next)
- if (nm->node)
- {
- size_t new_size = size + DIRENT_LEN (strlen (nm->name));
- if (new_size > max_data_len)
- break;
- size = new_size;
- count++;
- }
-
- /* Allocate it. */
- err = vm_allocate (mach_task_self (), (vm_address_t *) data, size, 1);
- if (! err)
- /* Copy out the result. */
- {
- char *p = *data;
-
- *data_len = size;
- *data_entries = count;
-
- /* See how much space we need for the result. */
- for (nm = first_name, count = 0;
- nm && (num_entries == -1 || count < num_entries);
- nm = nm->next)
- if (nm->node)
- {
- struct dirent hdr;
- size_t name_len = strlen (nm->name);
- size_t sz = DIRENT_LEN (name_len);
-
- if (sz > size)
- break;
- else
- size -= sz;
-
- hdr.d_fileno = nm->fileno;
- hdr.d_reclen = sz;
- hdr.d_type =
- (strcmp (nm->canon, nm->name) == 0 ? DT_REG : DT_LNK);
- hdr.d_namlen = name_len;
-
- memcpy (p, &hdr, DIRENT_NAME_OFFS);
- strcpy (p + DIRENT_NAME_OFFS, nm->name);
- p += sz;
-
- count++;
- }
-
- }
-
- rwlock_reader_unlock (&dir->nn->mux->names_lock);
-
- touch (dir, TOUCH_ATIME);
-
- return err;
-}
-
-/* Host lookup. */
-
-/* Free storage allocated consumed by the host mux name NM, but not the node
- it points to. */
-static void
-free_name (struct hostmux_name *nm)
-{
- free ((char *)nm->name);
- if (nm->name != nm->canon)
- free ((char *)nm->canon);
- free (nm);
-}
-
-/* See if there's an existing entry for the name HOST, and if so, return its
- node in NODE with an additional references. True is returned iff the
- lookup succeeds. If PURGE is true, then any nodes with a null node are
- removed. */
-static int
-lookup_cached (struct hostmux *mux, const char *host, int purge,
- struct node **node)
-{
- struct hostmux_name *nm = mux->names, **prevl = &mux->names;
-
- while (nm)
- {
- struct hostmux_name *next = nm->next;
-
- if (strcasecmp (host, nm->name) == 0)
- {
- spin_lock (&netfs_node_refcnt_lock);
- if (nm->node)
- nm->node->references++;
- spin_unlock (&netfs_node_refcnt_lock);
-
- if (nm->node)
- {
- *node = nm->node;
- return 1;
- }
- }
-
- if (purge && !nm->node)
- {
- *prevl = nm->next;
- free_name (nm);
- }
- else
- prevl = &nm->next;
-
- nm = next;
- }
-
- return 0;
-}
-
-/* See if there's an existing entry for the name HOST, and if so, return its
- node in NODE, with an additional reference, otherwise, create a new node
- for the host HE as referred to by HOST, and return that instead, with a
- single reference. The type of node created is either a translator node,
- if HOST refers to the official name of the host, or a symlink node to the
- official name, if it doesn't. */
-static error_t
-lookup_hostent (struct hostmux *mux, const char *host, struct hostent *he,
- struct node **node)
-{
- error_t err;
- struct hostmux_name *nm = malloc (sizeof (struct hostmux_name));
-
- if (! nm)
- return ENOMEM;
-
- nm->name = strdup (host);
- if (strcmp (host, he->h_name) == 0)
- nm->canon = nm->name;
- else
- nm->canon = strdup (he->h_name);
-
- err = create_host_node (mux, nm, node);
- if (err)
- {
- free_name (nm);
- return err;
- }
-
- rwlock_writer_lock (&mux->names_lock);
- if (lookup_cached (mux, host, 1, node))
- /* An entry for HOST has already been created between the time we last
- looked and now (which is possible because we didn't lock MUX).
- Just throw away our version and return the one already in the cache. */
- {
- rwlock_writer_unlock (&mux->names_lock);
- nm->node->nn->name = 0; /* Avoid touching the mux name list. */
- netfs_nrele (nm->node); /* Free the tentative new node. */
- free_name (nm); /* And the name it was under. */
- }
- else
- /* Enter NM into MUX's list of names, and return the new node. */
- {
- nm->fileno = mux->next_fileno++; /* Now that we hold the lock... */
- nm->next = mux->names;
- mux->names = nm;
- rwlock_writer_unlock (&mux->names_lock);
- }
-
- return 0;
-}
-
-/* Lookup the host HOST in MUX, and return the resulting node in NODE, with
- an additional reference, or an error. */
-static error_t
-lookup_host (struct hostmux *mux, const char *host, struct node **node)
-{
- int was_cached;
- int h_err;
- struct hostent _he, *he;
- struct in_addr inet_addr;
- char hostent_data[2048]; /* XXX what size should this be???? */
-
- rwlock_reader_lock (&mux->names_lock);
- was_cached = lookup_cached (mux, host, 0, node);
- rwlock_reader_unlock (&mux->names_lock);
-
- if (was_cached)
- return 0;
- else if (inet_aton (host, &inet_addr))
- {
- if (gethostbyaddr_r ((char *)&inet_addr, sizeof inet_addr, AF_INET,
- &_he, hostent_data, sizeof hostent_data,
- &he, &h_err) == 0)
- return lookup_hostent (mux, host, he, node);
- else
- return ENOENT;
- }
- else if (gethostbyname_r (host, &_he, hostent_data, sizeof hostent_data,
- &he, &h_err) == 0)
- return lookup_hostent (mux, host, he, node);
- else
- return ENOENT;
-}
-
-/* This should sync the entire remote filesystem. If WAIT is set, return
- only after sync is completely finished. */
-error_t
-netfs_attempt_syncfs (struct iouser *cred, int wait)
-{
- return 0;
-}
-
-/* This should attempt a chmod call for the user specified by CRED on node
- NODE, to change the owner to UID and the group to GID. */
-error_t
-netfs_attempt_chown (struct iouser *cred, struct node *node, uid_t uid, uid_t gid)
-{
- if (node->nn->name)
- return EOPNOTSUPP;
- else
- {
- struct hostmux *mux = node->nn->mux;
- error_t err = file_chown (mux->underlying, uid, gid);
-
- if (! err)
- {
- struct hostmux_name *nm;
-
- /* Change NODE's owner. */
- mux->stat_template.st_uid = uid;
- mux->stat_template.st_gid = gid;
- node->nn_stat.st_uid = uid;
- node->nn_stat.st_gid = gid;
-
- /* Change the owner of each leaf node. */
- rwlock_reader_lock (&mux->names_lock);
- for (nm = mux->names; nm; nm = nm->next)
- if (nm->node)
- {
- nm->node->nn_stat.st_uid = uid;
- nm->node->nn_stat.st_gid = gid;
- }
- rwlock_reader_unlock (&mux->names_lock);
-
- touch (node, TOUCH_CTIME);
- }
-
- return err;
- }
-}
-
-/* This should attempt a chauthor call for the user specified by CRED on node
- NODE, to change the author to AUTHOR. */
-error_t
-netfs_attempt_chauthor (struct iouser *cred, struct node *node, uid_t author)
-{
- if (node->nn->name)
- return EOPNOTSUPP;
- else
- {
- struct hostmux *mux = node->nn->mux;
- error_t err = file_chauthor (mux->underlying, author);
-
- if (! err)
- {
- struct hostmux_name *nm;
-
- /* Change NODE's owner. */
- mux->stat_template.st_author = author;
- node->nn_stat.st_author = author;
-
- /* Change the owner of each leaf node. */
- rwlock_reader_lock (&mux->names_lock);
- for (nm = mux->names; nm; nm = nm->next)
- if (nm->node)
- nm->node->nn_stat.st_author = author;
- rwlock_reader_unlock (&mux->names_lock);
-
- touch (node, TOUCH_CTIME);
- }
-
- return err;
- }
-}
-
-/* This should attempt a chmod call for the user specified by CRED on node
- NODE, to change the mode to MODE. Unlike the normal Unix and Hurd meaning
- of chmod, this function is also used to attempt to change files into other
- types. If such a transition is attempted which is impossible, then return
- EOPNOTSUPP. */
-error_t
-netfs_attempt_chmod (struct iouser *cred, struct node *node, mode_t mode)
-{
- mode &= ~S_ITRANS;
- if (node->nn->name || ((mode & S_IFMT) != (node->nn_stat.st_mode & S_IFMT)))
- return EOPNOTSUPP;
- else
- {
- error_t err = file_chmod (node->nn->mux->underlying, mode & ~S_IFMT);
- if (! err)
- {
- node->nn_stat.st_mode = mode;
- touch (node, TOUCH_CTIME);
- }
- return err;
- }
-}