VirtualBox

Changeset 87463 in vbox for trunk/src/VBox/Additions


Ignore:
Timestamp:
Jan 28, 2021 3:38:55 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
142482
Message:

linux/vboxsf,VBoxService: Modify mount.vboxsf and the VBoxService automounter to pass string-based mount options when calling mount(2). Also include the shared folder name with the mount options for Linux kernels < 2.6.0 since these kernel versions don't pass the shared folder name through to the vboxsf.ko kernel module. bugref:9816

Location:
trunk/src/VBox/Additions
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceAutoMount.cpp

    r84238 r87463  
    6565#  include <sys/mnttab.h>
    6666#  include <sys/vfs.h>
    67 RT_C_DECLS_BEGIN /* Only needed for old code.*/
    68 #  include "../../linux/sharedfolders/vbsfmount.h"
    69 RT_C_DECLS_END
    7067# elif defined(RT_OS_LINUX)
    7168#  include <mntent.h>
    7269#  include <paths.h>
     70#  include <sys/utsname.h>
    7371RT_C_DECLS_BEGIN
    7472#  include "../../linux/sharedfolders/vbsfmount.h"
     
    313311 * @param   pszMountPoint   The mount point.
    314312 * @param   pszShareName    Unused.
    315  * @param   pOpts           For getting the group ID.
    316  */
    317 static int vbsvcAutoMountPrepareMountPointOld(const char *pszMountPoint, const char *pszShareName, vbsf_mount_opts *pOpts)
    318 {
    319     AssertPtrReturn(pOpts, VERR_INVALID_PARAMETER);
     313 * @param   gidGroup        The group ID.
     314 */
     315static int vbsvcAutoMountPrepareMountPointOld(const char *pszMountPoint, const char *pszShareName, RTGID gidGroup)
     316{
    320317    AssertPtrReturn(pszMountPoint, VERR_INVALID_PARAMETER);
    321318    AssertPtrReturn(pszShareName, VERR_INVALID_PARAMETER);
     319
     320    /** @todo r=bird: There is no reason why gidGroup should have write access?
     321     *        Seriously, what kind of non-sense is this? */
    322322
    323323    RTFMODE fMode = RTFS_UNIX_IRWXU | RTFS_UNIX_IRWXG; /* Owner (=root) and the group (=vboxsf) have full access. */
     
    325325    if (RT_SUCCESS(rc))
    326326    {
    327         rc = RTPathSetOwnerEx(pszMountPoint, NIL_RTUID /* Owner, unchanged */, pOpts->gid, RTPATH_F_ON_LINK);
     327        rc = RTPathSetOwnerEx(pszMountPoint, NIL_RTUID /* Owner, unchanged */, gidGroup, RTPATH_F_ON_LINK);
    328328        if (RT_SUCCESS(rc))
    329329        {
     
    374374    }
    375375
    376     struct vbsf_mount_opts Opts =
    377     {
    378         -1,                    /* ttl */
    379         -1,                    /* msDirCacheTTL */
    380         -1,                    /* msInodeTTL */
    381         0,                     /* cMaxIoPages */
    382         0,                     /* cbDirBuf */
    383         kVbsfCacheMode_Default,
    384         0,                     /* uid */
    385         (int)grp_vboxsf->gr_gid, /* gid */
    386         0770,                  /* dmode, owner and group "vboxsf" have full access */
    387         0770,                  /* fmode, owner and group "vboxsf" have full access */
    388         0,                     /* dmask */
    389         0,                     /* fmask */
    390         0,                     /* ronly */
    391         0,                     /* sloppy */
    392         0,                     /* noexec */
    393         0,                     /* nodev */
    394         0,                     /* nosuid */
    395         0,                     /* remount */
    396         "\0",                  /* nls_name */
    397         NULL,                  /* convertcp */
    398     };
    399 
    400     int rc = vbsvcAutoMountPrepareMountPointOld(pszMountPoint, pszShareName, &Opts);
     376    int rc = vbsvcAutoMountPrepareMountPointOld(pszMountPoint, pszShareName, grp_vboxsf->gr_gid);
    401377    if (RT_SUCCESS(rc))
    402378    {
    403379# ifdef RT_OS_SOLARIS
    404         int fFlags = 0;
    405         if (Opts.ronly)
    406             fFlags |= MS_RDONLY;
     380        int const fFlags = MS_OPTIONSTR;
    407381        char szOptBuf[MAX_MNTOPT_STR] = { '\0', };
    408         RTStrPrintf(szOptBuf, sizeof(szOptBuf), "uid=%d,gid=%d,dmode=%0o,fmode=%0o,dmask=%0o,fmask=%0o",
    409                     Opts.uid, Opts.gid, Opts.dmode, Opts.fmode, Opts.dmask, Opts.fmask);
     382        RTStrPrintf(szOptBuf, sizeof(szOptBuf), "uid=0,gid=%d,dmode=0770,fmode=0770,dmask=0000,fmask=0000", grp_vboxsf->gr_gid);
    410383        int r = mount(pszShareName,
    411384                      pszMountPoint,
    412                       fFlags | MS_OPTIONSTR,
     385                      fFlags,
    413386                      "vboxfs",
    414387                      NULL,                     /* char *dataptr */
     
    423396
    424397# else /* RT_OS_LINUX */
    425         unsigned long fFlags = MS_NODEV;
    426 
    427         /*const char *szOptions = { "rw" }; - ??? */
    428         struct vbsf_mount_info_new mntinf;
    429         RT_ZERO(mntinf);
    430 
    431         mntinf.nullchar     = '\0';
    432         mntinf.signature[0] = VBSF_MOUNT_SIGNATURE_BYTE_0;
    433         mntinf.signature[1] = VBSF_MOUNT_SIGNATURE_BYTE_1;
    434         mntinf.signature[2] = VBSF_MOUNT_SIGNATURE_BYTE_2;
    435         mntinf.length       = sizeof(mntinf);
    436 
    437         mntinf.uid   = Opts.uid;
    438         mntinf.gid   = Opts.gid;
    439         mntinf.ttl   = Opts.ttl;
    440         mntinf.dmode = Opts.dmode;
    441         mntinf.fmode = Opts.fmode;
    442         mntinf.dmask = Opts.dmask;
    443         mntinf.fmask = Opts.fmask;
    444         mntinf.cMaxIoPages = Opts.cMaxIoPages;
    445         mntinf.szTag[0] = '\0';
    446 
    447         strcpy(mntinf.name, pszShareName);
    448         strcpy(mntinf.nls_name, "\0");
     398        struct utsname uts;
     399        AssertStmt(uname(&uts) != -1, strcpy(uts.release, "4.4.0"));
     400
     401        unsigned long const fFlags = MS_NODEV;
     402        char szOpts[MAX_MNTOPT_STR] = { '\0' };
     403        ssize_t cchOpts = RTStrPrintf2(szOpts, sizeof(szOpts), "uid=0,gid=%d,dmode=0770,fmode=0770,dmask=0000,fmask=0000",
     404                                       grp_vboxsf->gr_gid);
     405        if (cchOpts > 0 && RTStrVersionCompare(uts.release, "2.6.0") < 0)
     406            cchOpts = RTStrPrintf2(&szOpts[cchOpts], sizeof(szOpts) - cchOpts, ",sf_name=%s", pszShareName);
     407        if (cchOpts <= 0)
     408        {
     409            VGSvcError("vbsvcAutomounterMountIt: szOpts overflow! %zd (share %s)\n", cchOpts, pszShareName);
     410            return VERR_BUFFER_OVERFLOW;
     411        }
    449412
    450413        int r = mount(pszShareName,
     
    452415                      "vboxsf",
    453416                      fFlags,
    454                       &mntinf);
     417                      szOpts);
    455418        if (r == 0)
    456419        {
    457420            VGSvcVerbose(0, "vbsvcAutoMountWorker: Shared folder '%s' was mounted to '%s'\n", pszShareName, pszMountPoint);
    458421
    459             r = vbsfmount_complete(pszShareName, pszMountPoint, fFlags, &Opts);
     422            r = vbsfmount_complete(pszShareName, pszMountPoint, fFlags, szOpts);
    460423            switch (r)
    461424            {
     
    463426                    errno = 0; /* Clear all errors/warnings. */
    464427                    break;
    465 
    466428                case 1:
    467                     VGSvcError("vbsvcAutoMountWorker: Could not update mount table (failed to create memstream): %s\n",
    468                                strerror(errno));
     429                    VGSvcError("vbsvcAutoMountWorker: Could not update mount table (malloc failure)\n");
    469430                    break;
    470 
    471431                case 2:
    472432                    VGSvcError("vbsvcAutoMountWorker: Could not open mount table for update: %s\n", strerror(errno));
    473433                    break;
    474 
    475434                case 3:
    476435                    /* VGSvcError("vbsvcAutoMountWorker: Could not add an entry to the mount table: %s\n", strerror(errno)); */
    477436                    errno = 0;
    478437                    break;
    479 
    480438                default:
    481439                    VGSvcError("vbsvcAutoMountWorker: Unknown error while completing mount operation: %d\n", r);
     
    485443        else /* r == -1, we got some error in errno.  */
    486444        {
    487             if (errno == EPROTO)
    488             {
    489                 VGSvcVerbose(3, "vbsvcAutoMountWorker: Messed up share name, re-trying ...\n");
    490 
    491                 /** @todo r=bird: What on earth is going on here?????  Why can't you
    492                  *        strcpy(mntinf.name, pszShareName) to fix it again? */
    493 
    494                 /* Sometimes the mount utility messes up the share name.  Try to
    495                  * un-mangle it again. */
    496                 char szCWD[RTPATH_MAX];
    497                 size_t cchCWD;
    498                 if (!getcwd(szCWD, sizeof(szCWD)))
    499                 {
    500                     VGSvcError("vbsvcAutoMountWorker: Failed to get the current working directory\n");
    501                     szCWD[0] = '\0';
    502                 }
    503                 cchCWD = strlen(szCWD);
    504                 if (!strncmp(pszMountPoint, szCWD, cchCWD))
    505                 {
    506                     while (pszMountPoint[cchCWD] == '/')
    507                         ++cchCWD;
    508                     /* We checked before that we have enough space */
    509                     strcpy(mntinf.name, pszMountPoint + cchCWD);
    510                 }
    511                 r = mount(mntinf.name, pszMountPoint, "vboxsf", fFlags, &mntinf);
    512             }
    513             if (r == -1) /* Was there some error from one of the tries above? */
    514             {
    515                 switch (errno)
    516                 {
    517                     /* If we get EINVAL here, the system already has mounted the Shared Folder to another
    518                      * mount point. */
    519                     case EINVAL:
    520                         VGSvcVerbose(0, "vbsvcAutoMountWorker: Shared folder '%s' already is mounted!\n", pszShareName);
    521                         /* Ignore this error! */
    522                         break;
    523                     case EBUSY:
    524                         /* Ignore these errors! */
    525                         break;
    526 
    527                     default:
    528                         VGSvcError("vbsvcAutoMountWorker: Could not mount shared folder '%s' to '%s': %s (%d)\n",
    529                                          pszShareName, pszMountPoint, strerror(errno), errno);
    530                         rc = RTErrConvertFromErrno(errno);
    531                         break;
    532                 }
     445            switch (errno)
     446            {
     447                /* If we get EINVAL here, the system already has mounted the Shared Folder to another
     448                 * mount point. */
     449                case EINVAL:
     450                    VGSvcVerbose(0, "vbsvcAutoMountWorker: Shared folder '%s' is already mounted!\n", pszShareName);
     451                    /* Ignore this error! */
     452                    break;
     453                case EBUSY:
     454                    /* Ignore these errors! */
     455                    break;
     456                default:
     457                    VGSvcError("vbsvcAutoMountWorker: Could not mount shared folder '%s' to '%s': %s (%d)\n",
     458                               pszShareName, pszMountPoint, strerror(errno), errno);
     459                    rc = RTErrConvertFromErrno(errno);
     460                    break;
    533461            }
    534462        }
     
    15311459     * Linux a bit more work...
    15321460     */
    1533     struct vbsf_mount_info_new MntInfo;
    1534     RT_ZERO(MntInfo);
    1535     struct vbsf_mount_opts MntOpts;
    1536     RT_ZERO(MntOpts);
    1537     MntInfo.nullchar     = '\0';
    1538     MntInfo.signature[0] = VBSF_MOUNT_SIGNATURE_BYTE_0;
    1539     MntInfo.signature[1] = VBSF_MOUNT_SIGNATURE_BYTE_1;
    1540     MntInfo.signature[2] = VBSF_MOUNT_SIGNATURE_BYTE_2;
    1541     MntInfo.length       = sizeof(MntInfo);
    1542     MntInfo.ttl          = MntOpts.ttl              = -1 /*default*/;
    1543     MntInfo.msDirCacheTTL= MntOpts.msDirCacheTTL    = -1 /*default*/;
    1544     MntInfo.msInodeTTL   = MntOpts.msInodeTTL       = -1 /*default*/;
    1545     MntInfo.cMaxIoPages  = MntOpts.cMaxIoPages      = 0 /*default*/;
    1546     MntInfo.cbDirBuf     = MntOpts.cbDirBuf         = 0 /*default*/;
    1547     MntInfo.enmCacheMode = MntOpts.enmCacheMode     = kVbsfCacheMode_Default;
    1548     MntInfo.uid          = MntOpts.uid   = 0;
    1549     MntInfo.gid          = MntOpts.gid   = gidMount;
    1550     MntInfo.dmode        = MntOpts.dmode = 0770;
    1551     MntInfo.fmode        = MntOpts.fmode = 0770;
    1552     MntInfo.dmask        = MntOpts.dmask = 0000;
    1553     MntInfo.fmask        = MntOpts.fmask = 0000;
    1554     memcpy(MntInfo.szTag, g_szTag, sizeof(g_szTag)); AssertCompile(sizeof(MntInfo.szTag) >= sizeof(g_szTag));
    1555     rc = RTStrCopy(MntInfo.name, sizeof(MntInfo.name), pEntry->pszName);
    1556     if (RT_FAILURE(rc))
    1557     {
    1558         VGSvcError("vbsvcAutomounterMountIt: Share name '%s' is too long for the MntInfo.name field!\n", pEntry->pszName);
    1559         return rc;
    1560     }
    1561 
     1461    struct utsname uts;
     1462    AssertStmt(uname(&uts) != -1, strcpy(uts.release, "4.4.0"));
     1463
     1464    /* Built mount option string.  Need st_name for pre 2.6.0 kernels. */
     1465    unsigned long const fFlags = MS_NODEV;
     1466    char szOpts[MAX_MNTOPT_STR] = { '\0' };
     1467    ssize_t cchOpts = RTStrPrintf2(szOpts, sizeof(szOpts),
     1468                                   "uid=0,gid=%d,dmode=0770,fmode=0770,dmask=0000,fmask=0000,tag=%s", gidMount, g_szTag);
     1469    if (RTStrVersionCompare(uts.release, "2.6.0") < 0 && cchOpts > 0)
     1470        cchOpts += RTStrPrintf2(&szOpts[cchOpts], sizeof(szOpts) - cchOpts, ",sf_name=%s", pEntry->pszName);
     1471    if (cchOpts <= 0)
     1472    {
     1473        VGSvcError("vbsvcAutomounterMountIt: szOpts overflow! %zd\n", cchOpts);
     1474        return VERR_BUFFER_OVERFLOW;
     1475    }
     1476
     1477    /* Do the mounting. The fallback w/o tag is for the Linux vboxsf fork
     1478       which lagged a lot behind when it first appeared in 5.6. */
    15621479    errno = 0;
    1563     unsigned long fFlags = MS_NODEV;
    1564     rc = mount(pEntry->pszName, pEntry->pszActualMountPoint, "vboxsf", fFlags, &MntInfo);
     1480    rc = mount(pEntry->pszName, pEntry->pszActualMountPoint, "vboxsf", fFlags, szOpts);
     1481    if (rc != 0 && errno == EINVAL && RTStrVersionCompare(uts.release, "5.6.0") >= 0)
     1482    {
     1483        VGSvcVerbose(2, "vbsvcAutomounterMountIt: mount returned EINVAL, retrying without the tag.\n");
     1484        *strstr(szOpts, ",tag=") = '\0';
     1485        errno = 0;
     1486        rc = mount(pEntry->pszName, pEntry->pszActualMountPoint, "vboxsf", fFlags, szOpts);
     1487        if (rc == 0)
     1488            VGSvcVerbose(0, "vbsvcAutomounterMountIt: Running outdated vboxsf module without support for the 'tag' option?\n");
     1489    }
    15651490    if (rc == 0)
    15661491    {
     
    15691494
    15701495        errno = 0;
    1571         rc = vbsfmount_complete(pEntry->pszName, pEntry->pszActualMountPoint, fFlags, &MntOpts);
     1496        rc = vbsfmount_complete(pEntry->pszName, pEntry->pszActualMountPoint, fFlags, szOpts);
    15721497        if (rc != 0) /* Ignorable. /etc/mtab is probably a link to /proc/mounts. */
    15731498            VGSvcVerbose(1, "vbsvcAutomounterMountIt: vbsfmount_complete failed: %s (%d/%d)\n",
    1574                          rc == 1 ? "open_memstream" : rc == 2 ? "setmntent" : rc == 3 ? "addmntent" : "unknown", rc, errno);
     1499                         rc == 1 ? "malloc" : rc == 2 ? "setmntent" : rc == 3 ? "addmntent" : "unknown", rc, errno);
    15751500        return VINF_SUCCESS;
    15761501    }
    1577     else if (errno == EINVAL)
     1502
     1503    if (errno == EINVAL)
    15781504        VGSvcError("vbsvcAutomounterMountIt: Failed to mount '%s' on '%s' because it is probably mounted elsewhere arleady! (%d,%d)\n",
    15791505                   pEntry->pszName, pEntry->pszActualMountPoint, rc, errno);
  • trunk/src/VBox/Additions/linux/sharedfolders/mount.vboxsf.c

    r82968 r87463  
    4444#include <limits.h>
    4545#include <iconv.h>
     46#include <sys/utsname.h>
     47#include <linux/version.h>
    4648
    4749#include "vbsfmount.h"
    4850
    49 #include <iprt/assert.h>
    50 
    51 
     51#include <iprt/assertcompile.h>
     52#include <iprt/param.h>  /* PAGE_SIZE (used by MAX_MNTOPT_STR) */
     53#include <iprt/string.h>
     54
     55
     56/*********************************************************************************************************************************
     57*   Defined Constants And Macros                                                                                                 *
     58*********************************************************************************************************************************/
    5259#define PANIC_ATTR __attribute ((noreturn, __format__ (__printf__, 1, 2)))
     60
     61
     62/*********************************************************************************************************************************
     63*   Structures and Typedefs                                                                                                      *
     64*********************************************************************************************************************************/
     65struct vbsf_mount_opts
     66{
     67    unsigned long fFlags; /**< MS_XXX */
     68
     69    /** @name Preformatted option=value or empty if not specified.
     70     * Helps eliminate duplicate options as well as simplifying concatting.
     71     * @{ */
     72    char          szTTL[32];
     73    char          szMsDirCacheTTL[32];
     74    char          szMsInodeTTL[32];
     75    char          szMaxIoPages[32];
     76    char          szDirBuf[32];
     77    char          szCacheMode[32];
     78    char          szUid[32];
     79    char          szGid[32];
     80    char          szDMode[32];
     81    char          szFMode[32];
     82    char          szDMask[32];
     83    char          szFMask[32];
     84    char          szIoCharset[32];
     85    /** @} */
     86
     87    bool          fSloppy;
     88    char         *pszConvertCp;
     89};
     90
    5391
    5492static void PANIC_ATTR
     
    134172        HO_FMASK,
    135173        HO_IOCHARSET,
     174        HO_NLS,
    136175        HO_CONVERTCP,
    137176        HO_NOEXEC,
     
    164203        {"cache",       HO_CACHE,           1, "cache mode: none, strict (default), read, readwrite"},
    165204        {"iocharset",   HO_IOCHARSET,       1, "i/o charset (default utf8)"},
     205        {"nls",         HO_NLS,             1, "i/o charset (default utf8)"},
    166206        {"convertcp",   HO_CONVERTCP,       1, "convert share name from given charset to utf8"},
    167207        {"dmode",       HO_DMODE,           1, "mode of all directories"},
     
    230270                    {
    231271                        panic("%.*s requires an argument (i.e. %.*s=<arg>)\n",
    232                                (int)len, s, (int)len, s);
     272                              (int)len, s, (int)len, s);
    233273                    }
    234274                }
     
    237277                {
    238278                    case HO_RW:
    239                         opts->ronly = 0;
     279                        opts->fFlags &= ~MS_RDONLY;
    240280                        break;
    241281                    case HO_RO:
    242                         opts->ronly = 1;
     282                        opts->fFlags |= MS_RDONLY;
    243283                        break;
    244284                    case HO_NOEXEC:
    245                         opts->noexec = 1;
     285                        opts->fFlags |= MS_NOEXEC;
    246286                        break;
    247287                    case HO_EXEC:
    248                         opts->noexec = 0;
     288                        opts->fFlags &= ~MS_NOEXEC;
    249289                        break;
    250290                    case HO_NODEV:
    251                         opts->nodev = 1;
     291                        opts->fFlags |= MS_NODEV;
    252292                        break;
    253293                    case HO_DEV:
    254                         opts->nodev = 0;
     294                        opts->fFlags &= ~MS_NODEV;
    255295                        break;
    256296                    case HO_NOSUID:
    257                         opts->nosuid = 1;
     297                        opts->fFlags |= MS_NOSUID;
    258298                        break;
    259299                    case HO_SUID:
    260                         opts->nosuid = 0;
     300                        opts->fFlags &= ~MS_NOSUID;
    261301                        break;
    262302                    case HO_REMOUNT:
    263                         opts->remount = 1;
     303                        opts->fFlags |= MS_REMOUNT;
    264304                        break;
    265305                    case HO_TTL:
    266                         opts->ttl = safe_atoi(val, val_len, 10);
     306                        snprintf(opts->szTTL, sizeof(opts->szTTL),
     307                                 "ttl=%d", safe_atoi(val, val_len, 10));
    267308                        break;
    268309                    case HO_DENTRY_TTL:
    269                         opts->msDirCacheTTL = safe_atoi(val, val_len, 10);
     310                        snprintf(opts->szMsDirCacheTTL, sizeof(opts->szMsDirCacheTTL),
     311                                 "dcachettl=%d", safe_atoi(val, val_len, 10));
    270312                        break;
    271313                    case HO_INODE_TTL:
    272                         opts->msInodeTTL = safe_atoi(val, val_len, 10);
     314                        snprintf(opts->szMsInodeTTL, sizeof(opts->szMsInodeTTL),
     315                                 "inodettl=%d", safe_atoi(val, val_len, 10));
    273316                        break;
    274317                    case HO_MAX_IO_PAGES:
    275                         opts->cMaxIoPages = safe_atoiu(val, val_len, 10);
     318                        snprintf(opts->szMaxIoPages, sizeof(opts->szMaxIoPages),
     319                                 "maxiopages=%d", safe_atoiu(val, val_len, 10));
    276320                        break;
    277321                    case HO_DIR_BUF:
    278                         opts->cbDirBuf = safe_atoiu(val, val_len, 10);
     322                        snprintf(opts->szDirBuf, sizeof(opts->szDirBuf),
     323                                 "dirbuf=%d", safe_atoiu(val, val_len, 10));
    279324                        break;
    280325                    case HO_CACHE:
    281326#define IS_EQUAL(a_sz) (val_len == sizeof(a_sz) - 1U && strncmp(val, a_sz, sizeof(a_sz) - 1U) == 0)
    282327                        if (IS_EQUAL("default"))
    283                             opts->enmCacheMode = kVbsfCacheMode_Default;
     328                            strcpy(opts->szCacheMode, "cache=default");
    284329                        else if (IS_EQUAL("none"))
    285                             opts->enmCacheMode = kVbsfCacheMode_None;
     330                            strcpy(opts->szCacheMode, "cache=none");
    286331                        else if (IS_EQUAL("strict"))
    287                             opts->enmCacheMode = kVbsfCacheMode_Strict;
     332                            strcpy(opts->szCacheMode, "cache=strict");
    288333                        else if (IS_EQUAL("read"))
    289                             opts->enmCacheMode = kVbsfCacheMode_Read;
     334                            strcpy(opts->szCacheMode, "cache=read");
    290335                        else if (IS_EQUAL("readwrite"))
    291                             opts->enmCacheMode = kVbsfCacheMode_ReadWrite;
     336                            strcpy(opts->szCacheMode, "cache=readwrite");
    292337                        else
    293338                            panic("invalid cache mode '%.*s'\n"
     
    297342                    case HO_UID:
    298343                        /** @todo convert string to id. */
    299                         opts->uid = safe_atoi(val, val_len, 10);
     344                        snprintf(opts->szUid, sizeof(opts->szUid),
     345                                 "uid=%d", safe_atoi(val, val_len, 10));
    300346                        break;
    301347                    case HO_GID:
    302348                        /** @todo convert string to id. */
    303                         opts->gid = safe_atoi(val, val_len, 10);
     349                        snprintf(opts->szGid, sizeof(opts->szGid),
     350                                 "gid=%d", safe_atoi(val, val_len, 10));
    304351                        break;
    305352                    case HO_DMODE:
    306                         opts->dmode = safe_atoi(val, val_len, 8);
     353                        snprintf(opts->szDMode, sizeof(opts->szDMode),
     354                                 "dmode=0%o", safe_atoi(val, val_len, 8));
    307355                        break;
    308356                    case HO_FMODE:
    309                         opts->fmode = safe_atoi(val, val_len, 8);
     357                        snprintf(opts->szFMode, sizeof(opts->szFMode),
     358                                 "fmode=0%o", safe_atoi(val, val_len, 8));
    310359                        break;
    311360                    case HO_UMASK:
    312                         opts->dmask = opts->fmask = safe_atoi(val, val_len, 8);
    313                         break;
     361                    {
     362                        int fMask = safe_atoi(val, val_len, 8);
     363                        snprintf(opts->szDMask, sizeof(opts->szDMask), "dmask=0%o", fMask);
     364                        snprintf(opts->szFMask, sizeof(opts->szFMask), "fmask=0%o", fMask);
     365                        break;
     366                    }
    314367                    case HO_DMASK:
    315                         opts->dmask = safe_atoi(val, val_len, 8);
     368                        snprintf(opts->szDMask, sizeof(opts->szDMask),
     369                                 "dmask=0%o", safe_atoi(val, val_len, 8));
    316370                        break;
    317371                    case HO_FMASK:
    318                         opts->fmask = safe_atoi(val, val_len, 8);
     372                        snprintf(opts->szFMask, sizeof(opts->szFMask),
     373                                 "fmask=0%o", safe_atoi(val, val_len, 8));
    319374                        break;
    320375                    case HO_IOCHARSET:
    321                         if (val_len + 1 > sizeof(opts->nls_name))
    322                         {
    323                             panic("iocharset name too long\n");
    324                         }
    325                         memcpy(opts->nls_name, val, val_len);
    326                         opts->nls_name[val_len] = 0;
     376                    case HO_NLS:
     377                        if (val_len >= MAX_NLS_NAME)
     378                            panic("the character set name for I/O is too long: %*.*s\n", (int)val_len, (int)val_len, val);
     379                        snprintf(opts->szIoCharset, sizeof(opts->szIoCharset),
     380                                 "%s=%*.*s", handler->opt == HO_IOCHARSET ? "iocharset" : "nls", (int)val_len, (int)val_len, val);
    327381                        break;
    328382                    case HO_CONVERTCP:
    329                         opts->convertcp = malloc(val_len + 1);
    330                         if (!opts->convertcp)
    331                         {
     383                        opts->pszConvertCp = malloc(val_len + 1);
     384                        if (!opts->pszConvertCp)
    332385                            panic_err("could not allocate memory");
    333                         }
    334                         memcpy(opts->convertcp, val, val_len);
    335                         opts->convertcp[val_len] = 0;
     386                        memcpy(opts->pszConvertCp, val, val_len);
     387                        opts->pszConvertCp[val_len] = '\0';
    336388                        break;
    337389                    case HO_NOAUTO:
     
    345397
    346398        if (   !handler->name
    347             && !opts->sloppy)
     399            && !opts->fSloppy)
    348400        {
    349401            fprintf(stderr, "unknown mount option `%.*s'\n", (int)len, s);
     
    354406                if (handler->desc)
    355407                    fprintf(stderr, "  %-10s%s %s\n", handler->name,
    356                          handler->has_arg ? "=<arg>" : "", handler->desc);
     408                            handler->has_arg ? "=<arg>" : "", handler->desc);
    357409            }
    358410            exit(EXIT_FAILURE);
     
    361413}
    362414
     415/** Appends @a pszOptVal to pszOpts if not empty. */
     416static size_t append_option(char *pszOpts, size_t cbOpts, size_t offOpts, const char *pszOptVal)
     417{
     418    if (*pszOptVal != '\0')
     419    {
     420        size_t cchOptVal = strlen(pszOptVal);
     421        if (offOpts + (offOpts > 0) + cchOptVal < cbOpts)
     422        {
     423            if (offOpts)
     424                pszOpts[offOpts++] = ',';
     425            memcpy(&pszOpts[offOpts], pszOptVal, cchOptVal);
     426            offOpts += cchOptVal;
     427            pszOpts[offOpts] = '\0';
     428        }
     429        else
     430            panic("Too many options!");
     431    }
     432    return offOpts;
     433}
     434
    363435static void
    364 convertcp(char *in_codeset, char *host_name, struct vbsf_mount_info_new *info)
    365 {
    366     char *i = host_name;
    367     char *o = info->name;
    368     size_t ib = strlen(host_name);
    369     size_t ob = sizeof(info->name) - 1;
     436convertcp(char *in_codeset, char *pszSharedFolder, char *pszDst)
     437{
     438    char *i = pszSharedFolder;
     439    char *o = pszDst;
     440    size_t ib = strlen(pszSharedFolder);
     441    size_t ob = MAX_HOST_NAME - 1;
    370442    iconv_t cd;
    371443
    372444    cd = iconv_open("UTF-8", in_codeset);
    373     if (cd == (iconv_t) -1)
     445    if (cd == (iconv_t)-1)
    374446    {
    375447        panic_err("could not convert share name, iconv_open `%s' failed",
     
    380452    {
    381453        size_t c = iconv(cd, &i, &ib, &o, &ob);
    382         if (c == (size_t) -1)
     454        if (c == (size_t)-1)
    383455        {
    384456            panic_err("could not convert share name(%s) at %d",
    385                       host_name, (int)(strlen (host_name) - ib));
     457                      pszSharedFolder, (int)(strlen(pszSharedFolder) - ib));
    386458        }
    387459    }
     
    454526    int saved_errno;
    455527    int nomtab = 0;
    456     unsigned long flags = MS_NODEV;
    457     char *host_name;
    458     char *mount_point;
    459     struct vbsf_mount_info_new mntinf;
     528    char *pszSharedFolder;
     529    char *pszMountPoint;
     530    struct utsname uts;
     531    int major, minor, patch;
     532    size_t offOpts;
     533    static const char s_szSfNameOpt[] = "sf_name=";
     534    char szSharedFolderIconved[sizeof(s_szSfNameOpt) - 1 + MAX_HOST_NAME];
     535    char szOpts[MAX_MNTOPT_STR];
    460536    struct vbsf_mount_opts opts =
    461537    {
    462         -1,    /* ttl */
    463         -1,    /* msDirCacheTTL */
    464         -1,    /* msInodeTTL */
    465         0,     /* cMaxIoPages */
    466         0,     /* cbDirBuf */
    467         kVbsfCacheMode_Default,
    468         0,     /* uid */
    469         0,     /* gid */
    470        ~0U,    /* dmode */
    471        ~0U,    /* fmode*/
    472         0,     /* dmask */
    473         0,     /* fmask */
    474         0,     /* ronly */
    475         0,     /* sloppy */
    476         0,     /* noexec */
    477         0,     /* nodev */
    478         0,     /* nosuid */
    479         0,     /* remount */
    480         "\0",  /* nls_name */
    481         NULL,  /* convertcp */
     538        MS_NODEV,
     539        "",
     540        "",
     541        "",
     542        "",
     543        "",
     544        "",
     545        "",
     546        "",
     547        "",
     548        "",
     549        "",
     550        "",
     551        "",
     552        false, /*fSloppy*/
     553        NULL,
    482554    };
     555
    483556    AssertCompile(sizeof(uid_t) == sizeof(int));
    484557    AssertCompile(sizeof(gid_t) == sizeof(int));
    485558
    486     memset(&mntinf, 0, sizeof(mntinf));
    487     mntinf.nullchar = '\0';
    488     mntinf.signature[0] = VBSF_MOUNT_SIGNATURE_BYTE_0;
    489     mntinf.signature[1] = VBSF_MOUNT_SIGNATURE_BYTE_1;
    490     mntinf.signature[2] = VBSF_MOUNT_SIGNATURE_BYTE_2;
    491     mntinf.length       = sizeof(mntinf);
    492     mntinf.szTag[0] = '\0';
    493 
    494559    if (getuid())
    495560        panic("Only root can mount shared folders from the host.\n");
     
    498563        argv[0] = "mount.vboxsf";
    499564
     565    /*
     566     * Parse options.
     567     */
    500568    while ((c = getopt(argc, argv, "rwsno:h")) != -1)
    501569    {
     
    510578
    511579            case 'r':
    512                 opts.ronly = 1;
     580                opts.fFlags |= MS_RDONLY;
    513581                break;
    514582
    515583            case 'w':
    516                 opts.ronly = 0;
     584                opts.fFlags &= ~MS_RDONLY;
    517585                break;
    518586
    519587            case 's':
    520                 opts.sloppy = 1;
     588                opts.fSloppy = true;
    521589                break;
    522590
     
    534602        return usage(argv[0]);
    535603
    536     host_name = argv[optind];
    537     mount_point = argv[optind + 1];
    538 
    539     if (opts.convertcp)
    540         convertcp(opts.convertcp, host_name, &mntinf);
    541     else
    542     {
    543         if (strlen(host_name) > MAX_HOST_NAME - 1)
    544             panic("host name is too big\n");
    545 
    546         strcpy(mntinf.name, host_name);
    547     }
    548 
    549     if (strlen(opts.nls_name) > MAX_NLS_NAME - 1)
    550         panic("%s: the character set name for I/O is too long.\n", argv[0]);
    551 
    552     strcpy(mntinf.nls_name, opts.nls_name);
    553 
    554     if (opts.ronly)
    555         flags |= MS_RDONLY;
    556     if (opts.noexec)
    557         flags |= MS_NOEXEC;
    558     if (opts.nodev)
    559         flags |= MS_NODEV;
    560     if (opts.remount)
    561         flags |= MS_REMOUNT;
    562 
    563     mntinf.ttl              = opts.ttl;
    564     mntinf.msDirCacheTTL    = opts.msDirCacheTTL;
    565     mntinf.msInodeTTL       = opts.msInodeTTL;
    566     mntinf.cMaxIoPages      = opts.cMaxIoPages;
    567     mntinf.cbDirBuf         = opts.cbDirBuf;
    568     mntinf.enmCacheMode     = opts.enmCacheMode;
    569 
    570     mntinf.uid   = opts.uid;
    571     mntinf.gid   = opts.gid;
    572     mntinf.dmode = opts.dmode;
    573     mntinf.fmode = opts.fmode;
    574     mntinf.dmask = opts.dmask;
    575     mntinf.fmask = opts.fmask;
     604    pszSharedFolder = argv[optind];
     605    pszMountPoint   = argv[optind + 1];
     606    if (opts.pszConvertCp)
     607    {
     608        convertcp(opts.pszConvertCp, pszSharedFolder, &szSharedFolderIconved[sizeof(s_szSfNameOpt) - 1]);
     609        pszSharedFolder = &szSharedFolderIconved[sizeof(s_szSfNameOpt) - 1];
     610    }
    576611
    577612    /*
    578      * Note: When adding and/or modifying parameters of the vboxsf mounting
    579      *       options you also would have to adjust VBoxServiceAutoMount.cpp
    580      *       to keep this code here slick without having VbglR3.
     613     * Concat option strings.
    581614     */
    582     err = mount(host_name, mount_point, "vboxsf", flags, &mntinf);
     615    offOpts   = 0;
     616    szOpts[0] = '\0';
     617    offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szTTL);
     618    offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szMsDirCacheTTL);
     619    offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szMsInodeTTL);
     620    offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szMaxIoPages);
     621    offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szDirBuf);
     622    offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szCacheMode);
     623    offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szUid);
     624    offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szGid);
     625    offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szDMode);
     626    offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szFMode);
     627    offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szDMask);
     628    offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szFMask);
     629    offOpts = append_option(szOpts, sizeof(szOpts), offOpts, opts.szIoCharset);
     630
     631    /* For pre-2.6 kernels we have to supply the shared folder name as a
     632       string option because the kernel hides the device name from us. */
     633    RT_ZERO(uts);
     634    if (   uname(&uts) == -1
     635        || sscanf(uts.release, "%d.%d.%d", &major, &minor, &patch) != 3)
     636        major = minor = patch = 5;
     637
     638    if (KERNEL_VERSION(major, minor, patch) < KERNEL_VERSION(2,6,0))
     639    {
     640        memcpy(szSharedFolderIconved, s_szSfNameOpt, sizeof(s_szSfNameOpt) - 1);
     641        if (!opts.pszConvertCp)
     642        {
     643            if (strlen(pszSharedFolder) >= MAX_HOST_NAME)
     644                panic("%s: shared folder name is too long (max %d)", argv[0], (int)MAX_HOST_NAME - 1);
     645            strcpy(&szSharedFolderIconved[sizeof(s_szSfNameOpt) - 1], pszSharedFolder);
     646        }
     647        offOpts = append_option(szOpts, sizeof(szOpts), offOpts, szSharedFolderIconved);
     648    }
     649
     650    /*
     651     * Do the actual mounting.
     652     */
     653    err = mount(pszSharedFolder, pszMountPoint, "vboxsf", opts.fFlags, szOpts);
    583654    saved_errno = errno;
    584655
    585     /* Some versions of the mount utility (unknown which, if any) will turn the
    586        shared folder name into an absolute path.  So, we check if it starts with
    587        the CWD and removes it.  We must do this after failing, because there is
    588        not actual restrictions on the shared folder name wrt to slashes and such. */
    589     if (err == -1 && errno == ENXIO && host_name[0] == '/')
    590     {
    591         char szCWD[4096];
    592         if (getcwd(szCWD, sizeof(szCWD)) != NULL)
    593         {
    594             size_t cchCWD = strlen(szCWD);
    595             if (!strncmp(host_name, szCWD, cchCWD))
    596             {
    597                 while (host_name[cchCWD] == '/')
    598                     ++cchCWD;
    599                 if (host_name[cchCWD])
    600                 {
    601                     /* We checked before that we have enough space. */
    602                     strcpy(mntinf.name, host_name + cchCWD);
    603                     err = mount(host_name, mount_point, "vboxsf", flags, &mntinf);
    604                     saved_errno = errno;
    605                 }
    606             }
    607         }
    608         else
    609             fprintf(stderr, "%s: failed to get the current working directory: %s", argv[0], strerror(errno));
    610         errno = saved_errno;
    611     }
    612656    if (err)
    613657    {
    614658        if (saved_errno == ENXIO)
    615             panic("%s: shared folder '%s' was not found (check VM settings / spelling)\n", argv[0], host_name);
     659            panic("%s: shared folder '%s' was not found (check VM settings / spelling)\n", argv[0], pszSharedFolder);
    616660        else
    617661            panic_err("%s: mounting failed with the error", argv[0]);
     
    620664    if (!nomtab)
    621665    {
    622         err = vbsfmount_complete(host_name, mount_point, flags, &opts);
     666        err = vbsfmount_complete(pszSharedFolder, pszMountPoint, opts.fFlags, szOpts);
    623667        switch (err)
    624668        {
     
    627671
    628672            case 1:
    629                 panic_err("%s: Could not update mount table (failed to create memstream).", argv[0]);
     673                panic_err("%s: Could not update mount table (out of memory).", argv[0]);
    630674                break;
    631675
  • trunk/src/VBox/Additions/linux/sharedfolders/vbsfmount.c

    r82968 r87463  
    1717 */
    1818
     19
     20/*********************************************************************************************************************************
     21*   Header Files                                                                                                                 *
     22*********************************************************************************************************************************/
    1923#ifndef _GNU_SOURCE
    20 #define _GNU_SOURCE
     24# define _GNU_SOURCE
    2125#endif
     26#include <assert.h>
    2227#include <ctype.h>
    2328#include <mntent.h>
     
    3237
    3338/** @todo Use defines for return values! */
    34 int vbsfmount_complete(const char *host_name, const char *mount_point,
    35                        unsigned long flags, struct vbsf_mount_opts *opts)
     39int vbsfmount_complete(const char *pszSharedFolder, const char *pszMountPoint,
     40                       unsigned long fFlags, const char *pszOpts)
    3641{
    37     FILE *f, *m;
    38     char *buf;
    39     size_t size;
    40     struct mntent e;
    41     int rc = 0;
     42    /*
     43     * Combine pszOpts and fFlags.
     44     */
     45    int          rc;
     46    size_t const cchFlags = (fFlags & MS_NOSUID ? strlen(MNTOPT_NOSUID) + 1 : 0)
     47                          + (fFlags & MS_RDONLY ? strlen(MNTOPT_RO) : strlen(MNTOPT_RW));
     48    size_t const cchOpts  = pszOpts ? 1 + strlen(pszOpts) : 0;
     49    char        *pszBuf   = (char *)malloc(cchFlags + cchOpts + 8);
     50    if (pszBuf)
     51    {
     52        char         *psz = pszBuf;
     53        FILE         *pMTab;
    4254
    43     m = open_memstream(&buf, &size);
    44     if (!m)
    45         return 1; /* Could not update mount table (failed to create memstream). */
     55        strcpy(psz, fFlags & MS_RDONLY ? MNTOPT_RO : MNTOPT_RW);
     56        psz += strlen(psz);
    4657
    47     if (opts->ttl != -1)
    48         fprintf(m, "ttl=%d,", opts->ttl);
    49     if (opts->msDirCacheTTL >= 0)
    50         fprintf(m, "dcachettl=%d,", opts->msDirCacheTTL);
    51     if (opts->msInodeTTL >= 0)
    52         fprintf(m, "inodettl=%d,", opts->msInodeTTL);
    53     if (opts->cMaxIoPages)
    54         fprintf(m, "maxiopages=%u,", opts->cMaxIoPages);
    55     if (opts->cbDirBuf)
    56         fprintf(m, "dirbuf=%u,", opts->cbDirBuf);
    57     switch (opts->enmCacheMode)
    58     {
    59         default:
    60         case kVbsfCacheMode_Default:
    61             break;
    62         case kVbsfCacheMode_None:       fprintf(m, "cache=none,"); break;
    63         case kVbsfCacheMode_Strict:     fprintf(m, "cache=strict,"); break;
    64         case kVbsfCacheMode_Read:       fprintf(m, "cache=read,"); break;
    65         case kVbsfCacheMode_ReadWrite:  fprintf(m, "cache=readwrite,"); break;
    66     }
    67     if (opts->uid)
    68         fprintf(m, "uid=%d,", opts->uid);
    69     if (opts->gid)
    70         fprintf(m, "gid=%d,", opts->gid);
    71     if (*opts->nls_name)
    72         fprintf(m, "iocharset=%s,", opts->nls_name);
    73     if (flags & MS_NOSUID)
    74         fprintf(m, "%s,", MNTOPT_NOSUID);
    75     if (flags & MS_RDONLY)
    76         fprintf(m, "%s,", MNTOPT_RO);
    77     else
    78         fprintf(m, "%s,", MNTOPT_RW);
     58        if (fFlags & MS_NOSUID)
     59        {
     60            *psz++ = ',';
     61            strcpy(psz, MNTOPT_NOSUID);
     62            psz += strlen(psz);
     63        }
    7964
    80     fclose(m);
     65        if (cchOpts)
     66        {
     67            *psz++ = ',';
     68            strcpy(psz, pszOpts);
     69        }
    8170
    82     if (size > 0)
    83         buf[size - 1] = 0;
    84     else
    85         buf = "defaults";
     71        assert(strlen(pszBuf) <= cchFlags + cchOpts);
    8672
    87     f = setmntent(MOUNTED, "a+");
    88     if (!f)
    89     {
    90         rc = 2; /* Could not open mount table for update. */
     73        /*
     74         * Open the mtab and update it:
     75         */
     76        pMTab = setmntent(MOUNTED, "a+");
     77        if (pMTab)
     78        {
     79            struct mntent Entry;
     80            Entry.mnt_fsname = (char*)pszSharedFolder;
     81            Entry.mnt_dir = (char *)pszMountPoint;
     82            Entry.mnt_type = "vboxsf";
     83            Entry.mnt_opts = pszBuf;
     84            Entry.mnt_freq = 0;
     85            Entry.mnt_passno = 0;
     86
     87            if (!addmntent(pMTab, &Entry))
     88                rc = 0; /* success. */
     89            else
     90                rc = 3;  /* Could not add an entry to the mount table. */
     91
     92            endmntent(pMTab);
     93        }
     94        else
     95            rc = 2; /* Could not open mount table for update. */
     96
     97        free(pszBuf);
    9198    }
    9299    else
    93     {
    94         e.mnt_fsname = (char*)host_name;
    95         e.mnt_dir = (char*)mount_point;
    96         e.mnt_type = "vboxsf";
    97         e.mnt_opts = buf;
    98         e.mnt_freq = 0;
    99         e.mnt_passno = 0;
    100 
    101         if (addmntent(f, &e))
    102             rc = 3;  /* Could not add an entry to the mount table. */
    103 
    104         endmntent(f);
    105     }
    106 
    107     if (size > 0)
    108     {
    109         memset(buf, 0, size);
    110         free(buf);
    111     }
    112 
     100        rc = 1; /* allocation error */
    113101    return rc;
    114102}
     103
  • trunk/src/VBox/Additions/linux/sharedfolders/vbsfmount.h

    r82968 r87463  
    3535#endif
    3636
    37 /* Linux constraints the size of data mount argument to PAGE_SIZE - 1. */
    38 #define MAX_HOST_NAME  256
    39 #define MAX_NLS_NAME    32
     37/* Linux constrains the size of data mount argument to PAGE_SIZE - 1. */
     38#define MAX_MNTOPT_STR          PAGE_SIZE
     39#define MAX_HOST_NAME           256
     40#define MAX_NLS_NAME            32
    4041#define VBSF_DEFAULT_TTL_MS     200
    4142
     
    135136#endif
    136137
    137 /**
    138  * For use with the vbsfmount_complete() helper.
    139  */
    140 struct vbsf_mount_opts {
    141     int                     ttl;
    142     int32_t                 msDirCacheTTL;
    143     int32_t                 msInodeTTL;
    144     uint32_t                cMaxIoPages;
    145     uint32_t                cbDirBuf;
    146     enum vbsf_cache_mode    enmCacheMode;
    147     int uid;
    148     int gid;
    149     int dmode;
    150     int fmode;
    151     int dmask;
    152     int fmask;
    153     int ronly;
    154     int sloppy;
    155     int noexec;
    156     int nodev;
    157     int nosuid;
    158     int remount;
    159     char nls_name[MAX_NLS_NAME];
    160     char *convertcp;
    161 };
    162 
    163138/** Completes the mount operation by adding the new mount point to mtab if required. */
    164 int vbsfmount_complete(const char *host_name, const char *mount_point,
    165                        unsigned long flags, struct vbsf_mount_opts *opts);
     139int vbsfmount_complete(const char *pszSharedFolder, const char *pszMountPoint,
     140                       unsigned long fFlags, const char *pszOpts);
    166141
    167142#endif /* !GA_INCLUDED_SRC_linux_sharedfolders_vbsfmount_h */
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette