Exemplo n.º 1
0
void
pfinet_bind (int portclass, const char *name)
{
    struct trivfs_control *cntl;
    error_t err = 0;
    mach_port_t right;
    file_t file = file_name_lookup (name, O_CREAT|O_NOTRANS, 0666);

    if (file == MACH_PORT_NULL)
        err = errno;

    if (! err) {
        if (pfinet_protid_portclasses[portclass] != MACH_PORT_NULL)
            error (1, 0, "Cannot bind one protocol to multiple nodes.\n");

#ifdef CONFIG_IPV6
        if (portclass == PORTCLASS_INET6)
            pfinet_activate_ipv6 ();
#endif
        //mark
        err = trivfs_add_protid_port_class (&pfinet_protid_portclasses[portclass]);
        if (err)
            error (1, 0, "error creating control port class");

        err = trivfs_add_control_port_class (&pfinet_cntl_portclasses[portclass]);
        if (err)
            error (1, 0, "error creating control port class");

        err = trivfs_create_control (file, pfinet_cntl_portclasses[portclass],
                                     pfinet_bucket,
                                     pfinet_protid_portclasses[portclass],
                                     pfinet_bucket, &cntl);
    }

    if (! err)
    {
        right = ports_get_send_right (cntl);
        err = file_set_translator (file, 0, FS_TRANS_EXCL | FS_TRANS_SET,
                                   0, 0, 0, right, MACH_MSG_TYPE_COPY_SEND);
        mach_port_deallocate (mach_task_self (), right);
    }

    if (err)
        error (1, err, "%s", name);

    ports_port_deref (cntl);

}
Exemplo n.º 2
0
/* Try and start the translator for CTL_PORT on NODE.  If successful, this
   call will not return until the translator is stopped; otherwise it returns
   an error code describing the reason why it couldn't start.  */
