summaryrefslogtreecommitdiff
path: root/procfs/procfs.c
diff options
context:
space:
mode:
authorJustus Winter <4winter@informatik.uni-hamburg.de>2014-06-15 18:25:59 +0200
committerJustus Winter <4winter@informatik.uni-hamburg.de>2014-06-15 18:25:59 +0200
commitaac4aaf42372f61c78061711916c81a9d5bcb42d (patch)
tree167fb3e426cc7757a43da2c7d04fc2baa293c5de /procfs/procfs.c
parent65ebcc40e55dfb3ee776383891f8a6b15b176d27 (diff)
Prepare the procfs translator to be merged into the Hurd sourcesHEADmaster
Move the procfs translator to its own subdirectory 'procfs'. This is the last commit to this repository. Development of the procfs translator will continue in the main Hurd repository. * procfs/Makefile: Replace the standalone Makefile with the one from the Debian packaging repository.
Diffstat (limited to 'procfs/procfs.c')
-rw-r--r--procfs/procfs.c219
1 files changed, 219 insertions, 0 deletions
diff --git a/procfs/procfs.c b/procfs/procfs.c
new file mode 100644
index 0000000..cae4a51
--- /dev/null
+++ b/procfs/procfs.c
@@ -0,0 +1,219 @@
+/* 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.
+
+ 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 <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <mach.h>
+#include <hurd/netfs.h>
+#include <hurd/fshelp.h>
+#include "procfs.h"
+
+struct netnode
+{
+ const struct procfs_node_ops *ops;
+ void *hook;
+
+ /* (cached) contents of the node */
+ char *contents;
+ ssize_t contents_len;
+
+ /* parent directory, if applicable */
+ struct node *parent;
+};
+
+void
+procfs_cleanup_contents_with_free (void *hook, char *cont, ssize_t len)
+{
+ free (cont);
+}
+
+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;
+
+ np->nn_stat.st_uid = getuid ();
+ np->nn_stat.st_gid = getgid ();
+
+ return np;
+
+fail:
+ if (ops->cleanup)
+ ops->cleanup (hook);
+
+ free (nn);
+ return NULL;
+}
+
+void procfs_node_chown (struct node *np, uid_t owner)
+{
+ np->nn_stat.st_uid = owner;
+}
+
+void procfs_node_chmod (struct node *np, mode_t mode)
+{
+ np->nn_stat.st_mode = (np->nn_stat.st_mode & ~ALLPERMS) | mode;
+ np->nn_translated = np->nn_stat.st_mode;
+}
+
+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];
+
+ 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;
+
+ 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)
+{
+ if (! np->nn->contents && np->nn->ops->get_contents)
+ {
+ 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;
+}
+
+void procfs_refresh (struct node *np)
+{
+ 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, ".."))
+ {
+ netfs_nref(*npp = np->nn->parent);
+ err = 0;
+ }
+
+ if (err && np->nn->ops->lookup)
+ {
+ 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);
+ }
+ }
+
+ 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);
+}
+
+error_t procfs_get_translator (struct node *np,
+ char **argz,
+ size_t *argz_len)
+{
+ if (np->nn->ops->get_translator)
+ return np->nn->ops->get_translator (np->nn->hook, argz, argz_len);
+
+ *argz = NULL;
+ *argz_len = 0;
+ return 0;
+}