VirtualBox

Changeset 77858 in vbox for trunk


Ignore:
Timestamp:
Mar 24, 2019 12:10:24 AM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
129542
Message:

linux/vboxsf: Cleaning up the symlink related code and making it work on 2.4.x too. Untested. bugref:9172

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/VBoxGuestLibSharedFoldersInline.h

    r77854 r77858  
    4242#include <VBox/VMMDev.h>
    4343#include <VBox/shflsvc.h>
    44 #include <iprt/errcore.h>
     44#include <iprt/err.h>
    4545
    4646
     
    734734                                                    - sizeof(VBGLIOCIDCHGCMFASTCALL);
    735735        pReq->PgLst.flags                           = VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
    736         pReq->PgLst.offFirstPage                    = ((uint16_t)PhysSrcStr) & (uint16_t)(PAGE_OFFSET_MASK);
     736        pReq->PgLst.offFirstPage                    = (uint16_t)PhysSrcStr & (uint16_t)(PAGE_OFFSET_MASK);
    737737        pReq->PgLst.aPages[0]                       = PhysSrcStr & ~(RTGCPHYS64)PAGE_OFFSET_MASK;
    738738        pReq->PgLst.cPages                          = 1;
     
    13181318}
    13191319
     1320
     1321/** Request structure for VbglR0SfHostReqReadLink.  */
     1322typedef struct VBOXSFREADLINKREQ
     1323{
     1324    VBGLIOCIDCHGCMFASTCALL  Hdr;
     1325    VMMDevHGCMCall          Call;
     1326    VBoxSFParmReadLink      Parms;
     1327    HGCMPageListInfo        PgLst;
     1328    SHFLSTRING              StrPath;
     1329} VBOXSFREADLINKREQ;
     1330
     1331/**
     1332 * SHFL_FN_READLINK request.
     1333 *
     1334 * @note Buffer contains UTF-8 characters on success, regardless of the
     1335 *       UTF-8/UTF-16 setting of the connection.
     1336 */
     1337DECLINLINE(int) VbglR0SfHostReqReadLinkContig(SHFLROOT idRoot, void *pvBuffer, RTGCPHYS64 PhysBuffer, uint32_t cbBuffer,
     1338                                              VBOXSFREADLINKREQ *pReq)
     1339{
     1340    uint32_t const cbReq = g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS
     1341                         ? RT_UOFFSETOF(VBOXSFREADLINKREQ, StrPath.String) + pReq->StrPath.u16Size
     1342                         :    cbBuffer <= PAGE_SIZE - (PhysBuffer & PAGE_OFFSET_MASK)
     1343                           || (g_fHostFeatures & VMMDEV_HVF_HGCM_CONTIGUOUS_PAGE_LIST)
     1344                         ? RT_UOFFSETOF(VBOXSFREADLINKREQ, StrPath.String)
     1345                         : RT_UOFFSETOF(VBOXSFREADLINKREQ, PgLst);
     1346    VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
     1347                                SHFL_FN_READLINK, SHFL_CPARMS_READLINK, cbReq);
     1348
     1349    pReq->Parms.id32Root.type                   = VMMDevHGCMParmType_32bit;
     1350    pReq->Parms.id32Root.u.value32              = idRoot;
     1351
     1352    if (g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS)
     1353    {
     1354        pReq->Parms.pStrPath.type               = VMMDevHGCMParmType_Embedded;
     1355        pReq->Parms.pStrPath.u.Embedded.cbData  = SHFLSTRING_HEADER_SIZE + pReq->StrPath.u16Size;
     1356        pReq->Parms.pStrPath.u.Embedded.offData = RT_UOFFSETOF(VBOXSFREADLINKREQ, StrPath)
     1357                                                - sizeof(VBGLIOCIDCHGCMFASTCALL);
     1358        pReq->Parms.pStrPath.u.Embedded.fFlags  = VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
     1359    }
     1360    else
     1361    {
     1362        pReq->Parms.pStrPath.type               = VMMDevHGCMParmType_LinAddr_In;
     1363        pReq->Parms.pStrPath.u.LinAddr.cb       = SHFLSTRING_HEADER_SIZE + pReq->StrPath.u16Size;
     1364        pReq->Parms.pStrPath.u.LinAddr.uAddr    = (uintptr_t)&pReq->StrPath;
     1365    }
     1366
     1367    if (   cbBuffer <= PAGE_SIZE - (PhysBuffer & PAGE_OFFSET_MASK)
     1368        || (g_fHostFeatures & VMMDEV_HVF_HGCM_CONTIGUOUS_PAGE_LIST))
     1369    {
     1370        pReq->Parms.pBuffer.type                = cbBuffer <= PAGE_SIZE - (PhysBuffer & PAGE_OFFSET_MASK)
     1371                                                ? VMMDevHGCMParmType_PageList
     1372                                                : VMMDevHGCMParmType_ContiguousPageList;
     1373        pReq->Parms.pBuffer.u.PageList.size     = cbBuffer;
     1374        pReq->Parms.pBuffer.u.PageList.offset   = RT_UOFFSETOF(VBOXSFREADLINKREQ, PgLst)
     1375                                                - sizeof(VBGLIOCIDCHGCMFASTCALL);
     1376        pReq->PgLst.flags                       = VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
     1377        pReq->PgLst.offFirstPage                = (uint16_t)PhysBuffer & (uint16_t)(PAGE_OFFSET_MASK);
     1378        pReq->PgLst.aPages[0]                   = PhysBuffer & ~(RTGCPHYS64)PAGE_OFFSET_MASK;
     1379        pReq->PgLst.cPages                      = 1;
     1380    }
     1381    else
     1382    {
     1383        pReq->Parms.pBuffer.type                = VMMDevHGCMParmType_LinAddr_Out;
     1384        pReq->Parms.pBuffer.u.LinAddr.cb        = cbBuffer;
     1385        pReq->Parms.pBuffer.u.LinAddr.uAddr     = (uintptr_t)pvBuffer;
     1386    }
     1387
     1388    int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, cbReq);
     1389    if (RT_SUCCESS(vrc))
     1390        vrc = pReq->Call.header.result;
     1391    return vrc;
     1392}
     1393
     1394/**
     1395 * SHFL_FN_READLINK request, simplified version.
     1396 *
     1397 *
     1398 * @note Buffer contains UTF-8 characters on success, regardless of the
     1399 *       UTF-8/UTF-16 setting of the connection.
     1400 */
     1401DECLINLINE(int) VbglR0SfHostReqReadLinkContigSimple(SHFLROOT idRoot, const char *pszPath, size_t cchPath, void *pvBuf,
     1402                                                    RTGCPHYS64 PhysBuffer, uint32_t cbBuffer)
     1403{
     1404    if (cchPath < _64K - 1)
     1405    {
     1406        VBOXSFREADLINKREQ *pReq = (VBOXSFREADLINKREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF(VBOXSFREADLINKREQ, StrPath.String)
     1407                                                                           + SHFLSTRING_HEADER_SIZE + cchPath);
     1408        if (pReq)
     1409        {
     1410            pReq->StrPath.u16Length = (uint16_t)cchPath;
     1411            pReq->StrPath.u16Size   = (uint16_t)cchPath + 1;
     1412            memcpy(pReq->StrPath.String.ach, pszPath, cchPath);
     1413            pReq->StrPath.String.ach[cchPath] = '\0';
     1414
     1415            {
     1416                int vrc = VbglR0SfHostReqReadLinkContig(idRoot, pvBuf, PhysBuffer, cbBuffer, pReq);
     1417                VbglR0PhysHeapFree(pReq);
     1418                return vrc;
     1419            }
     1420        }
     1421        return VERR_NO_MEMORY;
     1422    }
     1423    return VERR_FILENAME_TOO_LONG;
     1424}
     1425
     1426
     1427/** Request structure for VbglR0SfHostReqCreateSymlink.  */
     1428typedef struct VBOXSFCREATESYMLINKREQ
     1429{
     1430    VBGLIOCIDCHGCMFASTCALL  Hdr;
     1431    VMMDevHGCMCall          Call;
     1432    VBoxSFParmCreateSymlink Parms;
     1433    HGCMPageListInfo        PgLstTarget;
     1434    SHFLFSOBJINFO           ObjInfo;
     1435    SHFLSTRING              StrSymlinkPath;
     1436} VBOXSFCREATESYMLINKREQ;
     1437
     1438/**
     1439 * SHFL_FN_SYMLINK request.
     1440 *
     1441 * Caller fills in the symlink string and supplies a physical contiguous
     1442 * target string
     1443 */
     1444DECLINLINE(int) VbglR0SfHostReqCreateSymlinkContig(SHFLROOT idRoot, PCSHFLSTRING pStrTarget, RTGCPHYS64 PhysTarget,
     1445                                                   VBOXSFCREATESYMLINKREQ *pReq)
     1446{
     1447    uint32_t const cbTarget = SHFLSTRING_HEADER_SIZE + pStrTarget->u16Size;
     1448    uint32_t const cbReq    = g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS
     1449                            ? RT_UOFFSETOF(VBOXSFCREATESYMLINKREQ, StrSymlinkPath.String) + pReq->StrSymlinkPath.u16Size
     1450                            : RT_UOFFSETOF(VBOXSFCREATESYMLINKREQ, ObjInfo) /*simplified*/;
     1451    VBGLIOCIDCHGCMFASTCALL_INIT(&pReq->Hdr, VbglR0PhysHeapGetPhysAddr(pReq), &pReq->Call, g_SfClient.idClient,
     1452                                SHFL_FN_SYMLINK, SHFL_CPARMS_SYMLINK, cbReq);
     1453
     1454    pReq->Parms.id32Root.type                          = VMMDevHGCMParmType_32bit;
     1455    pReq->Parms.id32Root.u.value32                     = idRoot;
     1456
     1457    if (g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS)
     1458    {
     1459        pReq->Parms.pStrSymlink.type               = VMMDevHGCMParmType_Embedded;
     1460        pReq->Parms.pStrSymlink.u.Embedded.cbData  = SHFLSTRING_HEADER_SIZE + pReq->StrSymlinkPath.u16Size;
     1461        pReq->Parms.pStrSymlink.u.Embedded.offData = RT_UOFFSETOF(VBOXSFCREATESYMLINKREQ, StrSymlinkPath)
     1462                                                   - sizeof(VBGLIOCIDCHGCMFASTCALL);
     1463        pReq->Parms.pStrSymlink.u.Embedded.fFlags  = VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
     1464    }
     1465    else
     1466    {
     1467        pReq->Parms.pStrSymlink.type               = VMMDevHGCMParmType_LinAddr_In;
     1468        pReq->Parms.pStrSymlink.u.LinAddr.cb       = SHFLSTRING_HEADER_SIZE + pReq->StrSymlinkPath.u16Size;
     1469        pReq->Parms.pStrSymlink.u.LinAddr.uAddr    = (uintptr_t)&pReq->StrSymlinkPath;
     1470    }
     1471
     1472    if (   cbTarget <= PAGE_SIZE - (PhysTarget & PAGE_OFFSET_MASK)
     1473        || (g_fHostFeatures & VMMDEV_HVF_HGCM_CONTIGUOUS_PAGE_LIST))
     1474    {
     1475        pReq->Parms.pStrTarget.type                = cbTarget <= PAGE_SIZE - (PhysTarget & PAGE_OFFSET_MASK)
     1476                                                   ? VMMDevHGCMParmType_PageList
     1477                                                   : VMMDevHGCMParmType_ContiguousPageList;
     1478        pReq->Parms.pStrTarget.u.PageList.size     = cbTarget;
     1479        pReq->Parms.pStrTarget.u.PageList.offset   = RT_UOFFSETOF(VBOXSFCREATESYMLINKREQ, PgLstTarget)
     1480                                                   - sizeof(VBGLIOCIDCHGCMFASTCALL);
     1481        pReq->PgLstTarget.flags                    = VBOX_HGCM_F_PARM_DIRECTION_TO_HOST;
     1482        pReq->PgLstTarget.offFirstPage             = (uint16_t)PhysTarget & (uint16_t)(PAGE_OFFSET_MASK);
     1483        pReq->PgLstTarget.aPages[0]                = PhysTarget & ~(RTGCPHYS64)PAGE_OFFSET_MASK;
     1484        pReq->PgLstTarget.cPages                   = 1;
     1485    }
     1486    else
     1487    {
     1488        pReq->Parms.pStrTarget.type                = VMMDevHGCMParmType_LinAddr_In;
     1489        pReq->Parms.pStrTarget.u.LinAddr.cb        = cbTarget;
     1490        pReq->Parms.pStrTarget.u.LinAddr.uAddr     = (uintptr_t)pStrTarget;
     1491    }
     1492
     1493    if (g_fHostFeatures & VMMDEV_HVF_HGCM_EMBEDDED_BUFFERS)
     1494    {
     1495        pReq->Parms.pInfo.type                     = VMMDevHGCMParmType_Embedded;
     1496        pReq->Parms.pInfo.u.Embedded.cbData        = sizeof(pReq->ObjInfo);
     1497        pReq->Parms.pInfo.u.Embedded.offData       = RT_UOFFSETOF(VBOXSFCREATESYMLINKREQ, ObjInfo)
     1498                                                   - sizeof(VBGLIOCIDCHGCMFASTCALL);
     1499        pReq->Parms.pInfo.u.Embedded.fFlags        = VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST;
     1500    }
     1501    else
     1502    {
     1503        pReq->Parms.pInfo.type                     = VMMDevHGCMParmType_LinAddr_Out;
     1504        pReq->Parms.pInfo.u.LinAddr.cb             = sizeof(pReq->ObjInfo);
     1505        pReq->Parms.pInfo.u.LinAddr.uAddr          = (uintptr_t)&pReq->ObjInfo;
     1506    }
     1507
     1508    int vrc = VbglR0HGCMFastCall(g_SfClient.handle, &pReq->Hdr, cbReq);
     1509    if (RT_SUCCESS(vrc))
     1510        vrc = pReq->Call.header.result;
     1511    return vrc;
     1512}
     1513
    13201514/** @} */
    13211515
  • trunk/include/VBox/shflsvc.h

    r77854 r77858  
    119119/** Read symlink destination.
    120120 * @since VBox 4.0  */
    121 #define SHFL_FN_READLINK            (18)
     121#define SHFL_FN_READLINK            (18) /**< @todo rename to SHFL_FN_READ_LINK (see struct capitalization) */
    122122/** Create symlink.
    123123 * @since VBox 4.0  */
     
    16131613 */
    16141614
     1615/** SHFL_FN_READLINK parameters. */
     1616typedef struct VBoxSFParmReadLink
     1617{
     1618    /** value32, in: SHFLROOT of the mapping which the symlink is read. */
     1619    HGCMFunctionParameter id32Root;
     1620    /** pointer, in: SHFLSTRING full path to the symlink. */
     1621    HGCMFunctionParameter pStrPath;
     1622    /** pointer, out: Buffer to place the symlink target into.
     1623     * @note Buffer contains UTF-8 characters on success, regardless of the
     1624     *       UTF-8/UTF-16 setting of the connection.  Will be zero terminated.
     1625     *
     1626     * @todo r=bird: This should've been a string!
     1627     * @todo r=bird: There should've been a byte count returned! */
     1628    HGCMFunctionParameter pBuffer;
     1629} VBoxSFParmReadLink;
     1630
    16151631/** Parameters structure. */
    16161632typedef struct _VBoxSFReadLink
     
    16301646    /** pointer, out:
    16311647     * Buffer to place data to.
     1648     * @note Buffer contains UTF-8 characters on success, regardless of the
     1649     *       UTF-8/UTF-16 setting of the connection.  Will be zero terminated.
    16321650     */
    16331651    HGCMFunctionParameter buffer;
     
    18171835 * @{
    18181836 */
     1837
     1838/** Parameters structure. */
     1839typedef struct VBoxSFParmCreateSymlink
     1840{
     1841    /** value32, in: SHFLROOT of the mapping the symlink should be created on. */
     1842    HGCMFunctionParameter id32Root;
     1843    /** pointer, in: SHFLSTRING giving the path to the symlink. */
     1844    HGCMFunctionParameter pStrSymlink;
     1845    /** pointer, in: SHFLSTRING giving the target. */
     1846    HGCMFunctionParameter pStrTarget;
     1847    /** pointer, out: SHFLFSOBJINFO buffer to be filled with info about the created symlink. */
     1848    HGCMFunctionParameter pInfo;
     1849} VBoxSFParmCreateSymlink;
    18191850
    18201851/** Parameters structure. */
  • trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR0LibSharedFolders.c

    r77854 r77858  
    610610}
    611611
    612 
    613612DECLVBGL(int) VbglR0SfLock(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, SHFLHANDLE hFile,
    614613                           uint64_t offset, uint64_t cbSize, uint32_t fLock)
     
    637636}
    638637
    639 #endif /* !RT_OS_LINUX */
    640 
    641638DECLVBGL(int) VbglR0SfReadLink(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, PSHFLSTRING pParsedPath, uint32_t cbBuffer, uint8_t *pBuffer)
    642639{
     
    662659}
    663660
     661#endif /* !RT_OS_LINUX */
     662
    664663DECLVBGL(int) VbglR0SfSymlink(PVBGLSFCLIENT pClient, PVBGLSFMAP pMap, PSHFLSTRING pNewPath, PSHFLSTRING pOldPath,
    665664                              PSHFLFSOBJINFO pBuffer)
  • trunk/src/VBox/Additions/linux/sharedfolders/dirops.c

    r77741 r77858  
    274274}
    275275
     276
    276277/**
    277278 * Helper function for when we need to convert the name, avoids wasting stack in
     
    548549}
    549550
     551
    550552/**
    551553 * Directory file operations.
    552554 */
    553555struct file_operations vbsf_dir_fops = {
    554     .open = vbsf_dir_open,
     556    .open           = vbsf_dir_open,
    555557#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0)
    556558    .iterate_shared = vbsf_dir_iterate,
    557559#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
    558     .iterate = vbsf_dir_iterate,
     560    .iterate        = vbsf_dir_iterate,
    559561#else
    560     .readdir = vbsf_dir_read,
    561 #endif
    562     .release = vbsf_dir_release,
    563     .read = generic_read_dir
     562    .readdir        = vbsf_dir_read,
     563#endif
     564    .release        = vbsf_dir_release,
     565    .read           = generic_read_dir,
    564566#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
    565     , .llseek = generic_file_llseek
     567    .llseek      = generic_file_llseek
    566568#endif
    567569};
     
    676678     * Build the path.  We'll associate the path with dret's inode on success.
    677679     */
    678     rc = vbsf_path_from_dentry(__func__, sf_g, sf_i, dentry, &path);
     680    rc = vbsf_path_from_dentry(sf_g, sf_i, dentry, &path, __func__);
    679681    if (rc == 0) {
    680682        /*
     
    800802     * Build a path.  We'll donate this to the inode on success.
    801803     */
    802     rc = vbsf_path_from_dentry(__func__, sf_g, sf_parent_i, dentry, &path);
     804    rc = vbsf_path_from_dentry(sf_g, sf_parent_i, dentry, &path, __func__);
    803805    if (rc == 0) {
    804806        /*
     
    10591061}
    10601062
     1063
    10611064/**
    10621065 * Create a new directory.
     
    10831086}
    10841087
     1088
    10851089/**
    10861090 * Remove a regular file / directory.
     
    11011105    BUG_ON(!sf_g);
    11021106
    1103     err = vbsf_path_from_dentry(__func__, sf_g, sf_parent_i, dentry, &path);
     1107    err = vbsf_path_from_dentry(sf_g, sf_parent_i, dentry, &path, __func__);
    11041108    if (!err) {
    11051109        VBOXSFREMOVEREQ *pReq = (VBOXSFREMOVEREQ *)VbglR0PhysHeapAlloc(RT_UOFFSETOF(VBOXSFREMOVEREQ, StrPath.String)
     
    11371141}
    11381142
     1143
    11391144/**
    11401145 * Remove a regular file.
     
    11501155}
    11511156
     1157
    11521158/**
    11531159 * Remove a directory.
     
    11621168    return vbsf_unlink_worker(parent, dentry, true /*fDirectory*/);
    11631169}
     1170
    11641171
    11651172/**
     
    11941201    if (sf_g != VBSF_GET_SUPER_INFO(new_parent->i_sb)) {
    11951202        LogFunc(("rename with different roots\n"));
    1196         err = -EINVAL;
     1203        err = -EXDEV;
    11971204    } else {
    11981205        struct vbsf_inode_info *sf_old_i = VBSF_GET_INODE_INFO(old_parent);
     
    12091216
    12101217        old_path = sf_file_i->path;
    1211         err = vbsf_path_from_dentry(__func__, sf_g, sf_new_i, new_dentry, &new_path);
     1218        err = vbsf_path_from_dentry(sf_g, sf_new_i, new_dentry, &new_path, __func__);
    12121219        if (err)
    12131220            LogFunc(("failed to create new path\n"));
     
    12431250}
    12441251
    1245 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
    1246 static int vbsf_ino_symlink(struct inode *parent, struct dentry *dentry, const char *symname)
    1247 {
    1248     int err;
    1249     int rc;
    1250     struct vbsf_inode_info *sf_i;
    1251     struct vbsf_super_info *sf_g;
    1252     SHFLSTRING *path, *ssymname;
    1253     SHFLFSOBJINFO info;
    1254     int symname_len = strlen(symname) + 1;
    1255 
    1256     TRACE();
    1257     sf_g = VBSF_GET_SUPER_INFO(parent->i_sb);
    1258     sf_i = VBSF_GET_INODE_INFO(parent);
    1259 
    1260     BUG_ON(!sf_g);
    1261     BUG_ON(!sf_i);
    1262 
    1263     err = vbsf_path_from_dentry(__func__, sf_g, sf_i, dentry, &path);
    1264     if (err)
    1265         goto fail0;
    1266 
    1267     ssymname = kmalloc(offsetof(SHFLSTRING, String.utf8) + symname_len, GFP_KERNEL);
    1268     if (!ssymname) {
    1269         LogRelFunc(("kmalloc failed, caller=sf_symlink\n"));
    1270         err = -ENOMEM;
    1271         goto fail1;
    1272     }
    1273 
    1274     ssymname->u16Length = symname_len - 1;
    1275     ssymname->u16Size = symname_len;
    1276     memcpy(ssymname->String.utf8, symname, symname_len);
    1277 
    1278     rc = VbglR0SfSymlink(&g_SfClient, &sf_g->map, path, ssymname, &info);
    1279     kfree(ssymname);
    1280 
    1281     if (RT_FAILURE(rc)) {
    1282         err = RTErrConvertFromErrno(rc);
    1283         LogFunc(("VbglR0SfSymlink(%s) failed rc=%Rrc\n", sf_i->path->String.utf8, rc));
    1284         goto fail1;
    1285     }
    1286 
    1287     err = vbsf_inode_instantiate(parent, dentry, path, &info, SHFL_HANDLE_NIL);
    1288     if (err) {
    1289         LogFunc(("could not instantiate dentry for %s err=%d\n", sf_i->path->String.utf8, err));
    1290         goto fail1;
    1291     }
    1292 
    1293     sf_i->force_restat = 1;
    1294     return 0;
    1295 
    1296  fail1:
    1297     kfree(path);
    1298  fail0:
    1299     return err;
    1300 }
    1301 #endif /* LINUX_VERSION_CODE >= 2.6.0 */
    1302 
     1252
     1253/**
     1254 * Create a symbolic link.
     1255 */
     1256static int vbsf_inode_symlink(struct inode *parent, struct dentry *dentry, const char *target)
     1257{
     1258    /*
     1259     * Turn the target into a string (contiguous physcial memory).
     1260     */
     1261    /** @todo we can save a kmalloc here if we switch to embedding the target rather
     1262     * than the symlink path into the request.  Will require more NLS helpers. */
     1263    struct vbsf_super_info *sf_g    = VBSF_GET_SUPER_INFO(parent->i_sb);
     1264    PSHFLSTRING             pTarget = NULL;
     1265    int rc = vbsf_nls_to_shflstring(sf_g, target, &pTarget);
     1266    if (rc == 0) {
     1267        /*
     1268         * Create a full path for the symlink name.
     1269         */
     1270        struct vbsf_inode_info *sf_i  = VBSF_GET_INODE_INFO(parent);
     1271        PSHFLSTRING             pPath = NULL;
     1272        rc = vbsf_path_from_dentry(sf_g, sf_i, dentry, &pPath, __func__);
     1273        if (rc == 0) {
     1274            /*
     1275             * Create the request and issue it.
     1276             */
     1277            uint32_t const          cbReq = RT_UOFFSETOF(VBOXSFCREATESYMLINKREQ, StrSymlinkPath.String) + pPath->u16Size;
     1278            VBOXSFCREATESYMLINKREQ *pReq  = (VBOXSFCREATESYMLINKREQ *)VbglR0PhysHeapAlloc(cbReq);
     1279            if (pReq) {
     1280                RT_ZERO(*pReq);
     1281                memcpy(&pReq->StrSymlinkPath, pPath, SHFLSTRING_HEADER_SIZE + pPath->u16Size);
     1282
     1283                rc = VbglR0SfHostReqCreateSymlinkContig(sf_g->map.root, pTarget, virt_to_phys(pTarget), pReq);
     1284                if (RT_SUCCESS(rc)) {
     1285                    sf_i->force_restat = 1;
     1286
     1287                    /*
     1288                     * Instantiate a new inode for the symlink.
     1289                     */
     1290                    rc = vbsf_inode_instantiate(parent, dentry, pPath, &pReq->ObjInfo, SHFL_HANDLE_NIL);
     1291                    if (rc == 0) {
     1292                        SFLOGFLOW(("vbsf_inode_symlink: Successfully created '%s' -> '%s'\n", pPath->String.ach, pTarget->String.ach));
     1293                        pPath = NULL; /* consumed by inode */
     1294                    } else {
     1295                        SFLOGFLOW(("vbsf_inode_symlink: Failed to create inode for '%s': %d\n", pPath->String.ach, rc));
     1296                    }
     1297                } else {
     1298                    int const vrc = rc;
     1299                    rc = -RTErrConvertToErrno(rc);
     1300                    SFLOGFLOW(("vbsf_inode_symlink: VbglR0SfHostReqCreateSymlinkContig failed for '%s' -> '%s': %Rrc (-> %d)\n",
     1301                               pPath->String.ach, pTarget->String.ach, vrc, rc));
     1302                }
     1303                VbglR0PhysHeapFree(pReq);
     1304            } else {
     1305                SFLOGFLOW(("vbsf_inode_symlink: failed to allocate %u phys heap for the request!\n", cbReq));
     1306                rc = -ENOMEM;
     1307            }
     1308            if (pPath)
     1309                kfree(pPath);
     1310        }
     1311        kfree(pTarget);
     1312    }
     1313    return rc;
     1314}
     1315
     1316
     1317/**
     1318 * Directory inode operations.
     1319 */
    13031320struct inode_operations vbsf_dir_iops = {
    1304     .lookup = vbsf_inode_lookup,
     1321    .lookup         = vbsf_inode_lookup,
    13051322#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
    1306     .atomic_open = vbsf_inode_atomic_open,
    1307 #endif
    1308     .create = vbsf_inode_create,
    1309     .mkdir = vbsf_inode_mkdir,
    1310     .rmdir = vbsf_inode_rmdir,
    1311     .unlink = vbsf_inode_unlink,
    1312     .rename = vbsf_inode_rename,
     1323    .atomic_open    = vbsf_inode_atomic_open,
     1324#endif
     1325    .create         = vbsf_inode_create,
     1326    .symlink        = vbsf_inode_symlink,
     1327    .mkdir          = vbsf_inode_mkdir,
     1328    .rmdir          = vbsf_inode_rmdir,
     1329    .unlink         = vbsf_inode_unlink,
     1330    .rename         = vbsf_inode_rename,
    13131331#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 18)
    1314     .getattr = vbsf_inode_getattr,
     1332    .getattr        = vbsf_inode_getattr,
    13151333#else
    1316     .revalidate = vbsf_inode_revalidate,
    1317 #endif
    1318     .setattr = vbsf_inode_setattr,
    1319 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
    1320     .symlink = vbsf_ino_symlink,
    1321 #endif
     1334    .revalidate     = vbsf_inode_revalidate,
     1335#endif
     1336    .setattr        = vbsf_inode_setattr,
    13221337};
    13231338
  • trunk/src/VBox/Additions/linux/sharedfolders/lnkops.c

    r77530 r77858  
    2929 */
    3030
     31
     32/*********************************************************************************************************************************
     33*   Header Files                                                                                                                 *
     34*********************************************************************************************************************************/
    3135#include "vfsmod.h"
    3236
    33 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8) /* no generic_readlink() before 2.6.8 */
    34 
    35 # if LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)
    36 
    37 #  if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
     37
     38/**
     39 * Converts error codes as best we can.
     40 */
     41DECLINLINE(int) vbsf_convert_symlink_error(int vrc)
     42{
     43    if (   vrc == VERR_IS_A_DIRECTORY
     44        || vrc == VERR_IS_A_FIFO
     45        || vrc == VERR_IS_A_FILE
     46        || vrc == VERR_IS_A_BLOCK_DEVICE
     47        || vrc == VERR_IS_A_CHAR_DEVICE
     48        || vrc == VERR_IS_A_SOCKET
     49        || vrc == VERR_NOT_SYMLINK)
     50        return -EINVAL;
     51    if (vrc == VERR_PATH_NOT_FOUND)
     52        return -ENOTDIR;
     53    if (vrc == VERR_FILE_NOT_FOUND)
     54        return -ENOENT;
     55    return -EPROTO;
     56}
     57
     58
     59/**
     60 * Does the NLS conversion of the symlink target.
     61 */
     62static int vbsf_symlink_nls_convert_slow(struct vbsf_super_info *pSuperInfo, char *pszTarget, size_t cbTargetBuf)
     63{
     64    int          rc;
     65    size_t const cchUtf8 = RTStrNLen(pszTarget, cbTargetBuf);
     66    if (cchUtf8 < cbTargetBuf) {
     67        /*
     68         * If the target is short and there is a lot of space left in the target
     69         * buffer (typically PAGE_SIZE in size), we move the  input to the end
     70         * instead of allocating a temporary buffer for it.  This works because
     71         * there shouldn't be anything that is more than 8x worse than UTF-8
     72         * when it comes to efficiency.
     73         */
     74        char  *pszFree = NULL;
     75        char  *pszUtf8;
     76        if (cchUtf8 - 1 <= cbTargetBuf / 8) {
     77            pszUtf8 = &pszTarget[cbTargetBuf - cchUtf8 - 1];
     78            cbTargetBuf -= cchUtf8 - 1;
     79        } else {
     80            pszFree = pszUtf8 = kmalloc(cchUtf8 + 1, GFP_KERNEL);
     81            if (RT_UNLIKELY(!pszUtf8)) {
     82                LogRelMax(50, ("vbsf_symlink_nls_convert_slow: failed to allocate %u bytes\n", cchUtf8 + 1));
     83                return -ENOMEM;
     84            }
     85        }
     86        memcpy(pszUtf8, pszTarget, cchUtf8);
     87        pszUtf8[cchUtf8] = '\0';
     88
     89        rc = vbsf_nlscpy(pSuperInfo, pszTarget, cbTargetBuf, pszUtf8, cchUtf8);
     90        if (pszFree)
     91            kfree(pszFree);
     92    } else {
     93        SFLOGFLOW(("vbsf_symlink_nls_convert_slow: Impossible! Unterminated target!\n"));
     94        rc = -ENAMETOOLONG;
     95    }
     96    return rc;
     97}
     98
     99
     100/**
     101 * Does NLS conversion if needed.
     102 */
     103DECLINLINE(int) vbsf_symlink_nls_convert(struct vbsf_super_info *pSuperInfo, char *pszTarget, size_t cbTargetBuf)
     104{
     105    if (pSuperInfo->fNlsIsUtf8)
     106        return 0;
     107    return vbsf_symlink_nls_convert_slow(pSuperInfo, pszTarget, cbTargetBuf);
     108}
     109
     110#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
     111
     112/**
     113 * Get symbolic link.
     114 */
     115static const char *vbsf_get_link(struct dentry *dentry, struct inode *inode, struct delayed_call *done)
     116{
     117    char *pszTarget;
     118    if (dentry) {
     119        pszTarget = (char *)kzalloc(PAGE_SIZE, GFP_KERNEL);
     120        if (pszTarget) {
     121            struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
     122            struct vbsf_inode_info *sf_i = VBSF_GET_INODE_INFO(inode);
     123            int rc = VbglR0SfHostReqReadLinkContigSimple(sf_g->map.root, sf_i->path->String.ach, sf_i->path->u16Length,
     124                                                         pszTarget, virt_to_phys(pszTarget), RT_MIN(PATH_MAX, PAGE_SIZE - 1));
     125            if (RT_SUCCESS(rc)) {
     126                pszTarget[PAGE_SIZE - 1] = '\0';
     127                SFLOGFLOW(("vbsf_get_link: %s -> %s\n", sf_i->path->String.ach, pszTarget));
     128                rc = vbsf_symlink_nls_convert(sf_g, pszTarget, PAGE_SIZE);
     129                if (rc == 0) {
     130                    set_delayed_call(done, kfree_link, pszTarget);
     131                    return pszTarget;
     132                }
     133            } else {
     134                SFLOGFLOW(("vbsf_get_link: VbglR0SfHostReqReadLinkContigSimple failed on '%s': %Rrc\n",
     135                           sf_i->path->String.ach, rc));
     136            }
     137            kfree(pszTarget);
     138            pszTarget = ERR_PTR(vbsf_convert_symlink_error(rc));
     139        } else
     140            pszTarget = ERR_PTR(-ENOMEM);
     141    } else
     142        pszTarget = ERR_PTR(-ECHILD);
     143    return pszTarget;
     144}
     145
     146#else /* < 4.5 */
     147
     148# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 8)
     149/**
     150 * Reads the link into the given buffer.
     151 */
     152static int vbsf_readlink(struct dentry *dentry, char *buffer, int len)
     153{
     154    int   rc;
     155    char *pszTarget = (char *)get_zeroed_page(GFP_KERNEL);
     156    if (pszTarget) {
     157        struct inode           *inode = dentry->d_inode;
     158        struct vbsf_super_info *sf_g  = VBSF_GET_SUPER_INFO(inode->i_sb);
     159        struct vbsf_inode_info *sf_i  = VBSF_GET_INODE_INFO(inode);
     160        rc = VbglR0SfHostReqReadLinkContigSimple(sf_g->map.root, sf_i->path->String.ach, sf_i->path->u16Length,
     161                                                 pszTarget, virt_to_phys(pszTarget), RT_MIN(PATH_MAX, PAGE_SIZE - 1));
     162        if (RT_SUCCESS(rc)) {
     163            pszTarget[PAGE_SIZE - 1] = '\0';
     164            SFLOGFLOW(("vbsf_readlink: %s -> %*s\n", sf_i->path->String.ach, pszTarget));
     165            rc = vbsf_symlink_nls_convert(sf_g, pszTarget, PAGE_SIZE);
     166            if (rc == 0)
     167                rc = vfs_readlink(dentry, buffer, len, pszTarget);
     168        } else {
     169            SFLOGFLOW(("vbsf_readlink: VbglR0SfHostReqReadLinkContigSimple failed on '%s': %Rrc\n", sf_i->path->String.ach, rc));
     170            rc = vbsf_convert_symlink_error(rc);
     171        }
     172        free_page((unsigned long)pszTarget);
     173    } else
     174        rc = -ENOMEM;
     175    return rc;
     176}
     177# endif /* < 2.6.8 */
     178
     179/**
     180 * Follow link in dentry.
     181 */
     182# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
    38183static const char *vbsf_follow_link(struct dentry *dentry, void **cookie)
    39 #  elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
     184# elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
    40185static void       *vbsf_follow_link(struct dentry *dentry, struct nameidata *nd)
     186# else
     187static int         vbsf_follow_link(struct dentry *dentry, struct nameidata *nd)
     188# endif
     189{
     190    int rc;
     191    char *pszTarget = (char *)get_zeroed_page(GFP_KERNEL);
     192    if (pszTarget) {
     193        struct inode           *inode = dentry->d_inode;
     194        struct vbsf_super_info *sf_g  = VBSF_GET_SUPER_INFO(inode->i_sb);
     195        struct vbsf_inode_info *sf_i  = VBSF_GET_INODE_INFO(inode);
     196
     197        rc = VbglR0SfHostReqReadLinkContigSimple(sf_g->map.root, sf_i->path->String.ach, sf_i->path->u16Length,
     198                                                 pszTarget, virt_to_phys(pszTarget), RT_MIN(PATH_MAX, PAGE_SIZE - 1));
     199        if (RT_SUCCESS(rc)) {
     200            pszTarget[PAGE_SIZE - 1] = '\0';
     201            SFLOGFLOW(("vbsf_follow_link: %s -> %s\n", sf_i->path->String.ach, pszTarget));
     202            rc = vbsf_symlink_nls_convert(sf_g, pszTarget, PAGE_SIZE);
     203            if (rc == 0) {
     204                /*
     205                 * Succeeded.  For 2.6.8 and later the page gets associated
     206                 * with the caller-cookie or nameidata structure and freed
     207                 * later by vbsf_put_link().  On earlier kernels we have to
     208                 * call vfs_follow_link() which will try continue the walking
     209                 * using the buffer we pass it here.
     210                 */
     211# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
     212                *cookie = pszTarget;
     213                return pszTarget;
     214# elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
     215                nd_set_link(nd, pszTarget);
     216#  if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
     217                return NULL;
    41218#  else
    42 static int         vbsf_follow_link(struct dentry *dentry, struct nameidata *nd)
     219                return 0;
    43220#  endif
    44 {
    45     struct inode *inode = dentry->d_inode;
    46     struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
    47     struct vbsf_inode_info *sf_i = VBSF_GET_INODE_INFO(inode);
    48     int error = -ENOMEM;
    49     char *path = (char *)get_zeroed_page(GFP_KERNEL);
    50     int rc;
    51 
    52     if (path) {
    53         error = 0;
    54         rc = VbglR0SfReadLink(&g_SfClient, &sf_g->map, sf_i->path, PATH_MAX, path);
    55         if (RT_FAILURE(rc)) {
     221# else /* < 2.6.8 */
     222                rc = vfs_follow_link(nd, pszTarget);
     223                free_page((unsigned long)pszTarget);
     224                return rc;
     225# endif
     226            }
     227
     228            /*
     229             * Failed.
     230             */
     231        } else {
    56232            LogFunc(("VbglR0SfReadLink failed, caller=%s, rc=%Rrc\n", __func__, rc));
    57             free_page((unsigned long)path);
    58             error = -EPROTO;
     233            rc = vbsf_convert_symlink_error(rc);
    59234        }
     235        free_page((unsigned long)pszTarget);
     236    } else {
     237        rc = -ENOMEM;
    60238    }
    61 #  if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
    62     return error ? ERR_PTR(error) : (*cookie = path);
     239# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
     240    *cookie = ERR_PTR(rc);
     241    return (const char *)ERR_PTR(rc);
     242# elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
     243    nd_set_link(nd, (char *)ERR_PTR(rc));
     244#  if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
     245    return NULL;
    63246#  else
    64     nd_set_link(nd, error ? ERR_PTR(error) : path);
    65 #   if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
    66     return NULL;
    67 #   else
    68247    return 0;
    69 #   endif
    70248#  endif
    71 }
    72 
    73 #  if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0)
    74 #   if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
     249# else  /* < 2.6.8 */
     250    return rc;
     251# endif /* < 2.6.8 */
     252}
     253
     254# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
     255/**
     256 * For freeing target link buffer allocated by vbsf_follow_link.
     257 *
     258 * For kernel before 2.6.8 memory isn't being kept around.
     259 */
     260#  if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
    75261static void vbsf_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
    76  else
     262else
    77263static void vbsf_put_link(struct dentry *dentry, struct nameidata *nd)
    78 #   endif
    79 {
     264#  endif
     265{
     266#  if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
     267    char *page = cookie;
     268#  else
    80269    char *page = nd_get_link(nd);
     270#  endif
     271    SFLOGFLOW(("vbsf_put_link: page=%p\n", page));
    81272    if (!IS_ERR(page))
    82273        free_page((unsigned long)page);
    83274}
    84 #  endif /* < 4.2.0 */
    85 
    86 # else  /* >= 4.5.0 */
    87 
    88 static const char *vbsf_get_link(struct dentry *dentry, struct inode *inode, struct delayed_call *done)
    89 {
    90     struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(inode->i_sb);
    91     struct vbsf_inode_info *sf_i = VBSF_GET_INODE_INFO(inode);
    92     char *path;
    93     int rc;
    94 
    95     if (!dentry)
    96         return ERR_PTR(-ECHILD);
    97     path = kzalloc(PAGE_SIZE, GFP_KERNEL);
    98     if (!path)
    99         return ERR_PTR(-ENOMEM);
    100     rc = VbglR0SfReadLink(&g_SfClient, &sf_g->map, sf_i->path, PATH_MAX, path);
    101     if (RT_FAILURE(rc)) {
    102         LogFunc(("VbglR0SfReadLink failed, rc=%Rrc\n", rc));
    103         kfree(path);
    104         return ERR_PTR(-EPROTO);
    105     }
    106     set_delayed_call(done, kfree_link, path);
    107     return path;
    108 }
    109 
    110 # endif /* >= 4.5.0 */
    111 
     275# endif /* >= 2.6.8 */
     276
     277#endif /* < 4.5.0 */
     278
     279/**
     280 * Symlink inode operations.
     281 */
    112282struct inode_operations vbsf_lnk_iops = {
    113 # if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
    114     .readlink = generic_readlink,
     283#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
     284# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
     285    .readlink    = generic_readlink,
     286# else
     287    .readlink    = vbsf_readlink,
    115288# endif
    116 # if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
    117     .get_link = vbsf_get_link
    118 # elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
     289#endif
     290#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)
     291    .get_link    = vbsf_get_link
     292#else
    119293    .follow_link = vbsf_follow_link,
    120     .put_link = free_page_put_link,
    121 # else
    122     .follow_link = vbsf_follow_link,
    123     .put_link = vbsf_put_link
     294# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
     295    .put_link    = vbsf_put_link,
    124296# endif
     297#endif
    125298};
    126299
    127 #endif  /* LINUX_VERSION_CODE >= 2.6.8 */
     300
  • trunk/src/VBox/Additions/linux/sharedfolders/utils.c

    r77741 r77858  
    3939int vbsf_nlscpy(struct vbsf_super_info *sf_g, char *name, size_t name_bound_len, const unsigned char *utf8_name, size_t utf8_len)
    4040{
     41    Assert(name_bound_len > 1);
    4142    Assert(RTStrNLen(utf8_name, utf8_len) == utf8_len);
    4243
     
    4546        size_t      in_bound_len    = utf8_len;
    4647        char       *out             = name;
    47         size_t      out_bound_len   = name_bound_len;
     48        size_t      out_bound_len   = name_bound_len - 1;
    4849        size_t      out_len         = 0;
    4950
     
    9091
    9192/**
     93 * Converts the given NLS string to a host one, kmalloc'ing
     94 * the output buffer (use kfree on result).
     95 */
     96int vbsf_nls_to_shflstring(struct vbsf_super_info *sf_g, const char *pszNls, PSHFLSTRING *ppString)
     97{
     98    int          rc;
     99    size_t const cchNls = strlen(pszNls);
     100    PSHFLSTRING  pString = NULL;
     101    if (sf_g->nls) {
     102        /*
     103         * NLS -> UTF-8 w/ SHLF string header.
     104         */
     105        /* Calc length first: */
     106        size_t cchUtf8 = 0;
     107        size_t offNls  = 0;
     108        while (offNls < cchNls) {
     109            linux_wchar_t uc; /* Note! We renamed the type due to clashes. */
     110            int const cbNlsCodepoint = sf_g->nls->char2uni(&pszNls[offNls], cchNls - offNls, &uc);
     111            if (cbNlsCodepoint >= 0) {
     112                char achTmp[16];
     113#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
     114                int cbUtf8Codepoint = utf32_to_utf8(uc, achTmp, sizeof(achTmp));
     115#else
     116                int cbUtf8Codepoint = utf8_wctomb(achTmp, uc, sizeof(achTmp));
     117#endif
     118                if (cbUtf8Codepoint > 0) {
     119                    cchUtf8 += cbUtf8Codepoint;
     120                    offNls  += cbNlsCodepoint;
     121                } else {
     122                    Log(("vbsf_nls_to_shflstring: nls->uni2char(%#x) failed: %d\n", uc, cbUtf8Codepoint));
     123                    return -EINVAL;
     124                }
     125            } else {
     126                Log(("vbsf_nls_to_shflstring: nls->char2uni(%.*Rhxs) failed: %d\n",
     127                     RT_MIN(8, cchNls - offNls), &pszNls[offNls], cbNlsCodepoint));
     128                return -EINVAL;
     129            }
     130        }
     131        if (cchUtf8 + 1 < _64K) {
     132            /* Allocate: */
     133            pString = (PSHFLSTRING)kmalloc(SHFLSTRING_HEADER_SIZE + cchUtf8 + 1, GFP_KERNEL);
     134            if (pString) {
     135                char *pchDst = pString->String.ach;
     136                pString->u16Length = (uint16_t)cchUtf8;
     137                pString->u16Size   = (uint16_t)(cchUtf8 + 1);
     138
     139                /* Do the conversion (cchUtf8 is counted down): */
     140                rc     = 0;
     141                offNls = 0;
     142                while (offNls < cchNls) {
     143                    linux_wchar_t uc; /* Note! We renamed the type due to clashes. */
     144                    int const cbNlsCodepoint = sf_g->nls->char2uni(&pszNls[offNls], cchNls - offNls, &uc);
     145                    if (cbNlsCodepoint >= 0) {
     146#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
     147                        int cbUtf8Codepoint = utf32_to_utf8(uc, pchDst, cchUtf8);
     148#else
     149                        int cbUtf8Codepoint = utf8_wctomb(pchDst, uc, cchUtf8);
     150#endif
     151                        if (cbUtf8Codepoint > 0) {
     152                            AssertBreakStmt(cbUtf8Codepoint <= cchUtf8, rc = -EINVAL);
     153                            cchUtf8 -= cbUtf8Codepoint;
     154                            pchDst  += cbUtf8Codepoint;
     155                            offNls  += cbNlsCodepoint;
     156                        } else {
     157                            Log(("vbsf_nls_to_shflstring: nls->uni2char(%#x) failed! %d, cchUtf8=%zu\n",
     158                                 uc, cbUtf8Codepoint, cchUtf8));
     159                            rc = -EINVAL;
     160                            break;
     161                        }
     162                    } else {
     163                        Log(("vbsf_nls_to_shflstring: nls->char2uni(%.*Rhxs) failed! %d\n",
     164                             RT_MIN(8, cchNls - offNls), &pszNls[offNls], cbNlsCodepoint));
     165                        rc = -EINVAL;
     166                        break;
     167                    }
     168                }
     169                if (rc == 0) {
     170                    /*
     171                     * Succeeded.  Just terminate the string and we're good.
     172                     */
     173                    Assert(pchDst - pString->String.ach == pString->u16Length);
     174                    *pchDst = '\0';
     175                } else {
     176                    kfree(pString);
     177                    pString = NULL;
     178                }
     179            } else {
     180                Log(("vbsf_nls_to_shflstring: failed to allocate %u bytes\n", SHFLSTRING_HEADER_SIZE + cchUtf8 + 1));
     181                rc = -ENOMEM;
     182            }
     183        } else {
     184            Log(("vbsf_nls_to_shflstring: too long: %zu bytes (%zu nls bytes)\n", cchUtf8, cchNls));
     185            rc = -ENAMETOOLONG;
     186        }
     187    } else {
     188        /*
     189         * UTF-8 -> UTF-8 w/ SHLF string header.
     190         */
     191        if (cchNls + 1 < _64K) {
     192            pString = (PSHFLSTRING)kmalloc(SHFLSTRING_HEADER_SIZE + cchNls + 1, GFP_KERNEL);
     193            if (pString) {
     194                pString->u16Length = (uint16_t)cchNls;
     195                pString->u16Size   = (uint16_t)(cchNls + 1);
     196                memcpy(pString->String.ach, pszNls, cchNls);
     197                pString->String.ach[cchNls] = '\0';
     198                rc = 0;
     199            } else {
     200                Log(("vbsf_nls_to_shflstring: failed to allocate %u bytes\n", SHFLSTRING_HEADER_SIZE + cchNls + 1));
     201                rc = -ENOMEM;
     202            }
     203        } else {
     204            Log(("vbsf_nls_to_shflstring: too long: %zu bytes\n", cchNls));
     205            rc = -ENAMETOOLONG;
     206        }
     207    }
     208    *ppString = pString;
     209    return rc;
     210}
     211
     212
     213/**
    92214 * Convert from VBox to linux time.
    93215 */
     
    197319        set_nlink(inode, 1);
    198320    }
    199 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
    200321    else if (RTFS_IS_SYMLINK(pAttr->fMode)) {
    201322        /** @todo r=bird: Aren't System V symlinks w/o any mode mask? IIRC there is
     
    204325        inode->i_op = &vbsf_lnk_iops;
    205326        set_nlink(inode, 1);
    206     }
    207 #endif
    208     else {
     327    } else {
    209328        inode->i_mode = sf_file_mode_to_linux(pAttr->fMode, sf_g->fmode, sf_g->fmask, S_IFREG);
    210329        inode->i_op = &vbsf_reg_iops;
     
    261380    if (RTFS_IS_DIRECTORY(pAttr->fMode))
    262381        fMode = sf_file_mode_to_linux(pAttr->fMode, sf_g->dmode, sf_g->dmask, S_IFDIR);
    263 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
    264382    else if (RTFS_IS_SYMLINK(pAttr->fMode))
    265383        /** @todo r=bird: Aren't System V symlinks w/o any mode mask? IIRC there is
    266384         *        no lchmod on Linux. */
    267385        fMode = sf_file_mode_to_linux(pAttr->fMode, sf_g->fmode, sf_g->fmask, S_IFLNK);
    268 #endif
    269386    else
    270387        fMode = sf_file_mode_to_linux(pAttr->fMode, sf_g->fmode, sf_g->fmask, S_IFREG);
     
    828945 * [vbsf_make_path] which will allocate SHFLSTRING and fill it in
    829946 */
    830 int vbsf_path_from_dentry(const char *caller, struct vbsf_super_info *sf_g, struct vbsf_inode_info *sf_i,
    831                           struct dentry *dentry, SHFLSTRING **result)
     947int vbsf_path_from_dentry(struct vbsf_super_info *sf_g, struct vbsf_inode_info *sf_i, struct dentry *dentry, SHFLSTRING **result,
     948                          const char *caller)
    832949{
    833950    int err;
  • trunk/src/VBox/Additions/linux/sharedfolders/vfsmod.c

    r77854 r77858  
    7070spinlock_t   g_SfHandleLock;
    7171
    72 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 52)
     72/** The 'follow_symlinks' module parameter.
     73 * @todo Figure out how do this for 2.4.x! */
    7374static int   g_fFollowSymlinks = 0;
    74 #endif
    7575
    7676/* forward declaration */
     
    871871            rc = VbglR0SfHostReqSetUtf8Simple();
    872872            if (RT_SUCCESS(rc)) {
    873 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
    874873                if (!g_fFollowSymlinks) {
    875874                    rc = VbglR0SfHostReqSetSymlinksSimple();
    876875                    if (RT_FAILURE(rc))
    877                         printk(KERN_WARNING "vboxsf: Host unable to show symlinks, rc=%d\n", rc);
     876                        printk(KERN_WARNING "vboxsf: Host unable to enable showing symlinks, rc=%d\n", rc);
    878877                }
    879 #endif
    880878                /*
    881879                 * Now that we're ready for action, try register the
     
    929927module_param_named(follow_symlinks, g_fFollowSymlinks, int, 0);
    930928MODULE_PARM_DESC(follow_symlinks,
    931          "Let host resolve symlinks rather than showing them");
     929                 "Let host resolve symlinks rather than showing them");
    932930#endif
    933931
  • trunk/src/VBox/Additions/linux/sharedfolders/vfsmod.h

    r77853 r77858  
    394394
    395395extern int  vbsf_stat(const char *caller, struct vbsf_super_info *sf_g, SHFLSTRING * path, PSHFLFSOBJINFO result, int ok_to_fail);
    396 extern int  vbsf_path_from_dentry(const char *caller, struct vbsf_super_info *sf_g, struct vbsf_inode_info *sf_i,
    397                                   struct dentry *dentry, SHFLSTRING ** result);
     396extern int  vbsf_path_from_dentry(struct vbsf_super_info *sf_g, struct vbsf_inode_info *sf_i, struct dentry *dentry,
     397                                  SHFLSTRING ** result, const char *caller);
    398398extern int  vbsf_nlscpy(struct vbsf_super_info *sf_g, char *name, size_t name_bound_len,
    399399                        const unsigned char *utf8_name, size_t utf8_len);
     400extern int  vbsf_nls_to_shflstring(struct vbsf_super_info *sf_g, const char *pszNls, PSHFLSTRING *ppString);
    400401
    401402
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