VirtualBox

Changeset 71976 in vbox for trunk


Ignore:
Timestamp:
Apr 23, 2018 10:52:51 AM (7 years ago)
Author:
vboxsync
Message:

Guest Control/Main: Added stubs for IGuestSession:copy[From|To]Guest() (@bugref{9135}) and implemented internal source specification handling for sharing as much code as possible across all the guest session copy methods. Work in progress.

Location:
trunk/src/VBox/Main
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r71932 r71976  
    1114511145
    1114611146  <enum
     11147    name="GuestCopyFlag"
     11148    uuid="84d6430f-dfe6-4415-a26d-3cdde1c3205a"
     11149    >
     11150    <desc>
     11151      Flags for use when copying elements from or to the guest, see
     11152      <link to="IGuestSession::copyFromGuest"/> and
     11153      <link to="IGuestSession::copyToGuest"/>.
     11154    </desc>
     11155
     11156    <const name="NoReplace"             value="0">
     11157      <desc>Do not replace any destination object.</desc>
     11158    </const>
     11159    <const name="Replace"               value="1">
     11160      <desc>This will attempt to replace any destination object other except
     11161        directories. (The default is to fail if the destination exists.)</desc>
     11162    </const>
     11163    <const name="CopyIntoExisting"      value="2">
     11164      <desc>Allow copying into an existing destination directory.</desc>
     11165    </const>
     11166    <const name="Recursive"             value="4">
     11167      <desc>Copies directories recursively.</desc>
     11168    </const>
     11169    <const name="FollowSymlinks"        value="8">
     11170      <desc>Follows (and handles) symbolic links.</desc>
     11171    </const>
     11172  </enum>
     11173
     11174  <enum
    1114711175    name="ProcessCreateFlag"
    1114811176    uuid="C544CD2B-F02D-4886-9901-71C523DB8DC5"
     
    1187011898  <interface
    1187111899    name="IGuestSession" extends="$unknown"
    11872     uuid="8d3485b3-64a9-4995-998e-6c602b91abd2"
     11900    uuid="a71fcf9a-a45e-440a-886a-5b4c664195ef"
    1187311901    wsmap="managed"
    1187411902    reservedMethods="8" reservedAttributes="8"
     
    1203212060        are running in the guest will be terminated automatically.
    1203312061      </desc>
     12062    </method>
     12063
     12064    <method name="copyFromGuest">
     12065      <desc>
     12066        Copies directories and/or files from guest to the host.
     12067
     12068        <result name="E_NOTIMPL">
     12069          Not yet implemented.
     12070        </result>
     12071      </desc>
     12072      <param name="sources" type="wstring" dir="in" safearray="yes">
     12073        <desc>Paths to directories and/or files on the guest side that should be
     12074          copied to the host. Guest path style.</desc>
     12075      </param>
     12076      <param name="filters" type="wstring" dir="in" safearray="yes">
     12077        <desc>Array of filters corresponding to the sources. This uses the
     12078          DOS/NT style wildcard characters '?' and '*'.</desc>
     12079      </param>
     12080      <param name="types" type="FsObjType" dir="in" safearray="yes">
     12081        <desc>Array of <link to="FsObjType"/> types which define the type of
     12082          source entries.</desc>
     12083      </param>
     12084      <param name="flags" type="GuestCopyFlag" dir="in" safearray="yes">
     12085        <desc>Array of <link to="GuestCopyFlag"/> flags corresponding to the
     12086          sources.</desc>
     12087      </param>
     12088      <param name="destination" type="wstring" dir="in">
     12089        <desc>Where to put the sources on the host. Host path style.</desc>
     12090      </param>
     12091      <param name="progress" type="IProgress" dir="return">
     12092        <desc>Progress object to track the operation to completion.</desc>
     12093      </param>
     12094    </method>
     12095
     12096    <method name="copyToGuest">
     12097      <desc>
     12098        Copies directories and/or files from host to the guest.
     12099
     12100        <result name="E_NOTIMPL">
     12101          Not yet implemented.
     12102        </result>
     12103      </desc>
     12104      <param name="sources" type="wstring" dir="in" safearray="yes">
     12105        <desc>Paths to directories and/or files on the host side that should be
     12106          copied to the guest. Host path style.</desc>
     12107      </param>
     12108      <param name="filters" type="wstring" dir="in" safearray="yes">
     12109        <desc>Array of filters corresponding to the sources. This uses the
     12110          DOS/NT style wildcard characters '?' and '*'.</desc>
     12111      </param>
     12112      <param name="types" type="FsObjType" dir="in" safearray="yes">
     12113        <desc>Array of <link to="FsObjType"/> types which define the type of
     12114          source entries.</desc>
     12115      </param>
     12116      <param name="flags" type="GuestCopyFlag" dir="in" safearray="yes">
     12117        <desc>Array of <link to="GuestCopyFlag"/> flags corresponding to the
     12118          sources.</desc>
     12119      </param>
     12120      <param name="destination" type="wstring" dir="in">
     12121        <desc>Where to put the sources on the guest. Guest path style.</desc>
     12122      </param>
     12123      <param name="progress" type="IProgress" dir="return">
     12124        <desc>Progress object to track the operation to completion.</desc>
     12125      </param>
    1203412126    </method>
    1203512127
  • trunk/src/VBox/Main/include/GuestSessionImpl.h

    r71846 r71976  
    7979     * @{ */
    8080    HRESULT close();
     81
     82    HRESULT copyFromGuest(const std::vector<com::Utf8Str> &aSources,
     83                          const std::vector<com::Utf8Str> &aFilters,
     84                          const std::vector<FsObjType_T> &aTypes,
     85                          const std::vector<GuestCopyFlag_T> &aFlags,
     86                          const com::Utf8Str &aDestination,
     87                          ComPtr<IProgress> &aProgress);
     88    HRESULT copyToGuest(const std::vector<com::Utf8Str> &aSources,
     89                        const std::vector<com::Utf8Str> &aFilters,
     90                        const std::vector<FsObjType_T> &aTypes,
     91                        const std::vector<GuestCopyFlag_T> &aFlags,
     92                        const com::Utf8Str &aDestination,
     93                        ComPtr<IProgress> &aProgress);
    8194
    8295    HRESULT directoryCopy(const com::Utf8Str &aSource,
  • trunk/src/VBox/Main/include/GuestSessionImplTasks.h

    r71847 r71976  
    2828#include <iprt/isofs.h> /* For UpdateAdditions. */
    2929
     30#include <vector>
     31
    3032class Guest;
     33class GuestSessionTask;
    3134class GuestSessionTaskInternalOpen;
    3235
    3336/**
    34  * Abstract base class for a lenghtly per-session operation which
    35  * runs in a Main worker thread.
    36  */
    37 class GuestSessionTask : public ThreadTask
    38 {
    39 public:
    40 
    41     GuestSessionTask(GuestSession *pSession);
    42 
    43     virtual ~GuestSessionTask(void);
    44 
    45 public:
    46 
    47     virtual int Run(void) = 0;
    48     void handler()
    49     {
    50         int vrc = Run();
    51         NOREF(vrc);
    52         /** @todo
    53          *
    54          * r=bird: what was your idea WRT to Run status code and async tasks?
    55          *
    56          */
    57     }
    58 
    59     int RunAsync(const Utf8Str &strDesc, ComObjPtr<Progress> &pProgress);
    60 
    61     HRESULT Init(const Utf8Str &strTaskDesc)
    62     {
    63         HRESULT hr = S_OK;
    64         setTaskDesc(strTaskDesc);
    65         hr = createAndSetProgressObject();
    66         return hr;
    67     }
    68 
    69     const ComObjPtr<Progress>& GetProgressObject() const { return mProgress; }
    70 
    71 protected:
    72 
    73     /** @name Directory handling primitives.
    74      * @{ */
    75     int directoryCreate(const com::Utf8Str &strPath, DirectoryCreateFlag_T enmDirecotryCreateFlags, uint32_t uMode,
    76                         bool fFollowSymlinks);
    77     /** @}  */
    78 
    79     /** @name File handling primitives.
    80      * @{ */
    81     int fileCopyFromGuestInner(ComObjPtr<GuestFile> &srcFile, PRTFILE phDstFile, FileCopyFlag_T fFileCopyFlags,
    82                                uint64_t offCopy, uint64_t cbSize);
    83     int fileCopyFromGuest(const Utf8Str &strSource, const Utf8Str &strDest, FileCopyFlag_T fFileCopyFlags);
    84     int fileCopyToGuestInner(PRTFILE phSrcFile, ComObjPtr<GuestFile> &dstFile, FileCopyFlag_T fFileCopyFlags,
    85                              uint64_t offCopy, uint64_t cbSize);
    86     int fileCopyToGuest(const Utf8Str &strSource, const Utf8Str &strDest, FileCopyFlag_T fFileCopyFlags);
    87     /** @}  */
    88 
    89     /** @name Guest property handling primitives.
    90      * @{ */
    91     int getGuestProperty(const ComObjPtr<Guest> &pGuest, const Utf8Str &strPath, Utf8Str &strValue);
    92     /** @}  */
    93 
    94     /** @name Path handling primitives.
    95      * @{ */
    96     int pathConstructOnGuest(const Utf8Str &strSourceRoot, const Utf8Str &strSource, const Utf8Str &strDest, Utf8Str &strOut);
    97     /** @}  */
    98 
    99     int setProgress(ULONG uPercent);
    100     int setProgressSuccess(void);
    101     HRESULT setProgressErrorMsg(HRESULT hr, const Utf8Str &strMsg);
    102 
    103     inline void setTaskDesc(const Utf8Str &strTaskDesc) throw()
    104     {
    105         mDesc = strTaskDesc;
    106     }
    107 
    108     HRESULT createAndSetProgressObject();
    109 
    110 protected:
    111 
    112     Utf8Str                 mDesc;
    113     /** The guest session object this task is working on. */
    114     ComObjPtr<GuestSession> mSession;
    115     /** Progress object for getting updated when running
    116      *  asynchronously. Optional. */
    117     ComObjPtr<Progress>     mProgress;
    118     /** The guest's path style (depending on the guest OS type set). */
    119     uint32_t                mfPathStyle;
    120 };
    121 
    122 /**
    123  * Task for opening a guest session.
    124  */
    125 class SessionTaskOpen : public GuestSessionTask
    126 {
    127 public:
    128 
    129     SessionTaskOpen(GuestSession *pSession,
    130                     uint32_t uFlags,
    131                     uint32_t uTimeoutMS);
    132     virtual ~SessionTaskOpen(void);
    133     int Run(void);
    134 
    135 protected:
    136 
    137     /** Session creation flags. */
    138     uint32_t mFlags;
    139     /** Session creation timeout (in ms). */
    140     uint32_t mTimeoutMS;
    141 };
    142 
    143 class GuestSessionCopyTask : public GuestSessionTask
    144 {
    145 public:
    146 
    147     GuestSessionCopyTask(GuestSession *pSession)
    148         : GuestSessionTask(pSession)
    149     {
    150         RT_ZERO(u);
    151     }
    152 
    153     virtual ~GuestSessionCopyTask() { }
    154 
    155 protected:
    156 
    157     /** Source to copy from. */
    158     Utf8Str  mSource;
    159     /** Destination to copy to. */
    160     Utf8Str  mDest;
    161     /** Filter (wildcard-style) when copying directories. */
    162     Utf8Str  mFilter;
    163 
     37 * Enumeration which specifies the file system source type.
     38 */
     39enum GuestSessionFsSourceType
     40{
     41    /** Invalid / uknown source type, don't use. */
     42    GuestSessionFsSourceType_Unknown = 0,
     43    /** The source is a directory. */
     44    GuestSessionFsSourceType_Dir,
     45    /** The source is a file. */
     46    GuestSessionFsSourceType_File
     47};
     48
     49/**
     50 * Structure for keeping a file system source specification,
     51 * along with options.
     52 */
     53struct GuestSessionFsSourceSpec
     54{
     55    Utf8Str                  strSource;
     56    Utf8Str                  strFilter;
     57    GuestSessionFsSourceType enmType;
     58    PathStyle_T              enmPathStyle;
     59    bool                     fDryRun;
     60    bool                     fFollowSymlinks;
    16461    union
    16562    {
     
    16966            /** Directory copy flags. */
    17067            DirectoryCopyFlag_T fCopyFlags;
     68            bool                fRecursive;
    17169        } Dir;
    17270        /** File-specific data. */
     
    18381            uint64_t            cbSize;
    18482        } File;
    185     } u;
    186 };
    187 
    188 /**
    189  * Task for copying directories from guest to the host.
    190  */
    191 class SessionTaskCopyDirFrom : public GuestSessionCopyTask
    192 {
    193 public:
    194 
    195     SessionTaskCopyDirFrom(GuestSession *pSession, const Utf8Str &strSource, const Utf8Str &strDest, const Utf8Str &strFilter,
    196                            DirectoryCopyFlag_T fDirCopyFlags);
    197     virtual ~SessionTaskCopyDirFrom(void);
     83    } Type;
     84};
     85
     86/** A set of GuestSessionFsSourceSpec sources. */
     87typedef std::vector<GuestSessionFsSourceSpec> GuestSessionFsSourceSet;
     88
     89/**
     90 * Structure for keeping a file system entry.
     91 */
     92struct FsEntry
     93{
     94    /** The entrie's file mode. */
     95    RTFMODE fMode;
     96    /** The entrie's path, relative to the list's root path. */
     97    Utf8Str strPath;
     98};
     99
     100/** A vector of FsEntry entries. */
     101typedef std::vector<FsEntry *> FsEntries;
     102
     103/**
     104 * Class for storing and handling file system entries, neeed for doing
     105 * internal file / directory operations to / from the guest.
     106 */
     107class FsList
     108{
     109public:
     110
     111    FsList(const GuestSessionTask &Task);
     112    virtual ~FsList();
     113
     114public:
     115
     116    int Init(const Utf8Str &strSrcRootAbs, const Utf8Str &strDstRootAbs, const GuestSessionFsSourceSpec &SourceSpec);
     117    void Destroy(void);
     118
     119    int AddEntryFromGuest(const Utf8Str &strFile, const GuestFsObjData &fsObjData);
     120    int AddDirFromGuest(const Utf8Str &strPath, const Utf8Str &strSubDir = "");
     121
     122    int AddEntryFromHost(const Utf8Str &strFile, PCRTFSOBJINFO pcObjInfo);
     123    int AddDirFromHost(const Utf8Str &strPath, const Utf8Str &strSubDir = "");
     124
     125public:
     126
     127    /** The guest session task object this list is working on. */
     128    const GuestSessionTask  &mTask;
     129    /** File system filter / options to use for this task. */
     130    GuestSessionFsSourceSpec mSourceSpec;
     131    /** The source' root path.
     132     *  For a single file list this is the full (absolute) path to a file,
     133     *  for a directory list this is the source root directory. */
     134    Utf8Str                 mSrcRootAbs;
     135    /** The destinations's root path.
     136     *  For a single file list this is the full (absolute) path to a file,
     137     *  for a directory list this is the destination root directory. */
     138    Utf8Str                 mDstRootAbs;
     139    /** Total size (in bytes) of all list entries together. */
     140    uint64_t                mcbTotalSize;
     141    /** List of file system entries this list contains. */
     142    FsEntries               mVecEntries;
     143};
     144
     145/** A set of FsList lists. */
     146typedef std::vector<FsList *> FsLists;
     147
     148/**
     149 * Abstract base class for a lenghtly per-session operation which
     150 * runs in a Main worker thread.
     151 */
     152class GuestSessionTask : public ThreadTask
     153{
     154public:
     155
     156    GuestSessionTask(GuestSession *pSession);
     157
     158    virtual ~GuestSessionTask(void);
     159
     160public:
     161
     162    virtual int Run(void) = 0;
     163    void handler()
     164    {
     165        int vrc = Run();
     166        NOREF(vrc);
     167        /** @todo
     168         *
     169         * r=bird: what was your idea WRT to Run status code and async tasks?
     170         *
     171         */
     172    }
     173
     174    int RunAsync(const Utf8Str &strDesc, ComObjPtr<Progress> &pProgress);
     175
     176    virtual HRESULT Init(const Utf8Str &strTaskDesc)
     177    {
     178        setTaskDesc(strTaskDesc);
     179        int rc = createAndSetProgressObject(); /* Single operation by default. */
     180        if (RT_FAILURE(rc))
     181            return E_FAIL;
     182
     183        return S_OK;
     184    }
     185
     186    const ComObjPtr<Progress>& GetProgressObject() const { return mProgress; }
     187
     188    const ComObjPtr<GuestSession>& GetSession() const { return mSession; }
     189
     190protected:
     191
     192    /** @name Directory handling primitives.
     193     * @{ */
     194    int directoryCreate(const com::Utf8Str &strPath, DirectoryCreateFlag_T enmDirecotryCreateFlags, uint32_t uMode,
     195                        bool fFollowSymlinks);
     196    /** @}  */
     197
     198    /** @name File handling primitives.
     199     * @{ */
     200    int fileCopyFromGuestInner(ComObjPtr<GuestFile> &srcFile, PRTFILE phDstFile, FileCopyFlag_T fFileCopyFlags,
     201                               uint64_t offCopy, uint64_t cbSize);
     202    int fileCopyFromGuest(const Utf8Str &strSource, const Utf8Str &strDest, FileCopyFlag_T fFileCopyFlags);
     203    int fileCopyToGuestInner(PRTFILE phSrcFile, ComObjPtr<GuestFile> &dstFile, FileCopyFlag_T fFileCopyFlags,
     204                             uint64_t offCopy, uint64_t cbSize);
     205
     206    int fileCopyToGuest(const Utf8Str &strSource, const Utf8Str &strDest, FileCopyFlag_T fFileCopyFlags);
     207    /** @}  */
     208
     209    /** @name Guest property handling primitives.
     210     * @{ */
     211    int getGuestProperty(const ComObjPtr<Guest> &pGuest, const Utf8Str &strPath, Utf8Str &strValue);
     212    /** @}  */
     213
     214    int setProgress(ULONG uPercent);
     215    int setProgressSuccess(void);
     216    HRESULT setProgressErrorMsg(HRESULT hr, const Utf8Str &strMsg);
     217
     218    inline void setTaskDesc(const Utf8Str &strTaskDesc) throw()
     219    {
     220        mDesc = strTaskDesc;
     221    }
     222
     223    int createAndSetProgressObject(ULONG cOperations  = 1);
     224
     225protected:
     226
     227    Utf8Str                 mDesc;
     228    /** The guest session object this task is working on. */
     229    ComObjPtr<GuestSession> mSession;
     230    /** Progress object for getting updated when running
     231     *  asynchronously. Optional. */
     232    ComObjPtr<Progress>     mProgress;
     233    /** The guest's path style (depending on the guest OS type set). */
     234    uint32_t                mfPathStyle;
     235    /** The guest's path style as string representation (depending on the guest OS type set). */
     236    Utf8Str                 mPathStyle;
     237};
     238
     239/**
     240 * Task for opening a guest session.
     241 */
     242class GuestSessionTaskOpen : public GuestSessionTask
     243{
     244public:
     245
     246    GuestSessionTaskOpen(GuestSession *pSession,
     247                    uint32_t uFlags,
     248                    uint32_t uTimeoutMS);
     249    virtual ~GuestSessionTaskOpen(void);
    198250    int Run(void);
    199251
    200252protected:
    201253
    202     int directoryCopyToHost(const Utf8Str &strSource, const Utf8Str &strFilter, const Utf8Str &strDest, bool fRecursive,
    203                             bool fFollowSymlinks, const Utf8Str &strSubDir /* For recursion. */);
     254    /** Session creation flags. */
     255    uint32_t mFlags;
     256    /** Session creation timeout (in ms). */
     257    uint32_t mTimeoutMS;
     258};
     259
     260class GuestSessionCopyTask : public GuestSessionTask
     261{
     262public:
     263
     264    GuestSessionCopyTask(GuestSession *pSession);
     265    virtual ~GuestSessionCopyTask();
     266
     267protected:
     268
     269    /** Source set. */
     270    GuestSessionFsSourceSet mSources;
     271    /** Destination to copy to. */
     272    Utf8Str                 mDest;
     273    /** Vector of file system lists to handle.
     274     *  This either can be from the guest or the host side. */
     275    FsLists                 mVecLists;
     276};
     277
     278/**
     279 * Guest session task for copying files / directories from guest to the host.
     280 */
     281class GuestSessionTaskCopyFrom : public GuestSessionCopyTask
     282{
     283public:
     284
     285    GuestSessionTaskCopyFrom(GuestSession *pSession, GuestSessionFsSourceSet vecSrc, const Utf8Str &strDest);
     286    virtual ~GuestSessionTaskCopyFrom(void);
     287
     288    HRESULT Init(const Utf8Str &strTaskDesc);
     289    int Run(void);
    204290};
    205291
     
    207293 * Task for copying directories from host to the guest.
    208294 */
    209 class SessionTaskCopyDirTo : public GuestSessionCopyTask
    210 {
    211 public:
    212 
    213     SessionTaskCopyDirTo(GuestSession *pSession, const Utf8Str &strSource, const Utf8Str &strDest, const Utf8Str &strFilter,
    214                          DirectoryCopyFlag_T fDirCopyFlags);
    215     virtual ~SessionTaskCopyDirTo(void);
     295class GuestSessionTaskCopyTo : public GuestSessionCopyTask
     296{
     297public:
     298
     299    GuestSessionTaskCopyTo(GuestSession *pSession, GuestSessionFsSourceSet vecSrc, const Utf8Str &strDest);
     300    virtual ~GuestSessionTaskCopyTo(void);
     301
     302    HRESULT Init(const Utf8Str &strTaskDesc);
    216303    int Run(void);
    217 
    218 protected:
    219 
    220     int directoryCopyToGuest(const Utf8Str &strSource, const Utf8Str &strFilter, const Utf8Str &strDest, bool fRecursive,
    221                              bool fFollowSymlinks, const Utf8Str &strSubDir /* For recursion. */);
    222 };
    223 
    224 /**
    225  * Task for copying files from host to the guest.
    226  */
    227 class SessionTaskCopyFileTo : public GuestSessionCopyTask
    228 {
    229 public:
    230 
    231     SessionTaskCopyFileTo(GuestSession *pSession,
    232                           const Utf8Str &strSource, const Utf8Str &strDest, FileCopyFlag_T fFileCopyFlags);
    233     virtual ~SessionTaskCopyFileTo(void);
    234     int Run(void);
    235 };
    236 
    237 /**
    238  * Task for copying files from guest to the host.
    239  */
    240 class SessionTaskCopyFileFrom : public GuestSessionCopyTask
    241 {
    242 public:
    243 
    244     SessionTaskCopyFileFrom(GuestSession *pSession,
    245                             const Utf8Str &strSource, const Utf8Str &strDest, FileCopyFlag_T fFileCopyFlags);
    246     virtual ~SessionTaskCopyFileFrom(void);
    247     int Run(void);
    248 };
    249 
    250 /**
    251  * Task for automatically updating the Guest Additions on the guest.
    252  */
    253 class SessionTaskUpdateAdditions : public GuestSessionTask
    254 {
    255 public:
    256 
    257     SessionTaskUpdateAdditions(GuestSession *pSession,
     304};
     305
     306/**
     307 * Guest session task for automatically updating the Guest Additions on the guest.
     308 */
     309class GuestSessionTaskUpdateAdditions : public GuestSessionTask
     310{
     311public:
     312
     313    GuestSessionTaskUpdateAdditions(GuestSession *pSession,
    258314                               const Utf8Str &strSource, const ProcessArguments &aArguments,
    259315                               uint32_t fFlags);
    260     virtual ~SessionTaskUpdateAdditions(void);
     316    virtual ~GuestSessionTaskUpdateAdditions(void);
    261317    int Run(void);
    262318
  • trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp

    r71648 r71976  
    535535
    536536            ComObjPtr<Progress> pProgress;
    537             SessionTaskUpdateAdditions *pTask = NULL;
     537            GuestSessionTaskUpdateAdditions *pTask = NULL;
    538538            try
    539539            {
    540540                try
    541541                {
    542                     pTask = new SessionTaskUpdateAdditions(pSession /* GuestSession */, aSource, aArgs, fFlags);
     542                    pTask = new GuestSessionTaskUpdateAdditions(pSession /* GuestSession */, aSource, aArgs, fFlags);
    543543                }
    544544                catch(...)
  • trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp

    r71848 r71976  
    26302630    LogFlowThisFuncEnter();
    26312631
    2632     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    2633 
    26342632    try
    26352633    {
    2636         SessionTaskCopyFileFrom *pTask = NULL;
     2634        GuestSessionTaskCopyFrom *pTask = NULL;
    26372635        ComObjPtr<Progress> pProgress;
    26382636        try
    26392637        {
    2640             pTask = new SessionTaskCopyFileFrom(this /* GuestSession */, aSource, aDest, (FileCopyFlag_T)fFlags);
     2638            GuestSessionFsSourceSpec source;
     2639            source.strSource            = aSource;
     2640            source.enmType              = GuestSessionFsSourceType_File;
     2641            source.enmPathStyle         = i_getPathStyle();
     2642            source.Type.File.fCopyFlags = (FileCopyFlag_T)fFlags;
     2643
     2644            GuestSessionFsSourceSet vecSources;
     2645            vecSources.push_back(source);
     2646
     2647            pTask = new GuestSessionTaskCopyFrom(this /* GuestSession */, vecSources, aDest);
    26412648        }
    26422649        catch(...)
    26432650        {
    2644             hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to create SessionTaskCopyFileFrom object"));
     2651            hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to create SessionTaskCopyFrom object"));
    26452652            throw;
    26462653        }
     
    26522659            delete pTask;
    26532660            hrc = setError(VBOX_E_IPRT_ERROR,
    2654                            tr("Creating progress object for SessionTaskCopyFileFrom object failed"));
     2661                           tr("Creating progress object for SessionTaskCopyFrom object failed"));
    26552662            throw hrc;
    26562663        }
     
    27172724    LogFlowThisFuncEnter();
    27182725
    2719     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    2720 
    27212726    try
    27222727    {
    2723         SessionTaskCopyFileTo *pTask = NULL;
     2728        GuestSessionTaskCopyTo *pTask = NULL;
    27242729        ComObjPtr<Progress> pProgress;
    27252730        try
    27262731        {
    2727             pTask = new SessionTaskCopyFileTo(this /* GuestSession */, aSource, aDest, (FileCopyFlag_T)fFlags);
     2732            GuestSessionFsSourceSpec source;
     2733            source.strSource            = aSource;
     2734            source.enmType              = GuestSessionFsSourceType_File;
     2735#if RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS
     2736            source.enmPathStyle         = PathStyle_DOS;
     2737#else
     2738            source.enmPathStyle         = PathStyle_UNIX;
     2739#endif
     2740            source.Type.File.fCopyFlags = (FileCopyFlag_T)fFlags;
     2741
     2742            GuestSessionFsSourceSet vecSources;
     2743            vecSources.push_back(source);
     2744
     2745            pTask = new GuestSessionTaskCopyTo(this /* GuestSession */, vecSources, aDest);
    27282746        }
    27292747        catch(...)
    27302748        {
    2731             hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to create SessionTaskCopyFileTo object"));
     2749            hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to create SessionTaskCopyTo object"));
    27322750            throw;
    27332751        }
     
    27382756            delete pTask;
    27392757            hrc = setError(VBOX_E_IPRT_ERROR,
    2740                            tr("Creating progress object for SessionTaskCopyFileTo object failed"));
     2758                           tr("Creating progress object for SessionTaskCopyTo object failed"));
    27412759            throw hrc;
    27422760        }
     
    27682786}
    27692787
     2788HRESULT GuestSession::copyFromGuest(const std::vector<com::Utf8Str> &aSources, const std::vector<com::Utf8Str> &aFilters,
     2789                                    const std::vector<FsObjType_T> &aTypes, const std::vector<GuestCopyFlag_T> &aFlags,
     2790                                    const com::Utf8Str &aDestination, ComPtr<IProgress> &aProgress)
     2791{
     2792    RT_NOREF(aSources, aFilters, aTypes, aFlags, aDestination, aProgress);
     2793    ReturnComNotImplemented();
     2794}
     2795
     2796HRESULT GuestSession::copyToGuest(const std::vector<com::Utf8Str> &aSources, const std::vector<com::Utf8Str> &aFilters,
     2797                                  const std::vector<FsObjType_T> &aTypes, const std::vector<GuestCopyFlag_T> &aFlags,
     2798                                  const com::Utf8Str &aDestination, ComPtr<IProgress> &aProgress)
     2799{
     2800    RT_NOREF(aSources, aFilters, aTypes, aFlags, aDestination, aProgress);
     2801    ReturnComNotImplemented();
     2802}
     2803
    27702804HRESULT GuestSession::directoryCopy(const com::Utf8Str &aSource, const com::Utf8Str &aDestination,
    27712805                                    const std::vector<DirectoryCopyFlag_T> &aFlags, ComPtr<IProgress> &aProgress)
     
    28062840    LogFlowThisFuncEnter();
    28072841
    2808     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    2809 
    28102842    try
    28112843    {
    2812         SessionTaskCopyDirFrom *pTask = NULL;
     2844        GuestSessionTaskCopyFrom *pTask = NULL;
    28132845        ComObjPtr<Progress> pProgress;
    28142846        try
    28152847        {
    2816             pTask = new SessionTaskCopyDirFrom(this /* GuestSession */, aSource, aDestination, "" /* strFilter */,
    2817                                                (DirectoryCopyFlag_T)fFlags);
     2848            GuestSessionFsSourceSpec source;
     2849            source.strSource           = aSource;
     2850            source.enmType             = GuestSessionFsSourceType_Dir;
     2851            source.enmPathStyle        = i_getPathStyle();
     2852            source.Type.Dir.fCopyFlags = (DirectoryCopyFlag_T)fFlags;
     2853
     2854            GuestSessionFsSourceSet vecSources;
     2855            vecSources.push_back(source);
     2856
     2857            pTask = new GuestSessionTaskCopyFrom(this /* GuestSession */, vecSources, aDestination);
    28182858        }
    28192859        catch(...)
    28202860        {
    2821             hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to create SessionTaskCopyDirFrom object"));
     2861            hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to create SessionTaskCopyFrom object"));
    28222862            throw;
    28232863        }
     
    28932933    LogFlowThisFuncEnter();
    28942934
    2895     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    2896 
    28972935    try
    28982936    {
    2899         SessionTaskCopyDirTo *pTask = NULL;
     2937        GuestSessionTaskCopyTo *pTask = NULL;
    29002938        ComObjPtr<Progress> pProgress;
    29012939        try
    29022940        {
    2903             pTask = new SessionTaskCopyDirTo(this /* GuestSession */, aSource, aDestination, "" /* strFilter */,
    2904                                              (DirectoryCopyFlag_T)fFlags);
     2941            GuestSessionFsSourceSpec source;
     2942            source.strSource           = aSource;
     2943            source.enmType             = GuestSessionFsSourceType_Dir;
     2944#if RTPATH_STYLERTPATH_STYLE == RTPATH_STR_F_STYLE_DOS
     2945            source.enmPathStyle         = PathStyle_DOS;
     2946#else
     2947            source.enmPathStyle         = PathStyle_UNIX;
     2948#endif
     2949            source.fFollowSymlinks     = true;
     2950            source.Type.Dir.fRecursive = true;
     2951            source.Type.Dir.fCopyFlags = (DirectoryCopyFlag_T)fFlags;
     2952
     2953            GuestSessionFsSourceSet vecSources;
     2954            vecSources.push_back(source);
     2955
     2956            pTask = new GuestSessionTaskCopyTo(this /* GuestSession */, vecSources, aDestination);
    29052957        }
    29062958        catch(...)
    29072959        {
    2908             hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to create SessionTaskCopyDirTo object"));
     2960            hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to create SessionTaskCopyTo object"));
    29092961            throw;
    29102962        }
  • trunk/src/VBox/Main/src-client/GuestSessionImplTasks.cpp

    r71849 r71976  
    7272    mSession = pSession;
    7373
    74     mfPathStyle = mSession->i_getPathStyle() == PathStyle_DOS
    75                 ? RTPATH_STR_F_STYLE_DOS : RTPATH_STR_F_STYLE_UNIX;
     74    switch (mSession->i_getPathStyle())
     75    {
     76        case PathStyle_DOS:
     77            mfPathStyle = RTPATH_STR_F_STYLE_DOS;
     78            mPathStyle  = "\\";
     79            break;
     80
     81        default:
     82            mfPathStyle = RTPATH_STR_F_STYLE_UNIX;
     83            mPathStyle  = "/";
     84            break;
     85    }
    7686}
    7787
     
    8090}
    8191
    82 HRESULT GuestSessionTask::createAndSetProgressObject()
    83 {
    84     LogFlowThisFunc(("Task Description = %s, pTask=%p\n", mDesc.c_str(), this));
    85 
     92int GuestSessionTask::createAndSetProgressObject(ULONG cOperations /* = 1 */)
     93{
     94    LogFlowThisFunc(("cOperations=%ld\n", cOperations));
     95
     96    /* Create the progress object. */
    8697    ComObjPtr<Progress> pProgress;
    87     HRESULT hr = S_OK;
    88     /* Create the progress object. */
    89     hr = pProgress.createObject();
     98    HRESULT hr = pProgress.createObject();
    9099    if (FAILED(hr))
    91100        return VERR_COM_UNEXPECTED;
     
    93102    hr = pProgress->init(static_cast<IGuestSession*>(mSession),
    94103                         Bstr(mDesc).raw(),
    95                          TRUE /* aCancelable */);
     104                         TRUE /* aCancelable */, cOperations, Bstr(mDesc).raw());
    96105    if (FAILED(hr))
    97106        return VERR_COM_UNEXPECTED;
     
    100109
    101110    LogFlowFuncLeave();
    102 
    103     return hr;
     111    return VINF_SUCCESS;
    104112}
    105113
     
    207215 * @return VBox status code. VWRN_ALREADY_EXISTS if directory on the guest already exists.
    208216 * @param  strPath                  Absolute path to directory on the guest (guest style path) to create.
    209  * @param  enmDirecotryCreateFlags  Directory creation flags.
     217 * @param  enmDirectoryCreateFlags  Directory creation flags.
    210218 * @param  uMode                    Directory mode to use for creation.
    211219 * @param  fFollowSymlinks          Whether to follow symlinks on the guest or not.
    212220 */
    213221int GuestSessionTask::directoryCreate(const com::Utf8Str &strPath,
    214                                       DirectoryCreateFlag_T enmDirecotryCreateFlags, uint32_t uMode, bool fFollowSymlinks)
     222                                      DirectoryCreateFlag_T enmDirectoryCreateFlags, uint32_t uMode, bool fFollowSymlinks)
    215223{
    216224    LogFlowFunc(("strPath=%s, fFlags=0x%x, uMode=%RU32, fFollowSymlinks=%RTbool\n",
    217                  strPath.c_str(), enmDirecotryCreateFlags, uMode, fFollowSymlinks));
     225                 strPath.c_str(), enmDirectoryCreateFlags, uMode, fFollowSymlinks));
    218226
    219227    GuestFsObjData objData; int rcGuest;
    220 
    221228    int rc = mSession->i_directoryQueryInfo(strPath, fFollowSymlinks, objData, &rcGuest);
    222229    if (RT_SUCCESS(rc))
     
    234241                    case VERR_FILE_NOT_FOUND:
    235242                    case VERR_PATH_NOT_FOUND:
    236                         rc = mSession->i_directoryCreate(strPath.c_str(), uMode, enmDirecotryCreateFlags, &rcGuest);
     243                        rc = mSession->i_directoryCreate(strPath.c_str(), uMode, enmDirectoryCreateFlags, &rcGuest);
    237244                        break;
    238245                    default:
     
    390397
    391398    GuestFsObjData srcObjData;
    392     RT_ZERO(srcObjData);
    393 
    394399    int rcGuest = VERR_IPE_UNINITIALIZED_STATUS;
    395400    int rc = mSession->i_fsQueryInfo(strSource, TRUE /* fFollowSymlinks */, srcObjData, &rcGuest);
     
    708713
    709714    GuestFsObjData dstObjData;
    710     RT_ZERO(dstObjData);
    711 
    712715    int rcGuest = VERR_IPE_UNINITIALIZED_STATUS;
    713716    int rc = mSession->i_fsQueryInfo(strDest, TRUE /* fFollowSymlinks */, dstObjData, &rcGuest);
     
    738741            case FsObjType_Directory:
    739742            {
    740                 if (   strDest.endsWith("\\")
    741                     || strDest.endsWith("/"))
    742                 {
    743                     /* Build the final file name with destination path (on the host). */
    744                     char szDstPath[RTPATH_MAX];
    745                     RTStrPrintf2(szDstPath, sizeof(szDstPath), "%s", strDest.c_str());
    746 
    747                     RTPathAppend(szDstPath, sizeof(szDstPath), RTPathFilename(strSource.c_str()));
    748 
    749                     strDestFinal = szDstPath;
    750                 }
    751                 else
    752                 {
    753                     setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    754                                         Utf8StrFmt(GuestSession::tr("Destination directory \"%s\" already exists"),
    755                                                    strDest.c_str(), rc));
    756                     rc = VERR_ALREADY_EXISTS;
    757                 }
     743                /* Build the final file name with destination path (on the host). */
     744                char szDstPath[RTPATH_MAX];
     745                RTStrPrintf2(szDstPath, sizeof(szDstPath), "%s", strDest.c_str());
     746
     747                if (   !strDest.endsWith("\\")
     748                    && !strDest.endsWith("/"))
     749                    RTStrCat(szDstPath, sizeof(szDstPath), mPathStyle.c_str());
     750
     751                RTStrCat(szDstPath, sizeof(szDstPath), RTPathFilename(strSource.c_str()));
     752
     753                strDestFinal = szDstPath;
    758754                break;
    759755            }
     
    821817        return rc;
    822818
     819    char szSrcReal[RTPATH_MAX];
     820
    823821    RTFSOBJINFO srcObjInfo;
    824822    RT_ZERO(srcObjInfo);
     
    828826    if (RT_SUCCESS(rc))
    829827    {
    830         rc = RTPathQueryInfo(strSource.c_str(), &srcObjInfo, RTFSOBJATTRADD_NOTHING);
    831         if (RT_SUCCESS(rc))
    832         {
    833             if (fFileCopyFlags & FileCopyFlag_Update)
    834             {
    835                 RTTIMESPEC dstModificationTimeTS;
    836                 RTTimeSpecSetSeconds(&dstModificationTimeTS, dstObjData.mModificationTime);
    837                 if (RTTimeSpecCompare(&dstModificationTimeTS, &srcObjInfo.ModificationTime) <= 0)
    838                 {
    839                     setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    840                                         Utf8StrFmt(GuestSession::tr("Destination file \"%s\" has same or newer modification date"),
    841                                                    strDestFinal.c_str()));
    842                     fSkip = true;
    843                 }
    844             }
     828        rc = RTPathReal(strSource.c_str(), szSrcReal, sizeof(szSrcReal));
     829        if (RT_FAILURE(rc))
     830        {
     831            setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     832                                Utf8StrFmt(GuestSession::tr("Source path lookup for \"%s\" failed: %Rrc"),
     833                                           strSource.c_str(), rc));
    845834        }
    846835        else
    847836        {
    848             setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    849                                 Utf8StrFmt(GuestSession::tr("Source file lookup for \"%s\" failed: %Rrc"),
    850                                            strSource.c_str(), rc));
     837            rc = RTPathQueryInfo(szSrcReal, &srcObjInfo, RTFSOBJATTRADD_NOTHING);
     838            if (RT_SUCCESS(rc))
     839            {
     840                if (fFileCopyFlags & FileCopyFlag_Update)
     841                {
     842                    RTTIMESPEC dstModificationTimeTS;
     843                    RTTimeSpecSetSeconds(&dstModificationTimeTS, dstObjData.mModificationTime);
     844                    if (RTTimeSpecCompare(&dstModificationTimeTS, &srcObjInfo.ModificationTime) <= 0)
     845                    {
     846                        setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     847                                            Utf8StrFmt(GuestSession::tr("Destination file \"%s\" has same or newer modification date"),
     848                                                       strDestFinal.c_str()));
     849                        fSkip = true;
     850                    }
     851                }
     852            }
     853            else
     854            {
     855                setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     856                                    Utf8StrFmt(GuestSession::tr("Source file lookup for \"%s\" failed: %Rrc"),
     857                                               szSrcReal, rc));
     858            }
    851859        }
    852860    }
     
    862870    {
    863871        RTFILE hSrcFile;
    864         rc = RTFileOpen(&hSrcFile, strSource.c_str(),
     872        rc = RTFileOpen(&hSrcFile, szSrcReal,
    865873                        RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); /** @todo Use the correct open modes! */
    866874        if (RT_SUCCESS(rc))
    867875        {
    868876            LogFlowThisFunc(("Copying '%s' to '%s' (%RI64 bytes) ...\n",
    869                              strSource.c_str(), strDestFinal.c_str(), srcObjInfo.cbObject));
     877                             szSrcReal, strDestFinal.c_str(), srcObjInfo.cbObject));
    870878
    871879            rc = fileCopyToGuestInner(&hSrcFile, dstFile, fFileCopyFlags, 0 /* Offset, unused */, srcObjInfo.cbObject);
     
    877885            setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    878886                                Utf8StrFmt(GuestSession::tr("Opening source file \"%s\" failed: %Rrc"),
    879                                            strSource.c_str(), rc));
     887                                           szSrcReal, rc));
    880888    }
    881889
     
    888896
    889897/**
    890  * Translates a source path to a destination path (can be both sides,
    891  * either host or guest). The source root is needed to determine the start
    892  * of the relative source path which also needs to present in the destination
    893  * path.
     898 * Adds a guest file system entry to a given list.
    894899 *
    895  * @return  IPRT status code.
    896  * @param   strSourceRoot           Source root path. No trailing directory slash!
    897  * @param   strSource               Actual source to transform. Must begin with
    898  *                                  the source root path!
    899  * @param   strDest                 Destination path.
    900  * @param   strOut                  where to store the output path.
     900 * @return VBox status code.
     901 * @param  strFile              Path to file system entry to add.
     902 * @param  fsObjData            Guest file system information of entry to add.
    901903 */
    902 int GuestSessionTask::pathConstructOnGuest(const Utf8Str &strSourceRoot, const Utf8Str &strSource,
    903                                            const Utf8Str &strDest, Utf8Str &strOut)
    904 {
    905     RT_NOREF(strSourceRoot, strSource, strDest, strOut);
     904int FsList::AddEntryFromGuest(const Utf8Str &strFile, const GuestFsObjData &fsObjData)
     905{
     906    LogFlowFunc(("Adding '%s'\n", strFile.c_str()));
     907
     908    FsEntry *pEntry = NULL;
     909    try
     910    {
     911        pEntry = new FsEntry();
     912        pEntry->fMode = fsObjData.GetFileMode();
     913        pEntry->strPath = strFile;
     914
     915        mVecEntries.push_back(pEntry);
     916    }
     917    catch (...)
     918    {
     919        if (pEntry)
     920            delete pEntry;
     921        return VERR_NO_MEMORY;
     922    }
     923
    906924    return VINF_SUCCESS;
    907925}
    908926
    909 SessionTaskOpen::SessionTaskOpen(GuestSession *pSession,
    910                                  uint32_t uFlags,
    911                                  uint32_t uTimeoutMS)
    912                                  : GuestSessionTask(pSession),
    913                                    mFlags(uFlags),
    914                                    mTimeoutMS(uTimeoutMS)
     927/**
     928 * Adds a host file system entry to a given list.
     929 *
     930 * @return VBox status code.
     931 * @param  strFile              Path to file system entry to add.
     932 * @param  pcObjInfo            File system information of entry to add.
     933 */
     934int FsList::AddEntryFromHost(const Utf8Str &strFile, PCRTFSOBJINFO pcObjInfo)
     935{
     936    LogFlowFunc(("Adding '%s'\n", strFile.c_str()));
     937
     938    FsEntry *pEntry = NULL;
     939    try
     940    {
     941        pEntry = new FsEntry();
     942        pEntry->fMode = pcObjInfo->Attr.fMode & RTFS_TYPE_MASK;
     943        pEntry->strPath = strFile;
     944
     945        mVecEntries.push_back(pEntry);
     946    }
     947    catch (...)
     948    {
     949        if (pEntry)
     950            delete pEntry;
     951        return VERR_NO_MEMORY;
     952    }
     953
     954    return VINF_SUCCESS;
     955}
     956
     957FsList::FsList(const GuestSessionTask &Task)
     958    : mTask(Task)
     959{
     960}
     961
     962FsList::~FsList()
     963{
     964    Destroy();
     965}
     966
     967/**
     968 * Initializes a file list.
     969 *
     970 * @return VBox status code.
     971 * @param  strSrcRootAbs        Source root path (absolute) for this file list.
     972 * @param  strDstRootAbs        Destination root path (absolute) for this file list.
     973 * @param  SourceSpec           Source specification to use.
     974 */
     975int FsList::Init(const Utf8Str &strSrcRootAbs, const Utf8Str &strDstRootAbs,
     976                 const GuestSessionFsSourceSpec &SourceSpec)
     977{
     978    mSrcRootAbs = strSrcRootAbs;
     979    mDstRootAbs = strDstRootAbs;
     980    mSourceSpec = SourceSpec;
     981
     982    /* If the source is a directory, make sure the path is properly terminated already. */
     983    if (mSourceSpec.enmType == GuestSessionFsSourceType_Dir)
     984    {
     985        if (   !mSrcRootAbs.endsWith("/")
     986            && !mSrcRootAbs.endsWith("\\"))
     987            mSrcRootAbs += mSourceSpec.enmPathStyle == PathStyle_DOS ? "\\" : "/";
     988
     989        if (   !mDstRootAbs.endsWith("/")
     990            && !mDstRootAbs.endsWith("\\"))
     991            mDstRootAbs += "/";
     992    }
     993
     994    return VINF_SUCCESS;
     995}
     996
     997/**
     998 * Destroys a file list.
     999 */
     1000void FsList::Destroy(void)
     1001{
     1002    LogFlowFuncEnter();
     1003
     1004    FsEntries::iterator itEntry = mVecEntries.begin();
     1005    while (itEntry != mVecEntries.end())
     1006    {
     1007        FsEntry *pEntry = *itEntry;
     1008        delete pEntry;
     1009        mVecEntries.erase(itEntry);
     1010        itEntry = mVecEntries.begin();
     1011    }
     1012
     1013    Assert(mVecEntries.empty());
     1014
     1015    LogFlowFuncLeave();
     1016}
     1017
     1018/**
     1019 * Builds a guest file list from a given path (and optional filter).
     1020 *
     1021 * @return VBox status code.
     1022 * @param  strPath              Directory on the guest to build list from.
     1023 * @param  strSubDir            Current sub directory path; needed for recursion.
     1024 *                              Set to an empty path.
     1025 */
     1026int FsList::AddDirFromGuest(const Utf8Str &strPath, const Utf8Str &strSubDir /* = "" */)
     1027{
     1028    Utf8Str strPathAbs = strPath;
     1029    if (   !strPathAbs.endsWith("/")
     1030        && !strPathAbs.endsWith("\\"))
     1031        strPathAbs += mSourceSpec.enmPathStyle == PathStyle_DOS ? "\\" : "/";
     1032
     1033    Utf8Str strPathSub = strSubDir;
     1034    if (   strPathSub.isNotEmpty()
     1035        && !strPathSub.endsWith("/")
     1036        && !strPathSub.endsWith("\\"))
     1037        strPathSub += mSourceSpec.enmPathStyle == PathStyle_DOS ? "\\" : "/";
     1038
     1039    strPathAbs += strPathSub;
     1040
     1041    LogFlowFunc(("Entering '%s' (sub '%s')\n", strPathAbs.c_str(), strPathSub.c_str()));
     1042
     1043    GuestDirectoryOpenInfo dirOpenInfo;
     1044    dirOpenInfo.mFilter = "";
     1045    dirOpenInfo.mPath   = strPathAbs;
     1046    dirOpenInfo.mFlags  = 0; /** @todo Handle flags? */
     1047
     1048    const ComObjPtr<GuestSession> &pSession = mTask.GetSession();
     1049
     1050    ComObjPtr <GuestDirectory> pDir; int rcGuest;
     1051    int rc = pSession->i_directoryOpen(dirOpenInfo, pDir, &rcGuest);
     1052    if (RT_FAILURE(rc))
     1053    {
     1054        switch (rc)
     1055        {
     1056            case VERR_INVALID_PARAMETER:
     1057               break;
     1058
     1059            case VERR_GSTCTL_GUEST_ERROR:
     1060                break;
     1061
     1062            default:
     1063                break;
     1064        }
     1065
     1066        return rc;
     1067    }
     1068
     1069    if (strPathSub.isNotEmpty())
     1070    {
     1071        GuestFsObjData fsObjData;
     1072        fsObjData.mType = FsObjType_Directory;
     1073
     1074        rc = AddEntryFromGuest(strPathSub, fsObjData);
     1075    }
     1076
     1077    if (RT_SUCCESS(rc))
     1078    {
     1079        ComObjPtr<GuestFsObjInfo> fsObjInfo;
     1080        while (RT_SUCCESS(rc = pDir->i_readInternal(fsObjInfo, &rcGuest)))
     1081        {
     1082            FsObjType_T enmObjType = FsObjType_Unknown; /* Shut up MSC. */
     1083            HRESULT hr2 = fsObjInfo->COMGETTER(Type)(&enmObjType);
     1084            AssertComRC(hr2);
     1085
     1086            com::Bstr bstrName;
     1087            hr2 = fsObjInfo->COMGETTER(Name)(bstrName.asOutParam());
     1088            AssertComRC(hr2);
     1089
     1090            Utf8Str strEntry = strPathSub + Utf8Str(bstrName);
     1091
     1092            LogFlowFunc(("Entry '%s'\n", strEntry.c_str()));
     1093
     1094            switch (enmObjType)
     1095            {
     1096                case FsObjType_Directory:
     1097                {
     1098                    if (   bstrName.equals(".")
     1099                        || bstrName.equals(".."))
     1100                    {
     1101                        break;
     1102                    }
     1103
     1104                    if (!(mSourceSpec.Type.Dir.fRecursive))
     1105                        break;
     1106
     1107                    rc = AddDirFromGuest(strPath, strEntry);
     1108                    break;
     1109                }
     1110
     1111                case FsObjType_Symlink:
     1112                {
     1113                    if (mSourceSpec.fFollowSymlinks)
     1114                    {
     1115                        /** @todo Symlink handling from guest is not imlemented yet.
     1116                         *        See IGuestSession::symlinkRead(). */
     1117                    }
     1118                    break;
     1119                }
     1120
     1121                case FsObjType_File:
     1122                {
     1123                    rc = AddEntryFromGuest(strEntry, fsObjInfo->i_getData());
     1124                    break;
     1125                }
     1126
     1127                default:
     1128                    break;
     1129            }
     1130        }
     1131    }
     1132
     1133    int rc2 = pDir->i_closeInternal(&rcGuest);
     1134    if (RT_SUCCESS(rc))
     1135        rc = rc2;
     1136
     1137    return rc;
     1138}
     1139
     1140/**
     1141 * Builds a host file list from a given path (and optional filter).
     1142 *
     1143 * @return VBox status code.
     1144 * @param  strPath              Directory on the host to build list from.
     1145 * @param  strSubDir            Current sub directory path; needed for recursion.
     1146 *                              Set to an empty path.
     1147 */
     1148int FsList::AddDirFromHost(const Utf8Str &strPath, const Utf8Str &strSubDir)
     1149{
     1150    Utf8Str strPathAbs = strPath;
     1151    if (   !strPathAbs.endsWith("/")
     1152        && !strPathAbs.endsWith("\\"))
     1153        strPathAbs += "/";
     1154
     1155    Utf8Str strPathSub = strSubDir;
     1156    if (   strPathSub.isNotEmpty()
     1157        && !strPathSub.endsWith("/")
     1158        && !strPathSub.endsWith("\\"))
     1159        strPathSub += "/";
     1160
     1161    strPathAbs += strPathSub;
     1162
     1163    LogFlowFunc(("Entering '%s' (sub '%s')\n", strPathAbs.c_str(), strPathSub.c_str()));
     1164
     1165    RTFSOBJINFO objInfo;
     1166    int rc = RTPathQueryInfo(strPathAbs.c_str(), &objInfo, RTFSOBJATTRADD_NOTHING);
     1167    if (RT_SUCCESS(rc))
     1168    {
     1169        if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode))
     1170        {
     1171            if (strPathSub.isNotEmpty())
     1172                rc = AddEntryFromHost(strPathSub, &objInfo);
     1173
     1174            if (RT_SUCCESS(rc))
     1175            {
     1176                RTDIR hDir;
     1177                rc = RTDirOpen(&hDir, strPathAbs.c_str());
     1178                if (RT_SUCCESS(rc))
     1179                {
     1180                    do
     1181                    {
     1182                        /* Retrieve the next directory entry. */
     1183                        RTDIRENTRYEX Entry;
     1184                        rc = RTDirReadEx(hDir, &Entry, NULL, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
     1185                        if (RT_FAILURE(rc))
     1186                        {
     1187                            if (rc == VERR_NO_MORE_FILES)
     1188                                rc = VINF_SUCCESS;
     1189                            break;
     1190                        }
     1191
     1192                        Utf8Str strEntry = strPathSub + Utf8Str(Entry.szName);
     1193
     1194                        LogFlowFunc(("Entry '%s'\n", strEntry.c_str()));
     1195
     1196                        switch (Entry.Info.Attr.fMode & RTFS_TYPE_MASK)
     1197                        {
     1198                            case RTFS_TYPE_DIRECTORY:
     1199                            {
     1200                                /* Skip "." and ".." entries. */
     1201                                if (RTDirEntryExIsStdDotLink(&Entry))
     1202                                    break;
     1203
     1204                                if (!(mSourceSpec.Type.Dir.fRecursive))
     1205                                    break;
     1206
     1207                                rc = AddDirFromHost(strPath, strEntry);
     1208                                break;
     1209                            }
     1210
     1211                            case RTFS_TYPE_FILE:
     1212                            {
     1213                                rc = AddEntryFromHost(strEntry, &Entry.Info);
     1214                                break;
     1215                            }
     1216
     1217                            case RTFS_TYPE_SYMLINK:
     1218                            {
     1219                                if (mSourceSpec.fFollowSymlinks)
     1220                                {
     1221                                    Utf8Str strEntryAbs = strPathAbs + Utf8Str(Entry.szName);
     1222
     1223                                    char szPathReal[RTPATH_MAX];
     1224                                    rc = RTPathReal(strEntryAbs.c_str(), szPathReal, sizeof(szPathReal));
     1225                                    if (RT_SUCCESS(rc))
     1226                                    {
     1227                                        rc = RTPathQueryInfo(szPathReal, &objInfo, RTFSOBJATTRADD_NOTHING);
     1228                                        if (RT_SUCCESS(rc))
     1229                                        {
     1230                                            LogFlowFunc(("Symlink '%s' -> '%s'\n", strEntryAbs.c_str(), szPathReal));
     1231
     1232                                            if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode))
     1233                                            {
     1234                                                LogFlowFunc(("Symlink to directory\n"));
     1235                                                rc = AddDirFromHost(strPath, strEntry);
     1236                                            }
     1237                                            else if (RTFS_IS_FILE(objInfo.Attr.fMode))
     1238                                            {
     1239                                                LogFlowFunc(("Symlink to file\n"));
     1240                                                rc = AddEntryFromHost(strEntry, &objInfo);
     1241                                            }
     1242                                            else
     1243                                                rc = VERR_NOT_SUPPORTED;
     1244                                        }
     1245                                       else
     1246                                           LogFlowFunc(("Unable to query symlink info for '%s', rc=%Rrc\n", szPathReal, rc));
     1247                                    }
     1248                                    else
     1249                                    {
     1250                                        LogFlowFunc(("Unable to resolve symlink for '%s', rc=%Rrc\n", strPathAbs.c_str(), rc));
     1251                                        if (rc == VERR_FILE_NOT_FOUND) /* Broken symlink, skip. */
     1252                                            rc = VINF_SUCCESS;
     1253                                    }
     1254                                }
     1255                                break;
     1256                            }
     1257
     1258                            default:
     1259                                break;
     1260                        }
     1261
     1262                    } while (RT_SUCCESS(rc));
     1263
     1264                    RTDirClose(hDir);
     1265                }
     1266            }
     1267        }
     1268        else if (RTFS_IS_FILE(objInfo.Attr.fMode))
     1269        {
     1270            rc = VERR_IS_A_FILE;
     1271        }
     1272        else if (RTFS_IS_SYMLINK(objInfo.Attr.fMode))
     1273        {
     1274            rc = VERR_IS_A_SYMLINK;
     1275        }
     1276        else
     1277            rc = VERR_NOT_SUPPORTED;
     1278    }
     1279    else
     1280        LogFlowFunc(("Unable to query '%s', rc=%Rrc\n", strPathAbs.c_str(), rc));
     1281
     1282    LogFlowFuncLeaveRC(rc);
     1283    return rc;
     1284}
     1285
     1286GuestSessionTaskOpen::GuestSessionTaskOpen(GuestSession *pSession, uint32_t uFlags, uint32_t uTimeoutMS)
     1287                                           : GuestSessionTask(pSession)
     1288                                           , mFlags(uFlags)
     1289                                           , mTimeoutMS(uTimeoutMS)
    9151290{
    9161291    m_strTaskName = "gctlSesOpen";
    9171292}
    9181293
    919 SessionTaskOpen::~SessionTaskOpen(void)
    920 {
    921 
    922 }
    923 
    924 int SessionTaskOpen::Run(void)
     1294GuestSessionTaskOpen::~GuestSessionTaskOpen(void)
     1295{
     1296
     1297}
     1298
     1299int GuestSessionTaskOpen::Run(void)
    9251300{
    9261301    LogFlowThisFuncEnter();
     
    9361311}
    9371312
    938 SessionTaskCopyDirFrom::SessionTaskCopyDirFrom(GuestSession *pSession, const Utf8Str &strSource, const Utf8Str &strDest, const Utf8Str &strFilter,
    939                                                DirectoryCopyFlag_T fDirCopyFlags)
    940                                                : GuestSessionCopyTask(pSession)
    941 {
    942     m_strTaskName = "gctlCpyDirFrm";
    943 
    944     mSource = strSource;
    945     mDest   = strDest;
    946     mFilter = strFilter;
    947 
    948     u.Dir.fCopyFlags = fDirCopyFlags;
    949 }
    950 
    951 SessionTaskCopyDirFrom::~SessionTaskCopyDirFrom(void)
    952 {
    953 }
    954 
     1313GuestSessionCopyTask::GuestSessionCopyTask(GuestSession *pSession)
     1314                                           : GuestSessionTask(pSession)
     1315{
     1316}
     1317
     1318GuestSessionCopyTask::~GuestSessionCopyTask()
     1319{
     1320    FsLists::iterator itList = mVecLists.begin();
     1321    while (itList != mVecLists.end())
     1322    {
     1323        FsList *pFsList = (*itList);
     1324        pFsList->Destroy();
     1325        delete pFsList;
     1326        mVecLists.erase(itList);
     1327        itList = mVecLists.begin();
     1328    }
     1329
     1330    Assert(mVecLists.empty());
     1331}
     1332
     1333GuestSessionTaskCopyFrom::GuestSessionTaskCopyFrom(GuestSession *pSession, GuestSessionFsSourceSet vecSrc, const Utf8Str &strDest)
     1334                                                   : GuestSessionCopyTask(pSession)
     1335{
     1336    m_strTaskName = "gctlCpyFrm";
     1337
     1338    mSources = vecSrc;
     1339    mDest    = strDest;
     1340}
     1341
     1342GuestSessionTaskCopyFrom::~GuestSessionTaskCopyFrom(void)
     1343{
     1344}
     1345
     1346#if 0
    9551347/**
    9561348 * Copys a directory (tree) from guest to the host.
     
    11131505    return rc;
    11141506}
    1115 
    1116 int SessionTaskCopyDirFrom::Run(void)
     1507#endif
     1508
     1509HRESULT GuestSessionTaskCopyFrom::Init(const Utf8Str &strTaskDesc)
     1510{
     1511    setTaskDesc(strTaskDesc);
     1512
     1513    /* Create the progress object. */
     1514    ComObjPtr<Progress> pProgress;
     1515    HRESULT hr = pProgress.createObject();
     1516    if (FAILED(hr))
     1517        return hr;
     1518
     1519    mProgress = pProgress;
     1520
     1521    int rc = VINF_SUCCESS;
     1522
     1523    ULONG cOperations = 0;
     1524
     1525    GuestSessionFsSourceSet::iterator itSrc = mSources.begin();
     1526    while (itSrc != mSources.end())
     1527    {
     1528        Utf8Str strSrc = itSrc->strSource;
     1529        Utf8Str strDst = mDest;
     1530
     1531        if (itSrc->enmType == GuestSessionFsSourceType_Dir)
     1532        {
     1533            /* If the source does not end with a slash, copy over the entire directory
     1534             * (and not just its contents). */
     1535            if (   !strSrc.endsWith("/")
     1536                && !strSrc.endsWith("\\"))
     1537            {
     1538                if (   !strDst.endsWith("/")
     1539                    && !strDst.endsWith("\\"))
     1540                    strDst += mPathStyle;
     1541
     1542                strDst += Utf8StrFmt("%s", RTPathFilenameEx(strSrc.c_str(), mfPathStyle));
     1543            }
     1544        }
     1545
     1546        GuestFsObjData srcObjData; int rcGuest;
     1547        rc = mSession->i_fsQueryInfo(strSrc, itSrc->fFollowSymlinks ? TRUE : FALSE,
     1548                                     srcObjData, &rcGuest);
     1549        if (RT_FAILURE(rc))
     1550        {
     1551            break;
     1552        }
     1553
     1554        if (srcObjData.mType == FsObjType_Directory)
     1555        {
     1556            if (itSrc->enmType != GuestSessionFsSourceType_Dir)
     1557            {
     1558                rc = VERR_NOT_A_FILE;
     1559                break;
     1560            }
     1561        }
     1562        else
     1563        {
     1564            if (itSrc->enmType != GuestSessionFsSourceType_File)
     1565            {
     1566                rc = VERR_NOT_A_DIRECTORY;
     1567                break;
     1568            }
     1569        }
     1570
     1571        LogFlowFunc(("strSrc=%s, strDst=%s\n", strSrc.c_str(), strDst.c_str()));
     1572
     1573#if 0
     1574        if (itSrc->enmType == GuestSessionFsSourceType_Dir)
     1575        {
     1576            bool fDstExists = RTDirExists(strDstDir.c_str());
     1577            if (fDstExists)
     1578            {
     1579                if (!(itSrc->Type.Dir.fCopyFlags & DirectoryCopyFlag_CopyIntoExisting))
     1580                {
     1581                    setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     1582                                        Utf8StrFmt(GuestSession::tr("Destination directory \"%s\" exists when it must not"), mDest.c_str()));
     1583                    rc = VERR_ALREADY_EXISTS;
     1584                    break;
     1585                }
     1586            }
     1587
     1588            if (   !strSrcDir.endsWith("/")
     1589                && !strSrcDir.endsWith("\\"))
     1590            {
     1591                if (   !strDstDir.endsWith("/")
     1592                    && !strDstDir.endsWith("\\"))
     1593                        strDstDir += "/"; /* IPRT can handle / on all hosts. */
     1594
     1595                strDstDir += Utf8StrFmt("%s", RTPathFilenameEx(strSrcDir.c_str(), mfPathStyle));
     1596            }
     1597
     1598            /* Create the final target directory on the host.
     1599             * The target directory might already exist on the host (which can be controlled by the copy flags). */
     1600            fDstExists = RTDirExists(strDstDir.c_str());
     1601            if (fDstExists)
     1602            {
     1603                if (!(itSrc->Type.Dir.fCopyFlags & DirectoryCopyFlag_CopyIntoExisting))
     1604                {
     1605                    setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     1606                                        Utf8StrFmt(GuestSession::tr("Destination directory \"%s\" exists when it must not"), strDstDir.c_str()));
     1607                    rc = VERR_ALREADY_EXISTS;
     1608                    break;
     1609                }
     1610            }
     1611            else
     1612            {
     1613                rc = RTDirCreate(strDstDir.c_str(), fDirMode, 0);
     1614                if (RT_FAILURE(rc))
     1615                {
     1616                    setProgressErrorMsg(VBOX_E_IPRT_ERROR,
     1617                                        Utf8StrFmt(GuestSession::tr("Error creating destination directory \"%s\", rc=%Rrc"),
     1618                                                   strDstDir.c_str(), rc));
     1619                    break;
     1620                }
     1621            }
     1622        }
     1623        else if (itSrc->enmType == GuestSessionFsSourceType_File)
     1624        {
     1625
     1626        }
     1627        else
     1628            AssertFailed();
     1629#endif
     1630
     1631        FsList *pFsList = NULL;
     1632        try
     1633        {
     1634            pFsList = new FsList(*this);
     1635            rc = pFsList->Init(strSrc, strDst, *itSrc);
     1636            if (RT_SUCCESS(rc))
     1637            {
     1638                if (itSrc->enmType == GuestSessionFsSourceType_Dir)
     1639                {
     1640                    rc = pFsList->AddDirFromGuest(strSrc);
     1641                }
     1642                else
     1643                    rc = pFsList->AddEntryFromGuest(RTPathFilename(strSrc.c_str()), srcObjData);
     1644            }
     1645
     1646            if (RT_FAILURE(rc))
     1647            {
     1648                delete pFsList;
     1649                break;
     1650            }
     1651
     1652            mVecLists.push_back(pFsList);
     1653        }
     1654        catch (...)
     1655        {
     1656            rc = VERR_NO_MEMORY;
     1657            break;
     1658        }
     1659
     1660        AssertPtr(pFsList);
     1661        cOperations += (ULONG)pFsList->mVecEntries.size();
     1662
     1663        itSrc++;
     1664    }
     1665
     1666    if (RT_SUCCESS(rc))
     1667    {
     1668        Utf8Str strFirstOp;
     1669        if (cOperations) /* Use the first element as description (if available). */
     1670        {
     1671            Assert(mVecLists.size());
     1672            Assert(mVecLists[0]->mVecEntries.size());
     1673
     1674            strFirstOp = mDest + mVecLists[0]->mVecEntries[0]->strPath;
     1675        }
     1676
     1677        hr = pProgress->init(static_cast<IGuestSession*>(mSession), Bstr(mDesc).raw(),
     1678                             TRUE /* aCancelable */, cOperations + 1 /* Number of operations */,
     1679                             Bstr(strFirstOp).raw());
     1680    }
     1681
     1682    return rc;
     1683}
     1684
     1685int GuestSessionTaskCopyFrom::Run(void)
    11171686{
    11181687    LogFlowThisFuncEnter();
     
    11211690    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    11221691
    1123     const bool fRecursive      = true; /** @todo Make this configurable. */
    1124     const bool fFollowSymlinks = true; /** @todo Make this configurable. */
    1125     const uint32_t fDirMode    = 0700; /* Play safe by default. */
    1126 
    11271692    int rc = VINF_SUCCESS;
    11281693
    1129     Utf8Str strSrcDir = mSource;
    1130     Utf8Str strDstDir = mDest;
    1131 
    1132     bool fDstExists = RTDirExists(strDstDir.c_str());
    1133     if (fDstExists)
    1134     {
    1135         if (!(u.Dir.fCopyFlags & DirectoryCopyFlag_CopyIntoExisting))
    1136         {
    1137             setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    1138                                 Utf8StrFmt(GuestSession::tr("Destination directory \"%s\" exists when it must not"), strDstDir.c_str()));
    1139             rc = VERR_ALREADY_EXISTS;
    1140         }
    1141     }
    1142 
    1143     if (RT_FAILURE(rc))
    1144         return rc;
    1145 
    1146     if (   !strSrcDir.endsWith("/")
    1147         && !strSrcDir.endsWith("\\"))
    1148     {
    1149         if (   !strDstDir.endsWith("/")
    1150             && !strDstDir.endsWith("\\"))
    1151                 strDstDir += "/"; /* IPRT can handle / on all hosts. */
    1152 
    1153         strDstDir += Utf8StrFmt("%s", RTPathFilenameEx(strSrcDir.c_str(), mfPathStyle));
    1154     }
    1155 
    1156     /* Create the final target directory on the host.
    1157      * The target directory might already exist on the host (based on u.Dir.fCopyFlags). */
    1158     fDstExists = RTDirExists(strDstDir.c_str());
    1159     if (fDstExists)
    1160     {
    1161         if (!(u.Dir.fCopyFlags & DirectoryCopyFlag_CopyIntoExisting))
    1162         {
    1163             setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    1164                                 Utf8StrFmt(GuestSession::tr("Destination directory \"%s\" exists when it must not"), strDstDir.c_str()));
    1165             rc = VERR_ALREADY_EXISTS;
    1166         }
    1167     }
    1168     else
    1169     {
    1170         rc = RTDirCreate(strDstDir.c_str(), fDirMode, 0);
     1694    FsLists::const_iterator itList = mVecLists.begin();
     1695    while (itList != mVecLists.end())
     1696    {
     1697        FsList *pList = *itList;
     1698        AssertPtr(pList);
     1699
     1700        const bool     fCopyIntoExisting = pList->mSourceSpec.Type.Dir.fCopyFlags & DirectoryCopyFlag_CopyIntoExisting;
     1701        const uint32_t fDirMode          = 0700; /** @todo Play safe by default; implement ACLs. */
     1702
     1703        LogFlowFunc(("List: srcRootAbs=%s, dstRootAbs=%s\n", pList->mSrcRootAbs.c_str(), pList->mDstRootAbs.c_str()));
     1704
     1705        /* Create the root directory. */
     1706        if (pList->mSourceSpec.enmType == GuestSessionFsSourceType_Dir)
     1707        {
     1708            rc = RTDirCreate(pList->mDstRootAbs.c_str(), fDirMode, 0 /* fCreate */);
     1709            if (   rc == VWRN_ALREADY_EXISTS
     1710                && !fCopyIntoExisting)
     1711            {
     1712                break;
     1713            }
     1714        }
     1715
     1716        FsEntries::const_iterator itEntry = pList->mVecEntries.begin();
     1717        while (itEntry != pList->mVecEntries.end())
     1718        {
     1719            FsEntry *pEntry = *itEntry;
     1720            AssertPtr(pEntry);
     1721
     1722            Utf8Str strSrcAbs = pList->mSrcRootAbs;
     1723            Utf8Str strDstAbs = pList->mDstRootAbs;
     1724            if (pList->mSourceSpec.enmType == GuestSessionFsSourceType_Dir)
     1725            {
     1726                strSrcAbs += pEntry->strPath;
     1727                strDstAbs += pEntry->strPath;
     1728            }
     1729
     1730            LogFlowFunc(("Entry '%s': %s -> %s\n", pEntry->strPath.c_str(), strSrcAbs.c_str(), strDstAbs.c_str()));
     1731
     1732            switch (pEntry->fMode & RTFS_TYPE_MASK)
     1733            {
     1734                case RTFS_TYPE_DIRECTORY:
     1735                    if (!pList->mSourceSpec.fDryRun)
     1736                    {
     1737                        rc = RTDirCreate(strDstAbs.c_str(), fDirMode, 0 /* fCreate */);
     1738                        if (rc == VERR_ALREADY_EXISTS)
     1739                        {
     1740                            if (!fCopyIntoExisting)
     1741                            {
     1742                                break;
     1743                            }
     1744
     1745                            rc = VINF_SUCCESS;
     1746                        }
     1747
     1748                        if (RT_FAILURE(rc))
     1749                            break;
     1750                    }
     1751                    break;
     1752
     1753                case RTFS_TYPE_FILE:
     1754                    if (!pList->mSourceSpec.fDryRun)
     1755                        rc = fileCopyFromGuest(strSrcAbs, strDstAbs, FileCopyFlag_None);
     1756                    break;
     1757
     1758                default:
     1759                    LogFlowFunc(("Warning: Type %d for '%s' is not supported\n",
     1760                                 pEntry->fMode & RTFS_TYPE_MASK, strSrcAbs.c_str()));
     1761                    break;
     1762            }
     1763
     1764            if (RT_FAILURE(rc))
     1765                break;
     1766
     1767            mProgress->SetNextOperation(Bstr(strSrcAbs).raw(), 1);
     1768
     1769            ++itEntry;
     1770        }
     1771
    11711772        if (RT_FAILURE(rc))
    1172             setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    1173                                 Utf8StrFmt(GuestSession::tr("Error creating destination directory \"%s\", rc=%Rrc"),
    1174                                            strDstDir.c_str(), rc));
    1175     }
    1176 
    1177     if (RT_FAILURE(rc))
    1178         return rc;
    1179 
    1180     RTDIR hDir;
    1181     rc = RTDirOpen(&hDir, strDstDir.c_str());
    1182     if (RT_FAILURE(rc))
    1183     {
    1184         setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    1185                             Utf8StrFmt(GuestSession::tr("Error opening destination directory \"%s\", rc=%Rrc"),
    1186                                        strDstDir.c_str(), rc));
    1187         return rc;
    1188     }
    1189 
    1190     LogFlowFunc(("Source: %s -> %s\n", mSource.c_str(), strSrcDir.c_str()));
    1191     LogFlowFunc(("Destination: %s -> %s\n", mDest.c_str(), strDstDir.c_str()));
    1192 
    1193     /* At this point the directory on the host was created and (hopefully) is ready
    1194      * to receive further content. */
    1195     rc = directoryCopyToHost(strSrcDir, mFilter, strDstDir, fRecursive, fFollowSymlinks,
    1196                              "" /* strSubDir; for recursion */);
     1773            break;
     1774
     1775        ++itList;
     1776    }
     1777
    11971778    if (RT_SUCCESS(rc))
    11981779        rc = setProgressSuccess();
    11991780
    1200     RTDirClose(hDir);
    1201 
    12021781    LogFlowFuncLeaveRC(rc);
    12031782    return rc;
    12041783}
    12051784
    1206 SessionTaskCopyDirTo::SessionTaskCopyDirTo(GuestSession *pSession,
    1207                                            const Utf8Str &strSource, const Utf8Str &strDest, const Utf8Str &strFilter,
    1208                                            DirectoryCopyFlag_T fDirCopyFlags)
    1209                                            : GuestSessionCopyTask(pSession)
    1210 {
    1211     m_strTaskName = "gctlCpyDirTo";
    1212 
    1213     mSource = strSource;
    1214     mDest   = strDest;
    1215     mFilter = strFilter;
    1216 
    1217     u.Dir.fCopyFlags = fDirCopyFlags;
    1218 }
    1219 
    1220 SessionTaskCopyDirTo::~SessionTaskCopyDirTo(void)
    1221 {
    1222 
    1223 }
    1224 
    1225 /**
    1226  * Copys a directory (tree) from host to the guest.
    1227  *
    1228  * @return  IPRT status code.
    1229  * @param   strSource               Source directory on the host to copy to the guest.
    1230  * @param   strFilter               DOS-style wildcard filter (?, *).  Optional.
    1231  * @param   strDest                 Destination directory on the guest.
    1232  * @param   fRecursive              Whether to recursively copy the directory contents or not.
    1233  * @param   fFollowSymlinks         Whether to follow symlinks or not.
    1234  * @param   strSubDir               Current sub directory to handle. Needs to NULL and only
    1235  *                                  is needed for recursion.
    1236  */
    1237 int SessionTaskCopyDirTo::directoryCopyToGuest(const Utf8Str &strSource, const Utf8Str &strFilter,
    1238                                                const Utf8Str &strDest, bool fRecursive, bool fFollowSymlinks,
    1239                                                const Utf8Str &strSubDir /* For recursion. */)
    1240 {
    1241     Utf8Str strSrcDir    = strSource;
    1242     Utf8Str strDstDir    = strDest;
    1243     Utf8Str strSrcSubDir = strSubDir;
    1244 
    1245     /* Validation and sanity. */
    1246     if (   !strSrcDir.endsWith("/")
    1247         && !strSrcDir.endsWith("\\"))
    1248         strSrcDir += "/";
    1249 
    1250     if (   !strDstDir.endsWith("/")
    1251         && !strDstDir.endsWith("\\"))
    1252         strDstDir+= "/";
    1253 
    1254     if (    strSrcSubDir.isNotEmpty() /* Optional, for recursion. */
    1255         && !strSrcSubDir.endsWith("/")
    1256         && !strSrcSubDir.endsWith("\\"))
    1257         strSrcSubDir += "/";
    1258 
    1259     Utf8Str strSrcCur = strSrcDir + strSrcSubDir;
    1260 
    1261     LogFlowFunc(("Entering '%s'\n", strSrcCur.c_str()));
    1262 
    1263     int rc;
    1264 
    1265     if (strSrcSubDir.isNotEmpty())
    1266     {
    1267         const uint32_t uMode = 0700; /** @todo */
    1268         rc = directoryCreate(strDstDir + strSrcSubDir, DirectoryCreateFlag_Parents, uMode, fFollowSymlinks);
     1785GuestSessionTaskCopyTo::GuestSessionTaskCopyTo(GuestSession *pSession, GuestSessionFsSourceSet vecSrc, const Utf8Str &strDest)
     1786                                               : GuestSessionCopyTask(pSession)
     1787{
     1788    m_strTaskName = "gctlCpyTo";
     1789
     1790    mSources = vecSrc;
     1791    mDest    = strDest;
     1792}
     1793
     1794GuestSessionTaskCopyTo::~GuestSessionTaskCopyTo(void)
     1795{
     1796}
     1797
     1798HRESULT GuestSessionTaskCopyTo::Init(const Utf8Str &strTaskDesc)
     1799{
     1800    LogFlowFuncEnter();
     1801
     1802    setTaskDesc(strTaskDesc);
     1803
     1804    /* Create the progress object. */
     1805    ComObjPtr<Progress> pProgress;
     1806    HRESULT hr = pProgress.createObject();
     1807    if (FAILED(hr))
     1808        return hr;
     1809
     1810    mProgress = pProgress;
     1811
     1812    int rc = VINF_SUCCESS;
     1813
     1814    ULONG cOperations = 0;
     1815
     1816    GuestSessionFsSourceSet::iterator itSrc = mSources.begin();
     1817    while (itSrc != mSources.end())
     1818    {
     1819        Utf8Str strSrc = itSrc->strSource;
     1820        Utf8Str strDst = mDest;
     1821
     1822        if (itSrc->enmType == GuestSessionFsSourceType_Dir)
     1823        {
     1824            /* If the source does not end with a slash, copy over the entire directory
     1825             * (and not just its contents). */
     1826            if (   !strSrc.endsWith("/")
     1827                && !strSrc.endsWith("\\"))
     1828            {
     1829                if (   !strDst.endsWith("/")
     1830                    && !strDst.endsWith("\\"))
     1831                    strDst += mPathStyle;
     1832
     1833                strDst += Utf8StrFmt("%s", RTPathFilenameEx(strSrc.c_str(), mfPathStyle));
     1834            }
     1835        }
     1836
     1837        RTFSOBJINFO srcFsObjInfo;
     1838        rc = RTPathQueryInfo(strSrc.c_str(), &srcFsObjInfo, RTFSOBJATTRADD_NOTHING);
    12691839        if (RT_FAILURE(rc))
    1270             return rc;
    1271     }
    1272 
    1273     /*
    1274      * Open directory without a filter - RTDirOpenFiltered unfortunately
    1275      * cannot handle sub directories so we have to do the filtering ourselves.
    1276      */
    1277     RTDIR hDir;
    1278     rc = RTDirOpen(&hDir, strSrcCur.c_str());
     1840            break;
     1841
     1842        if (RTFS_IS_DIRECTORY(srcFsObjInfo.Attr.fMode))
     1843        {
     1844            if (itSrc->enmType != GuestSessionFsSourceType_Dir)
     1845            {
     1846                rc = VERR_NOT_A_FILE;
     1847                break;
     1848            }
     1849        }
     1850        else
     1851        {
     1852            if (itSrc->enmType == GuestSessionFsSourceType_Dir)
     1853            {
     1854                rc = VERR_NOT_A_DIRECTORY;
     1855                break;
     1856            }
     1857        }
     1858
     1859        LogFlowFunc(("strSrc=%s, strDst=%s\n", strSrc.c_str(), strDst.c_str()));
     1860
     1861        FsList *pFsList = NULL;
     1862        try
     1863        {
     1864            pFsList = new FsList(*this);
     1865            rc = pFsList->Init(strSrc, strDst, *itSrc);
     1866            if (RT_SUCCESS(rc))
     1867            {
     1868                if (itSrc->enmType == GuestSessionFsSourceType_Dir)
     1869                {
     1870                    rc = pFsList->AddDirFromHost(strSrc);
     1871                }
     1872                else
     1873                    rc = pFsList->AddEntryFromHost(RTPathFilename(strSrc.c_str()), &srcFsObjInfo);
     1874            }
     1875
     1876            if (RT_FAILURE(rc))
     1877                break;
     1878
     1879            mVecLists.push_back(pFsList);
     1880        }
     1881        catch (...)
     1882        {
     1883            rc = VERR_NO_MEMORY;
     1884            break;
     1885        }
     1886
     1887        AssertPtr(pFsList);
     1888        cOperations += (ULONG)pFsList->mVecEntries.size();
     1889
     1890        itSrc++;
     1891    }
     1892
    12791893    if (RT_SUCCESS(rc))
    12801894    {
    1281         /*
    1282          * Enumerate the directory tree.
    1283          */
    1284         size_t        cbDirEntry = 0;
    1285         PRTDIRENTRYEX pDirEntry  = NULL;
    1286         while (RT_SUCCESS(rc))
    1287         {
    1288             rc = RTDirReadExA(hDir, &pDirEntry, &cbDirEntry, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
    1289             if (RT_FAILURE(rc))
    1290             {
    1291                 if (rc == VERR_NO_MORE_FILES)
    1292                     rc = VINF_SUCCESS;
    1293                 break;
    1294             }
    1295 
    1296 #ifdef LOG_ENABLED
    1297             Utf8Str strDbgCurEntry = strSrcCur + Utf8Str(pDirEntry->szName);
    1298             LogFlowFunc(("Handling '%s' (fMode=0x%x)\n", strDbgCurEntry.c_str(), pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK));
    1299 #endif
    1300             switch (pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK)
     1895        Utf8Str strFirstOp;
     1896        if (cOperations) /* Use the first element as description (if available). */
     1897        {
     1898            Assert(mVecLists.size());
     1899            Assert(mVecLists[0]->mVecEntries.size());
     1900
     1901            strFirstOp = mDest + mVecLists[0]->mVecEntries[0]->strPath;
     1902        }
     1903
     1904        hr = pProgress->init(static_cast<IGuestSession*>(mSession), Bstr(mDesc).raw(),
     1905                             TRUE /* aCancelable */, cOperations + 1 /* Number of operations */,
     1906                             Bstr(strFirstOp).raw());
     1907    }
     1908
     1909    LogFlowFunc(("rc=%Rrc\n", rc));
     1910    return hr;
     1911}
     1912
     1913int GuestSessionTaskCopyTo::Run(void)
     1914{
     1915    LogFlowThisFuncEnter();
     1916
     1917    AutoCaller autoCaller(mSession);
     1918    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     1919
     1920    int rc = VINF_SUCCESS;
     1921
     1922    FsLists::const_iterator itList = mVecLists.begin();
     1923    while (itList != mVecLists.end())
     1924    {
     1925        FsList *pList = *itList;
     1926        AssertPtr(pList);
     1927
     1928        const bool     fFollowSymlinks   = pList->mSourceSpec.fFollowSymlinks;
     1929        const bool     fCopyIntoExisting = pList->mSourceSpec.Type.Dir.fCopyFlags & DirectoryCopyFlag_CopyIntoExisting;
     1930        const uint32_t fDirMode          = 0700; /** @todo Play safe by default; implement ACLs. */
     1931
     1932        LogFlowFunc(("List: srcRootAbs=%s, dstRootAbs=%s\n", pList->mSrcRootAbs.c_str(), pList->mDstRootAbs.c_str()));
     1933
     1934        /* Create the root directory. */
     1935        if (pList->mSourceSpec.enmType == GuestSessionFsSourceType_Dir)
     1936        {
     1937            rc = directoryCreate(pList->mDstRootAbs.c_str(), DirectoryCreateFlag_None, fDirMode, fFollowSymlinks);
     1938            if (   rc == VWRN_ALREADY_EXISTS
     1939                && !fCopyIntoExisting)
     1940            {
     1941                break;
     1942            }
     1943        }
     1944
     1945        FsEntries::const_iterator itEntry = pList->mVecEntries.begin();
     1946        while (itEntry != pList->mVecEntries.end())
     1947        {
     1948            FsEntry *pEntry = *itEntry;
     1949            AssertPtr(pEntry);
     1950
     1951            Utf8Str strSrcAbs = pList->mSrcRootAbs;
     1952            Utf8Str strDstAbs = pList->mDstRootAbs;
     1953            if (pList->mSourceSpec.enmType == GuestSessionFsSourceType_Dir)
     1954            {
     1955                strSrcAbs += pEntry->strPath;
     1956                strDstAbs += pEntry->strPath;
     1957            }
     1958
     1959            LogFlowFunc(("Entry '%s': %s -> %s\n", pEntry->strPath.c_str(), strSrcAbs.c_str(), strDstAbs.c_str()));
     1960
     1961            switch (pEntry->fMode & RTFS_TYPE_MASK)
    13011962            {
    13021963                case RTFS_TYPE_DIRECTORY:
    1303                 {
    1304                     /* Skip "." and ".." entries. */
    1305                     if (RTDirEntryExIsStdDotLink(pDirEntry))
    1306                         break;
    1307 
    1308                     bool fSkip = false;
    1309 
    1310                     if (   strFilter.isNotEmpty()
    1311                         && !RTStrSimplePatternMatch(strFilter.c_str(), pDirEntry->szName))
    1312                         fSkip = true;
    1313 
    1314                     if (   fRecursive
    1315                         && !fSkip)
    1316                         rc = directoryCopyToGuest(strSrcDir, strFilter, strDstDir, fRecursive, fFollowSymlinks,
    1317                                                   strSrcSubDir + Utf8Str(pDirEntry->szName));
    1318                     break;
    1319                 }
    1320 
    1321                 case RTFS_TYPE_SYMLINK:
    1322                     if (fFollowSymlinks)
    1323                     { /* Fall through to next case is intentional. */ }
    1324                     else
    1325                         break;
    1326                     RT_FALL_THRU();
    1327 
    1328                 case RTFS_TYPE_FILE:
    1329                 {
    1330                     if (   strFilter.isNotEmpty()
    1331                         && !RTStrSimplePatternMatch(strFilter.c_str(), pDirEntry->szName))
     1964                    if (!pList->mSourceSpec.fDryRun)
    13321965                    {
    1333                         break; /* Filter does not match. */
    1334                     }
    1335 
    1336                     if (RT_SUCCESS(rc))
    1337                     {
    1338                         Utf8Str strSrcFile = strSrcDir + strSrcSubDir + Utf8Str(pDirEntry->szName);
    1339                         Utf8Str strDstFile = strDstDir + strSrcSubDir + Utf8Str(pDirEntry->szName);
    1340                         rc = fileCopyToGuest(strSrcFile, strDstFile, FileCopyFlag_None);
     1966                        rc = directoryCreate(strDstAbs.c_str(), DirectoryCreateFlag_None, fDirMode, fFollowSymlinks);
     1967                        if (   rc == VWRN_ALREADY_EXISTS
     1968                            && !fCopyIntoExisting)
     1969                        {
     1970                            break;
     1971                        }
    13411972                    }
    13421973                    break;
    1343                 }
     1974
     1975                case RTFS_TYPE_FILE:
     1976                    if (!pList->mSourceSpec.fDryRun)
     1977                        rc = fileCopyToGuest(strSrcAbs, strDstAbs, FileCopyFlag_None);
     1978                    break;
    13441979
    13451980                default:
     1981                    LogFlowFunc(("Warning: Type %d for '%s' is not supported\n",
     1982                                 pEntry->fMode & RTFS_TYPE_MASK, strSrcAbs.c_str()));
    13461983                    break;
    13471984            }
     1985
    13481986            if (RT_FAILURE(rc))
    13491987                break;
    1350         }
    1351 
    1352         RTDirReadExAFree(&pDirEntry, &cbDirEntry);
    1353         RTDirClose(hDir);
    1354     }
    1355 
    1356     LogFlowFunc(("Leaving '%s', rc=%Rrc\n", strSrcCur.c_str(), rc));
    1357     return rc;
    1358 }
    1359 
    1360 int SessionTaskCopyDirTo::Run(void)
    1361 {
    1362     LogFlowThisFuncEnter();
    1363 
    1364     AutoCaller autoCaller(mSession);
    1365     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    1366 
    1367     const bool fRecursive      = true; /** @todo Make this configurable. */
    1368     const bool fFollowSymlinks = true; /** @todo Make this configurable. */
    1369     const uint32_t uDirMode    = 0700; /* Play safe by default. */
    1370 
    1371     /* Figure out if we need to copy the entire source directory or just its contents. */
    1372     Utf8Str strSrcDir = mSource;
    1373     Utf8Str strDstDir = mDest;
    1374     if (   !strSrcDir.endsWith("/")
    1375         && !strSrcDir.endsWith("\\"))
    1376     {
    1377         if (   strDstDir.endsWith("/")
    1378             || strDstDir.endsWith("\\"))
    1379         {
    1380             strDstDir += Utf8StrFmt("%s", RTPathFilename(strSrcDir.c_str()));
    1381         }
    1382     }
    1383 
    1384     /* Create the root target directory on the guest.
    1385      * The target directory might already exist on the guest (based on u.Dir.fCopyFlags). */
    1386     int rc = directoryCreate(strDstDir, DirectoryCreateFlag_None, uDirMode, fFollowSymlinks);
    1387     if (   rc == VWRN_ALREADY_EXISTS
    1388         && !(u.Dir.fCopyFlags & DirectoryCopyFlag_CopyIntoExisting))
    1389     {
    1390         setProgressErrorMsg(VBOX_E_IPRT_ERROR,
    1391                             Utf8StrFmt(GuestSession::tr("Destination directory \"%s\" exists when it must not"), strDstDir.c_str()));
    1392     }
    1393 
    1394     if (RT_FAILURE(rc))
    1395         return rc;
    1396 
    1397     /* At this point the directory on the guest was created and (hopefully) is ready
    1398      * to receive further content. */
    1399     rc = directoryCopyToGuest(strSrcDir, mFilter, strDstDir, fRecursive, fFollowSymlinks,
    1400                               "" /* strSubDir; for recursion */);
     1988
     1989            mProgress->SetNextOperation(Bstr(strSrcAbs).raw(), 1);
     1990
     1991            ++itEntry;
     1992        }
     1993
     1994        if (RT_FAILURE(rc))
     1995            break;
     1996
     1997        ++itList;
     1998    }
     1999
    14012000    if (RT_SUCCESS(rc))
    14022001        rc = setProgressSuccess();
     
    14062005}
    14072006
    1408 SessionTaskCopyFileTo::SessionTaskCopyFileTo(GuestSession *pSession,
    1409                                              const Utf8Str &strSource, const Utf8Str &strDest, FileCopyFlag_T fFileCopyFlags)
    1410                                              : GuestSessionCopyTask(pSession)
    1411 {
    1412     m_strTaskName = "gctlCpyFileTo";
    1413 
    1414     mSource = strSource;
    1415     mDest   = strDest;
    1416 
    1417     u.File.fCopyFlags = fFileCopyFlags;
    1418 }
    1419 
    1420 SessionTaskCopyFileTo::~SessionTaskCopyFileTo(void)
    1421 {
    1422 
    1423 }
    1424 
    1425 int SessionTaskCopyFileTo::Run(void)
    1426 {
    1427     LogFlowThisFuncEnter();
    1428 
    1429     AutoCaller autoCaller(mSession);
    1430     if (FAILED(autoCaller.rc())) return autoCaller.rc();
    1431 
    1432     int rc = fileCopyToGuest(mSource, mDest, u.File.fCopyFlags);
    1433     if (RT_SUCCESS(rc))
    1434         rc = setProgressSuccess();
    1435 
    1436     LogFlowFuncLeaveRC(rc);
    1437     return rc;
    1438 }
    1439 
     2007#if 0
    14402008SessionTaskCopyFileFrom::SessionTaskCopyFileFrom(GuestSession *pSession,
    14412009                                                 const Utf8Str &strSource, const Utf8Str &strDest, FileCopyFlag_T fFileCopyFlags)
     
    14472015    mDest   = strDest;
    14482016
    1449     u.File.fCopyFlags = fFileCopyFlags;
     2017    Type.File.fCopyFlags = fFileCopyFlags;
    14502018}
    14512019
     
    14622030    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    14632031
    1464     int rc = fileCopyFromGuest(mSource, mDest, u.File.fCopyFlags);
     2032    int rc = fileCopyFromGuest(mSource, mDest, Type.File.fCopyFlags);
    14652033    if (RT_SUCCESS(rc))
    14662034        rc = setProgressSuccess();
     
    14692037    return rc;
    14702038}
    1471 
    1472 SessionTaskUpdateAdditions::SessionTaskUpdateAdditions(GuestSession *pSession,
    1473                                                        const Utf8Str &strSource,
    1474                                                        const ProcessArguments &aArguments,
    1475                                                        uint32_t fFlags)
    1476                                                        : GuestSessionTask(pSession)
     2039#endif
     2040
     2041GuestSessionTaskUpdateAdditions::GuestSessionTaskUpdateAdditions(GuestSession *pSession,
     2042                                                                 const Utf8Str &strSource,
     2043                                                                 const ProcessArguments &aArguments,
     2044                                                                 uint32_t fFlags)
     2045                                                                 : GuestSessionTask(pSession)
    14772046{
    14782047    m_strTaskName = "gctlUpGA";
     
    14832052}
    14842053
    1485 SessionTaskUpdateAdditions::~SessionTaskUpdateAdditions(void)
    1486 {
    1487 
    1488 }
    1489 
    1490 int SessionTaskUpdateAdditions::addProcessArguments(ProcessArguments &aArgumentsDest, const ProcessArguments &aArgumentsSource)
     2054GuestSessionTaskUpdateAdditions::~GuestSessionTaskUpdateAdditions(void)
     2055{
     2056
     2057}
     2058
     2059int GuestSessionTaskUpdateAdditions::addProcessArguments(ProcessArguments &aArgumentsDest, const ProcessArguments &aArgumentsSource)
    14912060{
    14922061    int rc = VINF_SUCCESS;
     
    15262095}
    15272096
    1528 int SessionTaskUpdateAdditions::copyFileToGuest(GuestSession *pSession, PRTISOFSFILE pISO,
     2097int GuestSessionTaskUpdateAdditions::copyFileToGuest(GuestSession *pSession, PRTISOFSFILE pISO,
    15292098                                                Utf8Str const &strFileSource, const Utf8Str &strFileDest,
    15302099                                                bool fOptional)
     
    15922161}
    15932162
    1594 int SessionTaskUpdateAdditions::runFileOnGuest(GuestSession *pSession, GuestProcessStartupInfo &procInfo)
     2163int GuestSessionTaskUpdateAdditions::runFileOnGuest(GuestSession *pSession, GuestProcessStartupInfo &procInfo)
    15952164{
    15962165    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
     
    16402209}
    16412210
    1642 int SessionTaskUpdateAdditions::Run(void)
     2211int GuestSessionTaskUpdateAdditions::Run(void)
    16432212{
    16442213    LogFlowThisFuncEnter();
Note: See TracChangeset for help on using the changeset viewer.

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