816
static int ctrlCopyContextCreate(IGuest *pGuest, bool fVerbose, bool fHostToGuest,
818
* Creates a copy context structure which then can be used with various
819
* guest control copy functions. Needs to be free'd with ctrlCopyContextFree().
821
* @return IPRT status code.
822
* @param pGuest Pointer to IGuest interface to use.
823
* @param fVerbose Flag indicating if we want to run in verbose mode.
824
* @param fDryRun Flag indicating if we want to run a dry run only.
825
* @param fHostToGuest Flag indicating if we want to copy from host to guest
827
* @param pszUsername Username of account to use on the guest side.
828
* @param pszPassword Password of account to use.
829
* @param ppContext Pointer which receives the allocated copy context.
831
static int ctrlCopyContextCreate(IGuest *pGuest, bool fVerbose, bool fDryRun,
817
833
const char *pszUsername, const char *pszPassword,
818
834
PCOPYCONTEXT *ppContext)
825
841
AssertPtrReturn(pContext, VERR_NO_MEMORY);
826
842
pContext->pGuest = pGuest;
827
843
pContext->fVerbose = fVerbose;
844
pContext->fDryRun = fDryRun;
828
845
pContext->fHostToGuest = fHostToGuest;
830
847
pContext->pszUsername = RTStrDup(pszUsername);
866
888
* @return IPRT status code.
867
* @param pszSourceRoot Source root path.
889
* @param pszSourceRoot Source root path. No trailing directory slash!
868
890
* @param pszSource Actual source to transform. Must begin with
869
891
* the source root path!
870
892
* @param pszDest Destination path.
878
900
AssertPtrReturn(pszSource, VERR_INVALID_POINTER);
879
901
AssertPtrReturn(pszDest, VERR_INVALID_POINTER);
880
902
AssertPtrReturn(ppszTranslated, VERR_INVALID_POINTER);
882
/* Source path must contain the source root! */
883
if (!RTPathStartsWith(pszSource, pszSourceRoot))
884
return VERR_INVALID_PARAMETER;
903
AssertReturn(RTPathStartsWith(pszSource, pszSourceRoot), VERR_INVALID_PARAMETER);
886
905
/* Construct the relative dest destination path by "subtracting" the
887
906
* source from the source root, e.g.
890
909
* dest = "d:\baz\"
891
910
* translated = "d:\baz\bar\"
894
size_t lenRoot = strlen(pszSourceRoot);
895
AssertReturn(lenRoot, VERR_INVALID_PARAMETER);
896
char *pszTranslated = RTStrDup(pszDest);
897
AssertReturn(pszTranslated, VERR_NO_MEMORY);
898
int vrc = RTStrAAppend(&pszTranslated, &pszSource[lenRoot]);
902
*ppszTranslated = pszTranslated;
912
char szTranslated[RTPATH_MAX];
913
size_t srcOff = strlen(pszSourceRoot);
914
AssertReturn(srcOff, VERR_INVALID_PARAMETER);
915
int rc = RTPathJoin(szTranslated, sizeof(szTranslated),
916
pszDest, &pszSource[srcOff]);
918
*ppszTranslated = RTStrDup(szTranslated);
907
922
#ifdef DEBUG_andy
908
static void tstTranslatePath()
923
static int tstTranslatePath()
954
969
RTStrFree(pszTranslated);
973
return VINF_SUCCESS; /* @todo */
978
* Creates a directory on the destination, based on the current copy
981
* @return IPRT status code.
982
* @param pContext Pointer to current copy control context.
983
* @param pszDir Directory to create.
960
985
static int ctrlCopyDirCreate(PCOPYCONTEXT pContext, const char *pszDir)
962
987
AssertPtrReturn(pContext, VERR_INVALID_POINTER);
963
988
AssertPtrReturn(pszDir, VERR_INVALID_POINTER);
990
if (pContext->fVerbose)
991
RTPrintf("Creating directory \"%s\" ...\n", pszDir);
993
if (pContext->fDryRun)
965
996
int rc = VINF_SUCCESS;
966
997
if (pContext->fHostToGuest) /* We want to create directories on the guest. */
974
1005
else /* ... or on the host. */
976
rc = RTDirCreate(pszDir, 700);
1007
rc = RTDirCreateFullPath(pszDir, 700);
977
1008
if (rc == VERR_ALREADY_EXISTS)
978
1009
rc = VINF_SUCCESS;
1015
* Checks whether a specific host/guest directory exists.
1017
* @return IPRT status code.
1018
* @param pContext Pointer to current copy control context.
1019
* @param bGuest true if directory needs to be checked on the guest
1020
* or false if on the host.
1021
* @param pszDir Actual directory to check.
1022
* @param fExists Pointer which receives the result if the
1023
* given directory exists or not.
983
1025
static int ctrlCopyDirExists(PCOPYCONTEXT pContext, bool bGuest,
984
1026
const char *pszDir, bool *fExists)
1051
* Checks whether a specific directory exists on the destination, based
1052
* on the current copy context.
1054
* @return IPRT status code.
1055
* @param pContext Pointer to current copy control context.
1056
* @param pszDir Actual directory to check.
1057
* @param fExists Pointer which receives the result if the
1058
* given directory exists or not.
1008
1060
static int ctrlCopyDirExistsOnDest(PCOPYCONTEXT pContext, const char *pszDir,
1012
1064
pszDir, fExists);
1068
* Checks whether a specific directory exists on the source, based
1069
* on the current copy context.
1071
* @return IPRT status code.
1072
* @param pContext Pointer to current copy control context.
1073
* @param pszDir Actual directory to check.
1074
* @param fExists Pointer which receives the result if the
1075
* given directory exists or not.
1015
1077
static int ctrlCopyDirExistsOnSource(PCOPYCONTEXT pContext, const char *pszDir,
1019
1081
pszDir, fExists);
1085
* Checks whether a specific host/guest file exists.
1087
* @return IPRT status code.
1088
* @param pContext Pointer to current copy control context.
1089
* @param bGuest true if file needs to be checked on the guest
1090
* or false if on the host.
1091
* @param pszFile Actual file to check.
1092
* @param fExists Pointer which receives the result if the
1093
* given file exists or not.
1022
1095
static int ctrlCopyFileExists(PCOPYCONTEXT pContext, bool bOnGuest,
1023
1096
const char *pszFile, bool *fExists)
1120
* Checks whether a specific file exists on the destination, based on the
1121
* current copy context.
1123
* @return IPRT status code.
1124
* @param pContext Pointer to current copy control context.
1125
* @param pszFile Actual file to check.
1126
* @param fExists Pointer which receives the result if the
1127
* given file exists or not.
1046
1129
static int ctrlCopyFileExistsOnDest(PCOPYCONTEXT pContext, const char *pszFile,
1050
1133
pszFile, fExists);
1137
* Checks whether a specific file exists on the source, based on the
1138
* current copy context.
1140
* @return IPRT status code.
1141
* @param pContext Pointer to current copy control context.
1142
* @param pszFile Actual file to check.
1143
* @param fExists Pointer which receives the result if the
1144
* given file exists or not.
1053
1146
static int ctrlCopyFileExistsOnSource(PCOPYCONTEXT pContext, const char *pszFile,
1057
1150
pszFile, fExists);
1060
static int ctrlCopyFileToTarget(PCOPYCONTEXT pContext, const char *pszFileSource,
1061
const char *pszFileDest, uint32_t fFlags)
1154
* Copies a source file to the destination.
1156
* @return IPRT status code.
1157
* @param pContext Pointer to current copy control context.
1158
* @param pszFileSource Source file to copy to the destination.
1159
* @param pszFileDest Name of copied file on the destination.
1160
* @param fFlags Copy flags. No supported at the moment and needs
1163
static int ctrlCopyFileToDest(PCOPYCONTEXT pContext, const char *pszFileSource,
1164
const char *pszFileDest, uint32_t fFlags)
1063
1166
AssertPtrReturn(pContext, VERR_INVALID_POINTER);
1064
1167
AssertPtrReturn(pszFileSource, VERR_INVALID_POINTER);
1065
1168
AssertPtrReturn(pszFileDest, VERR_INVALID_POINTER);
1169
AssertReturn(!fFlags, VERR_INVALID_POINTER); /* No flags supported yet. */
1067
1171
if (pContext->fVerbose)
1069
1172
RTPrintf("Copying \"%s\" to \"%s\" ...\n",
1070
1173
pszFileSource, pszFileDest);
1175
if (pContext->fDryRun)
1176
return VINF_SUCCESS;
1073
1178
int vrc = VINF_SUCCESS;
1074
1179
ComPtr<IProgress> progress;
1207
* Copys a directory (tree) from host to the guest.
1209
* @return IPRT status code.
1210
* @param pContext Pointer to current copy control context.
1211
* @param pszSource Source directory on the host to copy to the guest.
1212
* @param pszFilter DOS-style wildcard filter (?, *). Optional.
1213
* @param pszDest Destination directory on the guest.
1214
* @param fFlags Copy flags, such as recursive copying.
1215
* @param pszSubDir Current sub directory to handle. Needs to NULL and only
1216
* is needed for recursion.
1101
1218
static int ctrlCopyDirToGuest(PCOPYCONTEXT pContext,
1102
1219
const char *pszSource, const char *pszFilter,
1103
1220
const char *pszDest, uint32_t fFlags,
1104
const char *pszSubDir /* For recursion */)
1221
const char *pszSubDir /* For recursion. */)
1106
1223
AssertPtrReturn(pContext, VERR_INVALID_POINTER);
1107
1224
AssertPtrReturn(pszSource, VERR_INVALID_POINTER);
1117
1234
if (RT_SUCCESS(rc) && pszSubDir)
1118
1235
rc = RTPathAppend(szCurDir, sizeof(szCurDir), pszSubDir);
1237
if (pContext->fVerbose)
1238
RTPrintf("Processing directory: %s\n", szCurDir);
1120
1240
/* Flag indicating whether the current directory was created on the
1121
1241
* target or not. */
1122
1242
bool fDirCreated = false;
1156
1276
|| !strcmp(DirEntry.szName, ".."))
1279
if (pContext->fVerbose)
1280
RTPrintf("Directory: %s\n", DirEntry.szName);
1159
1282
if (fFlags & CopyFileFlag_Recursive)
1161
1284
char *pszNewSub = NULL;
1163
RTStrAPrintf(&pszNewSub, "%s/%s", pszSubDir, DirEntry.szName);
1286
pszNewSub = RTPathJoinA(pszSubDir, DirEntry.szName);
1165
RTStrAPrintf(&pszNewSub, "%s", DirEntry.szName);
1289
pszNewSub = RTStrDup(DirEntry.szName);
1290
RTPathStripTrailingSlash(pszNewSub);
1189
1315
case RTDIRENTRYTYPE_FILE:
1192
|| RTStrSimplePatternMatch(pszFilter, DirEntry.szName))
1197
rc = ctrlCopyTranslatePath(pszSource, szCurDir,
1198
pszDest, &pszDestDir);
1318
&& !RTStrSimplePatternMatch(pszFilter, DirEntry.szName))
1320
break; /* Filter does not match. */
1323
if (pContext->fVerbose)
1324
RTPrintf("File: %s\n", DirEntry.szName);
1329
rc = ctrlCopyTranslatePath(pszSource, szCurDir,
1330
pszDest, &pszDestDir);
1333
rc = ctrlCopyDirCreate(pContext, pszDestDir);
1334
RTStrFree(pszDestDir);
1342
char *pszFileSource = RTPathJoinA(szCurDir, DirEntry.szName);
1346
rc = ctrlCopyTranslatePath(pszSource, pszFileSource,
1347
pszDest, &pszFileDest);
1199
1348
if (RT_SUCCESS(rc))
1201
rc = ctrlCopyDirCreate(pContext, pszDestDir);
1202
RTStrFree(pszDestDir);
1210
char *pszFileSource;
1211
if (RTStrAPrintf(&pszFileSource, "%s/%s",
1212
szCurDir, DirEntry.szName))
1215
rc = ctrlCopyTranslatePath(pszSource, pszFileSource,
1216
pszDest, &pszFileDest);
1219
rc = ctrlCopyFileToTarget(pContext, pszFileSource,
1220
pszFileDest, 0 /* Flags? */);
1221
RTStrFree(pszFileDest);
1223
RTStrFree(pszFileSource);
1350
rc = ctrlCopyFileToDest(pContext, pszFileSource,
1351
pszFileDest, 0 /* Flags */);
1352
RTStrFree(pszFileDest);
1354
RTStrFree(pszFileSource);
1373
* Copys a directory (tree) from guest to the host.
1375
* @return IPRT status code.
1376
* @param pContext Pointer to current copy control context.
1377
* @param pszSource Source directory on the guest to copy to the host.
1378
* @param pszFilter DOS-style wildcard filter (?, *). Optional.
1379
* @param pszDest Destination directory on the host.
1380
* @param fFlags Copy flags, such as recursive copying.
1381
* @param pszSubDir Current sub directory to handle. Needs to NULL and only
1382
* is needed for recursion.
1242
1384
static int ctrlCopyDirToHost(PCOPYCONTEXT pContext,
1243
1385
const char *pszSource, const char *pszFilter,
1244
1386
const char *pszDest, uint32_t fFlags,
1245
const char *pszSubDir /* For recursion */)
1387
const char *pszSubDir /* For recursion. */)
1247
1389
AssertPtrReturn(pContext, VERR_INVALID_POINTER);
1248
1390
AssertPtrReturn(pszSource, VERR_INVALID_POINTER);
1292
1437
|| !strName.compare(Bstr("..")))
1440
if (pContext->fVerbose)
1442
Utf8Str Utf8Dir(strName);
1443
RTPrintf("Directory: %s\n", Utf8Dir.c_str());
1295
1446
if (fFlags & CopyFileFlag_Recursive)
1297
1448
Utf8Str strDir(strName);
1298
1449
char *pszNewSub = NULL;
1300
RTStrAPrintf(&pszNewSub, "%s/%s", pszSubDir, strDir.c_str());
1451
pszNewSub = RTPathJoinA(pszSubDir, strDir.c_str());
1302
RTStrAPrintf(&pszNewSub, "%s", strDir.c_str());
1454
pszNewSub = RTStrDup(strDir.c_str());
1455
RTPathStripTrailingSlash(pszNewSub);
1306
1459
rc = ctrlCopyDirToHost(pContext,
1326
1479
case GuestDirEntryType_File:
1328
1481
Utf8Str strFile(strName);
1330
|| RTStrSimplePatternMatch(pszFilter, strFile.c_str()))
1335
rc = ctrlCopyTranslatePath(pszSource, szCurDir,
1336
pszDest, &pszDestDir);
1483
&& !RTStrSimplePatternMatch(pszFilter, strFile.c_str()))
1485
break; /* Filter does not match. */
1488
if (pContext->fVerbose)
1489
RTPrintf("File: %s\n", strFile.c_str());
1494
rc = ctrlCopyTranslatePath(pszSource, szCurDir,
1495
pszDest, &pszDestDir);
1498
rc = ctrlCopyDirCreate(pContext, pszDestDir);
1499
RTStrFree(pszDestDir);
1507
char *pszFileSource = RTPathJoinA(szCurDir, strFile.c_str());
1511
rc = ctrlCopyTranslatePath(pszSource, pszFileSource,
1512
pszDest, &pszFileDest);
1337
1513
if (RT_SUCCESS(rc))
1339
rc = ctrlCopyDirCreate(pContext, pszDestDir);
1340
RTStrFree(pszDestDir);
1348
char *pszFileSource;
1349
if (RTStrAPrintf(&pszFileSource, "%s/%s",
1350
szCurDir, strFile.c_str()))
1353
rc = ctrlCopyTranslatePath(pszSource, pszFileSource,
1354
pszDest, &pszFileDest);
1357
rc = ctrlCopyFileToTarget(pContext, pszFileSource,
1358
pszFileDest, 0 /* Flags? */);
1359
RTStrFree(pszFileDest);
1361
RTStrFree(pszFileSource);
1364
rc = VERR_NO_MEMORY;
1515
rc = ctrlCopyFileToDest(pContext, pszFileSource,
1516
pszFileDest, 0 /* Flags */);
1517
RTStrFree(pszFileDest);
1519
RTStrFree(pszFileSource);
1522
rc = VERR_NO_MEMORY;
1398
static int ctrlCopyDirToTarget(PCOPYCONTEXT pContext,
1399
const char *pszSource, const char *pszFilter,
1400
const char *pszDest, uint32_t fFlags,
1401
const char *pszSubDir /* For recursion */)
1556
* Copys a directory (tree) to the destination, based on the current copy
1559
* @return IPRT status code.
1560
* @param pContext Pointer to current copy control context.
1561
* @param pszSource Source directory to copy to the destination.
1562
* @param pszFilter DOS-style wildcard filter (?, *). Optional.
1563
* @param pszDest Destination directory where to copy in the source
1565
* @param fFlags Copy flags, such as recursive copying.
1567
static int ctrlCopyDirToDest(PCOPYCONTEXT pContext,
1568
const char *pszSource, const char *pszFilter,
1569
const char *pszDest, uint32_t fFlags)
1403
1571
if (pContext->fHostToGuest)
1404
1572
return ctrlCopyDirToGuest(pContext, pszSource, pszFilter,
1405
pszDest, fFlags, pszSubDir);
1573
pszDest, fFlags, NULL /* Sub directory, only for recursion. */);
1406
1574
return ctrlCopyDirToHost(pContext, pszSource, pszFilter,
1407
pszDest, fFlags, pszSubDir);
1575
pszDest, fFlags, NULL /* Sub directory, only for recursion. */);
1579
* Creates a source root by stripping file names or filters of the specified source.
1581
* @return IPRT status code.
1582
* @param pszSource Source to create source root for.
1583
* @param ppszSourceRoot Pointer that receives the allocated source root. Needs
1584
* to be free'd with ctrlCopyFreeSourceRoot().
1410
1586
static int ctrlCopyCreateSourceRoot(const char *pszSource, char **ppszSourceRoot)
1412
1588
AssertPtrReturn(pszSource, VERR_INVALID_POINTER);
1582
1758
/* Create the copy context -- it contains all information
1583
1759
* the routines need to know when handling the actual copying. */
1584
1760
PCOPYCONTEXT pContext;
1585
vrc = ctrlCopyContextCreate(guest, fVerbose, fHostToGuest,
1761
vrc = ctrlCopyContextCreate(guest, fVerbose, fDryRun, fHostToGuest,
1586
1762
Utf8UserName.c_str(), Utf8Password.c_str(),
1588
1764
if (RT_FAILURE(vrc))
1611
1787
for (unsigned long s = 0; s < vecSources.size(); s++)
1613
const char *pszSource = vecSources[s].mSource.c_str();
1789
char *pszSource = RTStrDup(vecSources[s].mSource.c_str());
1790
AssertPtrBreakStmt(pszSource, vrc = VERR_NO_MEMORY);
1614
1791
const char *pszFilter = vecSources[s].mFilter.c_str();
1615
1792
if (!strlen(pszFilter))
1616
1793
pszFilter = NULL; /* If empty filter then there's no filter :-) */
1629
1806
/** @todo Files with filter?? */
1630
1807
bool fIsFile = false;
1632
Utf8Str Utf8CurSource(pszSource);
1633
if ( Utf8CurSource.endsWith("/")
1634
|| Utf8CurSource.endsWith("\\"))
1810
size_t cchSource = strlen(pszSource);
1812
&& RTPATH_IS_SLASH(pszSource[cchSource - 1]))
1636
1814
#ifndef DEBUG_andy
1637
1815
if (pContext->fHostToGuest)
1640
if (pszFilter) /* Directory with filter. */
1818
if (pszFilter) /* Directory with filter (so use source root w/o the actual filter). */
1641
1819
vrc = ctrlCopyDirExistsOnSource(pContext, pszSourceRoot, &fExists);
1642
1820
else /* Regular directory without filter. */
1643
1821
vrc = ctrlCopyDirExistsOnSource(pContext, pszSource, &fExists);
1825
/* Strip trailing slash from our source element so that other functions
1826
* can use this stuff properly (like RTPathStartsWith). */
1827
RTPathStripTrailingSlash(pszSource);
1644
1829
#ifndef DEBUG_andy
1668
1856
Utf8Dest.c_str(), &pszDestFile);
1669
1857
if (RT_SUCCESS(vrc))
1671
vrc = ctrlCopyFileToTarget(pContext, pszSource,
1672
pszDestFile, fFlags);
1859
vrc = ctrlCopyFileToDest(pContext, pszSource,
1860
pszDestFile, 0 /* Flags */);
1673
1861
RTStrFree(pszDestFile);
1677
1864
RTMsgError("Unable to translate path for \"%s\", rc=%Rrc\n",
1678
1865
pszSource, vrc);
1683
1869
/* Directory (with filter?). */
1684
vrc = ctrlCopyDirToTarget(pContext, pszSource, pszFilter,
1685
Utf8Dest.c_str(), fFlags, NULL /* Subdir */);
1870
vrc = ctrlCopyDirToDest(pContext, pszSource, pszFilter,
1871
Utf8Dest.c_str(), fFlags);
2058
2250
AssertPtrReturn(pArg, VERR_INVALID_PARAMETER);
2253
if (RT_FAILURE(tstTranslatePath()))
2254
return RTEXITCODE_FAILURE;
2060
2257
HandlerArg arg = *pArg;
2061
2258
arg.argc = pArg->argc - 2; /* Skip VM name and sub command. */
2062
2259
arg.argv = pArg->argv + 2; /* Same here. */