static int tstDirOpenFiltered(const char *pszFilter, unsigned *pcFilesMatch, int *pRc) { int rcRet = 0; unsigned cFilesMatch = 0; PRTDIR pDir; int rc = RTDirOpenFiltered(&pDir, pszFilter, RTDIRFILTER_WINNT, 0); if (RT_SUCCESS(rc)) { for (;;) { RTDIRENTRY DirEntry; rc = RTDirRead(pDir, &DirEntry, NULL); if (RT_FAILURE(rc)) break; cFilesMatch++; } if (rc != VERR_NO_MORE_FILES) { RTPrintf("tstDir-3: Enumeration '%s' failed! rc=%Rrc\n", pszFilter, rc); rcRet = 1; } /* close up */ rc = RTDirClose(pDir); if (RT_FAILURE(rc)) { RTPrintf("tstDir-3: Failed to close dir '%s'! rc=%Rrc\n", pszFilter, rc); rcRet = 1; } } else { RTPrintf("tstDir-3: Failed to open '%s', rc=%Rrc\n", pszFilter, rc); rcRet = 1; } *pcFilesMatch = cFilesMatch; *pRc = rc; return rcRet; }
/** * Recursive worker for rtDbgSymCacheAddDir, for minimal stack wasting. * * @returns IPRT status code (fully bitched). * @param pszPath Pointer to a RTPATH_MAX size buffer containing * the path to the current directory ending with a * slash. * @param cchPath The size of the current directory path. * @param pDirEntry Pointer to the RTDIRENTRYEX structure to use. * @param pCfg The configuration. */ static int rtDbgSymCacheAddDirWorker(char *pszPath, size_t cchPath, PRTDIRENTRYEX pDirEntry, PCRTDBGSYMCACHEADDCFG pCfg) { /* * Open the directory. */ PRTDIR pDir; int rc, rc2; if (pCfg->pszFilter) { rc = RTStrCopy(&pszPath[cchPath], RTPATH_MAX - cchPath, pCfg->pszFilter); if (RT_FAILURE(rc)) { pszPath[cchPath] = '\0'; return RTMsgErrorRc(rc, "Filename too long (%Rrc): '%s" RTPATH_SLASH_STR "%s'", rc, pszPath, pCfg->pszFilter); } rc = RTDirOpenFiltered(&pDir, pszPath, RTDIRFILTER_WINNT, 0 /*fFlags*/); } else rc = RTDirOpen(&pDir, pszPath); if (RT_FAILURE(rc)) return RTMsgErrorRc(rc, "RTDirOpen%s failed on '%s': %Rrc", pCfg->pszFilter ? "Filtered" : "", pszPath, rc); /* * Enumerate the files. */ for (;;) { rc2 = RTDirReadEx(pDir, pDirEntry, NULL, RTFSOBJATTRADD_NOTHING, RTPATH_F_FOLLOW_LINK); if (RT_FAILURE(rc2)) { pszPath[cchPath] = '\0'; if (rc2 != VERR_NO_MORE_FILES) { RTMsgError("RTDirReadEx failed in '%s': %Rrc\n", pszPath, rc2); rc = rc2; } break; } /* Skip dot and dot-dot. */ if (RTDirEntryExIsStdDotLink(pDirEntry)) continue; /* Construct a full path. */ rc = RTStrCopy(&pszPath[cchPath], RTPATH_MAX, pDirEntry->szName); if (RT_FAILURE(rc)) { pszPath[cchPath] = '\0'; RTMsgError("File name too long in '%s': '%s' (%Rrc)", pszPath, pDirEntry->szName, rc); break; } switch (rtDbgSymCacheFigureType2(pszPath, &pDirEntry->Info)) { case RTDBGSYMCACHEFILETYPE_DIR: if (!pCfg->fRecursive) RTMsgInfo("Skipping directory '%s'...", pszPath); else { if (cchPath + pDirEntry->cbName + 3 <= RTPATH_MAX) { pszPath[cchPath + pDirEntry->cbName] = RTPATH_SLASH; pszPath[cchPath + pDirEntry->cbName + 1] = '\0'; rc2 = rtDbgSymCacheAddDirWorker(pszPath, cchPath + pDirEntry->cbName + 1, pDirEntry, pCfg); } else { RTMsgError("File name too long in '%s': '%s' (%Rrc)", pszPath, pDirEntry->szName, rc); rc2 = VERR_FILENAME_TOO_LONG; } } break; case RTDBGSYMCACHEFILETYPE_DEBUG_FILE: rc2 = rtDbgSymCacheAddDebugFile(pszPath, pCfg); break; case RTDBGSYMCACHEFILETYPE_IMAGE_FILE: rc2 = rtDbgSymCacheAddImageFile(pszPath, NULL /*pszExtraSuff*/, RTDBG_CACHE_UUID_MAP_DIR_IMAGES, pCfg); break; case RTDBGSYMCACHEFILETYPE_DEBUG_BUNDLE: rc2 = rtDbgSymCacheAddDebugBundle(pszPath, cchPath, pDirEntry->cbName, pCfg); break; case RTDBGSYMCACHEFILETYPE_IMAGE_BUNDLE: rc2 = rtDbgSymCacheAddImageBundle(pszPath, cchPath, pDirEntry->cbName, pDirEntry, pCfg); break; case RTDBGSYMCACHEFILETYPE_DIR_FILTER: case RTDBGSYMCACHEFILETYPE_INVALID: rc2 = RTMsgErrorRc(VERR_INTERNAL_ERROR_2, "Invalid: '%s'", pszPath); break; case RTDBGSYMCACHEFILETYPE_IGNORE: rc2 = VINF_SUCCESS; break; } if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) rc = rc2; } /* * Clean up. */ rc2 = RTDirClose(pDir); if (RT_FAILURE(rc2)) { RTMsgError("RTDirClose failed in '%s': %Rrc", pszPath, rc); rc = rc2; } return rc; }
int main(int argc, char **argv) { int rcRet = 0; RTR3InitExe(argc, &argv, 0); /* * Iterate arguments. */ for (int i = 1; i < argc; i++) { /* open */ PRTDIR pDir; int rc = RTDirOpenFiltered(&pDir, argv[i], RTDIRFILTER_WINNT, 0); if (RT_SUCCESS(rc)) { for (;;) { RTDIRENTRY DirEntry; rc = RTDirRead(pDir, &DirEntry, NULL); if (RT_FAILURE(rc)) break; switch (DirEntry.enmType) { case RTDIRENTRYTYPE_UNKNOWN: RTPrintf("u"); break; case RTDIRENTRYTYPE_FIFO: RTPrintf("f"); break; case RTDIRENTRYTYPE_DEV_CHAR: RTPrintf("c"); break; case RTDIRENTRYTYPE_DIRECTORY: RTPrintf("d"); break; case RTDIRENTRYTYPE_DEV_BLOCK: RTPrintf("b"); break; case RTDIRENTRYTYPE_FILE: RTPrintf("-"); break; case RTDIRENTRYTYPE_SYMLINK: RTPrintf("l"); break; case RTDIRENTRYTYPE_SOCKET: RTPrintf("s"); break; case RTDIRENTRYTYPE_WHITEOUT: RTPrintf("w"); break; default: rcRet = 1; RTPrintf("?"); break; } RTPrintf(" %#18llx %3d %s\n", (uint64_t)DirEntry.INodeId, DirEntry.cbName, DirEntry.szName); } if (rc != VERR_NO_MORE_FILES) { RTPrintf("tstDir-2: Enumeration failed! rc=%Rrc\n", rc); rcRet = 1; } /* close up */ rc = RTDirClose(pDir); if (RT_FAILURE(rc)) { RTPrintf("tstDir-2: Failed to close dir! rc=%Rrc\n", rc); rcRet = 1; } } else { RTPrintf("tstDir-2: Failed to open '%s', rc=%Rrc\n", argv[i], rc); rcRet = 1; } } return rcRet; }
/** * Returns the path of the ACPI CPU device with the given core and package ID. * * @returns VBox status code. * @param ppszPath Where to store the path. * @param idCpuCore The core ID of the CPU. * @param idCpuPackage The package ID of the CPU. */ static int VBoxServiceCpuHotPlugGetACPIDevicePath(char **ppszPath, uint32_t idCpuCore, uint32_t idCpuPackage) { int rc = VINF_SUCCESS; AssertPtrReturn(ppszPath, VERR_INVALID_PARAMETER); rc = VBoxServiceCpuHotPlugProbePath(); if (RT_SUCCESS(rc)) { /* Build the path from all components. */ bool fFound = false; unsigned iLvlCurr = 0; char *pszPath = NULL; char *pszPathDir = NULL; PSYSFSCPUPATH pAcpiCpuPathLvl = &g_aAcpiCpuPath[iLvlCurr]; /* Init everything. */ Assert(pAcpiCpuPathLvl->uId != ACPI_CPU_PATH_NOT_PROBED); pszPath = RTPathJoinA(SYSFS_ACPI_CPU_PATH, pAcpiCpuPathLvl->aComponentsPossible[pAcpiCpuPathLvl->uId].pcszName); if (!pszPath) return VERR_NO_STR_MEMORY; pAcpiCpuPathLvl->pszPath = RTStrDup(SYSFS_ACPI_CPU_PATH); if (!pAcpiCpuPathLvl->pszPath) { RTStrFree(pszPath); return VERR_NO_STR_MEMORY; } /* Open the directory */ rc = RTDirOpenFiltered(&pAcpiCpuPathLvl->pDir, pszPath, RTDIRFILTER_WINNT, 0); if (RT_SUCCESS(rc)) { RTStrFree(pszPath); /* Search for CPU */ while (!fFound) { /* Get the next directory. */ RTDIRENTRY DirFolderContent; rc = RTDirRead(pAcpiCpuPathLvl->pDir, &DirFolderContent, NULL); if (RT_SUCCESS(rc)) { /* Create the new path. */ char *pszPathCurr = RTPathJoinA(pAcpiCpuPathLvl->pszPath, DirFolderContent.szName); if (!pszPathCurr) { rc = VERR_NO_STR_MEMORY; break; } /* If this is the last level check for the given core and package id. */ if (iLvlCurr == RT_ELEMENTS(g_aAcpiCpuPath) - 1) { /* Get the sysdev */ uint32_t idCore = RTLinuxSysFsReadIntFile(10, "%s/sysdev/topology/core_id", pszPathCurr); uint32_t idPackage = RTLinuxSysFsReadIntFile(10, "%s/sysdev/topology/physical_package_id", pszPathCurr); if ( idCore == idCpuCore && idPackage == idCpuPackage) { /* Return the path */ pszPath = pszPathCurr; fFound = true; VBoxServiceVerbose(3, "CPU found\n"); break; } else { /* Get the next directory. */ RTStrFree(pszPathCurr); VBoxServiceVerbose(3, "CPU doesn't match, next directory\n"); } } else { /* Go deeper */ iLvlCurr++; VBoxServiceVerbose(3, "Going deeper (iLvlCurr=%u)\n", iLvlCurr); pAcpiCpuPathLvl = &g_aAcpiCpuPath[iLvlCurr]; Assert(!pAcpiCpuPathLvl->pDir); Assert(!pAcpiCpuPathLvl->pszPath); pAcpiCpuPathLvl->pszPath = pszPathCurr; PCSYSFSCPUPATHCOMP pPathComponent = &pAcpiCpuPathLvl->aComponentsPossible[pAcpiCpuPathLvl->uId]; Assert(pAcpiCpuPathLvl->uId != ACPI_CPU_PATH_NOT_PROBED); pszPathDir = RTPathJoinA(pszPathCurr, pPathComponent->pcszName); if (!pszPathDir) { rc = VERR_NO_STR_MEMORY; break; } VBoxServiceVerbose(3, "New path %s\n", pszPathDir); /* Open the directory */ rc = RTDirOpenFiltered(&pAcpiCpuPathLvl->pDir, pszPathDir, RTDIRFILTER_WINNT, 0); if (RT_FAILURE(rc)) break; } } else { /* Go back one level and try to get the next entry. */ Assert(iLvlCurr > 0); RTDirClose(pAcpiCpuPathLvl->pDir); RTStrFree(pAcpiCpuPathLvl->pszPath); pAcpiCpuPathLvl->pDir = NULL; pAcpiCpuPathLvl->pszPath = NULL; iLvlCurr--; pAcpiCpuPathLvl = &g_aAcpiCpuPath[iLvlCurr]; VBoxServiceVerbose(3, "Directory not found, going back (iLvlCurr=%u)\n", iLvlCurr); } } /* while not found */ } /* Successful init */ /* Cleanup */ for (unsigned i = 0; i < RT_ELEMENTS(g_aAcpiCpuPath); i++) { if (g_aAcpiCpuPath[i].pDir) RTDirClose(g_aAcpiCpuPath[i].pDir); if (g_aAcpiCpuPath[i].pszPath) RTStrFree(g_aAcpiCpuPath[i].pszPath); g_aAcpiCpuPath[i].pDir = NULL; g_aAcpiCpuPath[i].pszPath = NULL; } if (pszPathDir) RTStrFree(pszPathDir); if (RT_FAILURE(rc) && pszPath) RTStrFree(pszPath); if (RT_SUCCESS(rc)) *ppszPath = pszPath; } return rc; }
/** * Probes for the correct path to the ACPI CPU object in sysfs for the * various different kernel versions and distro's. * * @returns VBox status code. */ static int VBoxServiceCpuHotPlugProbePath(void) { int rc = VINF_SUCCESS; /* Probe for the correct path if we didn't already. */ if (RT_UNLIKELY(g_aAcpiCpuPath[0].uId == ACPI_CPU_PATH_NOT_PROBED)) { char *pszPath = NULL; /** < Current path, increasing while we dig deeper. */ pszPath = RTStrDup(SYSFS_ACPI_CPU_PATH); if (!pszPath) return VERR_NO_MEMORY; /* * Simple algorithm to find the path. * Performance is not a real problem because it is * only executed once. */ for (unsigned iLvlCurr = 0; iLvlCurr < RT_ELEMENTS(g_aAcpiCpuPath); iLvlCurr++) { PSYSFSCPUPATH pAcpiCpuPathLvl = &g_aAcpiCpuPath[iLvlCurr]; for (unsigned iCompCurr = 0; iCompCurr < pAcpiCpuPathLvl->cComponents; iCompCurr++) { PCSYSFSCPUPATHCOMP pPathComponent = &pAcpiCpuPathLvl->aComponentsPossible[iCompCurr]; /* Open the directory */ PRTDIR pDirCurr = NULL; char *pszPathTmp = RTPathJoinA(pszPath, pPathComponent->pcszName); if (pszPathTmp) { rc = RTDirOpenFiltered(&pDirCurr, pszPathTmp, RTDIRFILTER_WINNT, 0); RTStrFree(pszPathTmp); } else rc = VERR_NO_STR_MEMORY; if (RT_FAILURE(rc)) break; /* Search if the current directory contains one of the possible parts. */ size_t cchName = strlen(pPathComponent->pcszName); RTDIRENTRY DirFolderContent; bool fFound = false; /* Get rid of the * filter which is in the path component. */ if (pPathComponent->fNumberedSuffix) cchName--; while (RT_SUCCESS(RTDirRead(pDirCurr, &DirFolderContent, NULL))) /* Assumption that szName has always enough space */ { if ( DirFolderContent.cbName >= cchName && !strncmp(DirFolderContent.szName, pPathComponent->pcszName, cchName)) { /* Found, use the complete name to dig deeper. */ fFound = true; pAcpiCpuPathLvl->uId = iCompCurr; char *pszPathLvl = RTPathJoinA(pszPath, DirFolderContent.szName); if (pszPathLvl) { RTStrFree(pszPath); pszPath = pszPathLvl; } else rc = VERR_NO_STR_MEMORY; break; } } RTDirClose(pDirCurr); if (fFound) break; } /* For every possible component. */ /* No matching component for this part, no need to continue */ if (RT_FAILURE(rc)) break; } /* For every level */ VBoxServiceVerbose(1, "Final path after probing %s rc=%Rrc\n", pszPath, rc); RTStrFree(pszPath); } return rc; }
/** * Corrects the casing of the final component * * @returns * @param pClient . * @param pszFullPath . * @param pszStartComponent . */ static int vbsfCorrectCasing(SHFLCLIENTDATA *pClient, char *pszFullPath, char *pszStartComponent) { Log2(("vbsfCorrectCasing: %s %s\n", pszFullPath, pszStartComponent)); AssertReturn((uintptr_t)pszFullPath < (uintptr_t)pszStartComponent - 1U, VERR_INTERNAL_ERROR_2); AssertReturn(pszStartComponent[-1] == RTPATH_DELIMITER, VERR_INTERNAL_ERROR_5); /* * Allocate a buffer that can hold really long file name entries as well as * the initial search pattern. */ size_t cchComponent = strlen(pszStartComponent); size_t cchParentDir = pszStartComponent - pszFullPath; size_t cchFullPath = cchParentDir + cchComponent; Assert(strlen(pszFullPath) == cchFullPath); size_t cbDirEntry = 4096; if (cchFullPath + 4 > cbDirEntry - RT_OFFSETOF(RTDIRENTRYEX, szName)) cbDirEntry = RT_OFFSETOF(RTDIRENTRYEX, szName) + cchFullPath + 4; PRTDIRENTRYEX pDirEntry = (PRTDIRENTRYEX)RTMemAlloc(cbDirEntry); if (pDirEntry == NULL) return VERR_NO_MEMORY; /* * Construct the search criteria in the szName member of pDirEntry. */ /** @todo This is quite inefficient, especially for directories with many * files. If any of the typically case sensitive host systems start * supporting opendir wildcard filters, it would make sense to build * one here with '?' for case foldable charaters. */ /** @todo Use RTDirOpen here and drop the whole uncessary path copying? */ int rc = RTPathJoinEx(pDirEntry->szName, cbDirEntry - RT_OFFSETOF(RTDIRENTRYEX, szName), pszFullPath, cchParentDir, RT_STR_TUPLE("*")); AssertRC(rc); if (RT_SUCCESS(rc)) { RTDIR hSearch = NULL; rc = RTDirOpenFiltered(&hSearch, pDirEntry->szName, RTDIRFILTER_WINNT, 0 /*fFlags*/); if (RT_SUCCESS(rc)) { for (;;) { size_t cbDirEntrySize = cbDirEntry; rc = RTDirReadEx(hSearch, pDirEntry, &cbDirEntrySize, RTFSOBJATTRADD_NOTHING, SHFL_RT_LINK(pClient)); if (rc == VERR_NO_MORE_FILES) break; if ( rc != VINF_SUCCESS && rc != VWRN_NO_DIRENT_INFO) { if ( rc == VERR_NO_TRANSLATION || rc == VERR_INVALID_UTF8_ENCODING) continue; AssertMsgFailed(("%Rrc\n", rc)); break; } Log2(("vbsfCorrectCasing: found %s\n", &pDirEntry->szName[0])); if ( pDirEntry->cbName == cchComponent && !RTStrICmp(pszStartComponent, &pDirEntry->szName[0])) { Log(("Found original name %s (%s)\n", &pDirEntry->szName[0], pszStartComponent)); strcpy(pszStartComponent, &pDirEntry->szName[0]); rc = VINF_SUCCESS; break; } } RTDirClose(hSearch); } } if (RT_FAILURE(rc)) Log(("vbsfCorrectCasing %s failed with %Rrc\n", pszStartComponent, rc)); RTMemFree(pDirEntry); return rc; }
int main(int argc, char **argv) { int rcRet = 0; RTR3InitExe(argc, &argv, 0); /* * Iterate arguments. */ bool fLong = false; bool fShortName = false; bool fFiltered = false; bool fQuiet = false; for (int i = 1; i < argc; i++) { if (argv[i][0] == '-') { for (int j = 1; argv[i][j]; j++) { switch (argv[i][j]) { case 'l': fLong = true; break; case 's': fShortName = true; break; case 'f': fFiltered = true; break; case 'q': fQuiet = true; break; default: RTPrintf("Unknown option '%c' ignored!\n", argv[i][j]); break; } } } else { /* open */ PRTDIR pDir; int rc; if (!fFiltered) rc = RTDirOpen(&pDir, argv[i]); else rc = RTDirOpenFiltered(&pDir, argv[i], RTDIRFILTER_WINNT, 0); if (RT_SUCCESS(rc)) { /* list */ if (!fLong) { for (;;) { RTDIRENTRY DirEntry; rc = RTDirRead(pDir, &DirEntry, NULL); if (RT_FAILURE(rc)) break; if (!fQuiet) { switch (DirEntry.enmType) { case RTDIRENTRYTYPE_UNKNOWN: RTPrintf("u"); break; case RTDIRENTRYTYPE_FIFO: RTPrintf("f"); break; case RTDIRENTRYTYPE_DEV_CHAR: RTPrintf("c"); break; case RTDIRENTRYTYPE_DIRECTORY: RTPrintf("d"); break; case RTDIRENTRYTYPE_DEV_BLOCK: RTPrintf("b"); break; case RTDIRENTRYTYPE_FILE: RTPrintf("-"); break; case RTDIRENTRYTYPE_SYMLINK: RTPrintf("l"); break; case RTDIRENTRYTYPE_SOCKET: RTPrintf("s"); break; case RTDIRENTRYTYPE_WHITEOUT: RTPrintf("w"); break; default: rcRet = 1; RTPrintf("?"); break; } RTPrintf(" %#18llx %3d %s\n", (uint64_t)DirEntry.INodeId, DirEntry.cbName, DirEntry.szName); } } } else { for (;;) { RTDIRENTRYEX DirEntry; rc = RTDirReadEx(pDir, &DirEntry, NULL, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK); if (RT_FAILURE(rc)) break; if (!fQuiet) { RTFMODE fMode = DirEntry.Info.Attr.fMode; switch (fMode & RTFS_TYPE_MASK) { case RTFS_TYPE_FIFO: RTPrintf("f"); break; case RTFS_TYPE_DEV_CHAR: RTPrintf("c"); break; case RTFS_TYPE_DIRECTORY: RTPrintf("d"); break; case RTFS_TYPE_DEV_BLOCK: RTPrintf("b"); break; case RTFS_TYPE_FILE: RTPrintf("-"); break; case RTFS_TYPE_SYMLINK: RTPrintf("l"); break; case RTFS_TYPE_SOCKET: RTPrintf("s"); break; case RTFS_TYPE_WHITEOUT: RTPrintf("w"); break; default: rcRet = 1; RTPrintf("?"); break; } /** @todo sticy bits++ */ RTPrintf("%c%c%c", fMode & RTFS_UNIX_IRUSR ? 'r' : '-', fMode & RTFS_UNIX_IWUSR ? 'w' : '-', fMode & RTFS_UNIX_IXUSR ? 'x' : '-'); RTPrintf("%c%c%c", fMode & RTFS_UNIX_IRGRP ? 'r' : '-', fMode & RTFS_UNIX_IWGRP ? 'w' : '-', fMode & RTFS_UNIX_IXGRP ? 'x' : '-'); RTPrintf("%c%c%c", fMode & RTFS_UNIX_IROTH ? 'r' : '-', fMode & RTFS_UNIX_IWOTH ? 'w' : '-', fMode & RTFS_UNIX_IXOTH ? 'x' : '-'); RTPrintf(" %c%c%c%c%c%c%c%c%c%c%c%c%c%c", fMode & RTFS_DOS_READONLY ? 'R' : '-', fMode & RTFS_DOS_HIDDEN ? 'H' : '-', fMode & RTFS_DOS_SYSTEM ? 'S' : '-', fMode & RTFS_DOS_DIRECTORY ? 'D' : '-', fMode & RTFS_DOS_ARCHIVED ? 'A' : '-', fMode & RTFS_DOS_NT_DEVICE ? 'd' : '-', fMode & RTFS_DOS_NT_NORMAL ? 'N' : '-', fMode & RTFS_DOS_NT_TEMPORARY ? 'T' : '-', fMode & RTFS_DOS_NT_SPARSE_FILE ? 'P' : '-', fMode & RTFS_DOS_NT_REPARSE_POINT ? 'J' : '-', fMode & RTFS_DOS_NT_COMPRESSED ? 'C' : '-', fMode & RTFS_DOS_NT_OFFLINE ? 'O' : '-', fMode & RTFS_DOS_NT_NOT_CONTENT_INDEXED ? 'I' : '-', fMode & RTFS_DOS_NT_ENCRYPTED ? 'E' : '-'); RTPrintf(" %d %4d %4d %10lld %10lld %#llx %#llx %#llx %#llx", DirEntry.Info.Attr.u.Unix.cHardlinks, DirEntry.Info.Attr.u.Unix.uid, DirEntry.Info.Attr.u.Unix.gid, DirEntry.Info.cbObject, DirEntry.Info.cbAllocated, DirEntry.Info.BirthTime, DirEntry.Info.ChangeTime, DirEntry.Info.ModificationTime, DirEntry.Info.AccessTime); if (fShortName) RTPrintf(" %2d %-12ls ", DirEntry.cwcShortName, DirEntry.wszShortName); RTPrintf(" %2d %s\n", DirEntry.cbName, DirEntry.szName); } if (rc != VINF_SUCCESS) RTPrintf("^^ %Rrc\n", rc); } } if (rc != VERR_NO_MORE_FILES) { RTPrintf("tstDir: Enumeration failed! rc=%Rrc\n", rc); rcRet = 1; } /* close up */ rc = RTDirClose(pDir); if (RT_FAILURE(rc)) { RTPrintf("tstDir: Failed to close dir! rc=%Rrc\n", rc); rcRet = 1; } } else { RTPrintf("tstDir: Failed to open '%s', rc=%Rrc\n", argv[i], rc); rcRet = 1; } } } return rcRet; }
/** * Process the testcases found in the filter. * * @param pszFilter The filter (winnt) to pass to RTDirOpenFiltered for * selecting the testcases. * @param pszDir The directory we're processing. */ static void Process(const char *pszFilter, const char *pszDir) { /* * Open and enumerate the directory. */ PRTDIR pDir; int rc = RTDirOpenFiltered(&pDir, pszFilter, RTDIRFILTER_WINNT, 0); if (RT_SUCCESS(rc)) { for (;;) { RTDIRENTRY DirEntry; rc = RTDirRead(pDir, &DirEntry, NULL); if (RT_FAILURE(rc)) { if (rc == VERR_NO_MORE_FILES) rc = VINF_SUCCESS; else RTPrintf("tstRunTestcases: reading '%s' -> %Rrc\n", pszFilter, rc); break; } /* * Construct the testcase name. */ char *pszTestcase; RTStrAPrintf(&pszTestcase, "%s/%s", pszDir, DirEntry.szName); if (!pszTestcase) { RTPrintf("tstRunTestcases: out of memory!\n"); rc = VERR_NO_MEMORY; break; } if (IsTestcaseIncluded(pszTestcase)) { /* * Execute the testcase. */ RTPrintf("*** %s: Executing...\n", pszTestcase); RTStrmFlush(g_pStdOut); const char *papszArgs[2]; papszArgs[0] = pszTestcase; papszArgs[1] = NULL; RTPROCESS Process; rc = RTProcCreate(pszTestcase, papszArgs, RTENV_DEFAULT, 0, &Process); if (RT_SUCCESS(rc)) { /* * Wait for the process and collect it's return code. * If it takes too long, we'll terminate it and continue. */ RTTIMESPEC Start; RTTimeNow(&Start); RTPROCSTATUS ProcStatus; for (;;) { rc = RTProcWait(Process, RTPROCWAIT_FLAGS_NOBLOCK, &ProcStatus); if (rc != VERR_PROCESS_RUNNING) break; RTTIMESPEC Now; if (RTTimeSpecGetMilli(RTTimeSpecSub(RTTimeNow(&Now), &Start)) > 120*1000 /* 1 min */) { RTPrintf("*** %s: FAILED - timed out. killing it.\n", pszTestcase); RTProcTerminate(Process); RTThreadSleep(100); RTProcWait(Process, RTPROCWAIT_FLAGS_NOBLOCK, &ProcStatus); g_cFailures++; break; } RTThreadSleep(100); } /* * Examin the exit status. */ if (RT_SUCCESS(rc)) { if ( ProcStatus.enmReason == RTPROCEXITREASON_NORMAL && ProcStatus.iStatus == 0) { RTPrintf("*** %s: PASSED\n", pszTestcase); g_cPasses++; } else { RTPrintf("*** %s: FAILED\n", pszTestcase); g_cFailures++; } } else if (rc != VERR_PROCESS_RUNNING) { RTPrintf("tstRunTestcases: %s: RTProcWait failed -> %Rrc\n", pszTestcase, rc); g_cFailures++; } } else { RTPrintf("tstRunTestcases: %s: failed to start -> %Rrc\n", pszTestcase, rc); g_cFailures++; } } else { RTPrintf("tstRunTestcases: %s: SKIPPED\n", pszTestcase); g_cSkipped++; } RTStrFree(pszTestcase); } /* enumeration loop */ RTDirClose(pDir); } else RTPrintf("tstRunTestcases: opening '%s' -> %Rrc\n", pszDir, rc); }