Index: trunk/src/VBox/ValidationKit/testdriver/vbox.py
===================================================================
--- trunk/src/VBox/ValidationKit/testdriver/vbox.py	(revision 84590)
+++ trunk/src/VBox/ValidationKit/testdriver/vbox.py	(revision 84597)
@@ -3437,5 +3437,4 @@
 
         Returns False on error, logged.
-
         Returns task result on success.
         """
@@ -3543,29 +3542,42 @@
                               (sRemoteFile, sLocalFile, self.adjustTimeoutMs(cMsTimeout), fIgnoreErrors));
 
-    def txsDownloadFiles(self, oSession, oTxsSession, asFiles, fIgnoreErrors = False):
-        """
-        Convenience function to get files from the guest and stores it
-        into the scratch directory for later (manual) review.
+    def txsDownloadFiles(self, oSession, oTxsSession, aasFiles, fAddToLog = True, fIgnoreErrors = False):
+        """
+        Convenience function to get files from the guest, storing them in the
+        scratch and adding them to the test result set (optional, but default).
+
+        The aasFiles parameter contains an array of with guest-path + host-path
+        pairs, optionally a file 'kind', description and an alternative upload
+        filename can also be specified.
+
+        Host paths are relative to the scratch directory or they must be given
+        in absolute form.  The guest path should be using guest path style.
 
         Returns True on success.
-
-        Returns False on failure, logged.
-        """
-        fRc = True;
-        for sGstFile in asFiles:
-            sTmpFile = os.path.join(self.sScratchPath, 'tmp-' + os.path.basename(sGstFile));
-            reporter.log2('Downloading file "%s" to "%s" ...' % (sGstFile, sTmpFile));
-            # First try to remove (unlink) an existing temporary file, as we don't truncate the file.
-            try:    os.unlink(sTmpFile);
+        Returns False on failure (unless fIgnoreErrors is set), logged.
+        """
+        for asEntry in aasFiles:
+            # Unpack:
+            sGstFile     = asEntry[0];
+            sHstFile     = asEntry[1];
+            sKind        = asEntry[2] if len(asEntry) > 2 and asEntry[2] else 'misc/other';
+            sDescription = asEntry[3] if len(asEntry) > 3 and asEntry[3] else '';
+            sAltName     = asEntry[4] if len(asEntry) > 4 and asEntry[4] else None;
+            assert len(asEntry) <= 5 and sGstFile and sHstFile;
+            if not os.path.isabs(sHstFile):
+                sHstFile = os.path.join(self.sScratchPath, sHstFile);
+
+            reporter.log2('Downloading file "%s" to "%s" ...' % (sGstFile, sHstFile,));
+
+            try:    os.unlink(sHstFile); ## @todo txsDownloadFile doesn't truncate the output file.
             except: pass;
-            ## @todo Check for already existing files on the host and create a new
-            #        name for the current file to download.
-            fRc = self.txsDownloadFile(oSession, oTxsSession, sGstFile, sTmpFile, 30 * 1000, fIgnoreErrors);
+
+            fRc = self.txsDownloadFile(oSession, oTxsSession, sGstFile, sHstFile, 30 * 1000, fIgnoreErrors);
             if fRc:
-                reporter.addLogFile(sTmpFile, 'misc/other', 'guest - ' + sGstFile);
+                if fAddToLog:
+                    reporter.addLogFile(sHstFile, sKind, sDescription, sAltName);
             else:
                 if fIgnoreErrors is not True:
-                    reporter.error('error downloading file "%s" to "%s"' % (sGstFile, sTmpFile));
-                    return fRc;
+                    return reporter.error('error downloading file "%s" to "%s"' % (sGstFile, sHstFile));
                 reporter.log('warning: file "%s" was not downloaded, ignoring.' % (sGstFile,));
         return True;
Index: trunk/src/VBox/ValidationKit/tests/additions/tdAddBasic1.py
===================================================================
--- trunk/src/VBox/ValidationKit/tests/additions/tdAddBasic1.py	(revision 84590)
+++ trunk/src/VBox/ValidationKit/tests/additions/tdAddBasic1.py	(revision 84597)
@@ -193,13 +193,6 @@
         the actual test result.
         """
-        fRc = False;
-
-        if oTestVm.isWindows():
-            self.sFileCdWait = 'VBoxWindowsAdditions.exe';
-        elif oTestVm.isLinux():
-            self.sFileCdWait = 'VBoxLinuxAdditions.run';
-
-        self.logVmInfo(oVM);
-
+        # HACK ALERT! HORRIBLE MESS THAT SHOULDN'T BE HERE!
+        aasLogFiles = [ ];
         if oTestVm.isLinux():
             reporter.testStart('Enabling udev logging ...');
@@ -207,9 +200,9 @@
             reporter.testDone();
             if oTxsSession:
