Beispiel #1
0
int
main (int argc, char **argv)
{
    int c;
    int err;
    int nomtab = 0;
    unsigned long flags = MS_NODEV;
    char *host_name;
    char *mount_point;
    struct vbsf_mount_info_new mntinf;
    struct vbsf_mount_opts opts =
    {
        0,     /* uid */
        0,     /* gid */
        0,     /* ttl */
        ~0U,    /* dmode */
        ~0U,    /* fmode*/
        0,     /* dmask */
        0,     /* fmask */
        0,     /* ronly */
        0,     /* noexec */
        0,     /* nodev */
        0,     /* nosuid */
        0,     /* remount */
        "\0",  /* nls_name */
        NULL,  /* convertcp */
    };

    mntinf.nullchar = '\0';
    mntinf.signature[0] = VBSF_MOUNT_SIGNATURE_BYTE_0;
    mntinf.signature[1] = VBSF_MOUNT_SIGNATURE_BYTE_1;
    mntinf.signature[2] = VBSF_MOUNT_SIGNATURE_BYTE_2;
    mntinf.length       = sizeof(mntinf);

    if (getuid())
        panic("Only root can mount shared folders from the host.\n");

    if (!argv[0])
        argv[0] = "mount.vboxsf";

    /* Compile-time assertions */
    CT_ASSERT(sizeof(uid_t) == sizeof(int));
    CT_ASSERT(sizeof(gid_t) == sizeof(int));

    while ((c = getopt(argc, argv, "rwno:h")) != -1)
    {
        switch (c)
        {
        default:
            fprintf(stderr, "unknown option `%c:%#x'\n", c, c);
        case '?':
        case 'h':
            usage(argv[0]);

        case 'r':
            opts.ronly = 1;
            break;

        case 'w':
            opts.ronly = 0;

        case 'o':
            process_mount_opts(optarg, &opts);
            break;

        case 'n':
            nomtab = 1;
            break;
        }
    }

    if (argc - optind < 2)
        usage(argv[0]);

    host_name = argv[optind];
    mount_point = argv[optind + 1];

    if (opts.convertcp)
        convertcp(opts.convertcp, host_name, &mntinf);
    else
    {
        if (strlen(host_name) > MAX_HOST_NAME - 1)
            panic("host name is too big\n");

        strcpy(mntinf.name, host_name);
    }

    if (strlen(opts.nls_name) > MAX_NLS_NAME - 1)
        panic("%s: the character set name for I/O is too long.\n", argv[0]);

    strcpy(mntinf.nls_name, opts.nls_name);

    if (opts.ronly)
        flags |= MS_RDONLY;
    if (opts.noexec)
        flags |= MS_NOEXEC;
    if (opts.nodev)
        flags |= MS_NODEV;

    mntinf.uid   = opts.uid;
    mntinf.gid   = opts.gid;
    mntinf.ttl   = opts.ttl;
    mntinf.dmode = opts.dmode;
    mntinf.fmode = opts.fmode;
    mntinf.dmask = opts.dmask;
    mntinf.fmask = opts.fmask;

    /*
     * Note: When adding and/or modifying parameters of the vboxsf mounting
     *       options you also would have to adjust VBoxServiceAutoMount.cpp
     *       to keep this code here slick without having VbglR3.
     */
    err = mount(NULL, mount_point, "vboxsf", flags, &mntinf);
    if (err == -1 && errno == EPROTO)
    {
        /* Sometimes the mount utility messes up the share name.  Try to
         * un-mangle it again. */
        char szCWD[4096];
        size_t cchCWD;
        if (!getcwd(szCWD, sizeof(szCWD)))
            panic_err("%s: failed to get the current working directory", argv[0]);
        cchCWD = strlen(szCWD);
        if (!strncmp(host_name, szCWD, cchCWD))
        {
            while (host_name[cchCWD] == '/')
                ++cchCWD;
            /* We checked before that we have enough space */
            strcpy(mntinf.name, host_name + cchCWD);
        }
        err = mount(NULL, mount_point, "vboxsf", flags, &mntinf);
    }
    if (err == -1 && errno == EPROTO)
    {
        /* New mount tool with old vboxsf module? Try again using the old
         * vbsf_mount_info_old structure. */
        struct vbsf_mount_info_old mntinf_old;
        memcpy(&mntinf_old.name, &mntinf.name, MAX_HOST_NAME);
        memcpy(&mntinf_old.nls_name, mntinf.nls_name, MAX_NLS_NAME);
        mntinf_old.uid = mntinf.uid;
        mntinf_old.gid = mntinf.gid;
        mntinf_old.ttl = mntinf.ttl;
        err = mount(NULL, mount_point, "vboxsf", flags, &mntinf_old);
    }
    if (err)
        panic_err("%s: mounting failed with the error", argv[0]);

    if (!nomtab)
    {
        err = vbsfmount_complete(host_name, mount_point, flags, &opts);
        switch (err)
        {
        case 0: /* Success. */
            break;

        case 1:
            panic_err("%s: Could not update mount table (failed to create memstream).", argv[0]);
            break;

        case 2:
            panic_err("%s: Could not open mount table for update.", argv[0]);
            break;

        case 3:
            /* panic_err("%s: Could not add an entry to the mount table.", argv[0]); */
            break;

        default:
            panic_err("%s: Unknown error while completing mount operation: %d", argv[0], err);
            break;
        }
    }

    exit(EXIT_SUCCESS);
}
static int VBoxServiceAutoMountSharedFolder(const char *pszShareName, const char *pszMountPoint,
                                            vbsf_mount_opts *pOpts)
{
    AssertPtr(pOpts);

    int rc = VINF_SUCCESS;
    char szAlreadyMountedTo[RTPATH_MAX];
    /* If a Shared Folder already is mounted but not to our desired mount point,
     * do an unmount first! */
    if (   VBoxServiceAutoMountShareIsMounted(pszShareName, szAlreadyMountedTo, sizeof(szAlreadyMountedTo))
        && RTStrICmp(pszMountPoint, szAlreadyMountedTo))
    {
        VBoxServiceVerbose(3, "VBoxServiceAutoMountWorker: Shared folder \"%s\" already mounted to \"%s\", unmounting ...\n",
                           pszShareName, szAlreadyMountedTo);
        rc = VBoxServiceAutoMountUnmount(szAlreadyMountedTo);
        if (RT_FAILURE(rc))
            VBoxServiceError("VBoxServiceAutoMountWorker: Failed to unmount \"%s\", %s (%d)!\n",
                             szAlreadyMountedTo, strerror(errno), errno);
    }

    if (RT_SUCCESS(rc))
        rc = VBoxServiceAutoMountPrepareMountPoint(pszMountPoint, pszShareName, pOpts);
    if (RT_SUCCESS(rc))
    {
#ifdef RT_OS_SOLARIS
        char achOptBuf[MAX_MNTOPT_STR] = { '\0', };
        int flags = 0;
        if (pOpts->ronly)
            flags |= MS_RDONLY;
        RTStrPrintf(achOptBuf, sizeof(achOptBuf), "uid=%d,gid=%d", pOpts->uid, pOpts->gid);
        int r = mount(pszShareName,
                      pszMountPoint,
                      flags | MS_OPTIONSTR,
                      "vboxfs",
                      NULL,                     /* char *dataptr */
                      0,                        /* int datalen */
                      achOptBuf,
                      sizeof(achOptBuf));
        if (r == 0)
        {
            VBoxServiceVerbose(0, "VBoxServiceAutoMountWorker: Shared folder \"%s\" was mounted to \"%s\"\n", pszShareName, pszMountPoint);
        }
        else
        {
            if (errno != EBUSY) /* Share is already mounted? Then skip error msg. */
                VBoxServiceError("VBoxServiceAutoMountWorker: Could not mount shared folder \"%s\" to \"%s\", error = %s\n",
                                 pszShareName, pszMountPoint, strerror(errno));
        }
#else /* !RT_OS_SOLARIS */
        unsigned long flags = MS_NODEV;

        const char *szOptions = { "rw" };
        struct vbsf_mount_info_new mntinf;

        mntinf.nullchar     = '\0';
        mntinf.signature[0] = VBSF_MOUNT_SIGNATURE_BYTE_0;
        mntinf.signature[1] = VBSF_MOUNT_SIGNATURE_BYTE_1;
        mntinf.signature[2] = VBSF_MOUNT_SIGNATURE_BYTE_2;
        mntinf.length       = sizeof(mntinf);

        mntinf.uid   = pOpts->uid;
        mntinf.gid   = pOpts->gid;
        mntinf.ttl   = pOpts->ttl;
        mntinf.dmode = pOpts->dmode;
        mntinf.fmode = pOpts->fmode;
        mntinf.dmask = pOpts->dmask;
        mntinf.fmask = pOpts->fmask;

        strcpy(mntinf.name, pszShareName);
        strcpy(mntinf.nls_name, "\0");

        int r = mount(NULL,
                      pszMountPoint,
                      "vboxsf",
                      flags,
                      &mntinf);
        if (r == 0)
        {
            VBoxServiceVerbose(0, "VBoxServiceAutoMountWorker: Shared folder \"%s\" was mounted to \"%s\"\n", pszShareName, pszMountPoint);

            r = vbsfmount_complete(pszShareName, pszMountPoint, flags, pOpts);
            switch (r)
            {
                case 0: /* Success. */
                    errno = 0; /* Clear all errors/warnings. */
                    break;

                case 1:
                    VBoxServiceError("VBoxServiceAutoMountWorker: Could not update mount table (failed to create memstream): %s\n", strerror(errno));
                    break;

                case 2:
                    VBoxServiceError("VBoxServiceAutoMountWorker: Could not open mount table for update: %s\n", strerror(errno));
                    break;

                case 3:
                    /* VBoxServiceError("VBoxServiceAutoMountWorker: Could not add an entry to the mount table: %s\n", strerror(errno)); */
                    errno = 0;
                    break;

                default:
                    VBoxServiceError("VBoxServiceAutoMountWorker: Unknown error while completing mount operation: %d\n", r);
                    break;
            }
        }
        else /* r == -1, we got some error in errno.  */
        {
            if (errno == EPROTO)
            {
                VBoxServiceVerbose(3, "VBoxServiceAutoMountWorker: Messed up share name, re-trying ...\n");

                /* Sometimes the mount utility messes up the share name.  Try to
                 * un-mangle it again. */
                char szCWD[4096];
                size_t cchCWD;
                if (!getcwd(szCWD, sizeof(szCWD)))
                    VBoxServiceError("VBoxServiceAutoMountWorker: Failed to get the current working directory\n");
                cchCWD = strlen(szCWD);
                if (!strncmp(pszMountPoint, szCWD, cchCWD))
                {
                    while (pszMountPoint[cchCWD] == '/')
                        ++cchCWD;
                    /* We checked before that we have enough space */
                    strcpy(mntinf.name, pszMountPoint + cchCWD);
                }
                r = mount(NULL, pszMountPoint, "vboxsf", flags, &mntinf);
            }
            if (errno == EPROTO)
            {
                VBoxServiceVerbose(3, "VBoxServiceAutoMountWorker: Re-trying with old mounting structure ...\n");

                /* New mount tool with old vboxsf module? Try again using the old
                 * vbsf_mount_info_old structure. */
                struct vbsf_mount_info_old mntinf_old;
                memcpy(&mntinf_old.name, &mntinf.name, MAX_HOST_NAME);
                memcpy(&mntinf_old.nls_name, mntinf.nls_name, MAX_NLS_NAME);
                mntinf_old.uid = mntinf.uid;
                mntinf_old.gid = mntinf.gid;
                mntinf_old.ttl = mntinf.ttl;
                r = mount(NULL, pszMountPoint, "vboxsf", flags, &mntinf_old);
            }
            if (r == -1) /* Was there some error from one of the tries above? */
            {
                switch (errno)
                {
                    /* If we get EINVAL here, the system already has mounted the Shared Folder to another
                     * mount point. */
                    case EINVAL:
                        VBoxServiceVerbose(0, "VBoxServiceAutoMountWorker: Shared folder \"%s\" already is mounted!\n", pszShareName);
                        /* Ignore this error! */
                        break;
                    case EBUSY:
                        /* Ignore these errors! */
                        break;

                    default:
                        VBoxServiceError("VBoxServiceAutoMountWorker: Could not mount shared folder \"%s\" to \"%s\": %s (%d)\n",
                                         pszShareName, pszMountPoint, strerror(errno), errno);
                        rc = RTErrConvertFromErrno(errno);
                        break;
                }
            }
        }
#endif /* !RT_OS_SOLARIS */
    }
    VBoxServiceVerbose(3, "VBoxServiceAutoMountWorker: Mounting returned with rc=%Rrc\n", rc);
    return rc;
}