static error_t
start_translator(file_t node, fsys_t ctl_port)
{
  mach_port_t prev;
  error_t err =
    file_set_translator(node, 0, FS_TRANS_EXCL, 0, NULL, 0, ctl_port);

  if (err)
    return err;

  /* Set up a watch on the process we're interested in.  */
  err =
    mach_port_request_notification(mach_task_self(),
				   watched_process, MACH_NOTIFY_DEAD_NAME, 1,
				   node,
				   MACH_MSG_TYPE_MAKE_SEND_ONCE, &prev);
  if (prev)
    mach_port_deallocate(mach_task_self(), prev);

  /* Boogie. */
  ports_manage_port_operations_onethread();

  return 0;
}
Exemplo n.º 3
0
/* Unmount one filesystem.  */
static error_t
do_umount (struct fs *fs)
{
  error_t err = 0;

  file_t node = file_name_lookup (fs->mntent.mnt_dir, O_NOTRANS, 0666);
  if (node == MACH_PORT_NULL)
    {
      error (0, errno, "%s", fs->mntent.mnt_dir);
      return errno;
    }

  if (verbose)
    printf ("settrans -ag%s%s %s\n",
	    goaway_flags & FSYS_GOAWAY_NOSYNC? "S": "",
	    goaway_flags & FSYS_GOAWAY_FORCE? "f": "",
	    fs->mntent.mnt_dir);

  if (! fake)
    {
      err = file_set_translator (node,
				 0, active_flags, goaway_flags,
				 NULL, 0,
				 MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND);
      if (! err)
	{
	  if (strcmp (fs->mntent.mnt_fsname, "") != 0 &&
	      strcmp (fs->mntent.mnt_fsname, "none") != 0)
	    {
	      if (verbose)
		printf ("settrans -ag%s%s %s\n",
			goaway_flags & FSYS_GOAWAY_NOSYNC? "S": "",
			goaway_flags & FSYS_GOAWAY_FORCE? "f": "",
			fs->mntent.mnt_fsname);

	      file_t source = file_name_lookup (fs->mntent.mnt_fsname,
						O_NOTRANS,
						0666);
	      if (source == MACH_PORT_NULL)
		{
		  error (0, errno, "%s", fs->mntent.mnt_fsname);
		  return errno;
		}

	      err = file_set_translator (source,
					 0, active_flags, goaway_flags,
					 NULL, 0,
					 MACH_PORT_NULL,
					 MACH_MSG_TYPE_COPY_SEND);
	      if (!(goaway_flags & FSYS_GOAWAY_FORCE))
		err = 0;
	      if (err)
		error (0, err, "%s", fs->mntent.mnt_fsname);

	      mach_port_deallocate (mach_task_self (), source);

	    }
	}
      else
	{
	  error (0, err, "%s", fs->mntent.mnt_dir);

	  /* Try remounting readonly instead if requested.  */
	  if (readonly)
	    {
	      if (verbose)
		printf ("fsysopts %s --readonly\n", fs->mntent.mnt_dir);

	      error_t e = fs_set_readonly (fs, TRUE);
	      if (e)
		error (0, e, "%s", fs->mntent.mnt_dir);
	    }
	}
    }

  /* Deallocate the reference so that unmounting nested translators
     works properly.  */
  mach_port_deallocate (mach_task_self (), node);
  return err;
}
Exemplo n.º 4
0
/* Mount one filesystem.  */
static error_t
do_mount (struct fs *fs, int remount)
{
    error_t err;
    char *fsopts, *o;
    size_t fsopts_len;
    char *mntopts;
    size_t mntopts_len;
    fsys_t mounted;

    inline void explain (const char *command)
    {
        if (verbose)
        {
            const char *o;
            printf ("%s %s", command, fs->mntent.mnt_dir);
            for (o = fsopts; o; o = argz_next (fsopts, fsopts_len, o))
                printf (" %s", o);
            putchar ('\n');
        }
    }

    err = fs_fsys (fs, &mounted);
    if (err)
    {
        error (0, err, "cannot determine if %s is already mounted",
               fs->mntent.mnt_fsname);
        return err;
    }


    /* Produce an argz of translator option arguments from the
       given FS's options and the command-line options.  */

#define ARGZ(call)							      \
  err = argz_##call;							      \
  if (err)								      \
    error (3, ENOMEM, "collecting mount options");			      \

    if (fs->mntent.mnt_opts)
    {
        /* Append the fstab options to any specified on the command line.  */
        ARGZ (create_sep (fs->mntent.mnt_opts, ',', &mntopts, &mntopts_len));

        /* Remove the `noauto' and `bind' options, since they're for us not the
           filesystem.  */
        for (o = mntopts; o; o = argz_next (mntopts, mntopts_len, o))
        {
            if (strcmp (o, MNTOPT_NOAUTO) == 0)
                argz_delete (&mntopts, &mntopts_len, o);
            if (strcmp (o, "bind") == 0)
            {
                fs->mntent.mnt_type = strdup ("firmlink");
                if (!fs->mntent.mnt_type)
                    error (3, ENOMEM, "failed to allocate memory");
                argz_delete (&mntopts, &mntopts_len, o);
            }
        }

        ARGZ (append (&mntopts, &mntopts_len, options, options_len));
    }
    else
    {
        mntopts = options;
        mntopts_len = options_len;
    }

    /* Convert the list of options into a list of switch arguments.  */
    fsopts = 0;
    fsopts_len = 0;
    for (o = mntopts; o; o = argz_next (mntopts, mntopts_len, o))
        if (*o == '-')		/* Allow letter opts `-o -r,-E', BSD style.  */
        {
            ARGZ (add (&fsopts, &fsopts_len, o));
        }
        else if ((strcmp (o, "defaults") != 0) && (strlen (o) != 0))
        {
            /* Prepend `--' to the option to make a long option switch,
               e.g. `--ro' or `--rsize=1024'.  */
            char arg[2 + strlen (o) + 1];
            arg[0] = arg[1] = '-';
            memcpy (&arg[2], o, sizeof arg - 2);
            ARGZ (add (&fsopts, &fsopts_len, arg));
        }

    if (mntopts != options)
        free (mntopts);
#undef ARGZ

    if (remount)
    {
        if (mounted == MACH_PORT_NULL)
        {
            error (0, 0, "%s not already mounted", fs->mntent.mnt_fsname);
            return EBUSY;
        }

        /* Send an RPC to request the new options, including --update.  */
        explain ("fsysopts");
        err = fsys_set_options (mounted, fsopts, fsopts_len, 0);
        if (err)
            error (0, err, "cannot remount %s", fs->mntent.mnt_fsname);
        return err;
    }
    else
    {
        /* Error during file lookup; we use this to avoid duplicating error
        messages.  */
        error_t open_err = 0;
        /* The control port for any active translator we start up.  */
        fsys_t active_control;
        file_t node;		/* Port to the underlying node.  */
        struct fstype *type;

        /* The callback to start_translator opens NODE as a side effect.  */
        error_t open_node (int flags,
                           mach_port_t *underlying,
                           mach_msg_type_name_t *underlying_type,
                           task_t task, void *cookie)
        {
            node = file_name_lookup (fs->mntent.mnt_dir,
                                     flags | O_NOTRANS, 0666);
            if (node == MACH_PORT_NULL)
            {
                open_err = errno;
                return open_err;
            }

            *underlying = node;
            *underlying_type = MACH_MSG_TYPE_COPY_SEND;

            return 0;
        }

        /* Do not fail if there is an active translator if --fake is
           given. This mimics Linux mount utility more closely which
           just looks into the mtab file. */
        if (mounted != MACH_PORT_NULL && !fake)
        {
            error (0, 0, "%s already mounted", fs->mntent.mnt_fsname);
            return EBUSY;
        }

        if (strcmp (fs->mntent.mnt_type, "auto") == 0)
        {
#if HAVE_BLKID
            char *type =
                blkid_get_tag_value (NULL, "TYPE", fs->mntent.mnt_fsname);
            if (! type)
            {
                error (0, 0, "failed to detect file system type");
                return EFTYPE;
            }
            else
            {
                if (strcmp (type, "vfat") == 0)
                    fs->mntent.mnt_type = strdup ("fat");
                else
                    fs->mntent.mnt_type = strdup (type);
                if (! fs->mntent.mnt_type)
                    error (3, ENOMEM, "failed to allocate memory");
            }
#else
            fs->mntent.mnt_type = strdup ("ext2");
            if (! fs->mntent.mnt_type)
                error (3, ENOMEM, "failed to allocate memory");
#endif
        }

        err = fs_type (fs, &type);
        if (err)
        {
            error (0, err, "%s: cannot determine filesystem type",
                   fs->mntent.mnt_fsname);
            return err;
        }
        if (type->program == 0)
        {
            error (0, 0, "%s: filesystem type `%s' unknown",
                   fs->mntent.mnt_fsname, type->name);
            return EFTYPE;
        }

        /* Stick the translator program name in front of the option switches.  */
        err = argz_insert (&fsopts, &fsopts_len, fsopts, type->program);
        /* Now stick the device name on the end as the last argument.  */
        if (!err)
            err = argz_add (&fsopts, &fsopts_len, fs->mntent.mnt_fsname);
        if (err)
            error (3, ENOMEM, "collecting mount options");

        /* Now we have a translator command line argz in FSOPTS.  */

        if (fake) {
            /* Fake the translator startup. */
            mach_port_t underlying;
            mach_msg_type_name_t underlying_type;
            err = open_node (O_READ, &underlying, &underlying_type, 0, NULL);
            if (err)
                error (1, errno, "cannot mount on %s", fs->mntent.mnt_dir);

            mach_port_deallocate (mach_task_self (), underlying);

            /* See if the translator is at least executable. */
            if (access(type->program, X_OK) == -1)
                error (1, errno, "can not execute %s", type->program);

            return 0;
        }

        explain ("settrans -a");
        err = fshelp_start_translator (open_node, NULL, fsopts,
                                       fsopts, fsopts_len, timeout,
                                       &active_control);
        /* If ERR is due to a problem opening the translated node, we print
        that name, otherwise, the name of the translator.  */
        if (open_err)
            error (0, open_err, "cannot mount on %s", fs->mntent.mnt_dir);
        else if (err)
            error (0, err, "cannot start translator %s", fsopts);
        else
        {
            err = file_set_translator (node, 0, FS_TRANS_SET|FS_TRANS_EXCL, 0,
                                       0, 0,
                                       active_control, MACH_MSG_TYPE_COPY_SEND);
            if (err == EBUSY)
                error (0, 0, "%s already mounted on", fs->mntent.mnt_dir);
            else if (err)
                error (0, err, "cannot set translator on %s", fs->mntent.mnt_dir);
            if (err)
                fsys_goaway (active_control, FSYS_GOAWAY_FORCE);
            mach_port_deallocate (mach_task_self (), active_control);
        }

        return err;
    }