commit-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[hurd] 14/75: Add devnode translator


From: Samuel Thibault
Subject: [hurd] 14/75: Add devnode translator
Date: Thu, 14 Jan 2016 01:04:02 +0000

This is an automated email from the git hooks/post-receive script.

sthibault pushed a commit to branch dde
in repository hurd.

commit 87bc93725aea306e8bd4e4171622e4418869fc2f
Author: Samuel Thibault <address@hidden>
Date:   Sun Nov 29 12:47:14 2015 +0100

    Add devnode translator
    
    * devnode: New directory
    * Makefile (prog-subdirs): Add devnode.
---
 Makefile             |   1 +
 devnode/Makefile     |  30 +++++
 devnode/README       |  25 ++++
 devnode/devnode.c    | 359 +++++++++++++++++++++++++++++++++++++++++++++++++++
 devnode/mig-mutate.h |  27 ++++
 devnode/util.h       |  40 ++++++
 6 files changed, 482 insertions(+)

diff --git a/Makefile b/Makefile
index 3178740..ebda8aa 100644
--- a/Makefile
+++ b/Makefile
@@ -42,6 +42,7 @@ prog-subdirs = auth proc exec term \
               procfs \
               startup \
               init \
+              devnode \
 
 ifeq ($(HAVE_SUN_RPC),yes)
 prog-subdirs += nfs nfsd
