diff options
-rw-r--r-- | debian/patches/external.patch | 8 | ||||
-rw-r--r-- | procfs/ChangeLog | 6 | ||||
-rw-r--r-- | procfs/TODO | 24 | ||||
-rw-r--r-- | procfs/dircat.c | 128 | ||||
-rw-r--r-- | procfs/dircat.h | 29 | ||||
-rw-r--r-- | procfs/main.c | 315 | ||||
-rw-r--r-- | procfs/main.h | 25 | ||||
-rw-r--r-- | procfs/netfs.c | 461 | ||||
-rw-r--r-- | procfs/process.c | 414 | ||||
-rw-r--r-- | procfs/process.h | 27 | ||||
-rw-r--r-- | procfs/procfs.c | 219 | ||||
-rw-r--r-- | procfs/procfs.h | 99 | ||||
-rw-r--r-- | procfs/procfs_dir.c | 134 | ||||
-rw-r--r-- | procfs/procfs_dir.h | 63 | ||||
-rw-r--r-- | procfs/proclist.c | 94 | ||||
-rw-r--r-- | procfs/proclist.h | 23 | ||||
-rw-r--r-- | procfs/rootdir.c | 661 | ||||
-rw-r--r-- | procfs/rootdir.h | 23 | ||||
-rw-r--r-- | random/Makefile | 31 | ||||
-rw-r--r-- | random/TODO | 11 | ||||
-rw-r--r-- | random/gnupg-bithelp.h | 41 | ||||
-rw-r--r-- | random/gnupg-glue.h | 40 | ||||
-rw-r--r-- | random/gnupg-random.c | 810 | ||||
-rw-r--r-- | random/gnupg-random.h | 47 | ||||
-rw-r--r-- | random/gnupg-rmd.h | 38 | ||||
-rw-r--r-- | random/gnupg-rmd160.c | 656 | ||||
-rw-r--r-- | random/mig-decls.h | 47 | ||||
-rw-r--r-- | random/mig-mutate.h | 25 | ||||
-rw-r--r-- | random/random.c | 621 | ||||
-rw-r--r-- | random/random.h | 32 |
30 files changed, 5 insertions, 5147 deletions
diff --git a/debian/patches/external.patch b/debian/patches/external.patch index cfdbda37..a8355c26 100644 --- a/debian/patches/external.patch +++ b/debian/patches/external.patch @@ -14,12 +14,14 @@ Index: hurd-debian/Makefile # Hurd programs prog-subdirs = auth proc exec init term \ -@@ -40,7 +41,7 @@ +@@ -40,9 +41,10 @@ login daemons boot console \ hostmux usermux ftpfs trans \ console-client utils sutils \ -- benchmarks fstests -+ benchmarks fstests procfs random devnode + benchmarks fstests \ + random \ + procfs \ ++ devnode \ ifeq ($(HAVE_SUN_RPC),yes) prog-subdirs += nfs nfsd diff --git a/procfs/ChangeLog b/procfs/ChangeLog deleted file mode 100644 index 0cd74d02..00000000 --- a/procfs/ChangeLog +++ /dev/null @@ -1,6 +0,0 @@ -edb4593c38d421b5d538b221a991b50c36fdba15 is the last commit imported from CVS. -All commits after that one have valid author and committer information. - -Use this to examine the change log for earlier changes: - - $ git show edb4593c38d421b5d538b221a991b50c36fdba15:ChangeLog diff --git a/procfs/TODO b/procfs/TODO deleted file mode 100644 index 952d67bc..00000000 --- a/procfs/TODO +++ /dev/null @@ -1,24 +0,0 @@ -Known bugs to be fixed ----------------------- - -* The non-owned processes sometimes show up with INT_MAX as their owner, - instead of opt_anon_uid. This is likely to be a libps problem. - -Improvements and new features ------------------------------ - -* There is a lot of dynamic memory allocation going on and it comes with a - cost in performance. We could try to limit such allocation, as long as it - keeps the inner interface simple and preserves the read/readdir semantics - (performance is probably not critical for a proc filesystem.) - One way would be to add an (optional) "needed_length" field to - procfs_node_ops, and arrange to pass a sufficent buffer in (*contents, - *contents_len) when get_contents is called. Then the user-provided buffer - might be used directly under some circumstances. - -* Add thread directories as [pid]/task/[n]. This shouldn't be too hard if we - use "process" nodes for threads, and provide an "exists" hook for the "task" - entry itself so that it's disabled in thread nodes. It might prove necessary - to have "optional" libps flags for some content generators, though, since - some of them might be missing for threads. - diff --git a/procfs/dircat.c b/procfs/dircat.c deleted file mode 100644 index 5a60899a..00000000 --- a/procfs/dircat.c +++ /dev/null @@ -1,128 +0,0 @@ -/* Hurd /proc filesystem, concatenation of two directories. - 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 "procfs.h" - -struct dircat_node -{ - int num_dirs; - struct node *dirs[0]; -}; - -static error_t -dircat_get_contents (void *hook, char **contents, ssize_t *contents_len) -{ - struct dircat_node *dcn = hook; - int i, sz, pos; - error_t err; - - pos = 0; - *contents = malloc (sz = 512); - - for (i=0; i < dcn->num_dirs; i++) - { - char *subcon; - ssize_t sublen; - - /* Make sure we're not getting some old stuff. */ - procfs_refresh (dcn->dirs[i]); - - err = procfs_get_contents (dcn->dirs[i], &subcon, &sublen); - if (err) - { - free (*contents); - *contents = NULL; - return err; - } - - while (pos + sublen > sz) - *contents = realloc (*contents, sz *= 2); - - memcpy (*contents + pos, subcon, sublen); - pos += sublen; - } - - *contents_len = pos; - return 0; -} - -static error_t -dircat_lookup (void *hook, const char *name, struct node **np) -{ - struct dircat_node *dcn = hook; - error_t err; - int i; - - err = ENOENT; - for (i=0; err && i < dcn->num_dirs; i++) - err = procfs_lookup (dcn->dirs[i], name, np); - - return err; -} - -static void -dircat_release_dirs (struct node *const *dirs, int num_dirs) -{ - int i; - - for (i=0; i < num_dirs; i++) - if (dirs[i]) - netfs_nrele (dirs[i]); -} - -static void -dircat_cleanup (void *hook) -{ - struct dircat_node *dcn = hook; - - dircat_release_dirs (dcn->dirs, dcn->num_dirs); - free (dcn); -} - -struct node * -dircat_make_node (struct node *const *dirs, int num_dirs) -{ - static struct procfs_node_ops ops = { - .get_contents = dircat_get_contents, - .cleanup_contents = procfs_cleanup_contents_with_free, - .lookup = dircat_lookup, - .cleanup = dircat_cleanup, - }; - struct dircat_node *dcn; - int i; - - for (i=0; i < num_dirs; i++) - if (! dirs[i]) - goto fail; - - dcn = malloc (sizeof *dcn + num_dirs * sizeof dcn->dirs[0]); - if (! dcn) - goto fail; - - dcn->num_dirs = num_dirs; - memcpy (dcn->dirs, dirs, num_dirs * sizeof dcn->dirs[0]); - return procfs_make_node (&ops, dcn); - -fail: - dircat_release_dirs (dirs, num_dirs); - return NULL; -} - diff --git a/procfs/dircat.h b/procfs/dircat.h deleted file mode 100644 index 4177b384..00000000 --- a/procfs/dircat.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Hurd /proc filesystem, concatenation of two directories. - 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. */ - -/* Append the contents of NUM_DIRS directories. DIRS is an array of - directory nodes. One reference is consumed for each of them. If a - memory allocation error occurs, or if one of the directories is a - NULL pointer, the references are dropped immediately and NULL is - returned. The given DIRS array is duplicated and can therefore be - allocated on the caller's stack. Strange things will happen if some - elements of DIRS have entries with the same name or if one of them is - not a directory. */ -struct node * -dircat_make_node (struct node *const *dirs, int num_dirs); diff --git a/procfs/main.c b/procfs/main.c deleted file mode 100644 index 54e96823..00000000 --- a/procfs/main.c +++ /dev/null @@ -1,315 +0,0 @@ -/* Hurd /proc filesystem, main program. - 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 <mach.h> -#include <hurd.h> -#include <unistd.h> -#include <error.h> -#include <argp.h> -#include <argz.h> -#include <hurd/netfs.h> -#include <ps.h> -#include "procfs.h" -#include "proclist.h" -#include "rootdir.h" -#include "dircat.h" -#include "main.h" - -/* Command-line options */ -int opt_clk_tck; -mode_t opt_stat_mode; -pid_t opt_fake_self; -pid_t opt_kernel_pid; -uid_t opt_anon_owner; - -/* Default values */ -#define OPT_CLK_TCK sysconf(_SC_CLK_TCK) -#define OPT_STAT_MODE 0400 -#define OPT_FAKE_SELF -1 -#define OPT_KERNEL_PID 2 -#define OPT_ANON_OWNER 0 - -#define NODEV_KEY -1 /* <= 0, so no short option. */ -#define NOEXEC_KEY -2 /* Likewise. */ -#define NOSUID_KEY -3 /* Likewise. */ - -static error_t -argp_parser (int key, char *arg, struct argp_state *state) -{ - struct passwd *pw; - char *endp; - long int v; - - switch (key) - { - case 'h': - v = strtol (arg, &endp, 0); - if (*endp || ! *arg || v <= 0) - argp_error (state, "--clk-tck: HZ should be a positive integer"); - else - opt_clk_tck = v; - break; - - case 's': - v = strtol (arg, &endp, 8); - if (*endp || ! *arg || (mode_t) v & ~07777) - argp_error (state, "--stat-mode: MODE should be an octal mode"); - else - opt_stat_mode = v; - break; - - case 'S': - if (arg) - { - v = strtol (arg, &endp, 0); - if (*endp || ! *arg) - argp_error (state, "--fake-self: PID must be an integer"); - else - opt_fake_self = v; - } - else - opt_fake_self = 1; - break; - - case 'k': - v = strtol (arg, &endp, 0); - if (*endp || ! *arg || (signed) opt_kernel_pid < 0) - argp_error (state, "--kernel-process: PID must be a positive integer"); - else - opt_kernel_pid = v; - break; - - case 'c': - opt_clk_tck = 100; - opt_stat_mode = 0444; - opt_fake_self = 1; - break; - - case 'a': - pw = getpwnam (arg); - if (pw) - { - opt_anon_owner = pw->pw_uid; - break; - } - - v = strtol (arg, &endp, 0); - if (*endp || ! *arg || v < 0) - argp_error (state, "--anonymous-owner: USER should be " - "a user name or a numeric UID."); - else - opt_anon_owner = v; - break; - - case NODEV_KEY: - /* Ignored for compatibility with Linux' procfs. */ - ;; - - case NOEXEC_KEY: - /* Ignored for compatibility with Linux' procfs. */ - ;; - - case NOSUID_KEY: - /* Ignored for compatibility with Linux' procfs. */ - ;; - - default: - return ARGP_ERR_UNKNOWN; - } - - return 0; -} - -struct argp_option common_options[] = { - { "clk-tck", 'h', "HZ", 0, - "Unit used for the values expressed in system clock ticks " - "(default: sysconf(_SC_CLK_TCK))" }, - { "stat-mode", 's', "MODE", 0, - "The [pid]/stat file publishes information which on Hurd is only " - "available to the process owner. " - "You can use this option to override its mode to be more permissive " - "for compatibility purposes. " - "(default: 0400)" }, - { "fake-self", 'S', "PID", OPTION_ARG_OPTIONAL, - "Provide a fake \"self\" symlink to the given PID, for compatibility " - "purposes. If PID is omitted, \"self\" will point to init. " - "(default: no self link)" }, - { "kernel-process", 'k', "PID", 0, - "Process identifier for the kernel, used to retreive its command " - "line, as well as the global up and idle times. " - "(default: 2)" }, - { "compatible", 'c', NULL, 0, - "Try to be compatible with the Linux procps utilities. " - "Currently equivalent to -h 100 -s 0444 -S 1." }, - { "anonymous-owner", 'a', "USER", 0, - "Make USER the owner of files related to processes without one. " - "Be aware that USER will be granted access to the environment and " - "other sensitive information about the processes in question. " - "(default: use uid 0)" }, - { "nodev", NODEV_KEY, NULL, 0, - "Ignored for compatibility with Linux' procfs." }, - { "noexec", NOEXEC_KEY, NULL, 0, - "Ignored for compatibility with Linux' procfs." }, - { "nosuid", NOSUID_KEY, NULL, 0, - "Ignored for compatibility with Linux' procfs." }, - {} -}; - -struct argp argp = { - .options = common_options, - .parser = argp_parser, - .doc = "A virtual filesystem emulating the Linux procfs.", - .children = (struct argp_child []) { - { &netfs_std_startup_argp, }, - {} - }, -}; - -static error_t -runtime_argp_parser (int key, char *arg, struct argp_state *state) -{ - switch (key) - { - case 'u': - /* do nothing */ - break; - - default: - return ARGP_ERR_UNKNOWN; - } - - return 0; -} - -struct argp runtime_argp = { - .options = (struct argp_option []) { - { "update", 'u', NULL, 0, "remount; for procfs this does nothing" }, - {}, - }, - .parser = runtime_argp_parser, -}; - -struct argp netfs_runtime_argp_ = { - .options = common_options, - .parser = argp_parser, - .doc = "A virtual filesystem emulating the Linux procfs.", - .children = (struct argp_child []) { - { &runtime_argp, }, - { &netfs_std_runtime_argp, }, - {} - }, -}; - -/* Used by netfs_set_options to handle runtime option parsing. */ -struct argp *netfs_runtime_argp = &argp; - -/* Return an argz string describing the current options. Fill *ARGZ - with a pointer to newly malloced storage holding the list and *LEN - to the length of that storage. */ -error_t -netfs_append_args (char **argz, size_t *argz_len) -{ - char buf[80]; - error_t err = 0; - -#define FOPT(opt, default, fmt, args...) \ - do { \ - if (! err && opt != default) \ - { \ - snprintf (buf, sizeof buf, fmt, ## args); \ - err = argz_add (argz, argz_len, buf); \ - } \ - } while (0) - - FOPT (opt_clk_tck, OPT_CLK_TCK, - "--clk-tck=%d", opt_clk_tck); - - FOPT (opt_stat_mode, OPT_STAT_MODE, - "--stat-mode=%o", opt_stat_mode); - - FOPT (opt_fake_self, OPT_FAKE_SELF, - "--fake-self=%d", opt_fake_self); - - FOPT (opt_anon_owner, OPT_ANON_OWNER, - "--anonymous-owner=%d", opt_anon_owner); - - FOPT (opt_kernel_pid, OPT_KERNEL_PID, - "--kernel-process=%d", opt_kernel_pid); - -#undef FOPT - - if (! err) - err = netfs_append_std_options (argz, argz_len); - - return err; -} - -error_t -root_make_node (struct ps_context *pc, struct node **np) -{ - struct node *root_dirs[] = { - proclist_make_node (pc), - rootdir_make_node (pc), - }; - - *np = dircat_make_node (root_dirs, sizeof root_dirs / sizeof root_dirs[0]); - if (! *np) - return ENOMEM; - - /* Since this one is not created through proc_lookup(), we have to affect an - inode number to it. */ - (*np)->nn_stat.st_ino = * (uint32_t *) "PROC"; - - return 0; -} - -int main (int argc, char **argv) -{ - struct ps_context *pc; - mach_port_t bootstrap; - error_t err; - - opt_clk_tck = OPT_CLK_TCK; - opt_stat_mode = OPT_STAT_MODE; - opt_fake_self = OPT_FAKE_SELF; - opt_kernel_pid = OPT_KERNEL_PID; - opt_anon_owner = OPT_ANON_OWNER; - err = argp_parse (&argp, argc, argv, 0, 0, 0); - if (err) - error (1, err, "Could not parse command line"); - - err = ps_context_create (getproc (), &pc); - if (err) - error (1, err, "Could not create libps context"); - - task_get_bootstrap_port (mach_task_self (), &bootstrap); - if (bootstrap == MACH_PORT_NULL) - error (1, 0, "Must be started as a translator"); - - netfs_init (); - err = root_make_node (pc, &netfs_root_node); - if (err) - error (1, err, "Could not create the root node"); - - netfs_startup (bootstrap, 0); - netfs_server_loop (); - - assert (0 /* netfs_server_loop returned after all */); -} - diff --git a/procfs/main.h b/procfs/main.h deleted file mode 100644 index 4e28b7eb..00000000 --- a/procfs/main.h +++ /dev/null @@ -1,25 +0,0 @@ -/* Hurd /proc filesystem, command-line options set by main.c. - 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. */ - -/* Startup options */ -extern int opt_clk_tck; -extern mode_t opt_stat_mode; -extern pid_t opt_fake_self; -extern pid_t opt_kernel_pid; -extern uid_t opt_anon_owner; diff --git a/procfs/netfs.c b/procfs/netfs.c deleted file mode 100644 index 276c57cc..00000000 --- a/procfs/netfs.c +++ /dev/null @@ -1,461 +0,0 @@ -/* Hurd /proc filesystem, interface with libnetfs. - 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 <hurd/netfs.h> -#include <hurd/fshelp.h> -#include <sys/mman.h> -#include <mach/vm_param.h> -#include <dirent.h> -#include <fcntl.h> -#include <sys/statvfs.h> -#include <unistd.h> -#include "procfs.h" - -#define PROCFS_SERVER_NAME "procfs" -#define PROCFS_SERVER_VERSION "0.1.0" -#define PROCFS_MAXSYMLINKS 16 - - -/* Interesting libnetfs callback functions. */ - -/* The user must define this variable. Set this to the name of the - filesystem server. */ -char *netfs_server_name = PROCFS_SERVER_NAME; - -/* The user must define this variables. Set this to be the server - version number. */ -char *netfs_server_version = PROCFS_SERVER_VERSION; - -/* Maximum number of symlinks to follow before returning ELOOP. */ -int netfs_maxsymlinks = PROCFS_MAXSYMLINKS; - -/* The user must define this function. Make sure that NP->nn_stat is - filled with the most current information. CRED identifies the user - responsible for the operation. NP is locked. */ -error_t netfs_validate_stat (struct node *np, struct iouser *cred) -{ - char *contents; - ssize_t contents_len; - error_t err; - - /* Only symlinks need to have their size filled, before a read is - attempted. */ - if (! S_ISLNK (np->nn_stat.st_mode)) - return 0; - - err = procfs_get_contents (np, &contents, &contents_len); - if (err) - return err; - - np->nn_stat.st_size = contents_len; - return 0; -} - -/* The user must define this function. Read from the locked file NP - for user CRED starting at OFFSET and continuing for up to *LEN - bytes. Put the data at DATA. Set *LEN to the amount successfully - read upon return. */ -error_t netfs_attempt_read (struct iouser *cred, struct node *np, - loff_t offset, size_t *len, void *data) -{ - char *contents; - ssize_t contents_len; - error_t err; - - if (offset == 0) - procfs_refresh (np); - - err = procfs_get_contents (np, &contents, &contents_len); - if (err) - return err; - - contents += offset; - contents_len -= offset; - - if (*len > contents_len) - *len = contents_len; - if (*len < 0) - *len = 0; - - memcpy (data, contents, *len); - return 0; -} - -/* The user must define this function. Read the contents of locked - node NP (a symlink), for USER, into BUF. */ -error_t netfs_attempt_readlink (struct iouser *user, struct node *np, - char *buf) -{ - char *contents; - ssize_t contents_len; - error_t err; - - err = procfs_get_contents (np, &contents, &contents_len); - if (err) - return err; - - assert (contents_len == np->nn_stat.st_size); - memcpy (buf, contents, contents_len); - return 0; -} - -/* Helper function for netfs_get_dirents() below. CONTENTS is an argz - vector of directory entry names, as returned by procfs_get_contents(). - Convert at most NENTRIES of them to dirent structures, put them in - DATA (if not NULL), write the number of entries processed in *AMT and - return the required/used space in DATACNT. */ -static int putentries (char *contents, size_t contents_len, int nentries, - char *data, mach_msg_type_number_t *datacnt) -{ - int i; - - *datacnt = 0; - for (i = 0; contents_len && (nentries < 0 || i < nentries); i++) - { - int namlen = strlen (contents); - int reclen = sizeof (struct dirent) + namlen; - - if (data) - { - struct dirent *d = (struct dirent *) (data + *datacnt); - d->d_fileno = 42; /* XXX */ - d->d_namlen = namlen; - d->d_reclen = reclen; - d->d_type = DT_UNKNOWN; - strcpy (d->d_name, contents); - } - - *datacnt += reclen; - contents += namlen + 1; - contents_len -= namlen + 1; - } - - return i; -} - -/* The user must define this function. Fill the array *DATA of size - BUFSIZE with up to NENTRIES dirents from DIR (which is locked) - starting with entry ENTRY for user CRED. The number of entries in - the array is stored in *AMT and the number of bytes in *DATACNT. - If the supplied buffer is not large enough to hold the data, it - should be grown. */ -error_t netfs_get_dirents (struct iouser *cred, struct node *dir, - int entry, int nentries, char **data, - mach_msg_type_number_t *datacnt, - vm_size_t bufsize, int *amt) -{ - char *contents; - ssize_t contents_len; - error_t err; - - if (entry == 0) - procfs_refresh (dir); - - err = procfs_get_contents (dir, &contents, &contents_len); - if (err) - return err; - - /* We depend on the fact that CONTENTS is terminated. */ - assert (contents_len == 0 || contents[contents_len - 1] == '\0'); - - /* Skip to the first requested entry. */ - while (contents_len && entry--) - { - int ofs = strlen (contents) + 1; - contents += ofs; - contents_len -= ofs; - } - - /* Allocate a buffer if necessary. */ - putentries (contents, contents_len, nentries, NULL, datacnt); - if (bufsize < *datacnt) - { - char *n = mmap (0, *datacnt, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, 0, 0); - if (n == MAP_FAILED) - return ENOMEM; - - *data = n; - } - - /* Do the actual conversion. */ - *amt = putentries (contents, contents_len, nentries, *data, datacnt); - - return 0; -} - -/* The user must define this function. Lookup NAME in DIR (which is - locked) for USER; set *NP to the found name upon return. If the - name was not found, then return ENOENT. On any error, clear *NP. - (*NP, if found, should be locked and a reference to it generated. - This call should unlock DIR no matter what.) */ -error_t netfs_attempt_lookup (struct iouser *user, struct node *dir, - char *name, struct node **np) -{ - error_t err; - - err = procfs_lookup (dir, name, np); - pthread_mutex_unlock (&dir->lock); - - if (! err) - pthread_mutex_lock (&(*np)->lock); - - return err; -} - -/* The user must define this function. Node NP has no more references; - free all its associated storage. */ -void netfs_node_norefs (struct node *np) -{ - pthread_spin_unlock (&netfs_node_refcnt_lock); - - procfs_cleanup (np); - free (np); - - pthread_spin_lock (&netfs_node_refcnt_lock); -} - -/* The user may define this function (but should define it together - with netfs_set_translator). For locked node NODE with S_IPTRANS - set in its mode, look up the name of its translator. Store the - name into newly malloced storage, and return it in *ARGZ; set - *ARGZ_LEN to the total length. */ -error_t netfs_get_translator (struct node *np, char **argz, - size_t *argz_len) -{ - return procfs_get_translator (np, argz, argz_len); -} - - -/* Libnetfs callbacks managed with libfshelp. */ - -/* The user must define this function. Locked node NP is being opened - by USER, with FLAGS. NEWNODE is nonzero if we just created this - node. Return an error if we should not permit the open to complete - because of a permission restriction. */ -error_t netfs_check_open_permissions (struct iouser *user, struct node *np, - int flags, int newnode) -{ - error_t err = 0; - if (!err && (flags & O_READ)) - err = fshelp_access (&np->nn_stat, S_IREAD, user); - if (!err && (flags & O_WRITE)) - err = fshelp_access (&np->nn_stat, S_IWRITE, user); - if (!err && (flags & O_EXEC)) - err = fshelp_access (&np->nn_stat, S_IEXEC, user); - return err; -} - -/* The user must define this function. Return the valid access - types (bitwise OR of O_READ, O_WRITE, and O_EXEC) in *TYPES for - locked file NP and user CRED. */ -error_t netfs_report_access (struct iouser *cred, struct node *np, - int *types) -{ - *types = 0; - if (fshelp_access (&np->nn_stat, S_IREAD, cred) == 0) - *types |= O_READ; - if (fshelp_access (&np->nn_stat, S_IWRITE, cred) == 0) - *types |= O_WRITE; - if (fshelp_access (&np->nn_stat, S_IEXEC, cred) == 0) - *types |= O_EXEC; - return 0; -} - - -/* Trivial or unsupported libnetfs callbacks. */ - -/* The user must define this function. This should attempt a chmod - call for the user specified by CRED on locked node NP, to change - the owner to UID and the group to GID. */ -error_t netfs_attempt_chown (struct iouser *cred, struct node *np, - uid_t uid, uid_t gid) -{ - return EROFS; -} - -/* The user must define this function. This should attempt a chauthor - call for the user specified by CRED on locked node NP, thereby - changing the author to AUTHOR. */ -error_t netfs_attempt_chauthor (struct iouser *cred, struct node *np, - uid_t author) -{ - return EROFS; -} - -/* The user must define this function. This should attempt a chmod - call for the user specified by CRED on locked 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 *np, - mode_t mode) -{ - return EROFS; -} - -/* The user must define this function. Attempt to turn locked node NP - (user CRED) into a symlink with target NAME. */ -error_t netfs_attempt_mksymlink (struct iouser *cred, struct node *np, - char *name) -{ - return EROFS; -} - -/* The user must define this function. Attempt to turn NODE (user - CRED) into a device. TYPE is either S_IFBLK or S_IFCHR. NP is - locked. */ -error_t netfs_attempt_mkdev (struct iouser *cred, struct node *np, - mode_t type, dev_t indexes) -{ - return EROFS; -} - -/* The user must define this function. This should attempt a chflags - call for the user specified by CRED on locked node NP, to change - the flags to FLAGS. */ -error_t netfs_attempt_chflags (struct iouser *cred, struct node *np, - int flags) -{ - return EROFS; -} - -/* The user must define this function. This should attempt a utimes - call for the user specified by CRED on locked node NP, to change - the atime to ATIME and the mtime to MTIME. If ATIME or MTIME is - null, then set to the current time. */ -error_t netfs_attempt_utimes (struct iouser *cred, struct node *np, - struct timespec *atime, struct timespec *mtime) -{ - return EROFS; -} - -/* The user must define this function. This should attempt to set the - size of the locked file NP (for user CRED) to SIZE bytes long. */ -error_t netfs_attempt_set_size (struct iouser *cred, struct node *np, - loff_t size) -{ - return EROFS; -} - -/* The user must define this function. This should attempt to fetch - filesystem status information for the remote filesystem, for the - user CRED. NP is locked. */ -error_t netfs_attempt_statfs (struct iouser *cred, struct node *np, - fsys_statfsbuf_t *st) -{ - memset (st, 0, sizeof *st); - st->f_type = FSTYPE_PROC; - st->f_fsid = getpid (); - return 0; -} - -/* The user must define this function. This should sync the locked - file NP completely to disk, for the user CRED. If WAIT is set, - return only after the sync is completely finished. */ -error_t netfs_attempt_sync (struct iouser *cred, struct node *np, - int wait) -{ - return 0; -} - -/* The user must define this function. This should sync the entire - remote filesystem. If WAIT is set, return only after the sync is - completely finished. */ -error_t netfs_attempt_syncfs (struct iouser *cred, int wait) -{ - return 0; -} - -/* The user must define this function. Delete NAME in DIR (which is - locked) for USER. */ -error_t netfs_attempt_unlink (struct iouser *user, struct node *dir, - char *name) -{ - return EROFS; -} - -/* The user must define this function. Attempt to rename the - directory FROMDIR to TODIR. Note that neither of the specific nodes - are locked. */ -error_t netfs_attempt_rename (struct iouser *user, struct node *fromdir, - char *fromname, struct node *todir, - char *toname, int excl) -{ - return EROFS; -} - -/* The user must define this function. Attempt to create a new - directory named NAME in DIR (which is locked) for USER with mode - MODE. */ -error_t netfs_attempt_mkdir (struct iouser *user, struct node *dir, - char *name, mode_t mode) -{ - return EROFS; -} - -/* The user must define this function. Attempt to remove directory - named NAME in DIR (which is locked) for USER. */ -error_t netfs_attempt_rmdir (struct iouser *user, - struct node *dir, char *name) -{ - return EROFS; -} - - -/* The user must define this function. Create a link in DIR with name - NAME to FILE for USER. Note that neither DIR nor FILE are - locked. If EXCL is set, do not delete the target. Return EEXIST if - NAME is already found in DIR. */ -error_t netfs_attempt_link (struct iouser *user, struct node *dir, - struct node *file, char *name, int excl) -{ - return EROFS; -} - -/* The user must define this function. Attempt to create an anonymous - file related to DIR (which is locked) for USER with MODE. Set *NP - to the returned file upon success. No matter what, unlock DIR. */ -error_t netfs_attempt_mkfile (struct iouser *user, struct node *dir, - mode_t mode, struct node **np) -{ - return EROFS; -} - -/* The user must define this function. Attempt to create a file named - NAME in DIR (which is locked) for USER with MODE. Set *NP to the - new node upon return. On any error, clear *NP. *NP should be - locked on success; no matter what, unlock DIR before returning. */ -error_t netfs_attempt_create_file (struct iouser *user, struct node *dir, - char *name, mode_t mode, struct node **np) -{ - return EROFS; -} - -/* The user must define this function. Write to the locked file NP - for user CRED starting at OFSET and continuing for up to *LEN bytes - from DATA. Set *LEN to the amount successfully written upon - return. */ -error_t netfs_attempt_write (struct iouser *cred, struct node *np, - loff_t offset, size_t *len, void *data) -{ - return EROFS; -} - - diff --git a/procfs/process.c b/procfs/process.c deleted file mode 100644 index 269a18bb..00000000 --- a/procfs/process.c +++ /dev/null @@ -1,414 +0,0 @@ -/* Hurd /proc filesystem, implementation of process directories. - 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 <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <hurd/process.h> -#include <hurd/resource.h> -#include <mach/vm_param.h> -#include <ps.h> -#include "procfs.h" -#include "procfs_dir.h" -#include "process.h" -#include "main.h" - -/* This module implements the process directories and the files they - contain. A libps proc_stat structure is created for each process - node, and is used by the individual file content generators as a - source of information. Each possible file (cmdline, environ, ...) is - decribed in a process_file_desc structure, which specifies which bits - of information (ie. libps flags) it needs, and what function should - be used to generate the file's contents. - - The content generators are defined first, followed by glue logic and - entry table. */ - - -/* Helper functions */ - -static char state_char (struct proc_stat *ps) -{ - int i; - - for (i = 0; (1 << i) & (PSTAT_STATE_P_STATES | PSTAT_STATE_T_STATES); i++) - if (proc_stat_state (ps) & (1 << i)) - return proc_stat_state_tags[i]; - - return '?'; -} - -static const char *state_string (struct proc_stat *ps) -{ - static const char *const state_strings[] = { - "T (stopped)", - "Z (zombie)", - "R (running)", - "H (halted)", - "D (disk sleep)", - "S (sleeping)", - "I (idle)", - NULL - }; - int i; - - for (i = 0; state_strings[i]; i++) - if (proc_stat_state (ps) & (1 << i)) - return state_strings[i]; - - return "? (unknown)"; -} - -static long long int timeval_jiffies (time_value_t tv) -{ - double secs = tv.seconds * 1000000. + tv.microseconds; - return secs * opt_clk_tck / 1000000.; -} - -static const char *args_filename (const char *name) -{ - char *sp = strrchr (name, '/'); - return sp != NULL && *(sp + 1) != '\0' ? sp + 1 : name; -} - -static int args_filename_length (const char *name) -{ - return strchrnul (name, ' ') - name; -} - -/* Actual content generators */ - -static ssize_t -process_file_gc_cmdline (struct proc_stat *ps, char **contents) -{ - *contents = proc_stat_args(ps); - return proc_stat_args_len(ps); -} - -static ssize_t -process_file_gc_environ (struct proc_stat *ps, char **contents) -{ - *contents = proc_stat_env(ps); - return proc_stat_env_len(ps); -} - -static ssize_t -process_file_gc_stat (struct proc_stat *ps, char **contents) -{ - struct procinfo *pi = proc_stat_proc_info (ps); - task_basic_info_t tbi = proc_stat_task_basic_info (ps); - thread_basic_info_t thbi = proc_stat_thread_basic_info (ps); - const char *fn = args_filename (proc_stat_args (ps)); - - vm_address_t start_code = 1; /* 0 would make killall5.c consider it - a kernel process, thus use 1 as - default. */ - vm_address_t end_code = 1; - process_t p; - error_t err = proc_pid2proc (ps->context->server, ps->pid, &p); - if (! err) - { - boolean_t essential = 0; - proc_is_important (p, &essential); - if (essential) - start_code = end_code = 0; /* To make killall5.c consider it a - kernel process that is to be - left alone. */ - else - proc_get_code (p, &start_code, &end_code); - - mach_port_deallocate (mach_task_self (), p); - } - - /* See proc(5) for more information about the contents of each field for the - Linux procfs. */ - return asprintf (contents, - "%d (%.*s) %c " /* pid, command, state */ - "%d %d %d " /* ppid, pgid, session */ - "%d %d " /* controling tty stuff */ - "%u " /* flags, as defined by <linux/sched.h> */ - "%lu %lu %lu %lu " /* page fault counts */ - "%lu %lu %ld %ld " /* user/sys times, in sysconf(_SC_CLK_TCK) */ - "%d %d " /* scheduler params (priority, nice) */ - "%d %ld " /* number of threads, [obsolete] */ - "%llu " /* start time since boot (jiffies) */ - "%lu %ld %lu " /* virtual size (bytes), rss (pages), rss lim */ - "%lu %lu %lu %lu %lu " /* some vm addresses (code, stack, sp, pc) */ - "%lu %lu %lu %lu " /* pending, blocked, ignored and caught sigs */ - "%lu " /* wait channel */ - "%lu %lu " /* swap usage (not maintained in Linux) */ - "%d " /* exit signal, to be sent to the parent */ - "%d " /* last processor used */ - "%u %u " /* RT priority and policy */ - "%llu " /* aggregated block I/O delay */ - "\n", - proc_stat_pid (ps), args_filename_length (fn), fn, state_char (ps), - pi->ppid, pi->pgrp, pi->session, - 0, 0, /* no such thing as a major:minor for ctty */ - 0, /* no such thing as CLONE_* flags on Hurd */ - 0L, 0L, 0L, 0L, /* TASK_EVENTS_INFO is unavailable on GNU Mach */ - (long unsigned) timeval_jiffies (thbi->user_time), - (long unsigned) timeval_jiffies (thbi->system_time), - 0L, 0L, /* cumulative time for children */ - MACH_PRIORITY_TO_NICE(thbi->base_priority) + 20, - MACH_PRIORITY_TO_NICE(thbi->base_priority), - pi->nthreads, 0L, - timeval_jiffies (thbi->creation_time), /* FIXME: ... since boot */ - (long unsigned) tbi->virtual_size, - (long unsigned) tbi->resident_size / PAGE_SIZE, 0L, - start_code, - end_code, - 0L, 0L, 0L, - 0L, 0L, 0L, 0L, - (long unsigned) proc_stat_thread_rpc (ps), /* close enough */ - 0L, 0L, - 0, - 0, - 0, 0, - 0LL); -} - -static ssize_t -process_file_gc_statm (struct proc_stat *ps, char **contents) -{ - task_basic_info_t tbi = proc_stat_task_basic_info (ps); - - return asprintf (contents, - "%lu %lu 0 0 0 0 0\n", - tbi->virtual_size / sysconf(_SC_PAGE_SIZE), - tbi->resident_size / sysconf(_SC_PAGE_SIZE)); -} - -static ssize_t -process_file_gc_status (struct proc_stat *ps, char **contents) -{ - task_basic_info_t tbi = proc_stat_task_basic_info (ps); - const char *fn = args_filename (proc_stat_args (ps)); - - return asprintf (contents, - "Name:\t%.*s\n" - "State:\t%s\n" - "Tgid:\t%u\n" - "Pid:\t%u\n" - "PPid:\t%u\n" - "Uid:\t%u\t%u\t%u\t%u\n" - "VmSize:\t%8u kB\n" - "VmPeak:\t%8u kB\n" - "VmRSS:\t%8u kB\n" - "VmHWM:\t%8u kB\n" /* ie. resident peak */ - "Threads:\t%u\n", - args_filename_length (fn), fn, - state_string (ps), - proc_stat_pid (ps), /* XXX will need more work for threads */ - proc_stat_pid (ps), - proc_stat_proc_info (ps)->ppid, - proc_stat_owner_uid (ps), - proc_stat_owner_uid (ps), - proc_stat_owner_uid (ps), - proc_stat_owner_uid (ps), - tbi->virtual_size / 1024, - tbi->virtual_size / 1024, - tbi->resident_size / 1024, - tbi->resident_size / 1024, - proc_stat_num_threads (ps)); -} - - -/* Implementation of the file nodes. */ - -/* Describes a file in the process directories. This structure is - filled in as an "entry hook" in our procfs_dir entry table and is - passed to the process_file_make_node function defined below. */ -struct process_file_desc -{ - /* The proc_stat information required to get the contents of this file. */ - ps_flags_t needs; - - /* Content generator to use for this file. Once we have acquired the - necessary information, there can be only memory allocation errors, - hence this simplified signature. */ - ssize_t (*get_contents) (struct proc_stat *ps, char **contents); - - /* The cmdline and environ contents don't need any cleaning since they - point directly into the proc_stat structure. */ - int no_cleanup; - - /* If specified, the file mode to be set with procfs_node_chmod(). */ - mode_t mode; -}; - -struct process_file_node -{ - const struct process_file_desc *desc; - struct proc_stat *ps; -}; - -/* FIXME: lock the parent! */ -static error_t -process_file_get_contents (void *hook, char **contents, ssize_t *contents_len) -{ - struct process_file_node *file = hook; - error_t err; - - /* Fetch the required information. */ - err = proc_stat_set_flags (file->ps, file->desc->needs); - if (err) - return EIO; - if ((proc_stat_flags (file->ps) & file->desc->needs) != file->desc->needs) - return EIO; - - /* Call the actual content generator (see the definitions below). */ - *contents_len = file->desc->get_contents (file->ps, contents); - return 0; -} - -static void -process_file_cleanup_contents (void *hook, char *contents, ssize_t len) -{ - struct process_file_node *file = hook; - - if (! file->desc->no_cleanup) - free (contents); -} - -static struct node * -process_file_make_node (void *dir_hook, const void *entry_hook) -{ - static const struct procfs_node_ops ops = { - .get_contents = process_file_get_contents, - .cleanup_contents = process_file_cleanup_contents, - .cleanup = free, - }; - struct process_file_node *f; - struct node *np; - - f = malloc (sizeof *f); - if (! f) - return NULL; - - f->desc = entry_hook; - f->ps = dir_hook; - - np = procfs_make_node (&ops, f); - if (! np) - return NULL; - - procfs_node_chown (np, proc_stat_owner_uid (f->ps)); - if (f->desc->mode) - procfs_node_chmod (np, f->desc->mode); - - return np; -} - -/* Stat needs its own constructor in oreder to set its mode according to - the --stat-mode command-line option. */ -static struct node * -process_stat_make_node (void *dir_hook, const void *entry_hook) -{ - struct node *np = process_file_make_node (dir_hook, entry_hook); - if (np) procfs_node_chmod (np, opt_stat_mode); - return np; -} - - -/* Implementation of the process directory per se. */ - -static struct procfs_dir_entry entries[] = { - { - .name = "cmdline", - .hook = & (struct process_file_desc) { - .get_contents = process_file_gc_cmdline, - .needs = PSTAT_ARGS, - .no_cleanup = 1, - }, - }, - { - .name = "environ", - .hook = & (struct process_file_desc) { - .get_contents = process_file_gc_environ, - .needs = PSTAT_ENV, - .no_cleanup = 1, - .mode = 0400, - }, - }, - { - .name = "stat", - .hook = & (struct process_file_desc) { - .get_contents = process_file_gc_stat, - .needs = PSTAT_PID | PSTAT_ARGS | PSTAT_STATE | PSTAT_PROC_INFO - | PSTAT_TASK | PSTAT_TASK_BASIC | PSTAT_THREAD_BASIC - | PSTAT_THREAD_WAIT, - }, - .ops = { - .make_node = process_stat_make_node, - } - }, - { - .name = "statm", - .hook = & (struct process_file_desc) { - .get_contents = process_file_gc_statm, - .needs = PSTAT_TASK_BASIC, - }, - }, - { - .name = "status", - .hook = & (struct process_file_desc) { - .get_contents = process_file_gc_status, - .needs = PSTAT_PID | PSTAT_ARGS | PSTAT_STATE | PSTAT_PROC_INFO - | PSTAT_TASK_BASIC | PSTAT_OWNER_UID | PSTAT_NUM_THREADS, - }, - }, - {} -}; - -error_t -process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np) -{ - static const struct procfs_dir_ops dir_ops = { - .entries = entries, - .cleanup = (void (*)(void *)) _proc_stat_free, - .entry_ops = { - .make_node = process_file_make_node, - }, - }; - struct proc_stat *ps; - int owner; - error_t err; - - err = _proc_stat_create (pid, pc, &ps); - if (err == ESRCH) - return ENOENT; - if (err) - return EIO; - - err = proc_stat_set_flags (ps, PSTAT_OWNER_UID); - if (err || ! (proc_stat_flags (ps) & PSTAT_OWNER_UID)) - { - _proc_stat_free (ps); - return EIO; - } - - *np = procfs_dir_make_node (&dir_ops, ps); - if (! *np) - return ENOMEM; - - owner = proc_stat_owner_uid (ps); - procfs_node_chown (*np, owner >= 0 ? owner : opt_anon_owner); - return 0; -} diff --git a/procfs/process.h b/procfs/process.h deleted file mode 100644 index b230a281..00000000 --- a/procfs/process.h +++ /dev/null @@ -1,27 +0,0 @@ -/* Hurd /proc filesystem, implementation of process directories. - 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 <ps.h> - -/* Create a node for a directory representing the given PID, as published by - the proc server refrenced by the libps context PC. On success, returns the - newly created node in *NP. */ -error_t -process_lookup_pid (struct ps_context *pc, pid_t pid, struct node **np); - diff --git a/procfs/procfs.c b/procfs/procfs.c deleted file mode 100644 index cae4a519..00000000 --- a/procfs/procfs.c +++ /dev/null @@ -1,219 +0,0 @@ -/* 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; -} diff --git a/procfs/procfs.h b/procfs/procfs.h deleted file mode 100644 index d04bbad7..00000000 --- a/procfs/procfs.h +++ /dev/null @@ -1,99 +0,0 @@ -/* 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 <hurd/hurd_types.h> -#include <hurd/netfs.h> - - -/* Interface for the procfs side. */ - -/* Any of these callback functions can be omitted, in which case - reasonable defaults will be used. The initial file mode and type - depend on whether a lookup function is provided, but can be - overridden in update_stat(). */ -struct procfs_node_ops -{ - /* Fetch the contents of a node. A pointer to the contents should be - returned in *CONTENTS and their length in *CONTENTS_LEN. The exact - nature of these data depends on whether the node is a regular file, - symlink or directory, as determined by the file mode in - netnode->nn_stat. For regular files and symlinks, they are what - you would expect; for directories, they are an argz vector of the - names of the entries. If upon return, *CONTENTS_LEN is negative or - unchanged, the call is considered to have failed because of a memory - allocation error. */ - error_t (*get_contents) (void *hook, char **contents, ssize_t *contents_len); - void (*cleanup_contents) (void *hook, char *contents, ssize_t contents_len); - - /* Lookup NAME in this directory, and store the result in *np. The - returned node should be created by lookup() using procfs_make_node() - or a derived function. Note that the parent will be kept alive as - long as the child exists, so you can safely reference the parent's - data from the child. You may want to consider locking if there's - any mutation going on, though. */ - error_t (*lookup) (void *hook, const char *name, struct node **np); - - /* Destroy this node. */ - void (*cleanup) (void *hook); - - /* Get the passive translator record. */ - error_t (*get_translator) (void *hook, char **argz, size_t *argz_len); -}; - -/* These helper functions can be used as procfs_node_ops.cleanup_contents. */ -void procfs_cleanup_contents_with_free (void *, char *, ssize_t); -void procfs_cleanup_contents_with_vm_deallocate (void *, char *, ssize_t); - -/* Create a new node and return it. Returns NULL if it fails to allocate - enough memory. In this case, ops->cleanup will be invoked. */ -struct node *procfs_make_node (const struct procfs_node_ops *ops, void *hook); - -/* Set the owner of the node NP. Must be called right after the node - has been created. */ -void procfs_node_chown (struct node *np, uid_t owner); - -/* Set the permission bits of the node NP. Must be called right after - the node has been created. */ -void procfs_node_chmod (struct node *np, mode_t mode); - -/* Set the type of the node NP. If type is S_IFLNK, appropriate - permission bits will be set as well. Must be called right after the - node has been created. */ -void procfs_node_chtype (struct node *np, mode_t type); - - -/* Interface for the libnetfs side. */ - -/* Get the inode number which will be given to a child of NP named FILENAME. - This allows us to retreive them for readdir() without creating the - corresponding child nodes. */ -ino64_t procfs_make_ino (struct node *np, const char *filename); - -/* Forget the current cached contents for the node. This is done before reads - from offset 0, to ensure that the data are recent even for utilities such as - top which keep some nodes open. */ -void procfs_refresh (struct node *np); - -error_t procfs_get_contents (struct node *np, char **data, ssize_t *data_len); -error_t procfs_lookup (struct node *np, const char *name, struct node **npp); -void procfs_cleanup (struct node *np); - -/* Get the passive translator record if any. */ -error_t procfs_get_translator (struct node *np, char **argz, size_t *argz_len); - diff --git a/procfs/procfs_dir.c b/procfs/procfs_dir.c deleted file mode 100644 index c250aa48..00000000 --- a/procfs/procfs_dir.c +++ /dev/null @@ -1,134 +0,0 @@ -/* Hurd /proc filesystem, infrastructure for directories. - 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 "procfs.h" -#include "procfs_dir.h" - -struct procfs_dir_node -{ - const struct procfs_dir_ops *ops; - void *hook; -}; - -static int -entry_exists (struct procfs_dir_node *dir, const struct procfs_dir_entry *ent) -{ - if (ent->ops.exists) - return ent->ops.exists (dir->hook, ent->hook); - if (dir->ops->entry_ops.exists) - return dir->ops->entry_ops.exists (dir->hook, ent->hook); - - return 1; -} - -static error_t -procfs_dir_get_contents (void *hook, char **contents, ssize_t *contents_len) -{ - static const char dot_dotdot[] = ".\0.."; - struct procfs_dir_node *dir = hook; - const struct procfs_dir_entry *ent; - int pos; - - /* Evaluate how much space is needed. Note that we include the hidden - entries, just in case their status changes between now and then. */ - pos = sizeof dot_dotdot; - for (ent = dir->ops->entries; ent->name; ent++) - pos += strlen (ent->name) + 1; - - *contents = malloc (pos); - if (! *contents) - return ENOMEM; - - memcpy (*contents, dot_dotdot, sizeof dot_dotdot); - pos = sizeof dot_dotdot; - for (ent = dir->ops->entries; ent->name; ent++) - { - if (! entry_exists (dir, ent)) - continue; - - strcpy (*contents + pos, ent->name); - pos += strlen (ent->name) + 1; - } - - *contents_len = pos; - return 0; -} - -static error_t -procfs_dir_lookup (void *hook, const char *name, struct node **np) -{ - struct procfs_dir_node *dir = hook; - const struct procfs_dir_entry *ent; - - for (ent = dir->ops->entries; ent->name && strcmp (name, ent->name); ent++); - if (! ent->name) - return ENOENT; - - if (ent->ops.make_node) - *np = ent->ops.make_node (dir->hook, ent->hook); - else if (dir->ops->entry_ops.make_node) - *np = dir->ops->entry_ops.make_node (dir->hook, ent->hook); - else - return EGRATUITOUS; - - if (! *np) - return ENOMEM; - - return 0; -} - -static void -procfs_dir_cleanup (void *hook) -{ - struct procfs_dir_node *dir = hook; - - if (dir->ops->cleanup) - dir->ops->cleanup (dir->hook); - - free (dir); -} - -struct node * -procfs_dir_make_node (const struct procfs_dir_ops *dir_ops, void *dir_hook) -{ - static const struct procfs_node_ops ops = { - .get_contents = procfs_dir_get_contents, - .lookup = procfs_dir_lookup, - .cleanup_contents = procfs_cleanup_contents_with_free, - .cleanup = procfs_dir_cleanup, - }; - struct procfs_dir_node *dir; - - dir = malloc (sizeof *dir); - if (! dir) - { - if (dir_ops->cleanup) - dir_ops->cleanup (dir_hook); - - return NULL; - } - - dir->ops = dir_ops; - dir->hook = dir_hook; - - return procfs_make_node (&ops, dir); -} - diff --git a/procfs/procfs_dir.h b/procfs/procfs_dir.h deleted file mode 100644 index 94c5b019..00000000 --- a/procfs/procfs_dir.h +++ /dev/null @@ -1,63 +0,0 @@ -/* Hurd /proc filesystem, infrastructure for directories. - 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. */ - -/* This module provides an abstraction layer for implementing simple - directories with (mostly) static contents. The user defines the - contents of the directory by providing a table of entries and various - optional callback functions. */ - -/* These operations define how a given entry will behave. Either can be - omitted, both from the entry-specific operations and from the - directory-wide defaults. */ -struct procfs_dir_entry_ops -{ - /* Called when this entry is looked up to create a corresponding node. */ - struct node *(*make_node)(void *dir_hook, const void *entry_hook); - /* If this is provided and returns 0, this entry will be hidden. */ - int (*exists)(void *dir_hook, const void *entry_hook); -}; - -/* Describes an individual directory entry, associating a NAME with - * arbitrary HOOK data and node-specific OPS. */ -struct procfs_dir_entry -{ - const char *name; - const void *hook; - struct procfs_dir_entry_ops ops; -}; - -/* Describes a complete directory. ENTRIES is a table terminated by a - null NAME field. ENTRY_OPS provides default operations for the - entries which don't specify them. The optional CLEANUP function - should release all the resources associated with the directory hook. */ -struct procfs_dir_ops -{ - const struct procfs_dir_entry *entries; - void (*cleanup)(void *dir_hook); - struct procfs_dir_entry_ops entry_ops; -}; - -/* Create and return a new node for the directory described in OPS. - The DIR_HOOK is passed the MAKE_NODE callback function of looked up - entries, as well as to the CLEANUP callback when the node is - destroyed. If not enough memory can be allocated, OPS->CLEANUP is - invoked immediately and NULL is returned. */ -struct node * -procfs_dir_make_node (const struct procfs_dir_ops *ops, void *dir_hook); - diff --git a/procfs/proclist.c b/procfs/proclist.c deleted file mode 100644 index 58b942dc..00000000 --- a/procfs/proclist.c +++ /dev/null @@ -1,94 +0,0 @@ -/* Hurd /proc filesystem, list of processes as a directory. - 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 <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <mach.h> -#include <hurd/process.h> -#include <ps.h> -#include "procfs.h" -#include "process.h" - -#define PID_STR_SIZE (3 * sizeof (pid_t) + 1) - -static error_t -proclist_get_contents (void *hook, char **contents, ssize_t *contents_len) -{ - struct ps_context *pc = hook; - pidarray_t pids; - mach_msg_type_number_t num_pids; - error_t err; - int i; - - num_pids = 0; - err = proc_getallpids (pc->server, &pids, &num_pids); - if (err) - return EIO; - - *contents = malloc (num_pids * PID_STR_SIZE); - if (*contents) - { - *contents_len = 0; - for (i=0; i < num_pids; i++) - { - int n = sprintf (*contents + *contents_len, "%d", pids[i]); - assert (n >= 0); - *contents_len += (n + 1); - } - } - else - err = ENOMEM; - - vm_deallocate (mach_task_self (), (vm_address_t) pids, num_pids * sizeof pids[0]); - return err; -} - -static error_t -proclist_lookup (void *hook, const char *name, struct node **np) -{ - struct ps_context *pc = hook; - char *endp; - pid_t pid; - - /* Self-lookups should not end up here. */ - assert (name[0]); - - /* No leading zeros allowed */ - if (name[0] == '0' && name[1]) - return ENOENT; - - pid = strtol (name, &endp, 10); - if (*endp) - return ENOENT; - - return process_lookup_pid (pc, pid, np); -} - -struct node * -proclist_make_node (struct ps_context *pc) -{ - static const struct procfs_node_ops ops = { - .get_contents = proclist_get_contents, - .lookup = proclist_lookup, - .cleanup_contents = procfs_cleanup_contents_with_free, - }; - return procfs_make_node (&ops, pc); -} - diff --git a/procfs/proclist.h b/procfs/proclist.h deleted file mode 100644 index bfe95b3d..00000000 --- a/procfs/proclist.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Hurd /proc filesystem, list of processes as a directory. - 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 <ps.h> - -struct node * -proclist_make_node (struct ps_context *pc); diff --git a/procfs/rootdir.c b/procfs/rootdir.c deleted file mode 100644 index 0b131192..00000000 --- a/procfs/rootdir.c +++ /dev/null @@ -1,661 +0,0 @@ -/* Hurd /proc filesystem, permanent files of the root directory. - Copyright (C) 2010,13 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 <mach/gnumach.h> -#include <mach/vm_param.h> -#include <mach/vm_statistics.h> -#include <mach/vm_cache_statistics.h> -#include <mach/default_pager.h> -#include <mach_debug/mach_debug_types.h> -#include <hurd/paths.h> -#include <stdio.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/time.h> -#include <sys/utsname.h> -#include <sys/stat.h> -#include <argz.h> -#include <ps.h> -#include "procfs.h" -#include "procfs_dir.h" -#include "main.h" - -#include "mach_debug_U.h" - -/* This implements a directory node with the static files in /proc. - NB: the libps functions for host information return static storage; - using them would require locking and as a consequence it would be - more complicated, not simpler. */ - - -/* Helper functions */ - -/* We get the boot time by using that of the kernel process. */ -static error_t -get_boottime (struct ps_context *pc, struct timeval *tv) -{ - struct proc_stat *ps; - error_t err; - - err = _proc_stat_create (opt_kernel_pid, pc, &ps); - if (err) - return err; - - err = proc_stat_set_flags (ps, PSTAT_TASK_BASIC); - if (err || !(proc_stat_flags (ps) & PSTAT_TASK_BASIC)) - err = EIO; - - if (! err) - { - task_basic_info_t tbi = proc_stat_task_basic_info (ps); - tv->tv_sec = tbi->creation_time.seconds; - tv->tv_usec = tbi->creation_time.microseconds; - } - - _proc_stat_free (ps); - return err; -} - -/* We get the idle time by querying the kernel's idle thread. */ -static error_t -get_idletime (struct ps_context *pc, struct timeval *tv) -{ - struct proc_stat *ps, *pst; - thread_basic_info_t tbi; - error_t err; - int i; - - err = _proc_stat_create (opt_kernel_pid, pc, &ps); - if (err) - return err; - - pst = NULL, tbi = NULL; - - err = proc_stat_set_flags (ps, PSTAT_NUM_THREADS); - if (err || !(proc_stat_flags (ps) & PSTAT_NUM_THREADS)) - { - err = EIO; - goto out; - } - - /* Look for the idle thread */ - for (i=0; !tbi || !(tbi->flags & TH_FLAGS_IDLE); i++) - { - if (pst) - _proc_stat_free (pst); - - pst = NULL, tbi = NULL; - if (i >= proc_stat_num_threads (ps)) - { - err = ESRCH; - goto out; - } - - err = proc_stat_thread_create (ps, i, &pst); - if (err) - continue; - - err = proc_stat_set_flags (pst, PSTAT_THREAD_BASIC); - if (err || ! (proc_stat_flags (pst) & PSTAT_THREAD_BASIC)) - continue; - - tbi = proc_stat_thread_basic_info (pst); - } - - /* We found it! */ - tv->tv_sec = tbi->system_time.seconds; - tv->tv_usec = tbi->system_time.microseconds; - err = 0; - -out: - if (pst) _proc_stat_free (pst); - _proc_stat_free (ps); - return err; -} - -static error_t -get_swapinfo (default_pager_info_t *info) -{ - mach_port_t defpager; - error_t err; - - defpager = file_name_lookup (_SERVERS_DEFPAGER, O_READ, 0); - if (defpager == MACH_PORT_NULL) - return errno; - - err = default_pager_info (defpager, info); - mach_port_deallocate (mach_task_self (), defpager); - - return err; -} - - -/* Content generators */ - -static error_t -rootdir_gc_version (void *hook, char **contents, ssize_t *contents_len) -{ - struct utsname uts; - int r; - - r = uname (&uts); - if (r < 0) - return errno; - - *contents_len = asprintf (contents, - "Linux version 2.6.1 (%s %s %s %s)\n", - uts.sysname, uts.release, uts.version, uts.machine); - - return 0; -} - -static error_t -rootdir_gc_uptime (void *hook, char **contents, ssize_t *contents_len) -{ - struct timeval time, boottime, idletime; - double up_secs, idle_secs; - error_t err; - - err = gettimeofday (&time, NULL); - if (err < 0) - return errno; - - err = get_boottime (hook, &boottime); - if (err) - return err; - - err = get_idletime (hook, &idletime); - if (err) - return err; - - timersub (&time, &boottime, &time); - up_secs = (time.tv_sec * 1000000. + time.tv_usec) / 1000000.; - idle_secs = (idletime.tv_sec * 1000000. + idletime.tv_usec) / 1000000.; - - /* The second field is the total idle time. As far as I know we don't - keep track of it. However, procps uses it to compute "USER_HZ", and - proc(5) specifies that it should be equal to USER_HZ times the idle value - in ticks from /proc/stat. So we assume a completely idle system both here - and there to make that work. */ - *contents_len = asprintf (contents, "%.2lf %.2lf\n", up_secs, idle_secs); - - return 0; -} - -static error_t -rootdir_gc_stat (void *hook, char **contents, ssize_t *contents_len) -{ - struct timeval boottime, time, idletime; - struct vm_statistics vmstats; - unsigned long up_ticks, idle_ticks; - error_t err; - - err = gettimeofday (&time, NULL); - if (err < 0) - return errno; - - err = get_boottime (hook, &boottime); - if (err) - return err; - - err = get_idletime (hook, &idletime); - if (err) - return err; - - err = vm_statistics (mach_task_self (), &vmstats); - if (err) - return EIO; - - timersub (&time, &boottime, &time); - up_ticks = opt_clk_tck * (time.tv_sec * 1000000. + time.tv_usec) / 1000000.; - idle_ticks = opt_clk_tck * (idletime.tv_sec * 1000000. + idletime.tv_usec) / 1000000.; - - *contents_len = asprintf (contents, - "cpu %lu 0 0 %lu 0 0 0 0 0\n" - "cpu0 %lu 0 0 %lu 0 0 0 0 0\n" - "intr 0\n" - "page %d %d\n" - "btime %lu\n", - up_ticks - idle_ticks, idle_ticks, - up_ticks - idle_ticks, idle_ticks, - vmstats.pageins, vmstats.pageouts, - boottime.tv_sec); - - return 0; -} - -static error_t -rootdir_gc_loadavg (void *hook, char **contents, ssize_t *contents_len) -{ - host_load_info_data_t hli; - mach_msg_type_number_t cnt; - error_t err; - - cnt = HOST_LOAD_INFO_COUNT; - err = host_info (mach_host_self (), HOST_LOAD_INFO, (host_info_t) &hli, &cnt); - if (err) - return err; - - assert (cnt == HOST_LOAD_INFO_COUNT); - *contents_len = asprintf (contents, - "%.2f %.2f %.2f 1/0 0\n", - hli.avenrun[0] / (double) LOAD_SCALE, - hli.avenrun[1] / (double) LOAD_SCALE, - hli.avenrun[2] / (double) LOAD_SCALE); - - return 0; -} - -static error_t -rootdir_gc_meminfo (void *hook, char **contents, ssize_t *contents_len) -{ - host_basic_info_data_t hbi; - mach_msg_type_number_t cnt; - struct vm_statistics vmstats; - struct vm_cache_statistics cache_stats; - default_pager_info_t swap; - error_t err; - - err = vm_statistics (mach_task_self (), &vmstats); - if (err) - return EIO; - - err = vm_cache_statistics (mach_task_self (), &cache_stats); - if (err) - return EIO; - - cnt = HOST_BASIC_INFO_COUNT; - err = host_info (mach_host_self (), HOST_BASIC_INFO, (host_info_t) &hbi, &cnt); - if (err) - return err; - - err = get_swapinfo (&swap); - if (err) - return err; - - assert (cnt == HOST_BASIC_INFO_COUNT); - *contents_len = asprintf (contents, - "MemTotal: %14lu kB\n" - "MemFree: %14lu kB\n" - "Buffers: %14lu kB\n" - "Cached: %14lu kB\n" - "Active: %14lu kB\n" - "Inactive: %14lu kB\n" - "Mlocked: %14lu kB\n" - "SwapTotal:%14lu kB\n" - "SwapFree: %14lu kB\n" - , - (long unsigned) hbi.memory_size / 1024, - (long unsigned) vmstats.free_count * PAGE_SIZE / 1024, - 0UL, - (long unsigned) cache_stats.cache_count * PAGE_SIZE / 1024, - (long unsigned) vmstats.active_count * PAGE_SIZE / 1024, - (long unsigned) vmstats.inactive_count * PAGE_SIZE / 1024, - (long unsigned) vmstats.wire_count * PAGE_SIZE / 1024, - (long unsigned) swap.dpi_total_space / 1024, - (long unsigned) swap.dpi_free_space / 1024); - - return 0; -} - -static error_t -rootdir_gc_vmstat (void *hook, char **contents, ssize_t *contents_len) -{ - host_basic_info_data_t hbi; - mach_msg_type_number_t cnt; - struct vm_statistics vmstats; - error_t err; - - err = vm_statistics (mach_task_self (), &vmstats); - if (err) - return EIO; - - cnt = HOST_BASIC_INFO_COUNT; - err = host_info (mach_host_self (), HOST_BASIC_INFO, (host_info_t) &hbi, &cnt); - if (err) - return err; - - assert (cnt == HOST_BASIC_INFO_COUNT); - *contents_len = asprintf (contents, - "nr_free_pages %lu\n" - "nr_inactive_anon %lu\n" - "nr_active_anon %lu\n" - "nr_inactive_file %lu\n" - "nr_active_file %lu\n" - "nr_unevictable %lu\n" - "nr_mlock %lu\n" - "pgpgin %lu\n" - "pgpgout %lu\n" - "pgfault %lu\n", - (long unsigned) vmstats.free_count, - /* FIXME: how can we distinguish the anon/file pages? Maybe we can - ask the default pager how many it manages? */ - (long unsigned) vmstats.inactive_count, - (long unsigned) vmstats.active_count, - (long unsigned) 0, - (long unsigned) 0, - (long unsigned) vmstats.wire_count, - (long unsigned) vmstats.wire_count, - (long unsigned) vmstats.pageins, - (long unsigned) vmstats.pageouts, - (long unsigned) vmstats.faults); - - return 0; -} - -static error_t -rootdir_gc_cmdline (void *hook, char **contents, ssize_t *contents_len) -{ - struct ps_context *pc = hook; - struct proc_stat *ps; - error_t err; - - err = _proc_stat_create (opt_kernel_pid, pc, &ps); - if (err) - return EIO; - - err = proc_stat_set_flags (ps, PSTAT_ARGS); - if (err || ! (proc_stat_flags (ps) & PSTAT_ARGS)) - { - err = EIO; - goto out; - } - - *contents_len = proc_stat_args_len (ps); - *contents = malloc (*contents_len); - if (! *contents) - { - err = ENOMEM; - goto out; - } - - memcpy (*contents, proc_stat_args (ps), *contents_len); - argz_stringify (*contents, *contents_len, ' '); - (*contents)[*contents_len - 1] = '\n'; - -out: - _proc_stat_free (ps); - return err; -} - -static int -rootdir_fakeself_exists (void *dir_hook, const void *entry_hook) -{ - return opt_fake_self >= 0; -} - -static error_t -rootdir_gc_fakeself (void *hook, char **contents, ssize_t *contents_len) -{ - *contents_len = asprintf (contents, "%d", opt_fake_self); - return 0; -} - -/* The mtab translator to use by default for the "mounts" node. */ -#define MTAB_TRANSLATOR "/hurd/mtab" - -static struct node *rootdir_mounts_node; -static pthread_spinlock_t rootdir_mounts_node_lock = - PTHREAD_SPINLOCK_INITIALIZER; - -static struct node * -rootdir_mounts_make_node (void *dir_hook, const void *entry_hook) -{ - struct node *np, *prev; - - pthread_spin_lock (&rootdir_mounts_node_lock); - np = rootdir_mounts_node; - pthread_spin_unlock (&rootdir_mounts_node_lock); - - if (np != NULL) - { - netfs_nref (np); - return np; - } - - np = procfs_make_node (entry_hook, dir_hook); - if (np == NULL) - return NULL; - - procfs_node_chtype (np, S_IFREG | S_IPTRANS); - procfs_node_chmod (np, 0444); - - pthread_spin_lock (&rootdir_mounts_node_lock); - prev = rootdir_mounts_node; - if (rootdir_mounts_node == NULL) - rootdir_mounts_node = np; - pthread_spin_unlock (&rootdir_mounts_node_lock); - - if (prev != NULL) - { - procfs_cleanup (np); - np = prev; - } - - return np; -} - -static error_t -rootdir_mounts_get_translator (void *hook, char **argz, size_t *argz_len) -{ - static const char const mtab_argz[] = MTAB_TRANSLATOR "\0/"; - - *argz = malloc (sizeof mtab_argz); - if (! *argz) - return ENOMEM; - - memcpy (*argz, mtab_argz, sizeof mtab_argz); - *argz_len = sizeof mtab_argz; - return 0; -} - -static int -rootdir_mounts_exists (void *dir_hook, const void *entry_hook) -{ - static int translator_exists = -1; - if (translator_exists == -1) - translator_exists = access (MTAB_TRANSLATOR, F_OK|X_OK) == 0; - return translator_exists; -} - -static error_t -rootdir_gc_slabinfo (void *hook, char **contents, ssize_t *contents_len) -{ - error_t err; - FILE *m; - const char header[] = - "cache obj slab bufs objs bufs" - " total reclaimable\n" - "name flags size size /slab usage count" - " memory memory\n"; - cache_info_array_t cache_info; - size_t mem_usage, mem_reclaimable, mem_total, mem_total_reclaimable; - mach_msg_type_number_t cache_info_count; - int i; - - cache_info = NULL; - cache_info_count = 0; - - err = host_slab_info (mach_host_self(), &cache_info, &cache_info_count); - if (err) - return err; - - m = open_memstream (contents, contents_len); - if (m == NULL) - { - err = ENOMEM; - goto out; - } - - fprintf (m, "%s", header); - - mem_total = 0; - mem_total_reclaimable = 0; - - for (i = 0; i < cache_info_count; i++) - { - mem_usage = (cache_info[i].nr_slabs * cache_info[i].slab_size) - >> 10; - mem_total += mem_usage; - mem_reclaimable = (cache_info[i].flags & CACHE_FLAGS_NO_RECLAIM) - ? 0 : (cache_info[i].nr_free_slabs - * cache_info[i].slab_size) >> 10; - mem_total_reclaimable += mem_reclaimable; - fprintf (m, - "%-21s %04x %7zu %3zuk %4lu %6lu %6lu %7zuk %10zuk\n", - cache_info[i].name, cache_info[i].flags, - cache_info[i].obj_size, cache_info[i].slab_size >> 10, - cache_info[i].bufs_per_slab, cache_info[i].nr_objs, - cache_info[i].nr_bufs, mem_usage, mem_reclaimable); - } - - fprintf (m, "total: %zuk, reclaimable: %zuk\n", - mem_total, mem_total_reclaimable); - - fclose (m); - - out: - vm_deallocate (mach_task_self (), - cache_info, cache_info_count * sizeof *cache_info); - return err; -} - -/* Glue logic and entries table */ - -static struct node * -rootdir_file_make_node (void *dir_hook, const void *entry_hook) -{ - /* The entry hook we use is actually a procfs_node_ops for the file to be - created. The hook associated to these newly created files (and passed - to the generators above as a consequence) is always the same global - ps_context, which we get from rootdir_make_node as the directory hook. */ - return procfs_make_node (entry_hook, dir_hook); -} - -static struct node * -rootdir_symlink_make_node (void *dir_hook, const void *entry_hook) -{ - struct node *np = procfs_make_node (entry_hook, dir_hook); - if (np) - procfs_node_chtype (np, S_IFLNK); - return np; -} - -static const struct procfs_dir_entry rootdir_entries[] = { - { - .name = "self", - .hook = & (struct procfs_node_ops) { - .get_contents = rootdir_gc_fakeself, - .cleanup_contents = procfs_cleanup_contents_with_free, - }, - .ops = { - .make_node = rootdir_symlink_make_node, - .exists = rootdir_fakeself_exists, - } - }, - { - .name = "version", - .hook = & (struct procfs_node_ops) { - .get_contents = rootdir_gc_version, - .cleanup_contents = procfs_cleanup_contents_with_free, - }, - }, - { - .name = "uptime", - .hook = & (struct procfs_node_ops) { - .get_contents = rootdir_gc_uptime, - .cleanup_contents = procfs_cleanup_contents_with_free, - }, - }, - { - .name = "stat", - .hook = & (struct procfs_node_ops) { - .get_contents = rootdir_gc_stat, - .cleanup_contents = procfs_cleanup_contents_with_free, - }, - }, - { - .name = "loadavg", - .hook = & (struct procfs_node_ops) { - .get_contents = rootdir_gc_loadavg, - .cleanup_contents = procfs_cleanup_contents_with_free, - }, - }, - { - .name = "meminfo", - .hook = & (struct procfs_node_ops) { - .get_contents = rootdir_gc_meminfo, - .cleanup_contents = procfs_cleanup_contents_with_free, - }, - }, - { - .name = "vmstat", - .hook = & (struct procfs_node_ops) { - .get_contents = rootdir_gc_vmstat, - .cleanup_contents = procfs_cleanup_contents_with_free, - }, - }, - { - .name = "cmdline", - .hook = & (struct procfs_node_ops) { - .get_contents = rootdir_gc_cmdline, - .cleanup_contents = procfs_cleanup_contents_with_free, - }, - }, - { - .name = "mounts", - .hook = & (struct procfs_node_ops) { - .get_translator = rootdir_mounts_get_translator, - }, - .ops = { - .make_node = rootdir_mounts_make_node, - .exists = rootdir_mounts_exists, - } - }, - { - .name = "slabinfo", - .hook = & (struct procfs_node_ops) { - .get_contents = rootdir_gc_slabinfo, - .cleanup_contents = procfs_cleanup_contents_with_free, - }, - }, -#ifdef PROFILE - /* In order to get a usable gmon.out file, we must apparently use exit(). */ - { - .name = "exit", - .ops = { - .make_node = exit, - }, - }, -#endif - {} -}; - -struct node -*rootdir_make_node (struct ps_context *pc) -{ - static const struct procfs_dir_ops ops = { - .entries = rootdir_entries, - .entry_ops = { - .make_node = rootdir_file_make_node, - }, - }; - return procfs_dir_make_node (&ops, pc); -} - diff --git a/procfs/rootdir.h b/procfs/rootdir.h deleted file mode 100644 index 6980da8f..00000000 --- a/procfs/rootdir.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Hurd /proc filesystem, permanent files of the root directory. - 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 <ps.h> - -struct node * -rootdir_make_node (struct ps_context *pc); diff --git a/random/Makefile b/random/Makefile deleted file mode 100644 index 6291da0c..00000000 --- a/random/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -# -# Copyright (C) 1994,95,96,97,99,2000,2001 Free Software Foundation, Inc. -# -# This program 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. -# -# This program 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. - -dir := random -makemode := server - -CFLAGS += -D__HURD__ - -target = random -SRCS = random.c gnupg-random.c gnupg-rmd160.c -OBJS = $(SRCS:.c=.o) startup_notifyServer.o -LCLHDRS = gnupg-random.h gnupg-rmd.h gnupg-bithelp.h random.h -HURDLIBS = trivfs ports fshelp ihash shouldbeinlibc -OTHERLIBS = -lpthread -MIGSFLAGS = -DSEQNOS -imacros $(srcdir)/mig-mutate.h - -include ../Makeconf diff --git a/random/TODO b/random/TODO deleted file mode 100644 index 9cc57ab9..00000000 --- a/random/TODO +++ /dev/null @@ -1,11 +0,0 @@ -* read_poll uses random_poll until the pool is filled. This is ian - issue at first initialization, as this requries POOLSIZE good random (level 1 from - gather_random) even in level 0 and 1. - For now, the code is only applied to level 2. Eventually, readable_pool - should be fixed to return 0 if initialization is not done yet and not enough bytes - are available. Otherwise it enters an infinite loop. - -* Permissions? - -* Off by one error in gather_random/io_write? I can only get GATHERBUFSIZE - 1 - bytes from it. diff --git a/random/gnupg-bithelp.h b/random/gnupg-bithelp.h deleted file mode 100644 index 188db168..00000000 --- a/random/gnupg-bithelp.h +++ /dev/null @@ -1,41 +0,0 @@ -/* bithelp.h - Some bit manipulation helpers - * Copyright (C) 1999 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG 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 of the License, or - * (at your option) any later version. - * - * GnuPG 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-1307, USA - */ -#ifndef G10_BITHELP_H -#define G10_BITHELP_H - - -/**************** - * Rotate a 32 bit integer by n bytes - */ -#if defined(__GNUC__) && defined(__i386__) -static inline u32 -rol( u32 x, int n) -{ - __asm__("roll %%cl,%0" - :"=r" (x) - :"0" (x),"c" (n)); - return x; -} -#else - #define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) -#endif - - -#endif /*G10_BITHELP_H*/ diff --git a/random/gnupg-glue.h b/random/gnupg-glue.h deleted file mode 100644 index cbf0a103..00000000 --- a/random/gnupg-glue.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef __GNUPG_GLUE_H__ -#define __GNUPG_GLUE_H__ - -#include <sys/types.h> -#include <random.h> - -#define SIZEOF_UNSIGNED_LONG 4 -typedef unsigned int u32; -typedef unsigned char byte; - -/* GnuPG's config.h */ -#define HAVE_GETTIMEOFDAY 1 -#define HAVE_GETRUSAGE 1 -#define HAVE_RAND 1 - -/* GnuPG's memory.h */ -#define m_alloc malloc -#define m_alloc_secure malloc -#define m_alloc_clear(x) calloc(x, 1) -#define m_alloc_secure_clear(x) calloc(x, 1) -#define m_free free -#define m_strdup strdup - -/* GnuPG's dynaload.h */ -#define dynload_getfnc_fast_random_poll() (0) -#define dynload_getfnc_gather_random() &gather_random -int -gather_random( void (*add)(const void*, size_t, int), int requester, - size_t length, int level ); - -/* GnuPG's miscellaneous stuff. */ -#define BUG() assert(0) -#define _(x) x -#define make_timestamp() time(0) -#define tty_printf printf -#define log_info(format, args...) printf(format , ## args) -#define log_fatal(format, args...) { printf(format , ## args) ; exit(2); } -#define DIM(v) (sizeof(v)/sizeof((v)[0])) - -#endif /* __GNUPG_GLUE_H__ */ diff --git a/random/gnupg-random.c b/random/gnupg-random.c deleted file mode 100644 index 8f308621..00000000 --- a/random/gnupg-random.c +++ /dev/null @@ -1,810 +0,0 @@ -/* random.c - random number generator - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG 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 of the License, or - * (at your option) any later version. - * - * GnuPG 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-1307, USA - */ - - -/**************** - * This random number generator is modelled after the one described - * in Peter Gutmann's Paper: "Software Generation of Practically - * Strong Random Numbers". - */ - -#ifndef __HURD__ -#include <config.h> -#else -#include "gnupg-glue.h" -#endif -#include <stdio.h> -#include <stdlib.h> -#include <assert.h> -#include <errno.h> -#include <string.h> -#include <time.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <fcntl.h> -#ifdef HAVE_GETHRTIME - #include <sys/times.h> -#endif -#ifdef HAVE_GETTIMEOFDAY - #include <sys/times.h> -#endif -#ifdef HAVE_GETRUSAGE - #include <sys/resource.h> -#endif -#ifdef __MINGW32__ - #include <process.h> -#endif -#ifndef __HURD__ -#include "util.h" -#endif -#ifndef __HURD__ -#include "rmd.h" -#include "ttyio.h" -#include "i18n.h" -#include "random.h" -#include "rand-internal.h" -#include "dynload.h" -#else -#include "gnupg-rmd.h" -#include "gnupg-random.h" -#endif - -#ifndef RAND_MAX /* for SunOS */ - #define RAND_MAX 32767 -#endif - - -#if SIZEOF_UNSIGNED_LONG == 8 - #define ADD_VALUE 0xa5a5a5a5a5a5a5a5 -#elif SIZEOF_UNSIGNED_LONG == 4 - #define ADD_VALUE 0xa5a5a5a5 -#else - #error weird size for an unsigned long -#endif - -#define BLOCKLEN 64 /* hash this amount of bytes */ -#define DIGESTLEN 20 /* into a digest of this length (rmd160) */ -/* poolblocks is the number of digests which make up the pool - * and poolsize must be a multiple of the digest length - * to make the AND operations faster, the size should also be - * a multiple of ulong - */ -#define POOLBLOCKS 30 -#define POOLSIZE (POOLBLOCKS*DIGESTLEN) -#if (POOLSIZE % SIZEOF_UNSIGNED_LONG) - #error Please make sure that poolsize is a multiple of ulong -#endif -#define POOLWORDS (POOLSIZE / SIZEOF_UNSIGNED_LONG) - - -static int is_initialized; -#define MASK_LEVEL(a) do {if( a > 2 ) a = 2; else if( a < 0 ) a = 0; } while(0) -static char *rndpool; /* allocated size is POOLSIZE+BLOCKLEN */ -static char *keypool; /* allocated size is POOLSIZE+BLOCKLEN */ -static size_t pool_readpos; -static size_t pool_writepos; -static int pool_filled; -static int pool_balance; -static int just_mixed; -static int did_initial_extra_seeding; -static char *seed_file_name; -static int allow_seed_file_update; - -static int secure_alloc; -static int quick_test; -static int faked_rng; - - -#ifndef __HURD__ -static void read_pool( byte *buffer, size_t length, int level ); -#else -int read_pool( byte *buffer, size_t length, int level ); -#endif -static void add_randomness( const void *buffer, size_t length, int source ); -static void random_poll(void); -#ifndef __HURD__ -static void read_random_source( int requester, size_t length, int level); -#else -static int read_random_source( int requester, size_t length, int level); -#endif -static int gather_faked( void (*add)(const void*, size_t, int), int requester, - size_t length, int level ); - -static struct { - ulong mixrnd; - ulong mixkey; - ulong slowpolls; - ulong fastpolls; - ulong getbytes1; - ulong ngetbytes1; - ulong getbytes2; - ulong ngetbytes2; - ulong addbytes; - ulong naddbytes; -} rndstats; - -static void -initialize(void) -{ - /* The data buffer is allocated somewhat larger, so that - * we can use this extra space (which is allocated in secure memory) - * as a temporary hash buffer */ - rndpool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN) - : m_alloc_clear(POOLSIZE+BLOCKLEN); - keypool = secure_alloc ? m_alloc_secure_clear(POOLSIZE+BLOCKLEN) - : m_alloc_clear(POOLSIZE+BLOCKLEN); - is_initialized = 1; -#ifndef __HURD__ - cipher_modules_constructor(); -#endif -} - -static void -burn_stack (int bytes) -{ - char buf[128]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - -void -random_dump_stats() -{ - fprintf(stderr, - "random usage: poolsize=%d mixed=%lu polls=%lu/%lu added=%lu/%lu\n" - " outmix=%lu getlvl1=%lu/%lu getlvl2=%lu/%lu\n", - POOLSIZE, rndstats.mixrnd, rndstats.slowpolls, rndstats.fastpolls, - rndstats.naddbytes, rndstats.addbytes, - rndstats.mixkey, rndstats.ngetbytes1, rndstats.getbytes1, - rndstats.ngetbytes2, rndstats.getbytes2 ); -} - -void -secure_random_alloc() -{ - secure_alloc = 1; -} - - -int -quick_random_gen( int onoff ) -{ - int last; - - read_random_source(0,0,0); /* init */ - last = quick_test; - if( onoff != -1 ) - quick_test = onoff; - return faked_rng? 1 : last; -} - - -/**************** - * Fill the buffer with LENGTH bytes of cryptographically strong - * random bytes. level 0 is not very strong, 1 is strong enough - * for most usage, 2 is good for key generation stuff but may be very slow. - */ -void -randomize_buffer( byte *buffer, size_t length, int level ) -{ - char *p = get_random_bits( length*8, level, 1 ); - memcpy( buffer, p, length ); - m_free(p); -} - - -int -random_is_faked() -{ - if( !is_initialized ) - initialize(); - return faked_rng || quick_test; -} - -/**************** - * Return a pointer to a randomized buffer of level 0 and LENGTH bits - * caller must free the buffer. - * Note: The returned value is rounded up to bytes. - */ -byte * -get_random_bits( size_t nbits, int level, int secure ) -{ - byte *buf, *p; - size_t nbytes = (nbits+7)/8; - - if( quick_test && level > 1 ) - level = 1; - MASK_LEVEL(level); - if( level == 1 ) { - rndstats.getbytes1 += nbytes; - rndstats.ngetbytes1++; - } - else if( level >= 2 ) { - rndstats.getbytes2 += nbytes; - rndstats.ngetbytes2++; - } - - buf = secure && secure_alloc ? m_alloc_secure( nbytes ) : m_alloc( nbytes ); - for( p = buf; nbytes > 0; ) { - size_t n = nbytes > POOLSIZE? POOLSIZE : nbytes; -#ifdef __HURD__ - n = -#endif - read_pool( p, n, level ); - nbytes -= n; - p += n; - - } - return buf; -} - - -/**************** - * Mix the pool - */ -static void -mix_pool(byte *pool) -{ - char *hashbuf = pool + POOLSIZE; - char *p, *pend; - int i, n; - RMD160_CONTEXT md; - - rmd160_init( &md ); - #if DIGESTLEN != 20 - #error must have a digest length of 20 for ripe-md-160 - #endif - /* loop over the pool */ - pend = pool + POOLSIZE; - memcpy(hashbuf, pend - DIGESTLEN, DIGESTLEN ); - memcpy(hashbuf+DIGESTLEN, pool, BLOCKLEN-DIGESTLEN); - rmd160_mixblock( &md, hashbuf); - memcpy(pool, hashbuf, 20 ); - - p = pool; - for( n=1; n < POOLBLOCKS; n++ ) { - memcpy(hashbuf, p, DIGESTLEN ); - - p += DIGESTLEN; - if( p+DIGESTLEN+BLOCKLEN < pend ) - memcpy(hashbuf+DIGESTLEN, p+DIGESTLEN, BLOCKLEN-DIGESTLEN); - else { - char *pp = p+DIGESTLEN; - for(i=DIGESTLEN; i < BLOCKLEN; i++ ) { - if( pp >= pend ) - pp = pool; - hashbuf[i] = *pp++; - } - } - - rmd160_mixblock( &md, hashbuf); - memcpy(p, hashbuf, 20 ); - } - burn_stack (200); /* for the rmd160_mixblock() */ -} - - -void -set_random_seed_file( const char *name ) -{ - if( seed_file_name ) - BUG(); - seed_file_name = m_strdup( name ); -} - -/**************** - * Read in a seed form the random_seed file - * and return true if this was successful - */ -static int -read_seed_file() -{ - int fd; - struct stat sb; - unsigned char buffer[POOLSIZE]; - int n; - - if( !seed_file_name ) - return 0; - - #ifdef HAVE_DOSISH_SYSTEM - fd = open( seed_file_name, O_RDONLY | O_BINARY ); - #else - fd = open( seed_file_name, O_RDONLY ); - #endif - if( fd == -1 && errno == ENOENT) { - allow_seed_file_update = 1; - return 0; - } - - if( fd == -1 ) { - log_info(_("can't open `%s': %s\n"), seed_file_name, strerror(errno) ); - return 0; - } - if( fstat( fd, &sb ) ) { - log_info(_("can't stat `%s': %s\n"), seed_file_name, strerror(errno) ); - close(fd); - return 0; - } - if( !S_ISREG(sb.st_mode) ) { - log_info(_("`%s' is not a regular file - ignored\n"), seed_file_name ); - close(fd); - return 0; - } - if( !sb.st_size ) { - log_info(_("note: random_seed file is empty\n") ); - close(fd); - allow_seed_file_update = 1; - return 0; - } - if( sb.st_size != POOLSIZE ) { - log_info(_("warning: invalid size of random_seed file - not used\n") ); - close(fd); - return 0; - } - do { - n = read( fd, buffer, POOLSIZE ); - } while( n == -1 && errno == EINTR ); - if( n != POOLSIZE ) { - log_fatal(_("can't read `%s': %s\n"), seed_file_name,strerror(errno) ); - close(fd); - return 0; - } - - close(fd); - - add_randomness( buffer, POOLSIZE, 0 ); - /* add some minor entropy to the pool now (this will also force a mixing) */ - { pid_t x = getpid(); - add_randomness( &x, sizeof(x), 0 ); - } - { time_t x = time(NULL); - add_randomness( &x, sizeof(x), 0 ); - } - { clock_t x = clock(); - add_randomness( &x, sizeof(x), 0 ); - } - /* And read a few bytes from our entropy source. By using - * a level of 0 this will not block and might not return anything - * with some entropy drivers, however the rndlinux driver will use - * /dev/urandom and return some stuff - Do not read to much as we - * want to be friendly to the scare system entropy resource. */ - read_random_source( 0, 16, 0 ); - - allow_seed_file_update = 1; - return 1; -} - -void -update_random_seed_file() -{ - ulong *sp, *dp; - int fd, i; - - if( !seed_file_name || !is_initialized || !pool_filled ) - return; - if( !allow_seed_file_update ) { - log_info(_("note: random_seed file not updated\n")); - return; - } - - - /* copy the entropy pool to a scratch pool and mix both of them */ - for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool; - i < POOLWORDS; i++, dp++, sp++ ) { - *dp = *sp + ADD_VALUE; - } - mix_pool(rndpool); rndstats.mixrnd++; - mix_pool(keypool); rndstats.mixkey++; - - #ifdef HAVE_DOSISH_SYSTEM - fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, - S_IRUSR|S_IWUSR ); - #else - fd = open( seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR ); - #endif - if( fd == -1 ) { - log_info(_("can't create `%s': %s\n"), seed_file_name, strerror(errno) ); - return; - } - do { - i = write( fd, keypool, POOLSIZE ); - } while( i == -1 && errno == EINTR ); - if( i != POOLSIZE ) { - log_info(_("can't write `%s': %s\n"), seed_file_name, strerror(errno) ); - } - if( close(fd) ) - log_info(_("can't close `%s': %s\n"), seed_file_name, strerror(errno) ); -} - -#ifdef __HURD__ -int readable_pool( size_t length, int level ) -{ - size_t needed = 0; - size_t my_balance = pool_balance; - size_t available = (gatherwpos - gatherrpos + GATHERBUFSIZE) % GATHERBUFSIZE; - - if (length > POOLSIZE) - length = POOLSIZE; - - if (level < 2) - return length; - - if( !pool_filled ) { - if( read_seed_file() ) - pool_filled = 1; - } - - if (!did_initial_extra_seeding) - { - /* Take account for initial extra seeding. */ - needed = length; - if (needed < POOLSIZE/2) - needed = POOLSIZE/2; - my_balance = needed; - - if (!pool_filled && pool_writepos + needed < POOLSIZE) - { - /* If the pool is not filled yet, we couldn't read the seed - file. Too bad. We will now have to take account for so many - random_poll()s as fit into the remaining pool. */ - - needed += (POOLSIZE - pool_writepos + needed + POOLSIZE/5 - 1) / (POOLSIZE/5); - } - } - else - { - if (!pool_filled) - needed += (POOLSIZE - pool_writepos + needed + POOLSIZE/5 - 1) / (POOLSIZE/5); - } - - /* NEEDED contains the bytes needed for initialization, MY_BALANCE the resulting - available bytes. */ - if (available < needed) - return 0; - return available + my_balance - needed; -} -#endif - -#ifndef __HURD__ -static void -#else -int -#endif -read_pool( byte *buffer, size_t length, int level ) -{ - int i; - ulong *sp, *dp; - - if( length > POOLSIZE ) { -#ifndef __HURD__ - log_fatal(_("too many random bits requested; the limit is %d\n"), - POOLSIZE*8-1 ); -#else - length = POOLSIZE; -#endif - } - - if( !pool_filled ) { - if( read_seed_file() ) - pool_filled = 1; - } - - /* For level 2 quality (key generation) we alwas make - * sure that the pool has been seeded enough initially */ - if( level == 2 && !did_initial_extra_seeding ) { - size_t needed; - - pool_balance = 0; - needed = length - pool_balance; - if( needed < POOLSIZE/2 ) - needed = POOLSIZE/2; - else if( needed > POOLSIZE ) - BUG(); -#ifdef __HURD__ - needed = -#endif - read_random_source( 3, needed, 2 ); -#ifdef __HURD__ - if (! needed) - return 0; - /* XXX This will succeed with needed < POOLSIZE/2 even. But - erroring out will waste the random we already got. */ -#endif - pool_balance += needed; - did_initial_extra_seeding=1; - } - - /* for level 2 make sure that there is enough random in the pool */ - if( level == 2 && pool_balance < length ) { - size_t needed; - - if( pool_balance < 0 ) - pool_balance = 0; - needed = length - pool_balance; - if( needed > POOLSIZE ) - BUG(); -#ifdef __HURD__ - needed = -#endif - read_random_source( 3, needed, 2 ); - pool_balance += needed; - } - -#ifdef __HURD__ - /* XXX This makes level 0 and 1 worse than needed at first start up. */ - if (level == 2) -#endif - /* make sure the pool is filled */ - while( !pool_filled ) - random_poll(); - - /* do always a fast random poll */ - fast_random_poll(); - - if( !level ) { /* no need for cryptographic strong random */ - /* create a new pool */ - for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool; - i < POOLWORDS; i++, dp++, sp++ ) - *dp = *sp + ADD_VALUE; - /* must mix both pools */ - mix_pool(rndpool); rndstats.mixrnd++; - mix_pool(keypool); rndstats.mixkey++; - memcpy( buffer, keypool, length ); - return length; - } - else { -#ifdef __HURD__ - int amount; -#endif - /* mix the pool (if add_randomness() didn't it) */ - if( !just_mixed ) { - mix_pool(rndpool); - rndstats.mixrnd++; - } - /* create a new pool */ - for(i=0,dp=(ulong*)keypool, sp=(ulong*)rndpool; - i < POOLWORDS; i++, dp++, sp++ ) - *dp = *sp + ADD_VALUE; - /* and mix both pools */ - mix_pool(rndpool); rndstats.mixrnd++; - mix_pool(keypool); rndstats.mixkey++; - /* read the required data - * we use a readpoiter to read from a different postion each - * time */ -#ifdef __HURD__ - if (level == 2 && length > pool_balance) - length = pool_balance; - amount = length; -#endif - while( length-- ) { - *buffer++ = keypool[pool_readpos++]; - if( pool_readpos >= POOLSIZE ) - pool_readpos = 0; - pool_balance--; - } - if( pool_balance < 0 ) - pool_balance = 0; - /* and clear the keypool */ - memset( keypool, 0, POOLSIZE ); -#ifdef __HURD__ - return amount; -#endif - } -} - - -/**************** - * Add LENGTH bytes of randomness from buffer to the pool. - * source may be used to specify the randomness source. - * Source is: - * 0 - used ony for initialization - * 1 - fast random poll function - * 2 - normal poll function - * 3 - used when level 2 random quality has been requested - * to do an extra pool seed. - */ -static void -add_randomness( const void *buffer, size_t length, int source ) -{ - const byte *p = buffer; - - if( !is_initialized ) - initialize(); - rndstats.addbytes += length; - rndstats.naddbytes++; - while( length-- ) { - rndpool[pool_writepos++] = *p++; - if( pool_writepos >= POOLSIZE ) { - if( source > 1 ) - pool_filled = 1; - pool_writepos = 0; - mix_pool(rndpool); rndstats.mixrnd++; - just_mixed = !length; - } - } -} - - - -static void -random_poll() -{ - rndstats.slowpolls++; - read_random_source( 2, POOLSIZE/5, 1 ); -} - - -void -fast_random_poll() -{ - static void (*fnc)( void (*)(const void*, size_t, int), int) = NULL; - static int initialized = 0; - - rndstats.fastpolls++; - if( !initialized ) { - if( !is_initialized ) - initialize(); - initialized = 1; - fnc = dynload_getfnc_fast_random_poll(); - } - if( fnc ) { - (*fnc)( add_randomness, 1 ); - return; - } - - /* fall back to the generic function */ - #if HAVE_GETHRTIME - { hrtime_t tv; - tv = gethrtime(); - add_randomness( &tv, sizeof(tv), 1 ); - } - #elif HAVE_GETTIMEOFDAY - { struct timeval tv; - if( gettimeofday( &tv, NULL ) ) - BUG(); - add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 ); - add_randomness( &tv.tv_usec, sizeof(tv.tv_usec), 1 ); - } - #elif HAVE_CLOCK_GETTIME - { struct timespec tv; - if( clock_gettime( CLOCK_REALTIME, &tv ) == -1 ) - BUG(); - add_randomness( &tv.tv_sec, sizeof(tv.tv_sec), 1 ); - add_randomness( &tv.tv_nsec, sizeof(tv.tv_nsec), 1 ); - } - #else /* use times */ - #ifndef HAVE_DOSISH_SYSTEM - { struct tms buf; - times( &buf ); - add_randomness( &buf, sizeof buf, 1 ); - } - #endif - #endif - #ifdef HAVE_GETRUSAGE - #ifndef RUSAGE_SELF - #ifdef __GCC__ - #warning There is no RUSAGE_SELF on this system - #endif - #else - { struct rusage buf; - /* QNX/Neutrino does return ENOSYS - so we just ignore it and - * add whatever is in buf. In a chroot environment it might not - * work at all (i.e. because /proc/ is not accessible), so we better - * ognore all error codes and hope for the best - */ - getrusage( RUSAGE_SELF, &buf ); - - add_randomness( &buf, sizeof buf, 1 ); - memset( &buf, 0, sizeof buf ); - } - #endif - #endif - /* time and clock are availabe on all systems - so - * we better do it just in case one of the above functions - * didn't work */ - { time_t x = time(NULL); - add_randomness( &x, sizeof(x), 1 ); - } - { clock_t x = clock(); - add_randomness( &x, sizeof(x), 1 ); - } -} - - -#ifndef __HURD__ -static void -#else -static int -#endif -read_random_source( int requester, size_t length, int level ) -{ - static int (*fnc)(void (*)(const void*, size_t, int), int, - size_t, int) = NULL; -#ifdef __HURD__ - int got; -#endif - if( !fnc ) { - if( !is_initialized ) - initialize(); - fnc = dynload_getfnc_gather_random(); - if( !fnc ) { - faked_rng = 1; - fnc = gather_faked; - } - if( !requester && !length && !level ) -#ifndef __HURD__ - return; /* init only */ -#else - return 0; -#endif - } -#ifndef __HURD__ - if( (*fnc)( add_randomness, requester, length, level ) < 0 ) - log_fatal("No way to gather entropy for the RNG\n"); -#else - got = (*fnc)( add_randomness, requester, length, level ); - if (got < 0) - log_fatal("No way to gather entropy for the RNG\n"); - return got; -#endif -} - - -static int -gather_faked( void (*add)(const void*, size_t, int), int requester, - size_t length, int level ) -{ - static int initialized=0; - size_t n; - char *buffer, *p; - - if( !initialized ) { - log_info(_("WARNING: using insecure random number generator!!\n")); - tty_printf(_("The random number generator is only a kludge to let\n" - "it run - it is in no way a strong RNG!\n\n" - "DON'T USE ANY DATA GENERATED BY THIS PROGRAM!!\n\n")); - initialized=1; - #ifdef HAVE_RAND - srand(make_timestamp()*getpid()); - #else - srandom(make_timestamp()*getpid()); - #endif - } - printf("WAITING FOR %i bytes.\n", length); - p = buffer = m_alloc( length ); - n = length; - #ifdef HAVE_RAND - while( n-- ) - *p++ = ((unsigned)(1 + (int) (256.0*rand()/(RAND_MAX+1.0)))-1); - #else - while( n-- ) - *p++ = ((unsigned)(1 + (int) (256.0*random()/(RAND_MAX+1.0)))-1); - #endif - add_randomness( buffer, length, requester ); - m_free(buffer); - return 0; /* okay */ -} - diff --git a/random/gnupg-random.h b/random/gnupg-random.h deleted file mode 100644 index ee18febc..00000000 --- a/random/gnupg-random.h +++ /dev/null @@ -1,47 +0,0 @@ -/* random.h - random functions - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG 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 of the License, or - * (at your option) any later version. - * - * GnuPG 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-1307, USA - */ -#ifndef G10_RANDOM_H -#define G10_RANDOM_H - -#ifndef __HURD__ -#include "types.h" -#else -#include "gnupg-glue.h" -int read_pool (byte *, size_t, int); -int readable_pool (size_t, int); -#endif - -/*-- random.c --*/ -void random_dump_stats(void); -void secure_random_alloc(void); -void set_random_seed_file(const char *); -void update_random_seed_file(void); -int quick_random_gen( int onoff ); -int random_is_faked(void); -void randomize_buffer( byte *buffer, size_t length, int level ); -byte *get_random_bits( size_t nbits, int level, int secure ); -void fast_random_poll( void ); - -/*-- rndw32.c --*/ -#ifdef USE_STATIC_RNDW32 -void rndw32_set_dll_name( const char *name ); -#endif - -#endif /*G10_RANDOM_H*/ diff --git a/random/gnupg-rmd.h b/random/gnupg-rmd.h deleted file mode 100644 index 2446fc7d..00000000 --- a/random/gnupg-rmd.h +++ /dev/null @@ -1,38 +0,0 @@ -/* rmd.h - RIPE-MD hash functions - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG 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 of the License, or - * (at your option) any later version. - * - * GnuPG 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-1307, USA - */ -#ifndef G10_RMD_H -#define G10_RMD_H - -#ifdef __HURD__ -#include "gnupg-glue.h" -#endif - -/* we need this here because random.c must have direct access */ -typedef struct { - u32 h0,h1,h2,h3,h4; - u32 nblocks; - byte buf[64]; - int count; -} RMD160_CONTEXT; - -void rmd160_init( RMD160_CONTEXT *hd ); -void rmd160_mixblock( RMD160_CONTEXT *hd, char *buffer ); - -#endif /*G10_RMD_H*/ diff --git a/random/gnupg-rmd160.c b/random/gnupg-rmd160.c deleted file mode 100644 index 66107685..00000000 --- a/random/gnupg-rmd160.c +++ /dev/null @@ -1,656 +0,0 @@ -/* rmd160.c - RIPE-MD160 - * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. - * - * This file is part of GnuPG. - * - * GnuPG 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 of the License, or - * (at your option) any later version. - * - * GnuPG 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-1307, USA - */ - -#ifndef __HURD__ -#include <config.h> -#endif -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> -#ifndef __HURD__ -#include "util.h" -#include "memory.h" -#include "rmd.h" -#include "cipher.h" /* only used for the rmd160_hash_buffer() prototype */ -#include "dynload.h" - -#include "bithelp.h" -#else -#include "gnupg-rmd.h" -#include "gnupg-bithelp.h" -#endif - - -/********************************* - * RIPEMD-160 is not patented, see (as of 25.10.97) - * http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html - * Note that the code uses Little Endian byteorder, which is good for - * 386 etc, but we must add some conversion when used on a big endian box. - * - * - * Pseudo-code for RIPEMD-160 - * - * RIPEMD-160 is an iterative hash function that operates on 32-bit words. - * The round function takes as input a 5-word chaining variable and a 16-word - * message block and maps this to a new chaining variable. All operations are - * defined on 32-bit words. Padding is identical to that of MD4. - * - * - * RIPEMD-160: definitions - * - * - * nonlinear functions at bit level: exor, mux, -, mux, - - * - * f(j, x, y, z) = x XOR y XOR z (0 <= j <= 15) - * f(j, x, y, z) = (x AND y) OR (NOT(x) AND z) (16 <= j <= 31) - * f(j, x, y, z) = (x OR NOT(y)) XOR z (32 <= j <= 47) - * f(j, x, y, z) = (x AND z) OR (y AND NOT(z)) (48 <= j <= 63) - * f(j, x, y, z) = x XOR (y OR NOT(z)) (64 <= j <= 79) - * - * - * added constants (hexadecimal) - * - * K(j) = 0x00000000 (0 <= j <= 15) - * K(j) = 0x5A827999 (16 <= j <= 31) int(2**30 x sqrt(2)) - * K(j) = 0x6ED9EBA1 (32 <= j <= 47) int(2**30 x sqrt(3)) - * K(j) = 0x8F1BBCDC (48 <= j <= 63) int(2**30 x sqrt(5)) - * K(j) = 0xA953FD4E (64 <= j <= 79) int(2**30 x sqrt(7)) - * K'(j) = 0x50A28BE6 (0 <= j <= 15) int(2**30 x cbrt(2)) - * K'(j) = 0x5C4DD124 (16 <= j <= 31) int(2**30 x cbrt(3)) - * K'(j) = 0x6D703EF3 (32 <= j <= 47) int(2**30 x cbrt(5)) - * K'(j) = 0x7A6D76E9 (48 <= j <= 63) int(2**30 x cbrt(7)) - * K'(j) = 0x00000000 (64 <= j <= 79) - * - * - * selection of message word - * - * r(j) = j (0 <= j <= 15) - * r(16..31) = 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8 - * r(32..47) = 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12 - * r(48..63) = 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2 - * r(64..79) = 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 - * r0(0..15) = 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12 - * r0(16..31)= 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2 - * r0(32..47)= 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13 - * r0(48..63)= 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14 - * r0(64..79)= 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 - * - * - * amount for rotate left (rol) - * - * s(0..15) = 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8 - * s(16..31) = 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12 - * s(32..47) = 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5 - * s(48..63) = 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12 - * s(64..79) = 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 - * s'(0..15) = 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6 - * s'(16..31)= 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11 - * s'(32..47)= 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5 - * s'(48..63)= 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8 - * s'(64..79)= 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 - * - * - * initial value (hexadecimal) - * - * h0 = 0x67452301; h1 = 0xEFCDAB89; h2 = 0x98BADCFE; h3 = 0x10325476; - * h4 = 0xC3D2E1F0; - * - * - * RIPEMD-160: pseudo-code - * - * It is assumed that the message after padding consists of t 16-word blocks - * that will be denoted with X[i][j], with 0 <= i <= t-1 and 0 <= j <= 15. - * The symbol [+] denotes addition modulo 2**32 and rol_s denotes cyclic left - * shift (rotate) over s positions. - * - * - * for i := 0 to t-1 { - * A := h0; B := h1; C := h2; D = h3; E = h4; - * A' := h0; B' := h1; C' := h2; D' = h3; E' = h4; - * for j := 0 to 79 { - * T := rol_s(j)(A [+] f(j, B, C, D) [+] X[i][r(j)] [+] K(j)) [+] E; - * A := E; E := D; D := rol_10(C); C := B; B := T; - * T := rol_s'(j)(A' [+] f(79-j, B', C', D') [+] X[i][r'(j)] - [+] K'(j)) [+] E'; - * A' := E'; E' := D'; D' := rol_10(C'); C' := B'; B' := T; - * } - * T := h1 [+] C [+] D'; h1 := h2 [+] D [+] E'; h2 := h3 [+] E [+] A'; - * h3 := h4 [+] A [+] B'; h4 := h0 [+] B [+] C'; h0 := T; - * } - */ - -/* Some examples: - * "" 9c1185a5c5e9fc54612808977ee8f548b2258d31 - * "a" 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe - * "abc" 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc - * "message digest" 5d0689ef49d2fae572b881b123a85ffa21595f36 - * "a...z" f71c27109c692c1b56bbdceb5b9d2865b3708dbc - * "abcdbcde...nopq" 12a053384a9c0c88e405a06c27dcf49ada62eb2b - * "A...Za...z0...9" b0e20b6e3116640286ed3a87a5713079b21f5189 - * 8 times "1234567890" 9b752e45573d4b39f4dbd3323cab82bf63326bfb - * 1 million times "a" 52783243c1697bdbe16d37f97f68f08325dc1528 - */ - -static void -burn_stack (int bytes) -{ - char buf[150]; - - memset (buf, 0, sizeof buf); - bytes -= sizeof buf; - if (bytes > 0) - burn_stack (bytes); -} - - - -void -rmd160_init( RMD160_CONTEXT *hd ) -{ - hd->h0 = 0x67452301; - hd->h1 = 0xEFCDAB89; - hd->h2 = 0x98BADCFE; - hd->h3 = 0x10325476; - hd->h4 = 0xC3D2E1F0; - hd->nblocks = 0; - hd->count = 0; -} - - - -/**************** - * Transform the message X which consists of 16 32-bit-words - */ -static void -transform( RMD160_CONTEXT *hd, byte *data ) -{ - u32 a,b,c,d,e,aa,bb,cc,dd,ee,t; - #ifdef BIG_ENDIAN_HOST - u32 x[16]; - { int i; - byte *p2, *p1; - for(i=0, p1=data, p2=(byte*)x; i < 16; i++, p2 += 4 ) { - p2[3] = *p1++; - p2[2] = *p1++; - p2[1] = *p1++; - p2[0] = *p1++; - } - } - #else - #if 0 - u32 *x =(u32*)data; - #else - /* this version is better because it is always aligned; - * The performance penalty on a 586-100 is about 6% which - * is acceptable - because the data is more local it might - * also be possible that this is faster on some machines. - * This function (when compiled with -02 on gcc 2.7.2) - * executes on a 586-100 (39.73 bogomips) at about 1900kb/sec; - * [measured with a 4MB data and "gpgm --print-md rmd160"] */ - u32 x[16]; - memcpy( x, data, 64 ); - #endif - #endif - - -#define K0 0x00000000 -#define K1 0x5A827999 -#define K2 0x6ED9EBA1 -#define K3 0x8F1BBCDC -#define K4 0xA953FD4E -#define KK0 0x50A28BE6 -#define KK1 0x5C4DD124 -#define KK2 0x6D703EF3 -#define KK3 0x7A6D76E9 -#define KK4 0x00000000 -#define F0(x,y,z) ( (x) ^ (y) ^ (z) ) -#define F1(x,y,z) ( ((x) & (y)) | (~(x) & (z)) ) -#define F2(x,y,z) ( ((x) | ~(y)) ^ (z) ) -#define F3(x,y,z) ( ((x) & (z)) | ((y) & ~(z)) ) -#define F4(x,y,z) ( (x) ^ ((y) | ~(z)) ) -#define R(a,b,c,d,e,f,k,r,s) do { t = a + f(b,c,d) + k + x[r]; \ - a = rol(t,s) + e; \ - c = rol(c,10); \ - } while(0) - - /* left lane */ - a = hd->h0; - b = hd->h1; - c = hd->h2; - d = hd->h3; - e = hd->h4; - R( a, b, c, d, e, F0, K0, 0, 11 ); - R( e, a, b, c, d, F0, K0, 1, 14 ); - R( d, e, a, b, c, F0, K0, 2, 15 ); - R( c, d, e, a, b, F0, K0, 3, 12 ); - R( b, c, d, e, a, F0, K0, 4, 5 ); - R( a, b, c, d, e, F0, K0, 5, 8 ); - R( e, a, b, c, d, F0, K0, 6, 7 ); - R( d, e, a, b, c, F0, K0, 7, 9 ); - R( c, d, e, a, b, F0, K0, 8, 11 ); - R( b, c, d, e, a, F0, K0, 9, 13 ); - R( a, b, c, d, e, F0, K0, 10, 14 ); - R( e, a, b, c, d, F0, K0, 11, 15 ); - R( d, e, a, b, c, F0, K0, 12, 6 ); - R( c, d, e, a, b, F0, K0, 13, 7 ); - R( b, c, d, e, a, F0, K0, 14, 9 ); - R( a, b, c, d, e, F0, K0, 15, 8 ); - R( e, a, b, c, d, F1, K1, 7, 7 ); - R( d, e, a, b, c, F1, K1, 4, 6 ); - R( c, d, e, a, b, F1, K1, 13, 8 ); - R( b, c, d, e, a, F1, K1, 1, 13 ); - R( a, b, c, d, e, F1, K1, 10, 11 ); - R( e, a, b, c, d, F1, K1, 6, 9 ); - R( d, e, a, b, c, F1, K1, 15, 7 ); - R( c, d, e, a, b, F1, K1, 3, 15 ); - R( b, c, d, e, a, F1, K1, 12, 7 ); - R( a, b, c, d, e, F1, K1, 0, 12 ); - R( e, a, b, c, d, F1, K1, 9, 15 ); - R( d, e, a, b, c, F1, K1, 5, 9 ); - R( c, d, e, a, b, F1, K1, 2, 11 ); - R( b, c, d, e, a, F1, K1, 14, 7 ); - R( a, b, c, d, e, F1, K1, 11, 13 ); - R( e, a, b, c, d, F1, K1, 8, 12 ); - R( d, e, a, b, c, F2, K2, 3, 11 ); - R( c, d, e, a, b, F2, K2, 10, 13 ); - R( b, c, d, e, a, F2, K2, 14, 6 ); - R( a, b, c, d, e, F2, K2, 4, 7 ); - R( e, a, b, c, d, F2, K2, 9, 14 ); - R( d, e, a, b, c, F2, K2, 15, 9 ); - R( c, d, e, a, b, F2, K2, 8, 13 ); - R( b, c, d, e, a, F2, K2, 1, 15 ); - R( a, b, c, d, e, F2, K2, 2, 14 ); - R( e, a, b, c, d, F2, K2, 7, 8 ); - R( d, e, a, b, c, F2, K2, 0, 13 ); - R( c, d, e, a, b, F2, K2, 6, 6 ); - R( b, c, d, e, a, F2, K2, 13, 5 ); - R( a, b, c, d, e, F2, K2, 11, 12 ); - R( e, a, b, c, d, F2, K2, 5, 7 ); - R( d, e, a, b, c, F2, K2, 12, 5 ); - R( c, d, e, a, b, F3, K3, 1, 11 ); - R( b, c, d, e, a, F3, K3, 9, 12 ); - R( a, b, c, d, e, F3, K3, 11, 14 ); - R( e, a, b, c, d, F3, K3, 10, 15 ); - R( d, e, a, b, c, F3, K3, 0, 14 ); - R( c, d, e, a, b, F3, K3, 8, 15 ); - R( b, c, d, e, a, F3, K3, 12, 9 ); - R( a, b, c, d, e, F3, K3, 4, 8 ); - R( e, a, b, c, d, F3, K3, 13, 9 ); - R( d, e, a, b, c, F3, K3, 3, 14 ); - R( c, d, e, a, b, F3, K3, 7, 5 ); - R( b, c, d, e, a, F3, K3, 15, 6 ); - R( a, b, c, d, e, F3, K3, 14, 8 ); - R( e, a, b, c, d, F3, K3, 5, 6 ); - R( d, e, a, b, c, F3, K3, 6, 5 ); - R( c, d, e, a, b, F3, K3, 2, 12 ); - R( b, c, d, e, a, F4, K4, 4, 9 ); - R( a, b, c, d, e, F4, K4, 0, 15 ); - R( e, a, b, c, d, F4, K4, 5, 5 ); - R( d, e, a, b, c, F4, K4, 9, 11 ); - R( c, d, e, a, b, F4, K4, 7, 6 ); - R( b, c, d, e, a, F4, K4, 12, 8 ); - R( a, b, c, d, e, F4, K4, 2, 13 ); - R( e, a, b, c, d, F4, K4, 10, 12 ); - R( d, e, a, b, c, F4, K4, 14, 5 ); - R( c, d, e, a, b, F4, K4, 1, 12 ); - R( b, c, d, e, a, F4, K4, 3, 13 ); - R( a, b, c, d, e, F4, K4, 8, 14 ); - R( e, a, b, c, d, F4, K4, 11, 11 ); - R( d, e, a, b, c, F4, K4, 6, 8 ); - R( c, d, e, a, b, F4, K4, 15, 5 ); - R( b, c, d, e, a, F4, K4, 13, 6 ); - - aa = a; bb = b; cc = c; dd = d; ee = e; - - /* right lane */ - a = hd->h0; - b = hd->h1; - c = hd->h2; - d = hd->h3; - e = hd->h4; - R( a, b, c, d, e, F4, KK0, 5, 8); - R( e, a, b, c, d, F4, KK0, 14, 9); - R( d, e, a, b, c, F4, KK0, 7, 9); - R( c, d, e, a, b, F4, KK0, 0, 11); - R( b, c, d, e, a, F4, KK0, 9, 13); - R( a, b, c, d, e, F4, KK0, 2, 15); - R( e, a, b, c, d, F4, KK0, 11, 15); - R( d, e, a, b, c, F4, KK0, 4, 5); - R( c, d, e, a, b, F4, KK0, 13, 7); - R( b, c, d, e, a, F4, KK0, 6, 7); - R( a, b, c, d, e, F4, KK0, 15, 8); - R( e, a, b, c, d, F4, KK0, 8, 11); - R( d, e, a, b, c, F4, KK0, 1, 14); - R( c, d, e, a, b, F4, KK0, 10, 14); - R( b, c, d, e, a, F4, KK0, 3, 12); - R( a, b, c, d, e, F4, KK0, 12, 6); - R( e, a, b, c, d, F3, KK1, 6, 9); - R( d, e, a, b, c, F3, KK1, 11, 13); - R( c, d, e, a, b, F3, KK1, 3, 15); - R( b, c, d, e, a, F3, KK1, 7, 7); - R( a, b, c, d, e, F3, KK1, 0, 12); - R( e, a, b, c, d, F3, KK1, 13, 8); - R( d, e, a, b, c, F3, KK1, 5, 9); - R( c, d, e, a, b, F3, KK1, 10, 11); - R( b, c, d, e, a, F3, KK1, 14, 7); - R( a, b, c, d, e, F3, KK1, 15, 7); - R( e, a, b, c, d, F3, KK1, 8, 12); - R( d, e, a, b, c, F3, KK1, 12, 7); - R( c, d, e, a, b, F3, KK1, 4, 6); - R( b, c, d, e, a, F3, KK1, 9, 15); - R( a, b, c, d, e, F3, KK1, 1, 13); - R( e, a, b, c, d, F3, KK1, 2, 11); - R( d, e, a, b, c, F2, KK2, 15, 9); - R( c, d, e, a, b, F2, KK2, 5, 7); - R( b, c, d, e, a, F2, KK2, 1, 15); - R( a, b, c, d, e, F2, KK2, 3, 11); - R( e, a, b, c, d, F2, KK2, 7, 8); - R( d, e, a, b, c, F2, KK2, 14, 6); - R( c, d, e, a, b, F2, KK2, 6, 6); - R( b, c, d, e, a, F2, KK2, 9, 14); - R( a, b, c, d, e, F2, KK2, 11, 12); - R( e, a, b, c, d, F2, KK2, 8, 13); - R( d, e, a, b, c, F2, KK2, 12, 5); - R( c, d, e, a, b, F2, KK2, 2, 14); - R( b, c, d, e, a, F2, KK2, 10, 13); - R( a, b, c, d, e, F2, KK2, 0, 13); - R( e, a, b, c, d, F2, KK2, 4, 7); - R( d, e, a, b, c, F2, KK2, 13, 5); - R( c, d, e, a, b, F1, KK3, 8, 15); - R( b, c, d, e, a, F1, KK3, 6, 5); - R( a, b, c, d, e, F1, KK3, 4, 8); - R( e, a, b, c, d, F1, KK3, 1, 11); - R( d, e, a, b, c, F1, KK3, 3, 14); - R( c, d, e, a, b, F1, KK3, 11, 14); - R( b, c, d, e, a, F1, KK3, 15, 6); - R( a, b, c, d, e, F1, KK3, 0, 14); - R( e, a, b, c, d, F1, KK3, 5, 6); - R( d, e, a, b, c, F1, KK3, 12, 9); - R( c, d, e, a, b, F1, KK3, 2, 12); - R( b, c, d, e, a, F1, KK3, 13, 9); - R( a, b, c, d, e, F1, KK3, 9, 12); - R( e, a, b, c, d, F1, KK3, 7, 5); - R( d, e, a, b, c, F1, KK3, 10, 15); - R( c, d, e, a, b, F1, KK3, 14, 8); - R( b, c, d, e, a, F0, KK4, 12, 8); - R( a, b, c, d, e, F0, KK4, 15, 5); - R( e, a, b, c, d, F0, KK4, 10, 12); - R( d, e, a, b, c, F0, KK4, 4, 9); - R( c, d, e, a, b, F0, KK4, 1, 12); - R( b, c, d, e, a, F0, KK4, 5, 5); - R( a, b, c, d, e, F0, KK4, 8, 14); - R( e, a, b, c, d, F0, KK4, 7, 6); - R( d, e, a, b, c, F0, KK4, 6, 8); - R( c, d, e, a, b, F0, KK4, 2, 13); - R( b, c, d, e, a, F0, KK4, 13, 6); - R( a, b, c, d, e, F0, KK4, 14, 5); - R( e, a, b, c, d, F0, KK4, 0, 15); - R( d, e, a, b, c, F0, KK4, 3, 13); - R( c, d, e, a, b, F0, KK4, 9, 11); - R( b, c, d, e, a, F0, KK4, 11, 11); - - - t = hd->h1 + d + cc; - hd->h1 = hd->h2 + e + dd; - hd->h2 = hd->h3 + a + ee; - hd->h3 = hd->h4 + b + aa; - hd->h4 = hd->h0 + c + bb; - hd->h0 = t; -} - - -/* Update the message digest with the contents - * of INBUF with length INLEN. - */ -static void -rmd160_write( RMD160_CONTEXT *hd, byte *inbuf, size_t inlen) -{ - if( hd->count == 64 ) { /* flush the buffer */ - transform( hd, hd->buf ); - burn_stack (108+5*sizeof(void*)); - hd->count = 0; - hd->nblocks++; - } - if( !inbuf ) - return; - if( hd->count ) { - for( ; inlen && hd->count < 64; inlen-- ) - hd->buf[hd->count++] = *inbuf++; - rmd160_write( hd, NULL, 0 ); - if( !inlen ) - return; - } - - while( inlen >= 64 ) { - transform( hd, inbuf ); - hd->count = 0; - hd->nblocks++; - inlen -= 64; - inbuf += 64; - } - burn_stack (108+5*sizeof(void*)); - for( ; inlen && hd->count < 64; inlen-- ) - hd->buf[hd->count++] = *inbuf++; -} - -/**************** - * Apply the rmd160 transform function on the buffer which must have - * a length 64 bytes. Do not use this function together with the - * other functions, use rmd160_init to initialize internal variables. - * Returns: 16 bytes in buffer with the mixed contentes of buffer. - */ -void -rmd160_mixblock( RMD160_CONTEXT *hd, char *buffer ) -{ - char *p = buffer; - transform( hd, buffer ); - #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) - X(0); - X(1); - X(2); - X(3); - X(4); - #undef X -} - - -/* The routine terminates the computation - */ - -static void -rmd160_final( RMD160_CONTEXT *hd ) -{ - u32 t, msb, lsb; - byte *p; - - rmd160_write(hd, NULL, 0); /* flush */; - - t = hd->nblocks; - /* multiply by 64 to make a byte count */ - lsb = t << 6; - msb = t >> 26; - /* add the count */ - t = lsb; - if( (lsb += hd->count) < t ) - msb++; - /* multiply by 8 to make a bit count */ - t = lsb; - lsb <<= 3; - msb <<= 3; - msb |= t >> 29; - - if( hd->count < 56 ) { /* enough room */ - hd->buf[hd->count++] = 0x80; /* pad */ - while( hd->count < 56 ) - hd->buf[hd->count++] = 0; /* pad */ - } - else { /* need one extra block */ - hd->buf[hd->count++] = 0x80; /* pad character */ - while( hd->count < 64 ) - hd->buf[hd->count++] = 0; - rmd160_write(hd, NULL, 0); /* flush */; - memset(hd->buf, 0, 56 ); /* fill next block with zeroes */ - } - /* append the 64 bit count */ - hd->buf[56] = lsb ; - hd->buf[57] = lsb >> 8; - hd->buf[58] = lsb >> 16; - hd->buf[59] = lsb >> 24; - hd->buf[60] = msb ; - hd->buf[61] = msb >> 8; - hd->buf[62] = msb >> 16; - hd->buf[63] = msb >> 24; - transform( hd, hd->buf ); - burn_stack (108+5*sizeof(void*)); - - p = hd->buf; - #ifdef BIG_ENDIAN_HOST - #define X(a) do { *p++ = hd->h##a ; *p++ = hd->h##a >> 8; \ - *p++ = hd->h##a >> 16; *p++ = hd->h##a >> 24; } while(0) - #else /* little endian */ - #define X(a) do { *(u32*)p = hd->h##a ; p += 4; } while(0) - #endif - X(0); - X(1); - X(2); - X(3); - X(4); - #undef X -} - -static byte * -rmd160_read( RMD160_CONTEXT *hd ) -{ - return hd->buf; -} - - - -/**************** - * Shortcut functions which puts the hash value of the supplied buffer - * into outbuf which must have a size of 20 bytes. - */ -void -rmd160_hash_buffer( char *outbuf, const char *buffer, size_t length ) -{ - RMD160_CONTEXT hd; - - rmd160_init( &hd ); - rmd160_write( &hd, (byte*)buffer, length ); - rmd160_final( &hd ); - memcpy( outbuf, hd.buf, 20 ); -} - - -/**************** - * Return some information about the algorithm. We need algo here to - * distinguish different flavors of the algorithm. - * Returns: A pointer to string describing the algorithm or NULL if - * the ALGO is invalid. - */ -static const char * -rmd160_get_info( int algo, size_t *contextsize, - byte **r_asnoid, int *r_asnlen, int *r_mdlen, - void (**r_init)( void *c ), - void (**r_write)( void *c, byte *buf, size_t nbytes ), - void (**r_final)( void *c ), - byte *(**r_read)( void *c ) - ) -{ - static byte asn[15] = /* Object ID is 1.3.36.3.2.1 */ - { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03, - 0x02, 0x01, 0x05, 0x00, 0x04, 0x14 }; - - if( algo != 3 ) - return NULL; - - *contextsize = sizeof(RMD160_CONTEXT); - *r_asnoid = asn; - *r_asnlen = DIM(asn); - *r_mdlen = 20; - *(void (**)(RMD160_CONTEXT *))r_init = rmd160_init; - *(void (**)(RMD160_CONTEXT *, byte*, size_t))r_write = rmd160_write; - *(void (**)(RMD160_CONTEXT *))r_final = rmd160_final; - *(byte *(**)(RMD160_CONTEXT *))r_read = rmd160_read; - - return "RIPEMD160"; -} - - -#ifndef IS_MODULE -static -#endif -const char * const gnupgext_version = "RMD160 ($Revision: 1.17.2.4 $)"; - -static struct { - int class; - int version; - int value; - void (*func)(void); -} func_table[] = { - { 10, 1, 0, (void(*)(void))rmd160_get_info }, - { 11, 1, 3 }, -}; - - -#ifndef IS_MODULE -static -#endif -void * -gnupgext_enum_func( int what, int *sequence, int *class, int *vers ) -{ - void *ret; - int i = *sequence; - - do { - if( i >= DIM(func_table) || i < 0 ) { - return NULL; - } - *class = func_table[i].class; - *vers = func_table[i].version; - switch( *class ) { - case 11: - case 21: - case 31: - ret = &func_table[i].value; - break; - default: - ret = func_table[i].func; - break; - } - i++; - } while( what && what != *class ); - - *sequence = i; - return ret; -} - - - -#ifndef __HURD__ -#ifndef IS_MODULE -void -rmd160_constructor(void) -{ - register_internal_cipher_extension( gnupgext_version, gnupgext_enum_func ); -} -#endif -#endif diff --git a/random/mig-decls.h b/random/mig-decls.h deleted file mode 100644 index 87b7eb2a..00000000 --- a/random/mig-decls.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - Copyright (C) 2014 Free Software Foundation, Inc. - Written by Justus Winter. - - 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 the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */ - -#ifndef __RANDOM_MIG_DECLS_H__ -#define __RANDOM_MIG_DECLS_H__ - -#include <hurd/ports.h> - -typedef struct port_info *port_info_t; - -extern struct trivfs_control *fsys; -extern struct port_class *shutdown_notify_class; - -/* Called by server stub functions. */ - -static inline struct port_info * __attribute__ ((unused)) -begin_using_startup_port (mach_port_t port) -{ - return ports_lookup_port (fsys->pi.bucket, - handle, - shutdown_notify_class); -} - -static inline void __attribute__ ((unused)) -end_using_startup (struct port_info *p) -{ - if (p) - ports_port_deref (p); -} - -#endif /* __RANDOM_MIG_DECLS_H__ */ diff --git a/random/mig-mutate.h b/random/mig-mutate.h deleted file mode 100644 index dab89e56..00000000 --- a/random/mig-mutate.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - Copyright (C) 2014 Free Software Foundation, Inc. - Written by Justus Winter. - - 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 the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */ - -#define STARTUP_INTRAN \ - port_info_t begin_using_startup_port (mach_port_t) -#define STARTUP_DESTRUCTOR \ - end_using_startup (port_info_t) -#define STARTUP_IMPORTS \ - import "mig-decls.h"; diff --git a/random/random.c b/random/random.c deleted file mode 100644 index ca963580..00000000 --- a/random/random.c +++ /dev/null @@ -1,621 +0,0 @@ -/* random.c - A single-file translator providing random data - Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. - - This program 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. - - This program 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-1307 USA */ - -#define _GNU_SOURCE 1 - -#include <hurd/trivfs.h> -#include <hurd/startup.h> -#include <stdio.h> -#include <stdlib.h> -#include <argp.h> -#include <argz.h> -#include <error.h> -#include <string.h> -#include <fcntl.h> -#include <sys/mman.h> -#include <pthread.h> -#include <assert.h> - -#include <version.h> - -#include "random.h" -#include "gnupg-random.h" - -/* Our control port. */ -struct trivfs_control *fsys; - -int read_blocked; /* For read and select. */ -pthread_cond_t wait; /* For read and select. */ -pthread_cond_t select_alert; /* For read and select. */ - - -/* The quality of randomness we provide. - 0: Very weak randomness based on time() and getrusage(). - No external random data is used. - 1: Pseudo random numbers based on all available real random - numbers. - 2: Strong random numbers with a somewhat guaranteed entropy. -*/ -#define DEFAULT_LEVEL 2 -static int level = DEFAULT_LEVEL; - -/* Name of file to use as seed. */ -static char *seed_file; - -/* The random bytes we collected. */ -char gatherbuf[GATHERBUFSIZE]; - -/* The current positions in gatherbuf[]. */ -int gatherrpos; -int gatherwpos; - -/* XXX Yuk Yuk. */ -#define POOLSIZE 600 - -/* Take up to length bytes from gather_random if available. If - nothing is available, sleep until something becomes available. - Must be called with global_lock held. */ -int -gather_random( void (*add)(const void*, size_t, int), int requester, - size_t length, int level ) -{ - int avail = (gatherwpos - gatherrpos + GATHERBUFSIZE) % GATHERBUFSIZE; - int first = GATHERBUFSIZE - gatherrpos; - int second = length - first; - - /* If level is zero, we should not block and not add anything - to the pool. */ - if( !level ) - return 0; - - /* io_read() should guarantee that there is always data available. */ - if (level == 2) - assert (avail); - - if (length > avail) - length = avail; - - if (first > length) - first = length; - (*add) (&gatherbuf[gatherrpos], first, requester); - gatherrpos = (gatherrpos + first) % GATHERBUFSIZE; - if (second > 0) - { - (*add) (&gatherbuf[gatherrpos], second, requester); - gatherrpos += second; - } - return length; -} - - -const char *argp_program_version = STANDARD_HURD_VERSION (random); - -/* This lock protects the GnuPG code. */ -static pthread_mutex_t global_lock; - -/* Trivfs hooks. */ -int trivfs_fstype = FSTYPE_MISC; -int trivfs_fsid = 0; - -int trivfs_allow_open = O_READ | O_WRITE; - -int trivfs_support_read = 1; -int trivfs_support_write = 1; -int trivfs_support_exec = 0; - -void -trivfs_modify_stat (struct trivfs_protid *cred, struct stat *st) -{ - /* Mark the node as a read-only plain file. */ - st->st_mode &= ~S_IFMT; - st->st_mode |= (S_IFCHR); - st->st_size = 0; -} - -error_t -trivfs_goaway (struct trivfs_control *cntl, int flags) -{ - update_random_seed_file (); - exit (0); -} - -/* Read data from an IO object. If offset is -1, read from the object - maintained file pointer. If the object is not seekable, offset is - ignored. The amount desired to be read is in AMOUNT. */ -error_t -trivfs_S_io_read (struct trivfs_protid *cred, - mach_port_t reply, mach_msg_type_name_t reply_type, - data_t *data, mach_msg_type_number_t *data_len, - loff_t offs, mach_msg_type_number_t amount) -{ - /* Deny access if they have bad credentials. */ - if (! cred) - return EOPNOTSUPP; - else if (! (cred->po->openmodes & O_READ)) - return EBADF; - - pthread_mutex_lock (&global_lock); - - if (amount > 0) - { - while (readable_pool (amount, level) == 0) - { - if (cred->po->openmodes & O_NONBLOCK) - { - pthread_mutex_unlock (&global_lock); - return EWOULDBLOCK; - } - read_blocked = 1; - if (pthread_hurd_cond_wait_np (&wait, &global_lock)) - { - pthread_mutex_unlock (&global_lock); - return EINTR; - } - /* See term/users.c for possible race? */ - } - - /* Possibly allocate a new buffer. */ - if (*data_len < amount) - *data = mmap (0, amount, PROT_READ|PROT_WRITE, - MAP_ANON, 0, 0); - - amount = read_pool ((byte *) *data, amount, level); - } - *data_len = amount; - - /* Set atime, see term/users.c */ - - pthread_mutex_unlock (&global_lock); - - return 0; -} - -/* Write data to an IO object. If offset is -1, write at the object - maintained file pointer. If the object is not seekable, offset is - ignored. The amount successfully written is returned in amount. A - given user should not have more than one outstanding io_write on an - object at a time; servers implement congestion control by delaying - responses to io_write. Servers may drop data (returning ENOBUFS) - if they receive more than one write when not prepared for it. */ -error_t -trivfs_S_io_write (struct trivfs_protid *cred, - mach_port_t reply, - mach_msg_type_name_t replytype, - data_t data, - mach_msg_type_number_t datalen, - loff_t offset, - mach_msg_type_number_t *amount) -{ - int i = 0; - /* Deny access if they have bad credentials. */ - if (! cred) - return EOPNOTSUPP; - else if (! (cred->po->openmodes & O_WRITE)) - return EBADF; - - pthread_mutex_lock (&global_lock); - - while (i < datalen) - { - gatherbuf[gatherwpos] = data[i++]; - gatherwpos = (gatherwpos + 1) % GATHERBUFSIZE; - if (gatherrpos == gatherwpos) - /* Overrun. */ - gatherrpos = (gatherrpos + 1) % GATHERBUFSIZE; - } - *amount = datalen; - - if (datalen > 0 && read_blocked) - { - read_blocked = 0; - pthread_cond_broadcast (&wait); - pthread_cond_broadcast (&select_alert); - } - - pthread_mutex_unlock (&global_lock); - return 0; -} - -/* Tell how much data can be read from the object without blocking for - a "long time" (this should be the same meaning of "long time" used - by the nonblocking flag. */ -kern_return_t -trivfs_S_io_readable (struct trivfs_protid *cred, - mach_port_t reply, mach_msg_type_name_t replytype, - mach_msg_type_number_t *amount) -{ - /* Deny access if they have bad credentials. */ - if (! cred) - return EOPNOTSUPP; - else if (! (cred->po->openmodes & O_READ)) - return EBADF; - - pthread_mutex_lock (&global_lock); - - /* XXX: Before initialization, the amount depends on the amount we - want to read. Assume some medium value. */ - *amount = readable_pool (POOLSIZE/2, level); - - pthread_mutex_unlock (&global_lock); - - return 0; -} - -/* SELECT_TYPE is the bitwise OR of SELECT_READ, SELECT_WRITE, and SELECT_URG. - Block until one of the indicated types of i/o can be done "quickly", and - return the types that are then available. ID_TAG is returned as passed; it - is just for the convenience of the user in matching up reply messages with - specific requests sent. */ -error_t -trivfs_S_io_select (struct trivfs_protid *cred, - mach_port_t reply, - mach_msg_type_name_t reply_type, - int *type) -{ - if (!cred) - return EOPNOTSUPP; - - /* We only deal with SELECT_READ and SELECT_WRITE here. */ - if (*type & ~(SELECT_READ | SELECT_WRITE)) - return EINVAL; - - if (*type == 0) - return 0; - - pthread_mutex_lock (&global_lock); - - while (1) - { - /* XXX Before initialization, readable_pool depends on length. */ - int avail = readable_pool (POOLSIZE/2, level); - - if (avail != 0 || *type & SELECT_WRITE) - { - *type = (avail ? SELECT_READ : 0) | (*type & SELECT_WRITE); - pthread_mutex_unlock (&global_lock); - return 0; - } - - ports_interrupt_self_on_port_death (cred, reply); - read_blocked = 1; - - if (pthread_hurd_cond_wait_np (&select_alert, &global_lock)) - { - *type = 0; - pthread_mutex_unlock (&global_lock); - return EINTR; - } - } -} - - -/* Change current read/write offset */ -error_t -trivfs_S_io_seek (struct trivfs_protid *cred, - mach_port_t reply, mach_msg_type_name_t reply_type, - loff_t offs, int whence, loff_t *new_offs) -{ - if (! cred) - return EOPNOTSUPP; - - /* Not seekable. */ - return ESPIPE; -} - -/* Change the size of the file. If the size increases, new blocks are - zero-filled. After successful return, it is safe to reference mapped - areas of the file up to NEW_SIZE. */ -error_t -trivfs_S_file_set_size (struct trivfs_protid *cred, - mach_port_t reply, mach_msg_type_name_t reply_type, - loff_t size) -{ - if (!cred) - return EOPNOTSUPP; - - return size == 0 ? 0 : EINVAL; -} - -/* These four routines modify the O_APPEND, O_ASYNC, O_FSYNC, and - O_NONBLOCK bits for the IO object. In addition, io_get_openmodes - will tell you which of O_READ, O_WRITE, and O_EXEC the object can - be used for. The O_ASYNC bit affects icky async I/O; good async - I/O is done through io_async which is orthogonal to these calls. */ -error_t -trivfs_S_io_set_all_openmodes(struct trivfs_protid *cred, - mach_port_t reply, - mach_msg_type_name_t reply_type, - int mode) -{ - if (!cred) - return EOPNOTSUPP; - - return 0; -} - -error_t -trivfs_S_io_set_some_openmodes (struct trivfs_protid *cred, - mach_port_t reply, - mach_msg_type_name_t reply_type, - int bits) -{ - if (!cred) - return EOPNOTSUPP; - - return 0; -} - -error_t -trivfs_S_io_get_owner (struct trivfs_protid *cred, - mach_port_t reply, - mach_msg_type_name_t reply_type, - pid_t *owner) -{ - if (!cred) - return EOPNOTSUPP; - - *owner = 0; - return 0; -} - -error_t -trivfs_S_io_mod_owner (struct trivfs_protid *cred, - mach_port_t reply, mach_msg_type_name_t reply_type, - pid_t owner) -{ - if (!cred) - return EOPNOTSUPP; - - return EINVAL; -} - -/* Return objects mapping the data underlying this memory object. If - the object can be read then memobjrd will be provided; if the - object can be written then memobjwr will be provided. For objects - where read data and write data are the same, these objects will be - equal, otherwise they will be disjoint. Servers are permitted to - implement io_map but not io_map_cntl. Some objects do not provide - mapping; they will set none of the ports and return an error. Such - objects can still be accessed by io_read and io_write. */ -error_t -trivfs_S_io_map(struct trivfs_protid *cred, - mach_port_t reply, mach_msg_type_name_t reply_type, - mach_port_t *rdobj, - mach_msg_type_name_t *rdtype, - mach_port_t *wrobj, - mach_msg_type_name_t *wrtype) -{ - if (!cred) - return EOPNOTSUPP; - - return EINVAL; -} - - -int -random_demuxer (mach_msg_header_t *inp, - mach_msg_header_t *outp) -{ - extern int startup_notify_server (mach_msg_header_t *, mach_msg_header_t *); - - return (trivfs_demuxer (inp, outp) - || startup_notify_server (inp, outp)); -} - - -/* Options processing. We accept the same options on the command line - and from fsys_set_options. */ - -static const struct argp_option options[] = -{ - {"weak", 'w', 0, 0, "Output weak pseudo random data"}, - {"fast", 'f', 0, 0, "Output cheap random data fast"}, - {"secure", 's', 0, 0, "Output cryptographically secure random"}, - {"seed-file", 'S', "FILE", 0, "Use FILE to remember the seed"}, - {0} -}; - -static error_t -parse_opt (int opt, char *arg, struct argp_state *state) -{ - switch (opt) - { - default: - return ARGP_ERR_UNKNOWN; - case ARGP_KEY_INIT: - case ARGP_KEY_SUCCESS: - case ARGP_KEY_ERROR: - break; - - case 'w': - { - level = 0; - break; - } - case 'f': - { - level = 1; - break; - } - case 's': - { - level = 2; - break; - } - case 'S': - { - seed_file = strdup (arg); - set_random_seed_file (arg); - } - } - return 0; -} - -/* This will be called from libtrivfs to help construct the answer - to an fsys_get_options RPC. */ -error_t -trivfs_append_args (struct trivfs_control *fsys, - char **argz, size_t *argz_len) -{ - error_t err = 0; - char *opt; - - pthread_mutex_lock (&global_lock); - switch (level) - { - case 0: - { - opt = "--weak"; - break; - } - case 1: - { - opt = "--fast"; - break; - } - default: - { - opt = "--secure"; - break; - } - } - if (level != DEFAULT_LEVEL) - err = argz_add (argz, argz_len, opt); - - if (!err && seed_file) - { - if (asprintf (&opt, "--seed-file=%s", seed_file) < 0) - err = ENOMEM; - else - { - err = argz_add (argz, argz_len, opt); - free (opt); - } - } - pthread_mutex_unlock (&global_lock); - - return err; -} - -static struct argp random_argp = -{ options, parse_opt, 0, - "A translator providing random output." }; - -/* Setting this variable makes libtrivfs use our argp to - parse options passed in an fsys_set_options RPC. */ -struct argp *trivfs_runtime_argp = &random_argp; - -struct port_class *shutdown_notify_class; - -/* The system is going down; destroy all the extant port rights. That - will cause net channels and such to close promptly. */ -error_t -S_startup_dosync (struct port_info *inpi) -{ - if (!inpi) - return EOPNOTSUPP; - - update_random_seed_file (); - return 0; -} - -void -sigterm_handler (int signo) -{ - update_random_seed_file (); - signal (SIGTERM, SIG_DFL); - raise (SIGTERM); -} - -void -arrange_shutdown_notification () -{ - error_t err; - mach_port_t initport, notify; - process_t procserver; - struct port_info *pi; - - shutdown_notify_class = ports_create_class (0, 0); - - signal (SIGTERM, sigterm_handler); - - /* Arrange to get notified when the system goes down, - but if we fail for some reason, just silently give up. No big deal. */ - - err = ports_create_port (shutdown_notify_class, fsys->pi.bucket, - sizeof (struct port_info), &pi); - if (err) - return; - - procserver = getproc (); - if (!procserver) - return; - - err = proc_getmsgport (procserver, 1, &initport); - mach_port_deallocate (mach_task_self (), procserver); - if (err) - return; - - notify = ports_get_send_right (pi); - ports_port_deref (pi); - startup_request_notification (initport, notify, - MACH_MSG_TYPE_MAKE_SEND, - program_invocation_short_name); - mach_port_deallocate (mach_task_self (), notify); - mach_port_deallocate (mach_task_self (), initport); -} - - -int -main (int argc, char **argv) -{ - error_t err; - mach_port_t bootstrap; - - /* Initialize the lock that will protect everything. - We must do this before argp_parse, because parse_opt (above) will - use the lock. */ - pthread_mutex_init (&global_lock, NULL); - - /* The conditions are used to implement proper read/select - behaviour. */ - pthread_cond_init (&wait, NULL); - pthread_cond_init (&select_alert, NULL); - - /* We use the same argp for options available at startup - as for options we'll accept in an fsys_set_options RPC. */ - argp_parse (&random_argp, argc, argv, 0, 0, 0); - - task_get_bootstrap_port (mach_task_self (), &bootstrap); - if (bootstrap == MACH_PORT_NULL) - error (1, 0, "Must be started as a translator"); - - /* Reply to our parent */ - err = trivfs_startup (bootstrap, 0, 0, 0, 0, 0, &fsys); - mach_port_deallocate (mach_task_self (), bootstrap); - if (err) - error (3, err, "trivfs_startup"); - - arrange_shutdown_notification (); - - /* Launch. */ - ports_manage_port_operations_multithread (fsys->pi.bucket, random_demuxer, - 10 * 1000, /* idle thread */ - 10 * 60 * 1000, /* idle server */ - 0); - return 0; -} diff --git a/random/random.h b/random/random.h deleted file mode 100644 index a38a4177..00000000 --- a/random/random.h +++ /dev/null @@ -1,32 +0,0 @@ -/* random.c - A single-file translator providing random data - Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. - - This program 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. - - This program 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-1307 USA */ - -#ifndef __RANDOM_H__ -#define __RANDOM_H__ - -/* How many random bytes to gather at most. - XXX: Should be at least POOLSIZE. */ -#define GATHERBUFSIZE 32768 - -/* The random bytes we collected. */ -extern char gatherbuf[GATHERBUFSIZE]; - -/* The current positions in gatherbuf[]. */ -extern int gatherrpos; -extern int gatherwpos; - -#endif |