~ubuntu-branches/ubuntu/precise/virtualbox/precise-updates

« back to all changes in this revision

Viewing changes to src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-10-17 23:23:09 UTC
  • mfrom: (1.1.4 upstream)
  • mto: This revision was merged to the branch mainline in revision 8.
  • Revision ID: james.westby@ubuntu.com-20111017232309-5aoh813mfoxejkxc
* New upstream release.
  - Fixes missing icons when using pt_BR locale. (Closes: #507188)
  - Fixes guest additions download url. (Closes: #637349; LP: #840668)
* Refresh patches.
* Drop the vboxmouse x11 driver. The mouse integration is now completely
  handled by the kernel module.
* Restrict dh_pycentral to the virtualbox binary package.
* Merge changes from the Ubuntu package but use them only when built
  on Ubuntu:
  - Add an Apport hook.
  - Add vboxguest modalias to the package control field.
* Pass KBUILD_VERBOSE=2 to kmk.
* Add 36-fix-text-mode.patch to fix text mode when using the vboxvideo driver.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: VBoxManageGuestCtrl.cpp 38456 2011-08-15 10:16:40Z vboxsync $ */
 
1
/* $Id: VBoxManageGuestCtrl.cpp $ */
2
2
/** @file
3
3
 * VBoxManage - Implementation of guestcontrol command.
4
4
 */
72
72
{
73
73
    IGuest *pGuest;
74
74
    bool fVerbose;
 
75
    bool fDryRun;
75
76
    bool fHostToGuest;
76
77
    char *pszUsername;
77
78
    char *pszPassword;
813
814
    return rcProc;
814
815
}
815
816
 
816
 
static int ctrlCopyContextCreate(IGuest *pGuest, bool fVerbose, bool fHostToGuest,
 
817
/**
 
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().
 
820
 *
 
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
 
826
 *                                  or vice versa.
 
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.
 
830
 */
 
831
static int ctrlCopyContextCreate(IGuest *pGuest, bool fVerbose, bool fDryRun,
 
832
                                 bool fHostToGuest,
817
833
                                 const char *pszUsername, const char *pszPassword,
818
834
                                 PCOPYCONTEXT *ppContext)
819
835
{
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;
829
846
 
830
847
    pContext->pszUsername = RTStrDup(pszUsername);
847
864
    return VINF_SUCCESS;
848
865
}
849
866
 
 
867
/**
 
868
 * Frees are previously allocated copy context structure.
 
869
 *
 
870
 * @param   pContext                Pointer to copy context to free.
 
871
 */
850
872
static void ctrlCopyContextFree(PCOPYCONTEXT pContext)
851
873
{
852
874
    if (pContext)
864
886
 * path.
865
887
 *
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);
881
 
 
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);
885
904
 
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\"
892
911
     */
893
 
 
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]);
899
 
    if (RT_FAILURE(vrc))
900
 
        return vrc;
901
 
 
902
 
    *ppszTranslated = pszTranslated;
903
 
 
904
 
    return vrc;
 
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]);
 
917
    if (RT_SUCCESS(rc))
 
918
        *ppszTranslated = RTStrDup(szTranslated);
 
919
    return rc;
905
920
}
906
921
 
907
922
#ifdef DEBUG_andy
908
 
static void tstTranslatePath()
 
923
static int tstTranslatePath()
909
924
{
910
925
    static struct
911
926
    {
954
969
            RTStrFree(pszTranslated);
955
970
        }
956
971
    }
 
972
 
 
973
    return VINF_SUCCESS; /* @todo */
957
974
}
958
975
#endif
959
976
 
 
977
/**
 
978
 * Creates a directory on the destination, based on the current copy
 
979
 * context.
 
980
 *
 
981
 * @return  IPRT status code.
 
982
 * @param   pContext                Pointer to current copy control context.
 
983
 * @param   pszDir                  Directory to create.
 
984
 */
