VirtualBox

忽略:
時間撮記:
2015-5-11 下午03:00:35 (10 年 以前)
作者:
vboxsync
訊息:

DnDURIList: Implemented resolving symlinks.

檔案:
修改 1 筆資料

圖例:

未更動
新增
刪除
  • trunk/src/VBox/GuestHost/DragAndDrop/DnDURIList.cpp

    r55744 r55805  
    2424#include <iprt/fs.h>
    2525#include <iprt/path.h>
     26#include <iprt/symlink.h>
    2627#include <iprt/uri.h>
    2728
     
    4445}
    4546
    46 int DnDURIList::appendPathRecursive(const char *pcszPath, size_t cbBaseLen,
    47                                     uint32_t fFlags)
    48 {
    49     AssertPtrReturn(pcszPath, VERR_INVALID_POINTER);
     47int DnDURIList::addEntry(const char *pcszSource, const char *pcszTarget, uint32_t fFlags)
     48{
     49    AssertPtrReturn(pcszSource, VERR_INVALID_POINTER);
     50    AssertPtrReturn(pcszTarget, VERR_INVALID_POINTER);
     51
     52    LogFlowFunc(("pcszSource=%s, pcszTarget=%s\n", pcszSource, pcszTarget));
    5053
    5154    RTFSOBJINFO objInfo;
    52     int rc = RTPathQueryInfo(pcszPath, &objInfo, RTFSOBJATTRADD_NOTHING);
    53     if (RT_FAILURE(rc))
    54         return rc;
    55 
    56     /*
    57      * These are the types we currently support. Symlinks are not directly
    58      * supported. First the guest could be an OS which doesn't support it and
    59      * second the symlink could point to a file which is out of the base tree.
    60      * Both things are hard to support. For now we just copy the target file in
    61      * this case.
    62      */
    63     if (!(   RTFS_IS_DIRECTORY(objInfo.Attr.fMode)
    64           || RTFS_IS_FILE(objInfo.Attr.fMode)
    65           || RTFS_IS_SYMLINK(objInfo.Attr.fMode)))
    66         return VINF_SUCCESS;
    67 
    68     uint64_t cbSize = 0;
    69     rc = RTFileQuerySize(pcszPath, &cbSize);
    70     if (rc == VERR_IS_A_DIRECTORY)
    71         rc = VINF_SUCCESS;
    72 
    73     if (RT_FAILURE(rc))
    74         return rc;
    75 
    76     m_lstTree.append(DnDURIObject(  RTFS_IS_DIRECTORY(objInfo.Attr.fMode)
    77                                   ? DnDURIObject::Directory
    78                                   : DnDURIObject::File,
    79                                   pcszPath, &pcszPath[cbBaseLen],
    80                                   objInfo.Attr.fMode, cbSize));
    81     m_cTotal++;
    82     m_cbTotal += cbSize;
    83 #ifdef DEBUG_andy
    84     LogFlowFunc(("strSrcPath=%s, strDstPath=%s, fMode=0x%x, cbSize=%RU64, cTotal=%RU32, cbTotal=%zu\n",
    85                  pcszPath, &pcszPath[cbBaseLen], objInfo.Attr.fMode, cbSize, m_cTotal, m_cbTotal));
    86 #endif
    87 
    88     /* We have to try to open even symlinks, cause they could
    89      * be symlinks to directories. */
    90     PRTDIR hDir;
    91     rc = RTDirOpen(&hDir, pcszPath);
    92 
    93     /* The following error happens when this was a symlink
    94      * to a file or a regular file. */
    95     if (   rc == VERR_PATH_NOT_FOUND
    96         || rc == VERR_NOT_A_DIRECTORY)
    97         return VINF_SUCCESS;
    98     if (RT_FAILURE(rc))
    99         return rc;
    100 
    101     while (RT_SUCCESS(rc))
    102     {
    103         RTDIRENTRY DirEntry;
    104         rc = RTDirRead(hDir, &DirEntry, NULL);
    105         if (RT_FAILURE(rc))
    106         {
    107             if (rc == VERR_NO_MORE_FILES)
    108                 rc = VINF_SUCCESS;
    109             break;
    110         }
    111         switch (DirEntry.enmType)
    112         {
    113             case RTDIRENTRYTYPE_DIRECTORY:
     55    int rc = RTPathQueryInfo(pcszSource, &objInfo, RTFSOBJATTRADD_NOTHING);
     56    if (RT_SUCCESS(rc))
     57    {   
     58        if (RTFS_IS_FILE(objInfo.Attr.fMode))
     59        {
     60            LogFlowFunc(("File '%s' -> '%s'\n", pcszSource, pcszTarget));
     61
     62            m_lstTree.append(DnDURIObject(DnDURIObject::File, pcszSource, pcszTarget,
     63                             objInfo.Attr.fMode, (uint64_t)objInfo.cbObject));
     64            m_cTotal++;
     65            m_cbTotal += (uint64_t)objInfo.cbObject;
     66        }
     67        else if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode))
     68        {
     69            LogFlowFunc(("Directory '%s' -> '%s' \n", pcszSource, pcszTarget));
     70
     71            m_lstTree.append(DnDURIObject(DnDURIObject::Directory, pcszSource, pcszTarget,
     72                             objInfo.Attr.fMode, 0 /* Size */));
     73            m_cTotal++;
     74        }
     75        /* Note: Symlinks already should have been resolved at this point. */
     76        else
     77            rc = VERR_NOT_SUPPORTED;
     78    }
     79
     80    LogFlowFuncLeaveRC(rc);
     81    return rc;
     82}
     83
     84int DnDURIList::appendPathRecursive(const char *pcszSrcPath,
     85                                    const char *pcszDstPath, const char *pcszDstBase, size_t cchDstBase, uint32_t fFlags)
     86{
     87    AssertPtrReturn(pcszSrcPath, VERR_INVALID_POINTER);
     88    AssertPtrReturn(pcszDstBase, VERR_INVALID_POINTER);
     89    AssertPtrReturn(pcszDstPath, VERR_INVALID_POINTER);
     90   
     91    LogFlowFunc(("pcszSrcPath=%s, pcszDstPath=%s, pcszDstBase=%s, cchDstBase=%zu\n",
     92                 pcszSrcPath, pcszDstPath, pcszDstBase, cchDstBase));
     93
     94    RTFSOBJINFO objInfo;
     95    int rc = RTPathQueryInfo(pcszSrcPath, &objInfo, RTFSOBJATTRADD_NOTHING);
     96    if (RT_SUCCESS(rc))
     97    {   
     98        if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode))
     99        {
     100            rc = addEntry(pcszSrcPath, &pcszDstPath[cchDstBase], fFlags);
     101
     102            PRTDIR hDir;
     103            if (RT_SUCCESS(rc))
     104                rc = RTDirOpen(&hDir, pcszSrcPath);
     105            if (RT_SUCCESS(rc))
     106            {   
     107                do
     108                {
     109                    RTDIRENTRY DirEntry;
     110                    rc = RTDirRead(hDir, &DirEntry, NULL);
     111                    if (RT_FAILURE(rc))
     112                    {
     113                        if (rc == VERR_NO_MORE_FILES)
     114                            rc = VINF_SUCCESS;
     115                        break;
     116                    }
     117
     118                    switch (DirEntry.enmType)
     119                    {
     120                        case RTDIRENTRYTYPE_DIRECTORY:
     121                        {
     122                            /* Skip "." and ".." entries. */
     123                            if (   RTStrCmp(DirEntry.szName, ".")  == 0
     124                                || RTStrCmp(DirEntry.szName, "..") == 0)
     125                                break;                           
     126
     127                            char *pszSrc = RTPathJoinA(pcszSrcPath, DirEntry.szName);
     128                            if (pszSrc)
     129                            {
     130                                char *pszDst = RTPathJoinA(pcszDstPath, DirEntry.szName);
     131                                if (pszDst)
     132                                {
     133                                    rc = appendPathRecursive(pszSrc, pszDst, pcszDstBase, cchDstBase, fFlags);
     134                                    RTStrFree(pszDst);
     135                                }
     136                                else
     137                                    rc = VERR_NO_MEMORY;
     138
     139                                RTStrFree(pszSrc);
     140                            }
     141                            else
     142                                rc = VERR_NO_MEMORY;
     143                            break;
     144                        }
     145
     146                        case RTDIRENTRYTYPE_FILE:
     147                        {
     148                            char *pszSrc = RTPathJoinA(pcszSrcPath, DirEntry.szName);
     149                            if (pszSrc)
     150                            {
     151                                char *pszDst = RTPathJoinA(pcszDstPath, DirEntry.szName);
     152                                if (pszDst)
     153                                {
     154                                    rc = addEntry(pszSrc, &pszDst[cchDstBase], fFlags);
     155                                    RTStrFree(pszDst);
     156                                }
     157                                else
     158                                    rc = VERR_NO_MEMORY;
     159                                RTStrFree(pszSrc);
     160                            }
     161                            else
     162                                rc = VERR_NO_MEMORY;
     163                            break;
     164                        }
     165                        case RTDIRENTRYTYPE_SYMLINK:
     166                        {
     167                            if (fFlags & DNDURILIST_FLAGS_RESOLVE_SYMLINKS)
     168                            {
     169                                char *pszSrc = RTPathRealDup(pcszDstBase);
     170                                if (pszSrc)
     171                                {
     172                                    rc = RTPathQueryInfo(pszSrc, &objInfo, RTFSOBJATTRADD_NOTHING);
     173                                    if (RT_SUCCESS(rc))
     174                                    {
     175                                        if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode))
     176                                        {
     177                                            LogFlowFunc(("Directory entry is symlink to directory\n"));
     178                                            rc = appendPathRecursive(pszSrc, pcszDstPath, pcszDstBase, cchDstBase, fFlags);
     179                                        }
     180                                        else if (RTFS_IS_FILE(objInfo.Attr.fMode))
     181                                        {
     182                                            LogFlowFunc(("Directory entry is symlink to file\n"));
     183                                            rc = addEntry(pszSrc, &pcszDstPath[cchDstBase], fFlags);
     184                                        }
     185                                        else
     186                                            rc = VERR_NOT_SUPPORTED;
     187                                    }
     188
     189                                    RTStrFree(pszSrc);
     190                                }       
     191                                else
     192                                    rc = VERR_NO_MEMORY;
     193                            }
     194                            break;
     195                        }
     196
     197                        default:
     198                            break;
     199                    }
     200
     201                } while (RT_SUCCESS(rc));
     202
     203                RTDirClose(hDir);
     204            }
     205        }
     206        else if (RTFS_IS_FILE(objInfo.Attr.fMode))
     207        {
     208            rc = addEntry(pcszSrcPath, &pcszDstPath[cchDstBase], fFlags);
     209        }
     210        else if (RTFS_IS_SYMLINK(objInfo.Attr.fMode))
     211        {
     212            if (fFlags & DNDURILIST_FLAGS_RESOLVE_SYMLINKS)
    114213            {
    115                 /* Skip "." and ".." entries. */
    116                 if (   RTStrCmp(DirEntry.szName, ".")  == 0
    117                     || RTStrCmp(DirEntry.szName, "..") == 0)
    118                     break;
    119 
    120                 char *pszRecDir = RTPathJoinA(pcszPath, DirEntry.szName);
    121                 if (pszRecDir)
     214                char *pszSrc = RTPathRealDup(pcszSrcPath);
     215                if (pszSrc)
    122216                {
    123                     rc = appendPathRecursive(pszRecDir, cbBaseLen, fFlags);
    124                     RTStrFree(pszRecDir);
    125                 }
     217                    rc = RTPathQueryInfo(pszSrc, &objInfo, RTFSOBJATTRADD_NOTHING);
     218                    if (RT_SUCCESS(rc))
     219                    {
     220                        if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode))
     221                        {
     222                            LogFlowFunc(("Symlink to directory\n"));
     223                            rc = appendPathRecursive(pszSrc, pcszDstPath, pcszDstBase, cchDstBase, fFlags);
     224                        }
     225                        else if (RTFS_IS_FILE(objInfo.Attr.fMode))
     226                        {
     227                            LogFlowFunc(("Symlink to file\n"));
     228                            rc = addEntry(pszSrc, &pcszDstPath[cchDstBase], fFlags);
     229                        }
     230                        else
     231                            rc = VERR_NOT_SUPPORTED;
     232                    }
     233
     234                    RTStrFree(pszSrc);
     235                }       
    126236                else
    127                     rc = VERR_NO_MEMORY;
    128                 break;
    129             }
    130             case RTDIRENTRYTYPE_SYMLINK:
    131             case RTDIRENTRYTYPE_FILE:
    132             {
    133                 char *pszNewFile = RTPathJoinA(pcszPath, DirEntry.szName);
    134                 if (pszNewFile)
    135                 {
    136                     /* We need the size and the mode of the file. */
    137                     RTFSOBJINFO objInfo1;
    138                     rc = RTPathQueryInfo(pszNewFile, &objInfo1, RTFSOBJATTRADD_NOTHING);
    139                     if (RT_FAILURE(rc))
    140                         return rc;
    141                     rc = RTFileQuerySize(pszNewFile, &cbSize);
    142                     if (rc == VERR_IS_A_DIRECTORY) /* Happens for symlinks. */
    143                         rc = VINF_SUCCESS;
    144 
    145                     if (RT_FAILURE(rc))
    146                         break;
    147 
    148                     if (RTFS_IS_FILE(objInfo.Attr.fMode))
    149                     {
    150                         m_lstTree.append(DnDURIObject(DnDURIObject::File,
    151                                                       pszNewFile, &pszNewFile[cbBaseLen],
    152                                                       objInfo1.Attr.fMode, cbSize));
    153                         m_cTotal++;
    154                         m_cbTotal += cbSize;
    155 #ifdef DEBUG_andy
    156                         LogFlowFunc(("strSrcPath=%s, strDstPath=%s, fMode=0x%x, cbSize=%RU64, cTotal=%RU32, cbTotal=%zu\n",
    157                                      pszNewFile, &pszNewFile[cbBaseLen], objInfo1.Attr.fMode, cbSize, m_cTotal, m_cbTotal));
    158 #endif
    159                     }
    160                     else /* Handle symlink directories. */
    161                         rc = appendPathRecursive(pszNewFile, cbBaseLen, fFlags);
    162 
    163                     RTStrFree(pszNewFile);
    164                 }
    165                 else
    166                     rc = VERR_NO_MEMORY;
    167                 break;
    168             }
    169 
    170             default:
    171                 /* Just ignore the rest. */
    172                 break;
    173         }
    174     }
    175 
    176     RTDirClose(hDir);
     237                    rc = VERR_NO_MEMORY;         
     238            }
     239        }
     240        else
     241            rc = VERR_NOT_SUPPORTED;
     242    }
     243
     244    LogFlowFuncLeaveRC(rc);
    177245    return rc;
    178246}
     
    246314    /* Query the path component of a file URI. If this hasn't a
    247315     * file scheme NULL is returned. */
    248     char *pszFilePath = RTUriFilePath(pszURI, URI_FILE_FORMAT_AUTO);
    249     if (pszFilePath)
     316    char *pszSrcPath = RTUriFilePath(pszURI, URI_FILE_FORMAT_AUTO);
     317    if (pszSrcPath)
    250318    {
    251319        /* Add the path to our internal file list (recursive in
    252320         * the case of a directory). */
    253         size_t cbPathLen = RTPathStripTrailingSlash(pszFilePath);
     321        size_t cbPathLen = RTPathStripTrailingSlash(pszSrcPath);
    254322        if (cbPathLen)
    255323        {
    256             char *pszFileName = RTPathFilename(pszFilePath);
     324            char *pszFileName = RTPathFilename(pszSrcPath);
    257325            if (pszFileName)
    258326            {
    259                 Assert(pszFileName >= pszFilePath);
    260                 size_t cbBase = (fFlags & DNDURILIST_FLAGS_ABSOLUTE_PATHS)
    261                               ? 0 /* Use start of path as root. */
    262                               : pszFileName - pszFilePath;
    263                 char *pszRoot = &pszFilePath[cbBase];
    264                 m_lstRoot.append(pszRoot);
    265 #ifdef DEBUG_andy
     327                Assert(pszFileName >= pszSrcPath);
     328                size_t cchDstBase = (fFlags & DNDURILIST_FLAGS_ABSOLUTE_PATHS)
     329                                  ? 0 /* Use start of path as root. */
     330                                  : pszFileName - pszSrcPath;
     331                char *pszDstPath = &pszSrcPath[cchDstBase];
     332                m_lstRoot.append(pszDstPath);
     333
    266334                LogFlowFunc(("pszFilePath=%s, pszFileName=%s, pszRoot=%s\n",
    267                              pszFilePath, pszFileName, pszRoot));
    268 #endif
    269                 rc = appendPathRecursive(pszFilePath, cbBase, fFlags);
     335                             pszSrcPath, pszFileName, pszDstPath));
     336
     337                rc = appendPathRecursive(pszSrcPath, pszSrcPath, pszSrcPath, cchDstBase, fFlags);
    270338            }
    271339            else
    272                 rc = VERR_NOT_FOUND;
     340                rc = VERR_PATH_NOT_FOUND;
    273341        }
    274342        else
    275343            rc = VERR_INVALID_PARAMETER;
    276344
    277         RTStrFree(pszFilePath);
     345        RTStrFree(pszSrcPath);
    278346    }
    279347    else
注意: 瀏覽 TracChangeset 來幫助您使用更動檢視器

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