Changeset 42573 in vbox
- Timestamp:
- Aug 3, 2012 10:59:11 AM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp
r42567 r42573 32 32 33 33 #include <iprt/env.h> 34 #include <iprt/file.h> /* For CopyTo/From. */ 34 35 35 36 #include <VBox/com/array.h> … … 132 133 int SessionTaskCopyTo::Run(void) 133 134 { 134 return 0; 135 LogFlowThisFuncEnter(); 136 137 ComObjPtr<GuestSession> pSession = mSession; 138 Assert(!pSession.isNull()); 139 140 AutoCaller autoCaller(pSession); 141 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 142 143 int rc; 144 145 /** @todo Make use of exception (+ finally block) here! */ 146 147 try 148 { 149 /* Does our source file exist? */ 150 if (!RTFileExists(mSource.c_str())) 151 { 152 rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR, 153 Utf8StrFmt(GuestSession::tr("Source file \"%s\" does not exist or is not a file"), 154 mSource.c_str())); 155 } 156 else 157 { 158 RTFILE fileSource; 159 rc = RTFileOpen(&fileSource, mSource.c_str(), 160 RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE); 161 if (RT_FAILURE(rc)) 162 { 163 rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR, 164 Utf8StrFmt(GuestSession::tr("Could not open source file \"%s\" for reading (%Rrc)"), 165 mSource.c_str(), rc)); 166 } 167 else 168 { 169 uint64_t cbFileSize; 170 rc = RTFileGetSize(fileSource, &cbFileSize); 171 if (RT_FAILURE(rc)) 172 { 173 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 174 Utf8StrFmt(GuestSession::tr("Could not query file size of \"%s\" (%Rrc)"), 175 mSource.c_str(), rc)); 176 } 177 else 178 { 179 GuestProcessInfo procInfo; 180 procInfo.mName = Utf8StrFmt(GuestSession::tr("Copying file \"%s\" to the guest to \"%s\" (%RU64 bytes)"), 181 mSource.c_str(), mDest.c_str(), cbFileSize); 182 procInfo.mCommand = Utf8Str(VBOXSERVICE_TOOL_CAT); 183 procInfo.mFlags = ProcessCreateFlag_None; 184 185 /* Set arguments.*/ 186 procInfo.mArguments.push_back(Utf8StrFmt("--output=%s", mDest.c_str())); /** @todo Do we need path conversion? */ 187 188 /* Startup process. */ 189 ComObjPtr<GuestProcess> pProcess; 190 int rc = pSession->processCreateExInteral(procInfo, pProcess); 191 if (RT_SUCCESS(rc)) 192 { 193 GuestProcessWaitResult waitRes; 194 BYTE byBuf[_64K]; 195 196 BOOL fCanceled = FALSE; 197 uint64_t cbWrittenTotal = 0; 198 uint64_t cbToRead = cbFileSize; 199 200 for (;;) 201 { 202 rc = pProcess->waitFor(ProcessWaitForFlag_StdIn, 203 30 * 1000 /* Timeout */, waitRes); 204 if ( RT_FAILURE(rc) 205 || waitRes.mResult != ProcessWaitResult_StdIn) 206 { 207 break; 208 } 209 210 size_t cbRead = 0; 211 if (cbFileSize) /* If we have nothing to write, take a shortcut. */ 212 { 213 /** @todo Not very efficient, but works for now. */ 214 rc = RTFileSeek(fileSource, cbWrittenTotal, 215 RTFILE_SEEK_BEGIN, NULL /* poffActual */); 216 if (RT_SUCCESS(rc)) 217 { 218 rc = RTFileRead(fileSource, (uint8_t*)byBuf, 219 RT_MIN(cbToRead, sizeof(byBuf)), &cbRead); 220 /* 221 * Some other error occured? There might be a chance that RTFileRead 222 * could not resolve/map the native error code to an IPRT code, so just 223 * print a generic error. 224 */ 225 if (RT_FAILURE(rc)) 226 { 227 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 228 Utf8StrFmt(GuestSession::tr("Could not read from file \"%s\" (%Rrc)"), 229 mSource.c_str(), rc)); 230 break; 231 } 232 } 233 else 234 { 235 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 236 Utf8StrFmt(GuestSession::tr("Seeking file \"%s\" offset %RU64 failed: %Rrc"), 237 mSource.c_str(), cbWrittenTotal, rc)); 238 break; 239 } 240 } 241 242 uint32_t fFlags = ProcessInputFlag_None; 243 244 /* Did we reach the end of the content we want to transfer (last chunk)? */ 245 if ( (cbRead < sizeof(byBuf)) 246 /* Did we reach the last block which is exactly _64K? */ 247 || (cbToRead - cbRead == 0) 248 /* ... or does the user want to cancel? */ 249 || ( SUCCEEDED(mProgress->COMGETTER(Canceled(&fCanceled))) 250 && fCanceled) 251 ) 252 { 253 fFlags |= ProcessInputFlag_EndOfFile; 254 } 255 256 uint32_t cbWritten; 257 rc = pProcess->writeData(0 /* StdIn */, fFlags, 258 byBuf, sizeof(byBuf), 259 30 * 1000 /* Timeout */, &cbWritten); 260 if (RT_FAILURE(rc)) 261 { 262 setProgressErrorMsg(VBOX_E_IPRT_ERROR, 263 Utf8StrFmt(GuestSession::tr("Writing to file \"%s\" (offset %RU64) failed: %Rrc"), 264 mSource.c_str(), cbWrittenTotal, rc)); 265 break; 266 } 267 268 /* Safety first. */ 269 Assert(cbRead <= cbToRead); 270 Assert(cbToRead >= cbRead); 271 272 /* Only subtract bytes reported written by the guest. */ 273 cbToRead -= cbWritten; 274 275 /* Update total bytes written to the guest. */ 276 cbWrittenTotal += cbWritten; 277 Assert(cbWrittenTotal <= cbFileSize); 278 279 /* Did the user cancel the operation above? */ 280 if (fCanceled) 281 break; 282 283 /* Update the progress. */ 284 HRESULT hr = mProgress->SetCurrentOperationProgress((ULONG)(cbWrittenTotal * 100 / cbFileSize)); 285 if (FAILED(hr)) 286 { 287 rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR, 288 Utf8StrFmt(GuestSession::tr("Error updating the progress of copying files \"%s\" to \"%s\""), 289 mSource.c_str(), mDest.c_str())); 290 break; 291 } 292 293 /* End of file reached? */ 294 if (cbToRead == 0) 295 break; 296 } /* for */ 297 298 if ( !fCanceled 299 || RT_SUCCESS(rc)) 300 { 301 /* 302 * Even if we succeeded until here make sure to check whether we really transfered 303 * everything. 304 */ 305 if ( cbFileSize > 0 306 && cbWrittenTotal == 0) 307 { 308 /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write 309 * to the destination -> access denied. */ 310 rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR, 311 Utf8StrFmt(GuestSession::tr("Access denied when copying file \"%s\" to \"%s\""), 312 mSource.c_str(), mDest.c_str())); 313 } 314 else if (cbWrittenTotal < cbFileSize) 315 { 316 /* If we did not copy all let the user know. */ 317 rc = setProgressErrorMsg(VBOX_E_IPRT_ERROR, 318 Utf8StrFmt(GuestSession::tr("Copying file \"%s\" failed (%RU64/%RU64 bytes transfered)"), 319 mSource.c_str(), cbWrittenTotal, cbFileSize)); 320 } 321 else /* Yay, all went fine! */ 322 rc = setProgressSuccess(); 323 } 324 } /* processCreateExInteral */ 325 } /* RTFileGetSize */ 326 327 RTFileClose(fileSource); 328 329 } /* RTFileOpen */ 330 } /* RTFileExists */ 331 } 332 catch (int rc2) 333 { 334 rc = rc2; 335 } 336 337 LogFlowFuncLeaveRC(rc); 338 return rc; 135 339 } 136 340
Note:
See TracChangeset
for help on using the changeset viewer.