960
985
static int ctrlCopyDirCreate(PCOPYCONTEXT pContext, const char *pszDir)
961
986
{
962
987
    AssertPtrReturn(pContext, VERR_INVALID_POINTER);
963
988
    AssertPtrReturn(pszDir, VERR_INVALID_POINTER);
964
989
 
 
990
    if (pContext->fVerbose)
 
991
        RTPrintf("Creating directory \"%s\" ...\n", pszDir);
 
992
 
 
993
    if (pContext->fDryRun)
 
994
        return VINF_SUCCESS;
 
995
 
965
996
    int rc = VINF_SUCCESS;
966
997
    if (pContext->fHostToGuest) /* We want to create directories on the guest. */
967
998
    {
973
1004
    }
974
1005
    else /* ... or on the host. */
975
1006
    {
976
 
        rc = RTDirCreate(pszDir, 700);
 
1007
        rc = RTDirCreateFullPath(pszDir, 700);
977
1008
        if (rc == VERR_ALREADY_EXISTS)
978
1009
            rc = VINF_SUCCESS;
979
1010
    }
980
1011
    return rc;
981
1012
}
982
1013
 
 
1014
/**
 
1015
 * Checks whether a specific host/guest directory exists.
 
1016
 *
 
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.
 
1024
 */
983
1025
static int ctrlCopyDirExists(PCOPYCONTEXT pContext, bool bGuest,
984
1026
                             const char *pszDir, bool *fExists)
985
1027
{
1005
1047
    return rc;
1006
1048
}
1007
1049
 
 
1050
/**
 
1051
 * Checks whether a specific directory exists on the destination, based
 
1052
 * on the current copy context.
 
1053
 *
 
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.
 
1059
 */
1008
1060
static int ctrlCopyDirExistsOnDest(PCOPYCONTEXT pContext, const char *pszDir,
1009
1061
                                   bool *fExists)
1010
1062
{
1012
1064
                             pszDir, fExists);
1013
1065
}
1014
1066
 
 
1067
/**
 
1068
 * Checks whether a specific directory exists on the source, based
 
1069
 * on the current copy context.
 
1070
 *
 
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.
 
1076
 */
1015
1077
static int ctrlCopyDirExistsOnSource(PCOPYCONTEXT pContext, const char *pszDir,
1016
1078
                                     bool *fExists)
1017
1079
{
1019
1081
                             pszDir, fExists);
1020
1082
}
1021
1083
 
 
1084
/**
 
1085
 * Checks whether a specific host/guest file exists.
 
1086
 *
 
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.
 
1094
 */
1022
1095
static int ctrlCopyFileExists(PCOPYCONTEXT pContext, bool bOnGuest,
1023
1096
                              const char *pszFile, bool *fExists)
1024
1097
{
1043
1116
    return rc;
1044
1117
}
1045
1118
 
 
1119
/**
 
1120
 * Checks whether a specific file exists on the destination, based on the
 
1121
 * current copy context.
 
1122
 *
 
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.
 
1128
 */
1046
1129
static int ctrlCopyFileExistsOnDest(PCOPYCONTEXT pContext, const char *pszFile,
1047
1130
                                    bool *fExists)
1048
1131
{
1050
1133
                              pszFile, fExists);
1051
1134
}
1052
1135
 
 
1136
/**
 
1137
 * Checks whether a specific file exists on the source, based on the
 
1138
 * current copy context.
 
1139
 *
 
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.
 
1145
 */
1053
1146
static int ctrlCopyFileExistsOnSource(PCOPYCONTEXT pContext, const char *pszFile,
1054
1147
                                      bool *fExists)
1055
1148
{
1057
1150
                              pszFile, fExists);
1058
1151
}
1059
1152
 
1060
 
static int ctrlCopyFileToTarget(PCOPYCONTEXT pContext, const char *pszFileSource,
1061
 
                                const char *pszFileDest, uint32_t fFlags)
 
