Changeset 71976 in vbox for trunk/src/VBox
- Timestamp:
- Apr 23, 2018 10:52:51 AM (7 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/idl/VirtualBox.xidl
r71932 r71976 11145 11145 11146 11146 <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 11147 11175 name="ProcessCreateFlag" 11148 11176 uuid="C544CD2B-F02D-4886-9901-71C523DB8DC5" … … 11870 11898 <interface 11871 11899 name="IGuestSession" extends="$unknown" 11872 uuid=" 8d3485b3-64a9-4995-998e-6c602b91abd2"11900 uuid="a71fcf9a-a45e-440a-886a-5b4c664195ef" 11873 11901 wsmap="managed" 11874 11902 reservedMethods="8" reservedAttributes="8" … … 12032 12060 are running in the guest will be terminated automatically. 12033 12061 </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> 12034 12126 </method> 12035 12127 -
trunk/src/VBox/Main/include/GuestSessionImpl.h
r71846 r71976 79 79 * @{ */ 80 80 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); 81 94 82 95 HRESULT directoryCopy(const com::Utf8Str &aSource, -
trunk/src/VBox/Main/include/GuestSessionImplTasks.h
r71847 r71976 28 28 #include <iprt/isofs.h> /* For UpdateAdditions. */ 29 29 30 #include <vector> 31 30 32 class Guest; 33 class GuestSessionTask; 31 34 class GuestSessionTaskInternalOpen; 32 35 33 36 /** 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 */ 39 enum 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 */ 53 struct GuestSessionFsSourceSpec 54 { 55 Utf8Str strSource; 56 Utf8Str strFilter; 57 GuestSessionFsSourceType enmType; 58 PathStyle_T enmPathStyle; 59 bool fDryRun; 60 bool fFollowSymlinks; 164 61 union 165 62 { … … 169 66 /** Directory copy flags. */ 170 67 DirectoryCopyFlag_T fCopyFlags; 68 bool fRecursive; 171 69 } Dir; 172 70 /** File-specific data. */ … … 183 81 uint64_t cbSize; 184 82 } 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. */ 87 typedef std::vector<GuestSessionFsSourceSpec> GuestSessionFsSourceSet; 88 89 /** 90 * Structure for keeping a file system entry. 91 */ 92 struct 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. */ 101 typedef 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 */ 107 class FsList 108 { 109 public: 110 111 FsList(const GuestSessionTask &Task); 112 virtual ~FsList(); 113 114 public: 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 125 public: 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. */ 146 typedef 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 */ 152 class GuestSessionTask : public ThreadTask 153 { 154 public: 155 156 GuestSessionTask(GuestSession *pSession); 157 158 virtual ~GuestSessionTask(void); 159 160 public: 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 190 protected: 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 225 protected: 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 */ 242 class GuestSessionTaskOpen : public GuestSessionTask 243 { 244 public: 245 246 GuestSessionTaskOpen(GuestSession *pSession, 247 uint32_t uFlags, 248 uint32_t uTimeoutMS); 249 virtual ~GuestSessionTaskOpen(void); 198 250 int Run(void); 199 251 200 252 protected: 201 253 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 260 class GuestSessionCopyTask : public GuestSessionTask 261 { 262 public: 263 264 GuestSessionCopyTask(GuestSession *pSession); 265 virtual ~GuestSessionCopyTask(); 266 267 protected: 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 */ 281 class GuestSessionTaskCopyFrom : public GuestSessionCopyTask 282 { 283 public: 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); 204 290 }; 205 291 … … 207 293 * Task for copying directories from host to the guest. 208 294 */ 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); 295 class GuestSessionTaskCopyTo : public GuestSessionCopyTask 296 { 297 public: 298 299 GuestSessionTaskCopyTo(GuestSession *pSession, GuestSessionFsSourceSet vecSrc, const Utf8Str &strDest); 300 virtual ~GuestSessionTaskCopyTo(void); 301 302 HRESULT Init(const Utf8Str &strTaskDesc); 216 303 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 */ 309 class GuestSessionTaskUpdateAdditions : public GuestSessionTask 310 { 311 public: 312 313 GuestSessionTaskUpdateAdditions(GuestSession *pSession, 258 314 const Utf8Str &strSource, const ProcessArguments &aArguments, 259 315 uint32_t fFlags); 260 virtual ~ SessionTaskUpdateAdditions(void);316 virtual ~GuestSessionTaskUpdateAdditions(void); 261 317 int Run(void); 262 318 -
trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp
r71648 r71976 535 535 536 536 ComObjPtr<Progress> pProgress; 537 SessionTaskUpdateAdditions *pTask = NULL;537 GuestSessionTaskUpdateAdditions *pTask = NULL; 538 538 try 539 539 { 540 540 try 541 541 { 542 pTask = new SessionTaskUpdateAdditions(pSession /* GuestSession */, aSource, aArgs, fFlags);542 pTask = new GuestSessionTaskUpdateAdditions(pSession /* GuestSession */, aSource, aArgs, fFlags); 543 543 } 544 544 catch(...) -
trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp
r71848 r71976 2630 2630 LogFlowThisFuncEnter(); 2631 2631 2632 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);2633 2634 2632 try 2635 2633 { 2636 SessionTaskCopyFileFrom *pTask = NULL;2634 GuestSessionTaskCopyFrom *pTask = NULL; 2637 2635 ComObjPtr<Progress> pProgress; 2638 2636 try 2639 2637 { 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); 2641 2648 } 2642 2649 catch(...) 2643 2650 { 2644 hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to create SessionTaskCopyF ileFrom object"));2651 hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to create SessionTaskCopyFrom object")); 2645 2652 throw; 2646 2653 } … … 2652 2659 delete pTask; 2653 2660 hrc = setError(VBOX_E_IPRT_ERROR, 2654 tr("Creating progress object for SessionTaskCopyF ileFrom object failed"));2661 tr("Creating progress object for SessionTaskCopyFrom object failed")); 2655 2662 throw hrc; 2656 2663 } … … 2717 2724 LogFlowThisFuncEnter(); 2718 2725 2719 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);2720 2721 2726 try 2722 2727 { 2723 SessionTaskCopyFileTo *pTask = NULL;2728 GuestSessionTaskCopyTo *pTask = NULL; 2724 2729 ComObjPtr<Progress> pProgress; 2725 2730 try 2726 2731 { 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); 2728 2746 } 2729 2747 catch(...) 2730 2748 { 2731 hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to create SessionTaskCopy FileTo object"));2749 hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to create SessionTaskCopyTo object")); 2732 2750 throw; 2733 2751 } … … 2738 2756 delete pTask; 2739 2757 hrc = setError(VBOX_E_IPRT_ERROR, 2740 tr("Creating progress object for SessionTaskCopy FileTo object failed"));2758 tr("Creating progress object for SessionTaskCopyTo object failed")); 2741 2759 throw hrc; 2742 2760 } … … 2768 2786 } 2769 2787 2788 HRESULT 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 2796 HRESULT 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 2770 2804 HRESULT GuestSession::directoryCopy(const com::Utf8Str &aSource, const com::Utf8Str &aDestination, 2771 2805 const std::vector<DirectoryCopyFlag_T> &aFlags, ComPtr<IProgress> &aProgress) … … 2806 2840 LogFlowThisFuncEnter(); 2807 2841 2808 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);2809 2810 2842 try 2811 2843 { 2812 SessionTaskCopyDirFrom *pTask = NULL;2844 GuestSessionTaskCopyFrom *pTask = NULL; 2813 2845 ComObjPtr<Progress> pProgress; 2814 2846 try 2815 2847 { 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); 2818 2858 } 2819 2859 catch(...) 2820 2860 { 2821 hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to create SessionTaskCopy DirFrom object"));2861 hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to create SessionTaskCopyFrom object")); 2822 2862 throw; 2823 2863 } … … 2893 2933 LogFlowThisFuncEnter(); 2894 2934 2895 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);2896 2897 2935 try 2898 2936 { 2899 SessionTaskCopyDirTo *pTask = NULL;2937 GuestSessionTaskCopyTo *pTask = NULL; 2900 2938 ComObjPtr<Progress> pProgress; 2901 2939 try 2902 2940 { 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); 2905 2957 } 2906 2958 catch(...) 2907 2959 { 2908 hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to create SessionTaskCopy DirTo object"));2960 hrc = setError(VBOX_E_IPRT_ERROR, tr("Failed to create SessionTaskCopyTo object")); 2909 2961 throw; 2910 2962 } -
trunk/src/VBox/Main/src-client/GuestSessionImplTasks.cpp
r71849 r71976 72 72 mSession = pSession; 73 73 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 } 76 86 } 77 87 … … 80 90 } 81 91 82 HRESULT GuestSessionTask::createAndSetProgressObject() 83 { 84 LogFlowThisFunc(("Task Description = %s, pTask=%p\n", mDesc.c_str(), this)); 85 92 int GuestSessionTask::createAndSetProgressObject(ULONG cOperations /* = 1 */) 93 { 94 LogFlowThisFunc(("cOperations=%ld\n", cOperations)); 95 96 /* Create the progress object. */ 86 97 ComObjPtr<Progress> pProgress; 87 HRESULT hr = S_OK; 88 /* Create the progress object. */ 89 hr = pProgress.createObject(); 98 HRESULT hr = pProgress.createObject(); 90 99 if (FAILED(hr)) 91 100 return VERR_COM_UNEXPECTED; … … 93 102 hr = pProgress->init(static_cast<IGuestSession*>(mSession), 94 103 Bstr(mDesc).raw(), 95 TRUE /* aCancelable */ );104 TRUE /* aCancelable */, cOperations, Bstr(mDesc).raw()); 96 105 if (FAILED(hr)) 97 106 return VERR_COM_UNEXPECTED; … … 100 109 101 110 LogFlowFuncLeave(); 102 103 return hr; 111 return VINF_SUCCESS; 104 112 } 105 113 … … 207 215 * @return VBox status code. VWRN_ALREADY_EXISTS if directory on the guest already exists. 208 216 * @param strPath Absolute path to directory on the guest (guest style path) to create. 209 * @param enmDirec otryCreateFlags Directory creation flags.217 * @param enmDirectoryCreateFlags Directory creation flags. 210 218 * @param uMode Directory mode to use for creation. 211 219 * @param fFollowSymlinks Whether to follow symlinks on the guest or not. 212 220 */ 213 221 int GuestSessionTask::directoryCreate(const com::Utf8Str &strPath, 214 DirectoryCreateFlag_T enmDirec otryCreateFlags, uint32_t uMode, bool fFollowSymlinks)222 DirectoryCreateFlag_T enmDirectoryCreateFlags, uint32_t uMode, bool fFollowSymlinks) 215 223 { 216 224 LogFlowFunc(("strPath=%s, fFlags=0x%x, uMode=%RU32, fFollowSymlinks=%RTbool\n", 217 strPath.c_str(), enmDirec otryCreateFlags, uMode, fFollowSymlinks));225 strPath.c_str(), enmDirectoryCreateFlags, uMode, fFollowSymlinks)); 218 226 219 227 GuestFsObjData objData; int rcGuest; 220 221 228 int rc = mSession->i_directoryQueryInfo(strPath, fFollowSymlinks, objData, &rcGuest); 222 229 if (RT_SUCCESS(rc)) … … 234 241 case VERR_FILE_NOT_FOUND: 235 242 case VERR_PATH_NOT_FOUND: 236 rc = mSession->i_directoryCreate(strPath.c_str(), uMode, enmDirec otryCreateFlags, &rcGuest);243 rc = mSession->i_directoryCreate(strPath.c_str(), uMode, enmDirectoryCreateFlags, &rcGuest); 237 244 break; 238 245 default: … … 390 397 391 398 GuestFsObjData srcObjData; 392 RT_ZERO(srcObjData);393 394 399 int rcGuest = VERR_IPE_UNINITIALIZED_STATUS; 395 400 int rc = mSession->i_fsQueryInfo(strSource, TRUE /* fFollowSymlinks */, srcObjData, &rcGuest); … … 708 713 709 714 GuestFsObjData dstObjData; 710 RT_ZERO(dstObjData);711 712 715 int rcGuest = VERR_IPE_UNINITIALIZED_STATUS; 713 716 int rc = mSession->i_fsQueryInfo(strDest, TRUE /* fFollowSymlinks */, dstObjData, &rcGuest); … … 738 741 case FsObjType_Directory: 739 742 { 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; 758 754 break; 759 755 } … … 821 817 return rc; 822 818 819 char szSrcReal[RTPATH_MAX]; 820 823 821 RTFSOBJINFO srcObjInfo; 824 822 RT_ZERO(srcObjInfo); … … 828 826 if (RT_SUCCESS(rc)) 829 827 { 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)); 845 834 } 846 835 else 847 836 { 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 } 851 859 } 852 860 } … … 862 870 { 863 871 RTFILE hSrcFile; 864 rc = RTFileOpen(&hSrcFile, s trSource.c_str(),872 rc = RTFileOpen(&hSrcFile, szSrcReal, 865 873 RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); /** @todo Use the correct open modes! */ 866 874 if (RT_SUCCESS(rc)) 867 875 { 868 876 LogFlowThisFunc(("Copying '%s' to '%s' (%RI64 bytes) ...\n", 869 s trSource.c_str(), strDestFinal.c_str(), srcObjInfo.cbObject));877 szSrcReal, strDestFinal.c_str(), srcObjInfo.cbObject)); 870 878 871 879 rc = fileCopyToGuestInner(&hSrcFile, dstFile, fFileCopyFlags, 0 /* Offset, unused */, srcObjInfo.cbObject); … … 877 885 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 878 886 Utf8StrFmt(GuestSession::tr("Opening source file \"%s\" failed: %Rrc"), 879 s trSource.c_str(), rc));887 szSrcReal, rc)); 880 888 } 881 889 … … 888 896 889 897 /** 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. 894 899 * 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. 901 903 */ 902 int GuestSessionTask::pathConstructOnGuest(const Utf8Str &strSourceRoot, const Utf8Str &strSource, 903 const Utf8Str &strDest, Utf8Str &strOut) 904 { 905 RT_NOREF(strSourceRoot, strSource, strDest, strOut); 904 int 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 906 924 return VINF_SUCCESS; 907 925 } 908 926 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 */ 934 int 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 957 FsList::FsList(const GuestSessionTask &Task) 958 : mTask(Task) 959 { 960 } 961 962 FsList::~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 */ 975 int 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 */ 1000 void 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 */ 1026 int 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 */ 1148 int 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 1286 GuestSessionTaskOpen::GuestSessionTaskOpen(GuestSession *pSession, uint32_t uFlags, uint32_t uTimeoutMS) 1287 : GuestSessionTask(pSession) 1288 , mFlags(uFlags) 1289 , mTimeoutMS(uTimeoutMS) 915 1290 { 916 1291 m_strTaskName = "gctlSesOpen"; 917 1292 } 918 1293 919 SessionTaskOpen::~SessionTaskOpen(void)920 { 921 922 } 923 924 int SessionTaskOpen::Run(void)1294 GuestSessionTaskOpen::~GuestSessionTaskOpen(void) 1295 { 1296 1297 } 1298 1299 int GuestSessionTaskOpen::Run(void) 925 1300 { 926 1301 LogFlowThisFuncEnter(); … … 936 1311 } 937 1312 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 1313 GuestSessionCopyTask::GuestSessionCopyTask(GuestSession *pSession) 1314 : GuestSessionTask(pSession) 1315 { 1316 } 1317 1318 GuestSessionCopyTask::~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 1333 GuestSessionTaskCopyFrom::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 1342 GuestSessionTaskCopyFrom::~GuestSessionTaskCopyFrom(void) 1343 { 1344 } 1345 1346 #if 0 955 1347 /** 956 1348 * Copys a directory (tree) from guest to the host. … … 1113 1505 return rc; 1114 1506 } 1115 1116 int SessionTaskCopyDirFrom::Run(void) 1507 #endif 1508 1509 HRESULT 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 1685 int GuestSessionTaskCopyFrom::Run(void) 1117 1686 { 1118 1687 LogFlowThisFuncEnter(); … … 1121 1690 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 1122 1691 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 1127 1692 int rc = VINF_SUCCESS; 1128 1693 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 1171 1772 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 1197 1778 if (RT_SUCCESS(rc)) 1198 1779 rc = setProgressSuccess(); 1199 1780 1200 RTDirClose(hDir);1201 1202 1781 LogFlowFuncLeaveRC(rc); 1203 1782 return rc; 1204 1783 } 1205 1784 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); 1785 GuestSessionTaskCopyTo::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 1794 GuestSessionTaskCopyTo::~GuestSessionTaskCopyTo(void) 1795 { 1796 } 1797 1798 HRESULT 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); 1269 1839 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 1279 1893 if (RT_SUCCESS(rc)) 1280 1894 { 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 1913 int 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) 1301 1962 { 1302 1963 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) 1332 1965 { 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 } 1341 1972 } 1342 1973 break; 1343 } 1974 1975 case RTFS_TYPE_FILE: 1976 if (!pList->mSourceSpec.fDryRun) 1977 rc = fileCopyToGuest(strSrcAbs, strDstAbs, FileCopyFlag_None); 1978 break; 1344 1979 1345 1980 default: 1981 LogFlowFunc(("Warning: Type %d for '%s' is not supported\n", 1982 pEntry->fMode & RTFS_TYPE_MASK, strSrcAbs.c_str())); 1346 1983 break; 1347 1984 } 1985 1348 1986 if (RT_FAILURE(rc)) 1349 1987 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 1401 2000 if (RT_SUCCESS(rc)) 1402 2001 rc = setProgressSuccess(); … … 1406 2005 } 1407 2006 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 1440 2008 SessionTaskCopyFileFrom::SessionTaskCopyFileFrom(GuestSession *pSession, 1441 2009 const Utf8Str &strSource, const Utf8Str &strDest, FileCopyFlag_T fFileCopyFlags) … … 1447 2015 mDest = strDest; 1448 2016 1449 u.File.fCopyFlags = fFileCopyFlags;2017 Type.File.fCopyFlags = fFileCopyFlags; 1450 2018 } 1451 2019 … … 1462 2030 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 1463 2031 1464 int rc = fileCopyFromGuest(mSource, mDest, u.File.fCopyFlags);2032 int rc = fileCopyFromGuest(mSource, mDest, Type.File.fCopyFlags); 1465 2033 if (RT_SUCCESS(rc)) 1466 2034 rc = setProgressSuccess(); … … 1469 2037 return rc; 1470 2038 } 1471 1472 SessionTaskUpdateAdditions::SessionTaskUpdateAdditions(GuestSession *pSession, 1473 const Utf8Str &strSource, 1474 const ProcessArguments &aArguments, 1475 uint32_t fFlags) 1476 : GuestSessionTask(pSession) 2039 #endif 2040 2041 GuestSessionTaskUpdateAdditions::GuestSessionTaskUpdateAdditions(GuestSession *pSession, 2042 const Utf8Str &strSource, 2043 const ProcessArguments &aArguments, 2044 uint32_t fFlags) 2045 : GuestSessionTask(pSession) 1477 2046 { 1478 2047 m_strTaskName = "gctlUpGA"; … … 1483 2052 } 1484 2053 1485 SessionTaskUpdateAdditions::~SessionTaskUpdateAdditions(void)1486 { 1487 1488 } 1489 1490 int SessionTaskUpdateAdditions::addProcessArguments(ProcessArguments &aArgumentsDest, const ProcessArguments &aArgumentsSource)2054 GuestSessionTaskUpdateAdditions::~GuestSessionTaskUpdateAdditions(void) 2055 { 2056 2057 } 2058 2059 int GuestSessionTaskUpdateAdditions::addProcessArguments(ProcessArguments &aArgumentsDest, const ProcessArguments &aArgumentsSource) 1491 2060 { 1492 2061 int rc = VINF_SUCCESS; … … 1526 2095 } 1527 2096 1528 int SessionTaskUpdateAdditions::copyFileToGuest(GuestSession *pSession, PRTISOFSFILE pISO,2097 int GuestSessionTaskUpdateAdditions::copyFileToGuest(GuestSession *pSession, PRTISOFSFILE pISO, 1529 2098 Utf8Str const &strFileSource, const Utf8Str &strFileDest, 1530 2099 bool fOptional) … … 1592 2161 } 1593 2162 1594 int SessionTaskUpdateAdditions::runFileOnGuest(GuestSession *pSession, GuestProcessStartupInfo &procInfo)2163 int GuestSessionTaskUpdateAdditions::runFileOnGuest(GuestSession *pSession, GuestProcessStartupInfo &procInfo) 1595 2164 { 1596 2165 AssertPtrReturn(pSession, VERR_INVALID_POINTER); … … 1640 2209 } 1641 2210 1642 int SessionTaskUpdateAdditions::Run(void)2211 int GuestSessionTaskUpdateAdditions::Run(void) 1643 2212 { 1644 2213 LogFlowThisFuncEnter();
Note:
See TracChangeset
for help on using the changeset viewer.