diff options
Diffstat (limited to 'procfs.c')
-rw-r--r-- | procfs.c | 282 |
1 files changed, 168 insertions, 114 deletions
@@ -1,149 +1,203 @@ -/* procfs -- a translator for providing GNU/Linux compatible - proc pseudo-filesystem - - procfs.c -- This file is the main file of the translator. - This has important definitions and initializes - the translator - - Copyright (C) 2008, FSF. - Written as a Summer of Code Project - - procfs is free software; you can redistribute it and/or +/* Hurd /proc filesystem, basic infrastructure. + Copyright (C) 2010 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. - procfs is distributed in the hope that it will be useful, but + 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. -*/ + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <stdio.h> -#include <argp.h> -#include <string.h> #include <stdlib.h> - -#include <unistd.h> -#include <error.h> -#include <sys/stat.h> +#include <string.h> +#include <fcntl.h> +#include <mach.h> #include <hurd/netfs.h> - +#include <hurd/fshelp.h> #include "procfs.h" -/* Defines this Tanslator Name */ -char *netfs_server_name = PROCFS_SERVER_NAME; -char *netfs_server_version = PROCFS_SERVER_VERSION; -int netfs_maxsymlinks = 12; +struct netnode +{ + const struct procfs_node_ops *ops; + void *hook; -static const struct argp_child argp_children[] = - { - {&netfs_std_startup_argp, 0, NULL, 0}, - {0} - }; + /* (cached) contents of the node */ + char *contents; + ssize_t contents_len; + /* parent directory, if applicable */ + struct node *parent; +}; -const char *argp_program_version = "/proc pseudo-filesystem (" PROCFS_SERVER_NAME - ") " PROCFS_SERVER_VERSION "\n" -"Copyright (C) 2008 Free Software Foundation\n" -"This is free software; see the source for copying conditions. There is NO\n" -"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." -"\n"; +void +procfs_cleanup_contents_with_free (void *hook, char *cont, ssize_t len) +{ + free (cont); +} -static char *args_doc = "PROCFSROOT"; -static char *doc = "proc pseudo-filesystem for Hurd implemented as a translator. " -"This is still under very humble and initial stages of development.\n" -"Any Contribution or help is welcome. The code may not even compile"; +void +procfs_cleanup_contents_with_vm_deallocate (void *hook, char *cont, ssize_t len) +{ + vm_deallocate (mach_task_self (), (vm_address_t) cont, (vm_size_t) len); +} +struct node *procfs_make_node (const struct procfs_node_ops *ops, void *hook) +{ + struct netnode *nn; + struct node *np; + + nn = malloc (sizeof *nn); + if (! nn) + goto fail; + + memset (nn, 0, sizeof *nn); + nn->ops = ops; + nn->hook = hook; + + np = netfs_make_node (nn); + if (! np) + goto fail; + + np->nn = nn; + memset (&np->nn_stat, 0, sizeof np->nn_stat); + np->nn_translated = 0; + + if (np->nn->ops->lookup) + np->nn_stat.st_mode = S_IFDIR | 0555; + else + np->nn_stat.st_mode = S_IFREG | 0444; + + return np; + +fail: + if (ops->cleanup) + ops->cleanup (hook); + + free (nn); + return NULL; +} -/* The Filesystem */ -struct procfs *procfs; +void procfs_node_chown (struct node *np, uid_t owner) +{ + np->nn_stat.st_uid = owner; +} -/* The FILESYSTEM component of PROCFS_FS. */ -char *procfs_root = ""; +void procfs_node_chmod (struct node *np, mode_t mode) +{ + np->nn_stat.st_mode = (np->nn_stat.st_mode & S_IFMT) | mode; + np->nn_translated = np->nn_stat.st_mode; +} -volatile struct mapped_time_value *procfs_maptime; +void procfs_node_chtype (struct node *np, mode_t type) +{ + np->nn_stat.st_mode = (np->nn_stat.st_mode & ~S_IFMT) | type; + np->nn_translated = np->nn_stat.st_mode; + if (type == S_IFLNK) + procfs_node_chmod (np, 0777); +} + +/* FIXME: possibly not the fastest hash function... */ +ino64_t +procfs_make_ino (struct node *np, const char *filename) +{ + unsigned short x[3]; -/* Startup options. */ -static const struct argp_option procfs_options[] = - { - { 0 } - }; + if (! strcmp (filename, ".")) + return np->nn_stat.st_ino; + if (! strcmp (filename, "..")) + return np->nn->parent ? np->nn->parent->nn_stat.st_ino : /* FIXME: */ 2; - -/* argp parser function for parsing single procfs command line options */ -static error_t -parse_procfs_opt (int key, char *arg, struct argp_state *state) + assert (sizeof np->nn_stat.st_ino > sizeof x); + memcpy (x, &np->nn_stat.st_ino, sizeof x); + + while (*filename) + { + x[0] ^= *(filename++); + jrand48 (x); + } + + return (unsigned long) jrand48 (x); +} + +error_t procfs_get_contents (struct node *np, char **data, ssize_t *data_len) { - switch (key) + if (! np->nn->contents && np->nn->ops->get_contents) { - case ARGP_KEY_ARG: - if (state->arg_num > 1) - argp_usage (state); - break; - - case ARGP_KEY_NO_ARGS: - argp_usage(state); - break; - - default: - return ARGP_ERR_UNKNOWN; + char *contents; + ssize_t contents_len; + error_t err; + + contents_len = -1; + err = np->nn->ops->get_contents (np->nn->hook, &contents, &contents_len); + if (err) + return err; + if (contents_len < 0) + return ENOMEM; + + np->nn->contents = contents; + np->nn->contents_len = contents_len; } + + *data = np->nn->contents; + *data_len = np->nn->contents_len; + return 0; } -/* Program entry point. */ -int -main (int argc, char **argv) +void procfs_refresh (struct node *np) { - error_t err; - mach_port_t bootstrap, underlying_node; - struct stat underlying_stat; - - struct argp argp = + if (np->nn->contents && np->nn->ops->cleanup_contents) + np->nn->ops->cleanup_contents (np->nn->hook, np->nn->contents, np->nn->contents_len); + + np->nn->contents = NULL; +} + +error_t procfs_lookup (struct node *np, const char *name, struct node **npp) +{ + error_t err = ENOENT; + + if (err && ! strcmp (name, ".")) + { + netfs_nref(*npp = np); + err = 0; + } + + if (err && np->nn->parent && ! strcmp (name, "..")) { - procfs_options, parse_procfs_opt, - args_doc, doc, argp_children, - NULL, NULL - }; - - - /* Parse the command line arguments */ -// argp_parse (&argp, argc, argv, 0, 0, 0); - - task_get_bootstrap_port (mach_task_self (), &bootstrap); - - netfs_init (); - - if (maptime_map (0, 0, &procfs_maptime)) + netfs_nref(*npp = np->nn->parent); + err = 0; + } + + if (err && np->nn->ops->lookup) { - perror (PROCFS_SERVER_NAME ": Cannot map time"); - return 1; + err = np->nn->ops->lookup (np->nn->hook, name, npp); + if (! err) + { + (*npp)->nn_stat.st_ino = procfs_make_ino (np, name); + netfs_nref ((*npp)->nn->parent = np); + } } - - procfs_init (); - - err = procfs_create (procfs_root, getpid (), &procfs); - if (err) - error (4, err, "%s", procfs_root); - - /* Create our root node */ - netfs_root_node = procfs->root; - - /* Start netfs activities */ - underlying_node = netfs_startup (bootstrap, 0); - if (io_stat (underlying_node, &underlying_stat)) - error (1, err, "cannot stat underling node"); - - /* Initialize stat information of the root node. */ - netfs_root_node->nn_stat = underlying_stat; - netfs_root_node->nn_stat.st_mode = - S_IFDIR | (underlying_stat.st_mode & ~S_IFMT & ~S_ITRANS); - - for (;;) - netfs_server_loop (); - return 1; + + return err; +} + +void procfs_cleanup (struct node *np) +{ + procfs_refresh (np); + + if (np->nn->ops->cleanup) + np->nn->ops->cleanup (np->nn->hook); + + if (np->nn->parent) + netfs_nrele (np->nn->parent); + + free (np->nn); } |