1153
/**
 
1154
 * Copies a source file to the destination.
 
1155
 *
 
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
 
1161
 *                                  to be set to 0.
 
1162
 */
 
1163
static int ctrlCopyFileToDest(PCOPYCONTEXT pContext, const char *pszFileSource,
 
1164
                              const char *pszFileDest, uint32_t fFlags)
1062
1165
{
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. */
1066
1170
 
1067
1171
    if (pContext->fVerbose)
1068
 
    {
1069
1172
        RTPrintf("Copying \"%s\" to \"%s\" ...\n",
1070
1173
                 pszFileSource, pszFileDest);
1071
 
    }
 
1174
 
 
1175
    if (pContext->fDryRun)
 
1176
        return VINF_SUCCESS;
1072
1177
 
1073
1178
    int vrc = VINF_SUCCESS;
1074
1179
    ComPtr<IProgress> progress;
1098
1203
    return vrc;
1099
1204
}
1100
1205
 
 
1206
/**
 
1207
 * Copys a directory (tree) from host to the guest.
 
1208
 *
 
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.
 
1217
 */
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. */)
1105
1222
{
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);
1119
1236
 
 
1237
    if (pContext->fVerbose)
 
1238
        RTPrintf("Processing directory: %s\n", szCurDir);
 
1239
 
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, ".."))
1157
1277
                        break;
1158
1278
 
 
1279
                    if (pContext->fVerbose)
 
1280
                        RTPrintf("Directory: %s\n", DirEntry.szName);
 
1281
 
1159
1282
                    if (fFlags & CopyFileFlag_Recursive)
