summaryrefslogtreecommitdiff
path: root/procfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'procfs.c')
-rw-r--r--procfs.c282
1 files changed, 168 insertions, 114 deletions
diff --git a/procfs.c b/procfs.c
index 1fd0d619..ae5a6769 100644
--- a/procfs.c
+++ b/procfs.c
@@ -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);
}