VirtualBox

Changeset 77858 in vbox for trunk/src/VBox/Additions/linux


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/src/VBox/Additions/linux/sharedfolders
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • 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