1160
1283
                    {
1161
1284
                        char *pszNewSub = NULL;
1162
1285
                        if (pszSubDir)
1163
 
                            RTStrAPrintf(&pszNewSub, "%s/%s", pszSubDir, DirEntry.szName);
 
1286
                            pszNewSub = RTPathJoinA(pszSubDir, DirEntry.szName);
1164
1287
                        else
1165
 
                            RTStrAPrintf(&pszNewSub, "%s", DirEntry.szName);
 
1288
                        {
 
1289
                            pszNewSub = RTStrDup(DirEntry.szName);
 
1290
                            RTPathStripTrailingSlash(pszNewSub);
 
1291
                        }
1166
1292
 
1167
1293
                        if (pszNewSub)
1168
1294
                        {
1188
1314
 
1189
1315
                case RTDIRENTRYTYPE_FILE:
1190
1316
                {
1191
 
                    if (   !pszFilter
1192
 
                        || RTStrSimplePatternMatch(pszFilter, DirEntry.szName))
1193
 
                    {
1194
 
                        if (!fDirCreated)
1195
 
                        {
1196
 
                            char *pszDestDir;
1197
 
                            rc = ctrlCopyTranslatePath(pszSource, szCurDir,
1198
 
                                                       pszDest, &pszDestDir);
 
1317
                    if (   pszFilter
 
1318
                        && !RTStrSimplePatternMatch(pszFilter, DirEntry.szName))
 
1319
                    {
 
1320
                        break; /* Filter does not match. */
 
1321
                    }
 
1322
 
 
1323
                    if (pContext->fVerbose)
 
1324
                        RTPrintf("File: %s\n", DirEntry.szName);
 
1325
 
 
1326
                    if (!fDirCreated)
 
1327
                    {
 
1328
                        char *pszDestDir;
 
1329
                        rc = ctrlCopyTranslatePath(pszSource, szCurDir,
 
1330
                                                   pszDest, &pszDestDir);
 
1331
                        if (RT_SUCCESS(rc))
 
1332
                        {
 
1333
                            rc = ctrlCopyDirCreate(pContext, pszDestDir);
 
1334
                            RTStrFree(pszDestDir);
 
1335
 
 
1336
                            fDirCreated = true;
 
1337
                        }
 
1338
                    }
 
1339
 
 
1340
                    if (RT_SUCCESS(rc))
 
1341
                    {
 
1342
                        char *pszFileSource = RTPathJoinA(szCurDir, DirEntry.szName);
 
1343
                        if (pszFileSource)
 
1344
                        {
 
1345
                            char *pszFileDest;
 
1346
                            rc = ctrlCopyTranslatePath(pszSource, pszFileSource,
 
1347
                                                       pszDest, &pszFileDest);
1199
1348
                            if (RT_SUCCESS(rc))
1200
1349
                            {
1201
 
                                rc = ctrlCopyDirCreate(pContext, pszDestDir);
1202
 
                                RTStrFree(pszDestDir);
1203
 
 
1204
 
                                fDirCreated = true;
1205
 
                            }
1206
 
                        }
1207
 
 
1208
 
                        if (RT_SUCCESS(rc))
1209
 
                        {
1210
 
                            char *pszFileSource;
1211
 
                            if (RTStrAPrintf(&pszFileSource, "%s/%s",
1212
 
                                             szCurDir, DirEntry.szName))
1213
 
                            {
1214
 
                                char *pszFileDest;
1215
 
                                rc = ctrlCopyTranslatePath(pszSource, pszFileSource,
1216
 
                                                           pszDest, &pszFileDest);
1217
 
                                if (RT_SUCCESS(rc))
1218
 
                                {
1219
 
                                    rc = ctrlCopyFileToTarget(pContext, pszFileSource,
1220
 
                                                              pszFileDest, 0 /* Flags? */);
1221
 
                                    RTStrFree(pszFileDest);
1222
 
                                }
1223
 
                                RTStrFree(pszFileSource);
1224
 
                            }
 
1350
                                rc = ctrlCopyFileToDest(pContext, pszFileSource,
 
1351
                                                        pszFileDest, 0 /* Flags */);
 
1352
                                RTStrFree(pszFileDest);
 
1353
                            }
 
1354
                            RTStrFree(pszFileSource);
1225
1355
                        }
1226
1356
                    }
1227
1357
                    break;
1239
1369
    return rc;
1240
1370
}
1241
1371
 
 
1372
/**
 
1373
 * Copys a directory (tree) from guest to the host.
 
1374
 *
 
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.
 
1383
 */
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. */)
1246
1388
{
1247
1389
    AssertPtrReturn(pContext, VERR_INVALID_POINTER);
1248
1390
    AssertPtrReturn(pszSource, VERR_INVALID_POINTER);
1261
1403
    if (RT_FAILURE(rc))
1262
1404
        return rc;
1263
1405
 
 
1406
    if (pContext->fVerbose)
 
1407
        RTPrintf("Processing directory: %s\n", szCurDir);
 
1408
 
1264
1409
    /* Flag indicating whether the current directory was created on the
1265
1410
     * target or not. */
1266
1411
    bool fDirCreated = false;
1292
1437
                        || !strName.compare(Bstr("..")))
1293
1438
                        break;
1294
1439
 
 
1440
                    if (pContext->fVerbose)
 
1441
                    {
 
1442
                        Utf8Str Utf8Dir(strName);
 
1443
                        RTPrintf("Directory: %s\n", Utf8Dir.c_str());
 
1444
                    }
 
1445
 
1295
1446
                    if (fFlags & CopyFileFlag_Recursive)
1296
1447
                    {
1297
1448
                        Utf8Str strDir(strName);
1298
1449
                        char *pszNewSub = NULL;
1299
1450
                        if (pszSubDir)
1300
 
                            RTStrAPrintf(&pszNewSub, "%s/%s", pszSubDir, strDir.c_str());
 
1451
                            pszNewSub = RTPathJoinA(pszSubDir, strDir.c_str());
1301
1452
                        else
1302
 
                            RTStrAPrintf(&pszNewSub, "%s", strDir.c_str());
1303
 
 
 
1453
                        {
 
1454
                            pszNewSub = RTStrDup(strDir.c_str());
 
1455
                            RTPathStripTrailingSlash(pszNewSub);
 
1456
                        }
1304
1457
                        if (pszNewSub)
1305
1458
                        {
1306
1459
                            rc = ctrlCopyDirToHost(pContext,
1326
1479
                case GuestDirEntryType_File:
1327
1480
                {
1328
1481
                    Utf8Str strFile(strName);
1329
 
                    if (   !pszFilter
1330
 
                        || RTStrSimplePatternMatch(pszFilter, strFile.c_str()))
1331
 
                    {
1332
 
                        if (!fDirCreated)
1333
 
                        {
1334
 
                            char *pszDestDir;
1335
 
                            rc = ctrlCopyTranslatePath(pszSource, szCurDir,
1336
 
                                                       pszDest, &pszDestDir);
 
1482
                    if (   pszFilter
 
1483
                        && !RTStrSimplePatternMatch(pszFilter, strFile.c_str()))
 
1484
                    {
 
1485
                        break; /* Filter does not match. */
 
1486
                    }
 
1487
 
 
1488
                    if (pContext->fVerbose)
 
1489
                        RTPrintf("File: %s\n", strFile.c_str());
 
1490
 
 
1491
                    if (!fDirCreated)
 
1492
                    {
 
1493
                        char *pszDestDir;
 
1494
                        rc = ctrlCopyTranslatePath(pszSource, szCurDir,
 
1495
                                                   pszDest, &pszDestDir);
 
1496
                        if (RT_SUCCESS(rc))
 
1497
                        {
 
1498
                            rc = ctrlCopyDirCreate(pContext, pszDestDir);
 
1499
                            RTStrFree(pszDestDir);
 
1500
 
 
1501
                            fDirCreated = true;
 
1502
                        }
 
1503
                    }
 
1504
 
 
1505
                    if (RT_SUCCESS(rc))
 
1506
                    {
 
1507
                        char *pszFileSource = RTPathJoinA(szCurDir, strFile.c_str());
 
1508
                        if (pszFileSource)
 
1509
                        {
 
1510
                            char *pszFileDest;
 
1511
                            rc = ctrlCopyTranslatePath(pszSource, pszFileSource,
 
1512
                                                       pszDest, &pszFileDest);
1337
1513
                            if (RT_SUCCESS(rc))
1338
1514
                            {
1339
 
                                rc = ctrlCopyDirCreate(pContext, pszDestDir);
1340
 
                                RTStrFree(pszDestDir);
1341
 
 
1342
 
                                fDirCreated = true;
1343
 
                            }
1344
 
                        }
1345
 
 
1346
 
                        if (RT_SUCCESS(rc))
1347
 
                        {
1348
 
                            char *pszFileSource;
1349
 
                            if (RTStrAPrintf(&pszFileSource, "%s/%s",
1350
 
                                             szCurDir, strFile.c_str()))
1351
 
                            {
1352
 
                                char *pszFileDest;
1353
 
                                rc = ctrlCopyTranslatePath(pszSource, pszFileSource,
1354
 
                                                           pszDest, &pszFileDest);
1355
 
                                if (RT_SUCCESS(rc))
1356
 
                                {
1357
 
                                    rc = ctrlCopyFileToTarget(pContext, pszFileSource,
1358
 
                                                              pszFileDest, 0 /* Flags? */);
1359
 
                                    RTStrFree(pszFileDest);
1360
 
                                }
1361
 
                                RTStrFree(pszFileSource);
1362
 
                            }
1363
 
                            else
1364
 
                                rc = VERR_NO_MEMORY;
1365
 
                        }
 
1515
                                rc = ctrlCopyFileToDest(pContext, pszFileSource,
 
1516
                                                        pszFileDest, 0 /* Flags */);
 
1517
                                RTStrFree(pszFileDest);
 
1518
                            }
 
1519
                            RTStrFree(pszFileSource);
 
1520
                        }
 
1521
                        else
 
1522
                            rc = VERR_NO_MEMORY;
1366
1523
                    }
1367
1524
                    break;
1368
1525
                }
1395
1552
    return rc;
1396
1553
}
1397
1554
 
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 */)
 
1555
/**
 
1556
 * Copys a directory (tree) to the destination, based on the current copy
 
1557
 * context.
 
1558
 *
 
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
 
1564
 *                                  source directory.
 
1565
 * @param   fFlags                  Copy flags, such as recursive copying.
 
1566
 */
 
1567
static int ctrlCopyDirToDest(PCOPYCONTEXT pContext,
 
1568
                             const char *pszSource, const char *pszFilter,
 
1569
                             const char *pszDest, uint32_t fFlags)
1402
1570
{
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. */);
1408
1576
}
1409
1577
 
 
1578
/**
 
1579
 * Creates a source root by stripping file names or filters of the specified source.
 
1580
 *
 
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().
 
1585
 */
1410
1586
static int ctrlCopyCreateSourceRoot(const char *pszSource, char **ppszSourceRoot)
1411
1587
{
1412
1588
    AssertPtrReturn(pszSource, VERR_INVALID_POINTER);
1439
1615
    return VINF_SUCCESS;
1440
1616
}
1441
1617
 
 
1618
/**
 
1619
 * Frees a previously allocated source root.
 
1620
 *
 
1621
 * @return  IPRT status code.
 
1622
 * @param   pszSourceRoot           Source root to free.
 
1623
 */
1442
1624
static void ctrlCopyFreeSourceRoot(char *pszSourceRoot)
1443
1625
{
1444
1626
    RTStrFree(pszSourceRoot);
1463
1645
     * what and how to implement the file enumeration/recursive lookup, like VBoxManage
1464
1646
     * does in here.
1465
1647
     */
1466
 
 
1467
 
#ifdef DEBUG_andy
1468
 
    tstTranslatePath();
1469
 
    return VINF_SUCCESS;
1470
 
#endif
1471
 
 
1472
1648
    static const RTGETOPTDEF s_aOptions[] =
1473
1649
    {
1474
1650
        { "--dryrun",              GETOPTDEF_COPYTO_DRYRUN,         RTGETOPT_REQ_NOTHING },
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(),
1587
1763
                                &pContext);
1588
1764
    if (RT_FAILURE(vrc))
1610
1786
         */
1611
1787
        for (unsigned long s = 0; s < vecSources.size(); s++)
1612
1788
        {
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;
1631
1808
            bool fExists;
1632
 
            Utf8Str Utf8CurSource(pszSource);
1633
 
            if (   Utf8CurSource.endsWith("/")
1634
 
                || Utf8CurSource.endsWith("\\"))
 
1809
 
 
1810
            size_t cchSource = strlen(pszSource);
 
1811
            if (   cchSource > 1
 
1812
                && RTPATH_IS_SLASH(pszSource[cchSource - 1]))
1635
1813
            {
1636
1814
#ifndef DEBUG_andy
1637
1815
                if (pContext->fHostToGuest)
1638
1816
                {
1639
1817
#endif
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);
 
1822
 
 
1823
                    if (fExists)
 
1824
                    {
 
1825
                        /* Strip trailing slash from our source element so that other functions
 
1826
                         * can use this stuff properly (like RTPathStartsWith). */
 
1827
                        RTPathStripTrailingSlash(pszSource);
 
1828
                    }
1644
1829
#ifndef DEBUG_andy
1645
1830
                }
1646
1831
                else
1655
1840
                vrc = ctrlCopyFileExistsOnSource(pContext, pszSource, &fExists);
1656
1841
                if (   RT_SUCCESS(vrc)
1657
1842
                    && fExists)
 
1843
                {
1658
1844
                    fIsFile = true;
 
1845
                }
1659
1846
            }
1660
1847
 
1661
 
            if (RT_SUCCESS(vrc))
 
1848
            if (   RT_SUCCESS(vrc)
 
1849
                && fExists)
1662
1850
            {
1663
1851
                if (fIsFile)
1664
1852
                {
1668
1856
                                                Utf8Dest.c_str(), &pszDestFile);
1669
1857
                    if (RT_SUCCESS(vrc))
1670
1858
                    {
1671
 
                        vrc = ctrlCopyFileToTarget(pContext, pszSource,
1672
 
                                                   pszDestFile, fFlags);
 
1859
                        vrc = ctrlCopyFileToDest(pContext, pszSource,
 
1860
                                                 pszDestFile, 0 /* Flags */);
1673
1861
                        RTStrFree(pszDestFile);
1674
1862
                    }
1675
1863
                    else
1676
 
                    {
1677
1864
                        RTMsgError("Unable to translate path for \"%s\", rc=%Rrc\n",
1678
1865
                                   pszSource, vrc);
1679
 
                    }
1680
1866
                }
1681
1867
                else
1682
1868
                {
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);
1686
1872
                }
1687
1873
            }
1688
1874
 
1693
1879
            {
1694
1880
                RTMsgError("Warning: Source \"%s\" does not exist, skipping!\n",
1695
1881
                           pszSource);
 
1882
                RTStrFree(pszSource);
1696
1883
                continue;
1697
1884
            }
1698
 
 
1699
 
            if (RT_FAILURE(vrc))
 
1885
            else if (RT_FAILURE(vrc))
1700
1886
            {
1701
1887
                RTMsgError("Error processing \"%s\", rc=%Rrc\n",
1702
1888
                           pszSource, vrc);
 
1889
                RTStrFree(pszSource);
1703
1890
                break;
1704
1891
            }
 
1892
 
 
1893
            RTStrFree(pszSource);
1705
1894
        }
