summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiles Bader <miles@gnu.org>1995-03-30 00:29:36 +0000
committerMiles Bader <miles@gnu.org>1995-03-30 00:29:36 +0000
commitb37949f4b90d6aa0cd066e03011d2885f88a312e (patch)
treef390c7bd8174d2f83a4a7ad040a9dc3a77e56940
parent5b3603495a3b4f6721f66a3115391412e750847c (diff)
Initial revision
-rw-r--r--trans/magic.c142
-rw-r--r--trans/null.c394
2 files changed, 536 insertions, 0 deletions
diff --git a/trans/magic.c b/trans/magic.c
new file mode 100644
index 00000000..1bc4fe9a
--- /dev/null
+++ b/trans/magic.c
@@ -0,0 +1,142 @@
+/* A translator for returning FS_RETRY_MAGIC strings.
+
+ Copyright (C) 1995 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ 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. */
+
+#include <hurd.h>
+#include <stdio.h>
+#include <error.h>
+#include <hurd/fsys.h>
+#include "fsys_S.h"
+
+/* ---------------------------------------------------------------- */
+
+extern int fsys_server (mach_msg_header_t *, mach_msg_header_t *);
+
+/* The magic string we return for lookups. */
+static char *magic = NULL;
+
+void
+main (int argc, char **argv)
+{
+ error_t err;
+ mach_port_t bootstrap, control, realnode;
+
+ task_get_bootstrap_port (mach_task_self (), &bootstrap);
+ if (bootstrap == MACH_PORT_NULL)
+ error(3, 0, "Must be started as a translator");
+
+ if (argc != 2 || *argv[1] == '-')
+ {
+ fprintf(stderr, "Usage: %s MAGIC", program_invocation_name);
+ exit(-1);
+ }
+
+ magic = argv[1];
+
+ /* Reply to our parent */
+ mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &control);
+ err = fsys_startup (bootstrap, control, MACH_MSG_TYPE_MAKE_SEND, &realnode);
+ if (err)
+ error(1, err, "starting translator");
+
+ mach_port_deallocate (mach_task_self (), realnode);
+
+ /* Launch */
+ while (1)
+ {
+ /* The timeout here is 10 minutes */
+ err = mach_msg_server_timeout (fsys_server, 0, control,
+ MACH_RCV_TIMEOUT, 1000 * 60 * 10);
+ if (err == MACH_RCV_TIMED_OUT)
+ exit (0);
+ }
+}
+
+/* ---------------------------------------------------------------- */
+
+error_t
+S_fsys_getroot (mach_port_t fsys_t,
+ mach_port_t dotdotnode,
+ uid_t *uids, u_int nuids, uid_t *gids, u_int ngids,
+ int flags,
+ retry_type *do_retry, char *retry_name,
+ mach_port_t *ret, mach_msg_type_name_t *rettype)
+{
+ strcpy(retry_name, magic);
+ *do_retry = FS_RETRY_MAGICAL;
+ *ret = MACH_PORT_NULL;
+ *rettype = MACH_MSG_TYPE_COPY_SEND;
+ return 0;
+}
+
+error_t
+S_fsys_startup (mach_port_t bootstrap,
+ mach_port_t control,
+ mach_port_t *real,
+ mach_msg_type_name_t *realtype)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_fsys_goaway (mach_port_t control,
+ int flags)
+{
+ exit (0);
+}
+
+error_t
+S_fsys_syncfs (mach_port_t control,
+ int wait,
+ int recurse)
+{
+ return 0;
+}
+
+error_t
+S_fsys_mod_readonly (mach_port_t control,
+ int val,
+ int force)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_fsys_getfile (mach_port_t control,
+ uid_t *uids, u_int nuids, uid_t *gids, u_int ngids,
+ char *handle, u_int handllen,
+ mach_port_t *pt, mach_msg_type_name_t *pttype)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_fsys_getpriv (mach_port_t control,
+ mach_port_t *hostpriv, mach_port_t *devmaster, task_t *fstask)
+{
+ return EOPNOTSUPP;
+}
+
+error_t
+S_fsys_init (mach_port_t control,
+ mach_port_t reply, mach_msg_type_name_t replytype,
+ mach_port_t proc, auth_t auth)
+{
+ return EOPNOTSUPP;
+}
diff --git a/trans/null.c b/trans/null.c
new file mode 100644
index 00000000..3c6cb054
--- /dev/null
+++ b/trans/null.c
@@ -0,0 +1,394 @@
+/* A translator for providing endless empty space and immediate eof.
+
+ Copyright (C) 1995 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ 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. */
+
+#include <hurd.h>
+#include <hurd/ports.h>
+#include <hurd/trivfs.h>
+#include <hurd/fsys.h>
+
+#include <stdio.h>
+#include <error.h>
+#include <assert.h>
+#include <string.h>
+#include <fcntl.h>
+#include <limits.h>
+
+/* ---------------------------------------------------------------- */
+
+/* Ports port types. */
+#define PT_CTL 0
+#define PT_NODE 1
+
+/* If true, then reading from this device will yield an endless stream of
+ zeros instead of immediate EOF. This also makes it mappable. */
+static int provide_zeros = 0;
+
+void
+main (int argc, char **argv)
+{
+ error_t err;
+ mach_port_t bootstrap, control, realnode;
+ struct trivfs_control *trivfs_control;
+
+ task_get_bootstrap_port (mach_task_self (), &bootstrap);
+ if (bootstrap == MACH_PORT_NULL)
+ error(1, 0, "must be started as a translator");
+
+ if (argc == 2 &&
+ (strcmp(argv[1], "-z") == 0 || strcmp(argv[1], "--zero") == 0))
+ provide_zeros = 1;
+ else if (argc != 1)
+ {
+ fprintf(stderr, "Usage: %s [-z|--zero]", program_invocation_name);
+ exit(1);
+ }
+
+ _libports_initialize();
+
+ /* Reply to our parent */
+ control = trivfs_handle_port (MACH_PORT_NULL, PT_CTL, PT_NODE);
+ err = fsys_startup (bootstrap, control, MACH_MSG_TYPE_MAKE_SEND, &realnode);
+ if (err)
+ error(1, err, "starting translator");
+
+ /* Install the returned realnode for trivfs's use */
+ trivfs_control = ports_check_port_type (control, PT_CTL);
+ assert (trivfs_control);
+ ports_change_hardsoft (trivfs_control, 1);
+ trivfs_control->underlying = realnode;
+ ports_done_with_port (trivfs_control);
+
+ /* Launch. */
+ ports_manage_port_operations_onethread ();
+
+ exit(0);
+}
+
+/* ---------------------------------------------------------------- */
+/* Trivfs hooks */
+
+int trivfs_fstype = FSTYPE_DEV;
+int trivfs_fsid = 0; /* ??? */
+
+int trivfs_support_read = 1;
+int trivfs_support_write = 1;
+int trivfs_support_exec = 0;
+
+int trivfs_allow_open = O_READ | O_WRITE;
+
+int trivfs_protid_porttypes[] = {PT_NODE};
+int trivfs_cntl_porttypes[] = {PT_CTL};
+int trivfs_protid_nporttypes = 1;
+int trivfs_cntl_nporttypes = 1;
+
+void
+trivfs_modify_stat (struct stat *st)
+{
+ st->st_blksize = 1;
+
+ st->st_size = 0;
+ st->st_blocks = 0;
+
+ st->st_mode &= ~S_IFMT;
+ st->st_mode |= S_IFCHR;
+}
+
+error_t
+trivfs_goaway (int flags, mach_port_t realnode, int ctltype, int pitype)
+{
+ exit(0);
+}
+
+/* ---------------------------------------------------------------- */
+/* Ports hooks */
+
+void (*ports_cleanroutines[])(void *) =
+{
+ [PT_CTL] = trivfs_clean_cntl,
+ [PT_NODE] = trivfs_clean_protid,
+};
+
+int
+ports_demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp)
+{
+ return trivfs_demuxer(inp, outp);
+}
+
+/* This will be called whenever there have been no requests to the server for
+ a significant period of time. NHARD is the number of live hard ports;
+ NSOFT is the number of live soft ports. This function is called while an
+ internal lock is held, so it cannot reliably call any other functions of
+ the ports library. */
+void
+ports_notice_idle (int nhard, int nsoft)
+{
+ if (nhard == 0)
+ exit(0);
+}
+
+/* This will be called whenever there are no hard ports or soft ports
+ allocated. This function is called while an internal lock is held, so it
+ cannot reliably call any other functions of the ports library. */
+void
+ports_no_live_ports ()
+{
+ exit(0);
+}
+
+/* This will be called whenever there are no hard ports allocated but there
+ are still some soft ports. This function is called while an internal lock
+ is held, so it cannot reliably call any other functions of the ports
+ library. */
+void
+ports_no_hard_ports ()
+{
+}
+
+/* ---------------------------------------------------------------- */
+
+/* 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. */
+kern_return_t
+trivfs_S_io_map(struct trivfs_protid *cred,
+ memory_object_t *rdobj,
+ mach_msg_type_name_t *rdtype,
+ memory_object_t *wrobj,
+ mach_msg_type_name_t *wrtype)
+{
+ return EINVAL; /* XXX should work! */
+}
+
+/* ---------------------------------------------------------------- */
+
+/* Read data from an IO object. If offset if -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 AMT. */
+kern_return_t
+trivfs_S_io_read(struct trivfs_protid *cred,
+ mach_port_t reply, mach_msg_type_name_t replytype,
+ vm_address_t *data,
+ mach_msg_type_number_t *datalen,
+ off_t offs,
+ mach_msg_type_number_t amt)
+{
+ error_t err = 0;
+
+ if (!cred)
+ err = EOPNOTSUPP;
+ else if (!(cred->po->openmodes & O_READ))
+ err = EBADF;
+ else if (provide_zeros)
+ {
+ if (amt > *datalen)
+ err = vm_allocate(mach_task_self(), data, amt, 1);
+ else
+ bzero((void *)*data, amt);
+ *datalen = amt;
+ }
+ else
+ *datalen = 0;
+
+ 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)
+{
+ if (!cred)
+ return EOPNOTSUPP;
+ else if (!(cred->po->openmodes & O_READ))
+ return EINVAL;
+ else if (provide_zeros)
+ *amount = INT_MAX;
+ else
+ *amount = 0;
+ return 0;
+}
+
+/* ---------------------------------------------------------------- */
+
+/* Change current read/write offset */
+kern_return_t
+trivfs_S_io_seek (struct trivfs_protid *cred,
+ mach_port_t reply, mach_msg_type_name_t replytype,
+ off_t offset, int whence, off_t *new_offset)
+{
+ if (!cred)
+ return EOPNOTSUPP;
+ *new_offset = 0;
+ 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. */
+kern_return_t
+trivfs_S_io_select (struct trivfs_protid *cred,
+ mach_port_t reply, mach_msg_type_name_t replytype,
+ int *type, int *tag)
+{
+ if (!cred)
+ return EOPNOTSUPP;
+ else if (((*type & SELECT_READ) && !(cred->po->openmodes & O_READ))
+ || ((*type & SELECT_WRITE) && !(cred->po->openmodes & O_WRITE)))
+ return EBADF;
+ else
+ *type &= ~SELECT_URG;
+ 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 recevie more than one write when not prepared for it. */
+kern_return_t
+trivfs_S_io_write (struct trivfs_protid *cred,
+ mach_port_t reply, mach_msg_type_name_t replytype,
+ vm_address_t data, mach_msg_type_number_t datalen,
+ off_t offs, mach_msg_type_number_t *amt)
+{
+ if (!cred)
+ return EOPNOTSUPP;
+ else if (!(cred->po->openmodes & O_WRITE))
+ return EBADF;
+ *amt = datalen;
+ return 0;
+}
+
+/* ---------------------------------------------------------------- */
+
+/* Truncate file. */
+kern_return_t
+trivfs_S_file_truncate (struct trivfs_protid *cred, off_t size)
+{
+ /* The zero device is `big and fixed size', so can't be truncated; the null
+ device is always really truncated. */
+ return provide_zeros ? EINVAL : 0;
+}
+
+/* ---------------------------------------------------------------- */
+/* 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. */
+
+kern_return_t
+trivfs_S_io_get_openmodes (struct trivfs_protid *cred,
+ mach_port_t reply, mach_msg_type_name_t replytype,
+ int *bits)
+{
+ if (!cred)
+ return EOPNOTSUPP;
+ else
+ {
+ *bits = cred->po->openmodes;
+ return 0;
+ }
+}
+
+error_t
+trivfs_S_io_set_all_openmodes(struct trivfs_protid *cred,
+ mach_port_t reply,
+ mach_msg_type_name_t replytype,
+ int mode)
+{
+ if (!cred)
+ return EOPNOTSUPP;
+ else
+ return 0;
+}
+
+kern_return_t
+trivfs_S_io_set_some_openmodes (struct trivfs_protid *cred,
+ mach_port_t reply,
+ mach_msg_type_name_t replytype,
+ int bits)
+{
+ if (!cred)
+ return EOPNOTSUPP;
+ else
+ return 0;
+}
+
+kern_return_t
+trivfs_S_io_clear_some_openmodes (struct trivfs_protid *cred,
+ mach_port_t reply,
+ mach_msg_type_name_t replytype,
+ int bits)
+{
+ if (!cred)
+ return EOPNOTSUPP;
+ else
+ return 0;
+}
+
+/* ---------------------------------------------------------------- */
+/* Get/set the owner of the IO object. For terminals, this affects
+ controlling terminal behavior (see term_become_ctty). For all
+ objects this affects old-style async IO. Negative values represent
+ pgrps. This has nothing to do with the owner of a file (as
+ returned by io_stat, and as used for various permission checks by
+ filesystems). An owner of 0 indicates that there is no owner. */
+
+kern_return_t
+trivfs_S_io_get_owner (struct trivfs_protid *cred,
+ mach_port_t reply,
+ mach_msg_type_name_t replytype,
+ pid_t *owner)
+{
+ if (!cred)
+ return EOPNOTSUPP;
+ *owner = 0;
+ return 0;
+}
+
+kern_return_t
+trivfs_S_io_mod_owner (struct trivfs_protid *cred,
+ mach_port_t reply, mach_msg_type_name_t replytype,
+ pid_t owner)
+{
+ if (!cred)
+ return EOPNOTSUPP;
+ else
+ return EINVAL;
+}