-                oTxsSession.syncExec("sed",
-                                     ("sed", "-i", "'s/.*udev_log.*/udev_log=\"debug\"/'", "/etc/udev/udev.conf"),
+                oTxsSession.syncExec("sed", ("sed", "-i", "'s/.*udev_log.*/udev_log=\"debug\"/'", "/etc/udev/udev.conf"),
                                      fIgnoreErrors = True);
 
                 sUDevMonitorLog = '/tmp/udev_monitor.log';
+                aasLogFiles.append((sUDevMonitorLog, 'guest-udev_monitor-%s.log' % (oTestVm.sVmName,),));
 
                 reporter.testStart('Enabling udev monitoring ...');
@@ -228,7 +221,16 @@
                 oTxsSession.syncUploadString(sUdevSvc.getvalue(), '/etc/systemd/system/systemd-udev-monitor.service', 0o644,
                                              fIgnoreErrors = True);
-                oTxsSession.syncExec("systemctl", ("systemctl", "enable", "systemd-udev-monitor.service"),
-                                     fIgnoreErrors = True);
+                oTxsSession.syncExec("systemctl", ("systemctl", "enable", "systemd-udev-monitor.service"), fIgnoreErrors = True);
                 reporter.testDone();
+        # HACK ALERT - END.
+
+        fRc = False;
+
+        self.logVmInfo(oVM);
+
+        if oTestVm.isWindows():
+            self.sFileCdWait = 'VBoxWindowsAdditions.exe';
+        elif oTestVm.isLinux():
+            self.sFileCdWait = 'VBoxLinuxAdditions.run';
 
         reporter.testStart('Waiting for TXS + CD (%s)' % (self.sFileCdWait,));
@@ -243,7 +245,7 @@
         reporter.testDone();
 
-        if oTestVm.isLinux():
-            asLogFiles = [ sUDevMonitorLog ];
-            self.txsDownloadFiles(oSession, oTxsSession, asLogFiles, fIgnoreErrors = True);
+        # More HACK ALERT stuff.
+        if aasLogFiles and oTxsSession:
+            self.txsDownloadFiles(oSession, oTxsSession, aasLogFiles, fIgnoreErrors = True);
 
         if oSession is not None:
@@ -418,10 +420,10 @@
         #       deletion errors from the guest side (e.g. sharing violations) and just continue.
         #
-        asLogFiles = [];
-        fHaveSetupApiDevLog = False;
         sWinDir = self.getGuestWinDir(oTestVm);
-        asLogFiles = [ oTestVm.pathJoin(sWinDir, 'setupapi.log'),
-                       oTestVm.pathJoin(sWinDir, 'setupact.log'),
-                       oTestVm.pathJoin(sWinDir, 'setuperr.log') ];
+        aasLogFiles = [
+            ( oTestVm.pathJoin(sWinDir, 'setupapi.log'), 'ga-setupapi-%s.log' % (oTestVm.sVmName,), ),
+            ( oTestVm.pathJoin(sWinDir, 'setupact.log'), 'ga-setupact-%s.log' % (oTestVm.sVmName,), ),
+            ( oTestVm.pathJoin(sWinDir, 'setuperr.log'), 'ga-setuperr-%s.log' % (oTestVm.sVmName,), ),
+        ];
 
         # Apply The SetupAPI logging level so that we also get the (most verbose) setupapi.dev.log file.
@@ -435,6 +437,6 @@
                                                fCheckSessionStatus = True);
 
-        for sFile in asLogFiles:
-            self.txsRmFile(oSession, oTxsSession, sFile, 10 * 1000, fIgnoreErrors = True);
+        for sGstFile, _ in aasLogFiles:
+            self.txsRmFile(oSession, oTxsSession, sGstFile, 10 * 1000, fIgnoreErrors = True);
 
         #
@@ -447,14 +449,13 @@
 
         # Add the Windows Guest Additions installer files to the files we want to download
-        # from the guest.
-        sGuestAddsDir = 'C:/Program Files/Oracle/VirtualBox Guest Additions/';
-        asLogFiles.append(sGuestAddsDir + 'install.log');
-        # Note: There won't be a install_ui.log because of the silent installation.
-        asLogFiles.append(sGuestAddsDir + 'install_drivers.log');
-        asLogFiles.append('C:/Windows/setupapi.log');
+        # from the guest. Note: There won't be a install_ui.log because of the silent installation.
+        sGuestAddsDir = 'C:\\Program Files\\Oracle\\VirtualBox Guest Additions\\';
+        aasLogFiles.append((sGuestAddsDir + 'install.log',           'ga-install-%s.log' % (oTestVm.sVmName,),));
+        aasLogFiles.append((sGuestAddsDir + 'install_drivers.log',   'ga-install_drivers-%s.log' % (oTestVm.sVmName,),));
+        aasLogFiles.append(('C:\\Windows\\setupapi.log',             'ga-setupapi-%s.log' % (oTestVm.sVmName,),));
 
         # Note: setupapi.dev.log only is available since Windows 2000.
         if fHaveSetupApiDevLog:
-            asLogFiles.append('C:/Windows/setupapi.dev.log');
+            aasLogFiles.append(('C:\\Windows\\setupapi.dev.log',     'ga-setupapi.dev-%s.log' % (oTestVm.sVmName,),));
 
         #
@@ -463,5 +464,5 @@
         # on different Windows guests.
         #
-        self.txsDownloadFiles(oSession, oTxsSession, asLogFiles, fIgnoreErrors = True);
+        self.txsDownloadFiles(oSession, oTxsSession, aasLogFiles, fIgnoreErrors = True);
 
         #
@@ -494,9 +495,4 @@
 
     def testLinuxInstallAdditions(self, oSession, oTxsSession, oTestVm):
-        _ = oSession;
-        _ = oTestVm;
-
-        fRc = False;
-
         #
         # The actual install.
@@ -523,7 +519,7 @@
         # Ignore errors as all files above might not be present for whatever reason.
         #
-        asLogFile = [];
-        asLogFile.append('/var/log/vboxadd-install.log');
-        self.txsDownloadFiles(oSession, oTxsSession, asLogFile, fIgnoreErrors = True);
+        self.txsDownloadFiles(oSession, oTxsSession,
+                              [('/var/log/vboxadd-install.log', 'vboxadd-install-%s.log' % oTestVm.sName), ],
+                              fIgnoreErrors = True);
 
         # Do the final reboot to get the just installed Guest Additions up and running.