1706
1895
    }
1707
1896
 
1927
2116
                 * drop out with exitcode 1. */
1928
2117
                if (!fExists)
1929
2118
                {
1930
 
                    RTPrintf("Cannot stat for element \"%s\": No such file or directory.\n",
 
2119
                    RTPrintf("Cannot stat for element \"%s\": No such file or directory\n",
1931
2120
                             it->first.c_str());
1932
2121
                    rcExit = RTEXITCODE_FAILURE;
1933
2122
                }
2011
2200
            Utf8Source = Utf8Src2;
2012
2201
        else
2013
2202
        {
2014
 
            RTMsgError("Source could not be determined! Please use --source to specify a valid source.\n");
 
2203
            RTMsgError("Source could not be determined! Please use --source to specify a valid source\n");
2015
2204
            vrc = VERR_FILE_NOT_FOUND;
2016
2205
        }
2017
2206
    }
2039
2228
            rc = showProgress(progress);
2040
2229
            if (FAILED(rc))
2041
2230
                vrc = ctrlPrintProgressError(progress);
2042
 
            else if (fVerbose)
2043
 
                RTPrintf("Guest Additions update successful.\n");
 
2231
            else if (   SUCCEEDED(rc)
 
2232
                     && fVerbose)
 
2233
            {
 
2234
                RTPrintf("Guest Additions update successful\n");
 
2235
            }
2044
2236
        }
2045
2237
    }
2046
2238
 
2057
2249
{
2058
2250
    AssertPtrReturn(pArg, VERR_INVALID_PARAMETER);
2059
2251
 
 
2252
#ifdef DEBUG_andy
 
2253
    if (RT_FAILURE(tstTranslatePath()))
 
2254
        return RTEXITCODE_FAILURE;
 
2255
#endif
 
2256
 
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. */