diff --git a/devnode/Makefile b/devnode/Makefile
new file mode 100644
index 0000000..9529fa7
--- /dev/null
+++ b/devnode/Makefile
@@ -0,0 +1,30 @@
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 2008 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 the GNU Hurd; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+dir := devnode
+makemode := server
+
+SRCS = devnode.c
+LCLHDRS = util.h
+HURDLIBS = ports trivfs fshelp shouldbeinlibc
+target = devnode
+MIGSTUBS = deviceServer.o notifyServer.o
+MIGSFLAGS = -imacros $(srcdir)/mig-mutate.h
+device-MIGSFLAGS="-DMACH_PAYLOAD_TO_PORT=ports_payload_get_name"
+OBJS = $(SRCS:.c=.o) $(MIGSTUBS)
+
+include ../Makeconf
diff --git a/devnode/README b/devnode/README
new file mode 100644
index 0000000..90ca27c
--- /dev/null
+++ b/devnode/README
@@ -0,0 +1,25 @@
+[Introduction]
+
+devnode is a translator that creates the device file for the kernel device. It 
provides another way for other programs to open the kernel device.
+The device file should be created in /dev with the device name as its file 
name, so clients can find the device file easily.
+Clients need to get the port to the devnode translator by calling 
file_name_lookup() and uses this port as a master device port to open the 
device by calling device_open(). The device name used in device_open() is 
specified by '-n' option of devnode.
+
+
+[Usage]
+
+Usage: devnode [OPTION...] device
+Hurd devnode translator.
+
+  -n, --name=DEVICENAME      Accept open from clients only with DEVICENAME
+  -M, --master_device=FILE   Get a pseudo master device port
+  -?, --help                 Give this help list
+      --usage                Give a short usage message
+  -V, --version              Print program version
+
+The '-n' option specifies the device name used by clients in device_open(). It 
can be optional. If it's specified, clients must use the name to open the 
device. Otherwise, every device name used by clients in device_open() is 
acceptable. 
+The '-M' option specifies the file where devnode can get the master device 
port. This option can be useful to open the virtual interface created by 
eth-multiplexer, for example.
+
+
+[Internal]
+
+devnode is very simple. It implements the server side functions in 
device.defs, so it can receive the request of opening a device from clients. 
Only ds_device_open is actually implemented, which opens the device and returns 
the port to the device. Normally, devnode shouldn't get other requests.
diff --git a/devnode/devnode.c b/devnode/devnode.c
new file mode 100644
index 0000000..2802471
--- /dev/null
+++ b/devnode/devnode.c
@@ -0,0 +1,359 @@
+/* 
+   Copyright (C) 2008 Free Software Foundation, Inc.
+   Written by Zheng Da.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*
+ * This program is a translator that sits on the top of the network
+ * interface and helps socket servers open the interface.
+ */
+
+#include <argp.h>
+#include <argz.h>
+#include <errno.h>
+#include <error.h>
+#include <stddef.h>
+#include <fcntl.h>
+
+#include <hurd.h>
+#include <mach.h>
+#include <device/device.h>
+#include <hurd/trivfs.h>
+#include <hurd/ports.h>
+#include <version.h>
+
+#include "device_S.h"
+#include "notify_S.h"
+#include "util.h"
+
+/* The name of the network interface that the translator sits on. */
+static char *device_name;
+/* The device name used by the socket servers. */
+static char *user_device_name;
+static char *master_file;
+/* The master device port for opening the interface. */
+static mach_port_t master_device;
+
+const char *argp_program_version = STANDARD_HURD_VERSION (devnode);
+
+static const char args_doc[] = "device";
+static const char doc[] = "Hurd devnode translator.";
+static const struct argp_option options[] =
+{
+    {"name", 'n', "DEVICENAME", 0,
+      "Define the device name used by clients in device_open()", 2},
+    {"master-device", 'M', "FILE", 0, 
+      "Get a pseudo master device port", 3},
+    {0}
+};
+
+/* Port bucket we service requests on.  */
+struct port_bucket *port_bucket;
+
+/* Trivfs hooks.  */
+int trivfs_fstype = FSTYPE_MISC;
+int trivfs_fsid = 0;
+int trivfs_support_read = 0;
+int trivfs_support_write = 0;
+int trivfs_support_exec = 0;
+int trivfs_allow_open = O_READ | O_WRITE;
+
+/* Our port classes.  */
+struct port_class *trivfs_protid_class;
+struct port_class *trivfs_cntl_class;
+
+static int
+devnode_demuxer (mach_msg_header_t *inp,
+                   mach_msg_header_t *outp)
+{
+  mig_routine_t routine;
+  if ((routine = device_server_routine (inp)) ||
+      (routine = notify_server_routine (inp)) ||
+      (routine = NULL, trivfs_demuxer (inp, outp)))
+    {
+      if (routine)
+        (*routine) (inp, outp);
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+/* Implementation of notify interface */
+kern_return_t
+do_mach_notify_port_deleted (struct port_info *pi,
+                            mach_port_t name)
+{
+  return EOPNOTSUPP;
+}
+
+kern_return_t
+do_mach_notify_msg_accepted (struct port_info *pi,
+                            mach_port_t name)
+{
+  return EOPNOTSUPP;
+}
+
+kern_return_t
+do_mach_notify_port_destroyed (struct port_info *pi,
+                              mach_port_t port)
+{
+  return EOPNOTSUPP;
+}
+
+kern_return_t
+do_mach_notify_no_senders (struct port_info *pi,
+                          mach_port_mscount_t mscount)
+{
+  return ports_do_mach_notify_no_senders (pi, mscount);
+}
+
+kern_return_t
+do_mach_notify_send_once (struct port_info *pi)
+{
+  return EOPNOTSUPP;
+}
+
+kern_return_t
+do_mach_notify_dead_name (struct port_info *pi,
+                         mach_port_t name)
+{
+  return EOPNOTSUPP;
+}
+
+/* Implementation of device interface */
+kern_return_t
+ds_device_open (mach_port_t master_port, mach_port_t reply_port,
+               mach_msg_type_name_t reply_portPoly,
+               dev_mode_t mode, dev_name_t name, mach_port_t *device, 
+               mach_msg_type_name_t *devicetype)
+{
+  error_t err;
+
+  devnode_debug ("ds_device_open is called\n");
+
+  if ((user_device_name && strcmp (user_device_name, name))
+      || device_name == NULL) 
+      return D_NO_SUCH_DEVICE;
+
+  if (master_file != NULL)
+    {
+      if (master_device != MACH_PORT_NULL)
+        mach_port_deallocate (mach_task_self (), master_device);
+
+      master_device = file_name_lookup (master_file, 0, 0);
+      if (master_device == MACH_PORT_NULL)
+        error (1, errno, "file_name_lookup");
+    }
+
+  err = device_open (master_device, mode, device_name, device); 
+  *devicetype = MACH_MSG_TYPE_MOVE_SEND;
+  return err;
+}
+
+kern_return_t
+ds_device_close (device_t device)
+{
+  return D_INVALID_OPERATION;
+}
+
+kern_return_t
+ds_device_write (device_t device, mach_port_t reply_port,
+                mach_msg_type_name_t reply_type, dev_mode_t mode,
+                recnum_t recnum, io_buf_ptr_t data, size_t datalen,
+                int *bytes_written)
+{
+  return D_INVALID_OPERATION;
+}
+
+kern_return_t
+ds_device_write_inband (device_t device, mach_port_t reply_port,
+                       mach_msg_type_name_t reply_type, dev_mode_t mode,
+                       recnum_t recnum, io_buf_ptr_inband_t data,
+                       size_t datalen, int *bytes_written)
+{
+  return D_INVALID_OPERATION;
+}
+
+kern_return_t
+ds_device_read (device_t device, mach_port_t reply_port,
+               mach_msg_type_name_t reply_type, dev_mode_t mode,
+               recnum_t recnum, int bytes_wanted,
+               io_buf_ptr_t *data, size_t *datalen)
+{
+  return D_INVALID_OPERATION;
+}
+
+kern_return_t
+ds_device_read_inband (device_t device, mach_port_t reply_port,
+                      mach_msg_type_name_t reply_type, dev_mode_t mode,
+                      recnum_t recnum, int bytes_wanted,
+                      io_buf_ptr_inband_t data, size_t *datalen)
+{
+  return D_INVALID_OPERATION;
+}
+
+kern_return_t
+ds_device_map (device_t device, vm_prot_t prot, vm_offset_t offset,
+              vm_size_t size, memory_object_t *pager, int unmap)
+{
+  return D_INVALID_OPERATION;
+}
+
+kern_return_t
+ds_device_set_status (device_t device, dev_flavor_t flavor,
+                     dev_status_t status, size_t statuslen)
+{
+  return D_INVALID_OPERATION;
+}
+
+kern_return_t
+ds_device_get_status (device_t device, dev_flavor_t flavor,
+                     dev_status_t status, size_t *statuslen)
+{
+  return D_INVALID_OPERATION;
+}
+
+kern_return_t
+ds_device_set_filter (device_t device, mach_port_t receive_port,
+                     int priority, filter_array_t filter, size_t filterlen)
+{
+  return D_INVALID_OPERATION;
+}
+
+error_t
+trivfs_append_args (struct trivfs_control *fsys, char **argz, size_t *argz_len)
+{
+  error_t err = 0;
+
+#define ADD_OPT(fmt, args...)                                          \
+  do { char buf[100];                                                  \
+       if (! err) {                                                    \
+         snprintf (buf, sizeof buf, fmt , ##args);                     \
+         err = argz_add (argz, argz_len, buf); } } while (0)
+
+  if (user_device_name)
+    ADD_OPT ("--name=%s", user_device_name);
+  if (master_file)
+    ADD_OPT ("--master-device=%s", master_file);
+
+  ADD_OPT ("%s", device_name);
+
+#undef ADD_OPT
+  return err;
+}
+
+void
+trivfs_modify_stat (struct trivfs_protid *cred, io_statbuf_t *stat)
+{
+}
+
+error_t
+trivfs_goaway (struct trivfs_control *fsys, int flags)
+{
+  int count;
+
+  /* Stop new requests.  */
+  ports_inhibit_class_rpcs (trivfs_cntl_class);
+  ports_inhibit_class_rpcs (trivfs_protid_class);
+
+  count = ports_count_class (trivfs_protid_class);
+  devnode_debug ("the number of ports alive: %d\n", count);
+
+  if (count && !(flags & FSYS_GOAWAY_FORCE)) 
+    {
+      /* We won't go away, so start things going again...  */
+      ports_enable_class (trivfs_protid_class);
+      ports_resume_class_rpcs (trivfs_cntl_class);
+      ports_resume_class_rpcs (trivfs_protid_class);
+      return EBUSY;
+    } 
+
+  mach_port_deallocate (mach_task_self (), master_device);
+  devnode_debug ("the translator is gone away\n");
+  exit (0);
+}
+
+static error_t
+parse_opt (int opt, char *arg, struct argp_state *state)
+{
+  switch (opt)
+    {
+    case 'M':
+      master_file = arg;
+      master_device = file_name_lookup (arg, 0, 0);
+      if (master_device == MACH_PORT_NULL)
+       error (1, errno, "file_name_lookup");
+      break;
+    case 'n':
+      user_device_name = arg;
+      break;
+    case ARGP_KEY_ARG:
+      device_name = arg;
+      break;
+    case ARGP_KEY_ERROR:
+    case ARGP_KEY_SUCCESS:
+    case ARGP_KEY_INIT:
+      break;
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+  error_t err;
+  mach_port_t bootstrap;
+  struct trivfs_control *fsys;
+  const struct argp argp = { options, parse_opt, args_doc, doc };
+
+  port_bucket = ports_create_bucket ();
+  trivfs_cntl_class = ports_create_class (trivfs_clean_cntl, 0);
+  trivfs_protid_class = ports_create_class (trivfs_clean_protid, 0);
+
+  argp_parse (&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");
+
+  if (master_device == MACH_PORT_NULL) 
+    {
+      err = get_privileged_ports (0, &master_device);
+      if (err)
+       error (1, err, "get_privileged_ports");
+    }
+
+  /* Reply to our parent.  */
+  err = trivfs_startup (bootstrap, 0,
+                       trivfs_cntl_class, port_bucket,
+                       trivfs_protid_class, port_bucket, &fsys);
+  mach_port_deallocate (mach_task_self (), bootstrap);
+  if (err)
+    error (1, err, "Contacting parent");
+
+  /* Launch.  */
+  do 
+    {
+      ports_manage_port_operations_one_thread (port_bucket, 
+                                              devnode_demuxer, 0);
+    } while (trivfs_goaway (fsys, 0)); 
+  return 0;
+}
diff --git a/devnode/mig-mutate.h b/devnode/mig-mutate.h
new file mode 100644
index 0000000..0656014
--- /dev/null
+++ b/devnode/mig-mutate.h
@@ -0,0 +1,27 @@
+/*
+   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 NOTIFY_INTRAN                                          \
+  port_info_t begin_using_port_info_port (mach_port_t)
+#define NOTIFY_INTRAN_PAYLOAD                                  \
+  port_info_t begin_using_port_info_payload
+#define NOTIFY_DESTRUCTOR                                      \
+  end_using_port_info (port_info_t)
+#define NOTIFY_IMPORTS                                         \
+  import "libports/mig-decls.h";
diff --git a/devnode/util.h b/devnode/util.h
new file mode 100644
index 0000000..f3cc3c1
--- /dev/null
+++ b/devnode/util.h
@@ -0,0 +1,40 @@
+/* 
+   Copyright (C) 2008 Free Software Foundation, Inc.
+   Written by Zheng Da.
+
+   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; see the file COPYING.  If not, write to
+   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifndef UTIL_H
+#define UTIL_H
+
+#include <stdio.h>
+
+#ifdef DEBUG 
+
+#define devnode_debug(format, ...) do                  \
+{                                                      \
+  fprintf (stderr , "devnode: " format, ## __VA_ARGS__);\
+  fflush (stderr);                                     \
+} while (0)
+
+#else
+
+#define devnode_debug(format, ...) do {} while (0)
+
+#endif
+
+#endif

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/pkg-hurd/hurd.git



reply via email to

[Prev in Thread] Current Thread [Next in Thread]