/* static */ int getDriveInfoFromSysfs(DriveInfoList *pList, bool isDVD, bool *pfSuccess) { AssertPtrReturn(pList, VERR_INVALID_POINTER); AssertPtrNullReturn(pfSuccess, VERR_INVALID_POINTER); /* Valid or Null */ LogFlowFunc (("pList=%p, isDVD=%u, pfSuccess=%p\n", pList, (unsigned) isDVD, pfSuccess)); RTDIR hDir; int rc; bool fSuccess = false; unsigned cFound = 0; if (!RTPathExists("/sys")) return VINF_SUCCESS; rc = RTDirOpen(&hDir, "/sys/block"); /* This might mean that sysfs semantics have changed */ AssertReturn(rc != VERR_FILE_NOT_FOUND, VINF_SUCCESS); fSuccess = true; if (RT_SUCCESS(rc)) { for (;;) { RTDIRENTRY entry; rc = RTDirRead(hDir, &entry, NULL); Assert(rc != VERR_BUFFER_OVERFLOW); /* Should never happen... */ if (RT_FAILURE(rc)) /* Including overflow and no more files */ break; if (entry.szName[0] == '.') continue; sysfsBlockDev dev(entry.szName, isDVD); /* This might mean that sysfs semantics have changed */ AssertBreakStmt(dev.isConsistent(), fSuccess = false); if (!dev.isValid()) continue; try { pList->push_back(DriveInfo(dev.getNode(), dev.getUdi(), dev.getDesc())); } catch(std::bad_alloc &e) { rc = VERR_NO_MEMORY; break; } ++cFound; } RTDirClose(hDir); } if (rc == VERR_NO_MORE_FILES) rc = VINF_SUCCESS; if (RT_FAILURE(rc)) /* Clean up again */ for (unsigned i = 0; i < cFound; ++i) pList->pop_back(); if (pfSuccess) *pfSuccess = fSuccess; LogFlow (("rc=%Rrc, fSuccess=%u\n", rc, (unsigned) fSuccess)); return rc; }
/** * 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. */ bool fLong = false; bool fShortName = 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; default: RTPrintf("Unknown option '%c' ignored!\n", argv[i][j]); break; } } } else { /* open */ PRTDIR pDir; int rc = RTDirOpen(&pDir, argv[i]); if (RT_SUCCESS(rc)) { /* list */ if (!fLong) { 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); } } else { for (;;) { RTDIRENTRYEX DirEntry; rc = RTDirReadEx(pDir, &DirEntry, NULL, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK); if (RT_FAILURE(rc)) break; 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 && DirEntry.cwcShortName) RTPrintf(" %2d %ls\n", DirEntry.cwcShortName, DirEntry.wszShortName); else 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; }
RTR3DECL(bool) RTProcIsRunningByName(const char *pszName) { /* * Quick validation. */ if (!pszName) return false; bool const fWithPath = RTPathHavePath(pszName); /* * Enumerate /proc. */ RTDIR hDir; int rc = RTDirOpen(&hDir, "/proc"); AssertMsgRCReturn(rc, ("RTDirOpen on /proc failed: rc=%Rrc\n", rc), false); if (RT_SUCCESS(rc)) { RTDIRENTRY DirEntry; while (RT_SUCCESS(RTDirRead(hDir, &DirEntry, NULL))) { /* * Filter numeric directory entries only. */ if ( ( DirEntry.enmType == RTDIRENTRYTYPE_DIRECTORY || DirEntry.enmType == RTDIRENTRYTYPE_UNKNOWN) && RTStrToUInt32(DirEntry.szName) > 0) { /* * Try readlink on exe first since it's more faster and reliable. * Fall back on reading the first line in cmdline if that fails * (access errors typically). cmdline is unreliable as it might * contain whatever the execv caller passes as argv[0]. */ char szName[RTPATH_MAX]; RTStrPrintf(szName, sizeof(szName), "/proc/%s/exe", &DirEntry.szName[0]); char szExe[RTPATH_MAX]; int cchLink = readlink(szName, szExe, sizeof(szExe) - 1); if ( cchLink > 0 && (size_t)cchLink < sizeof(szExe)) { szExe[cchLink] = '\0'; rc = VINF_SUCCESS; } else { RTStrPrintf(szName, sizeof(szName), "/proc/%s/cmdline", &DirEntry.szName[0]); PRTSTREAM pStream; rc = RTStrmOpen(szName, "r", &pStream); if (RT_SUCCESS(rc)) { rc = RTStrmGetLine(pStream, szExe, sizeof(szExe)); RTStrmClose(pStream); } } if (RT_SUCCESS(rc)) { /* * We are interested on the file name part only. */ char const *pszProcName = fWithPath ? szExe : RTPathFilename(szExe); if (RTStrCmp(pszProcName, pszName) == 0) { /* Found it! */ RTDirClose(hDir); return true; } } } } RTDirClose(hDir); } return false; }
/** * Recursive worker function to walk the /dev tree looking for DVD or floppy * devices. * @returns true if we have already found MAX_DEVICE_NODES devices, false * otherwise * @param pszPath the path to start recursing. The function can modify * this string at and after the terminating zero * @param cchPath the size of the buffer (not the string!) in @a pszPath * @param aDevices where to fill in information about devices that we have * found * @param wantDVD are we looking for DVD devices (or floppies)? */ static bool devFindDeviceRecursive(char *pszPath, size_t cchPath, deviceNodeArray aDevices, bool wantDVD) { /* * Check assumptions made by the code below. */ size_t const cchBasePath = strlen(pszPath); AssertReturn(cchBasePath < RTPATH_MAX - 10U, false); AssertReturn(pszPath[cchBasePath - 1] != '/', false); PRTDIR pDir; if (RT_FAILURE(RTDirOpen(&pDir, pszPath))) return false; for (;;) { RTDIRENTRY Entry; RTFSOBJINFO ObjInfo; int rc = RTDirRead(pDir, &Entry, NULL); if (RT_FAILURE(rc)) break; if (Entry.enmType == RTDIRENTRYTYPE_UNKNOWN) { if (RT_FAILURE(RTPathQueryInfo(pszPath, &ObjInfo, RTFSOBJATTRADD_UNIX))) continue; if (RTFS_IS_SYMLINK(ObjInfo.Attr.fMode)) continue; } if (Entry.enmType == RTDIRENTRYTYPE_SYMLINK) continue; pszPath[cchBasePath] = '\0'; if (RT_FAILURE(RTPathAppend(pszPath, cchPath, Entry.szName))) break; /* Do the matching. */ dev_t DevNode; char szDesc[256], szUdi[256]; if (!devValidateDevice(pszPath, wantDVD, &DevNode, szDesc, sizeof(szDesc), szUdi, sizeof(szUdi))) continue; unsigned i; for (i = 0; i < MAX_DEVICE_NODES; ++i) if (!aDevices[i].Device || (aDevices[i].Device == DevNode)) break; AssertBreak(i < MAX_DEVICE_NODES); if (aDevices[i].Device) continue; aDevices[i].Device = DevNode; RTStrPrintf(aDevices[i].szPath, sizeof(aDevices[i].szPath), "%s", pszPath); AssertCompile(sizeof(aDevices[i].szDesc) == sizeof(szDesc)); strcpy(aDevices[i].szDesc, szDesc); AssertCompile(sizeof(aDevices[i].szUdi) == sizeof(szUdi)); strcpy(aDevices[i].szUdi, szUdi); if (i == MAX_DEVICE_NODES - 1) break; continue; /* Recurse into subdirectories. */ if ( (Entry.enmType == RTDIRENTRYTYPE_UNKNOWN) && !RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode)) continue; if (Entry.enmType != RTDIRENTRYTYPE_DIRECTORY) continue; if (Entry.szName[0] == '.') continue; if (devFindDeviceRecursive(pszPath, cchPath, aDevices, wantDVD)) break; } RTDirClose(pDir); return aDevices[MAX_DEVICE_NODES - 1].Device ? true : false; }
/** * Handles VMMDevCpuEventType_Plug. * * @param idCpuCore The CPU core ID. * @param idCpuPackage The CPU package ID. */ static void VBoxServiceCpuHotPlugHandlePlugEvent(uint32_t idCpuCore, uint32_t idCpuPackage) { #ifdef RT_OS_LINUX /* * The topology directory (containing the physical and core id properties) * is not available until the CPU is online. So we just iterate over all directories * and enable every CPU which is not online already. * Because the directory might not be available immediately we try a few times. * * @todo: Maybe use udev to monitor hot-add events from the kernel */ bool fCpuOnline = false; unsigned cTries = 5; do { PRTDIR pDirDevices = NULL; int rc = RTDirOpen(&pDirDevices, SYSFS_CPU_PATH); if (RT_SUCCESS(rc)) { RTDIRENTRY DirFolderContent; while (RT_SUCCESS(RTDirRead(pDirDevices, &DirFolderContent, NULL))) /* Assumption that szName has always enough space */ { /** @todo r-bird: This code is bringing all CPUs online; the idCpuCore and * idCpuPackage parameters are unused! * aeichner: These files are not available at this point unfortunately. (see comment above) * bird: Yes, but isn't that easily dealt with by doing: * if (matching_topology() || !have_topology_directory()) * bring_cpu_online() * That could save you the cpu0 and cpuidle checks to. */ /* * Check if this is a CPU object. * cpu0 is excluded because it is not possible to change the state * of the first CPU on Linux (it doesn't even have an online file) * and cpuidle is no CPU device. Prevents error messages later. */ if( !strncmp(DirFolderContent.szName, "cpu", 3) && strncmp(DirFolderContent.szName, "cpu0", 4) && strncmp(DirFolderContent.szName, "cpuidle", 7)) { /* Get the sysdev */ RTFILE hFileCpuOnline = NIL_RTFILE; rc = RTFileOpenF(&hFileCpuOnline, RTFILE_O_WRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE, "%s/%s/online", SYSFS_CPU_PATH, DirFolderContent.szName); if (RT_SUCCESS(rc)) { /* Write a 1 to online the CPU */ rc = RTFileWrite(hFileCpuOnline, "1", 1, NULL); RTFileClose(hFileCpuOnline); if (RT_SUCCESS(rc)) { VBoxServiceVerbose(1, "CpuHotPlug: CPU %u/%u was brought online\n", idCpuPackage, idCpuCore); fCpuOnline = true; break; } /* Error means CPU not present or online already */ } else VBoxServiceError("CpuHotPlug: Failed to open \"%s/%s/online\" rc=%Rrc\n", SYSFS_CPU_PATH, DirFolderContent.szName, rc); } } } else VBoxServiceError("CpuHotPlug: Failed to open path %s rc=%Rrc\n", SYSFS_CPU_PATH, rc); /* Sleep a bit */ if (!fCpuOnline) RTThreadSleep(10); } while ( !fCpuOnline && cTries-- > 0); #else # error "Port me" #endif }
/** * Open the object with a specific file type, and, depending on the type, specifying additional parameters. * * @return IPRT status code. * @param strPathAbs Absolute path of the object (file / directory / ...). * @param enmView View of the object. * @param fOpen Open mode to use; only valid for file objects. * @param fMode File mode to use; only valid for file objects. * @param fFlags Additional DnD URI object flags. */ int DnDURIObject::OpenEx(const RTCString &strPathAbs, View enmView, uint64_t fOpen /* = 0 */, RTFMODE fMode /* = 0 */, DNDURIOBJECTFLAGS fFlags /* = DNDURIOBJECT_FLAGS_NONE */) { AssertReturn(!(fFlags & ~DNDURIOBJECT_FLAGS_VALID_MASK), VERR_INVALID_FLAGS); RT_NOREF1(fFlags); int rc = VINF_SUCCESS; switch (enmView) { case View_Source: m_strSrcPathAbs = strPathAbs; break; case View_Target: m_strTgtPathAbs = strPathAbs; break; default: rc = VERR_NOT_IMPLEMENTED; break; } if ( RT_SUCCESS(rc) && fOpen) /* Opening mode specified? */ { LogFlowThisFunc(("strPath=%s, enmView=%RU32, fOpen=0x%x, fMode=0x%x, fFlags=0x%x\n", strPathAbs.c_str(), enmView, fOpen, fMode, fFlags)); switch (m_enmType) { case Type_File: { /* * Open files on the source with RTFILE_O_DENY_WRITE to prevent races * where the OS writes to the file while the destination side transfers * it over. */ LogFlowThisFunc(("Opening ...\n")); rc = RTFileOpen(&u.File.hFile, strPathAbs.c_str(), fOpen); if (RT_SUCCESS(rc)) { if ( (fOpen & RTFILE_O_WRITE) /* Only set the file mode on write. */ && fMode /* Some file mode to set specified? */) { rc = RTFileSetMode(u.File.hFile, fMode); } else if (fOpen & RTFILE_O_READ) { rc = queryInfoInternal(enmView); } } if (RT_SUCCESS(rc)) { LogFlowThisFunc(("File cbObject=%RU64, fMode=0x%x\n", u.File.objInfo.cbObject, u.File.objInfo.Attr.fMode)); u.File.cbToProcess = u.File.objInfo.cbObject; u.File.cbProcessed = 0; } break; } case Type_Directory: { rc = RTDirOpen(&u.Dir.hDir, strPathAbs.c_str()); if (RT_SUCCESS(rc)) rc = queryInfoInternal(enmView); break; } default: rc = VERR_NOT_IMPLEMENTED; break; } } if (RT_SUCCESS(rc)) { m_enmView = enmView; } LogFlowFuncLeaveRC(rc); return rc; }
int DnDURIList::appendPathRecursive(const char *pcszSrcPath, const char *pcszDstPath, const char *pcszDstBase, size_t cchDstBase, uint32_t fFlags) { AssertPtrReturn(pcszSrcPath, VERR_INVALID_POINTER); AssertPtrReturn(pcszDstBase, VERR_INVALID_POINTER); AssertPtrReturn(pcszDstPath, VERR_INVALID_POINTER); LogFlowFunc(("pcszSrcPath=%s, pcszDstPath=%s, pcszDstBase=%s, cchDstBase=%zu\n", pcszSrcPath, pcszDstPath, pcszDstBase, cchDstBase)); RTFSOBJINFO objInfo; int rc = RTPathQueryInfo(pcszSrcPath, &objInfo, RTFSOBJATTRADD_NOTHING); if (RT_SUCCESS(rc)) { if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode)) { rc = addEntry(pcszSrcPath, &pcszDstPath[cchDstBase], fFlags); if (RT_SUCCESS(rc)) { PRTDIR hDir; rc = RTDirOpen(&hDir, pcszSrcPath); if (RT_SUCCESS(rc)) { do { RTDIRENTRY DirEntry; rc = RTDirRead(hDir, &DirEntry, NULL); if (RT_FAILURE(rc)) { if (rc == VERR_NO_MORE_FILES) rc = VINF_SUCCESS; break; } switch (DirEntry.enmType) { case RTDIRENTRYTYPE_DIRECTORY: { /* Skip "." and ".." entries. */ if ( RTStrCmp(DirEntry.szName, ".") == 0 || RTStrCmp(DirEntry.szName, "..") == 0) break; char *pszSrc = RTPathJoinA(pcszSrcPath, DirEntry.szName); if (pszSrc) { char *pszDst = RTPathJoinA(pcszDstPath, DirEntry.szName); if (pszDst) { rc = appendPathRecursive(pszSrc, pszDst, pcszDstBase, cchDstBase, fFlags); RTStrFree(pszDst); } else rc = VERR_NO_MEMORY; RTStrFree(pszSrc); } else rc = VERR_NO_MEMORY; break; } case RTDIRENTRYTYPE_FILE: { char *pszSrc = RTPathJoinA(pcszSrcPath, DirEntry.szName); if (pszSrc) { char *pszDst = RTPathJoinA(pcszDstPath, DirEntry.szName); if (pszDst) { rc = addEntry(pszSrc, &pszDst[cchDstBase], fFlags); RTStrFree(pszDst); } else rc = VERR_NO_MEMORY; RTStrFree(pszSrc); } else rc = VERR_NO_MEMORY; break; } case RTDIRENTRYTYPE_SYMLINK: { if (fFlags & DNDURILIST_FLAGS_RESOLVE_SYMLINKS) { char *pszSrc = RTPathRealDup(pcszDstBase); if (pszSrc) { rc = RTPathQueryInfo(pszSrc, &objInfo, RTFSOBJATTRADD_NOTHING); if (RT_SUCCESS(rc)) { if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode)) { LogFlowFunc(("Directory entry is symlink to directory\n")); rc = appendPathRecursive(pszSrc, pcszDstPath, pcszDstBase, cchDstBase, fFlags); } else if (RTFS_IS_FILE(objInfo.Attr.fMode)) { LogFlowFunc(("Directory entry is symlink to file\n")); rc = addEntry(pszSrc, &pcszDstPath[cchDstBase], fFlags); } else rc = VERR_NOT_SUPPORTED; } RTStrFree(pszSrc); } else rc = VERR_NO_MEMORY; } break; } default: break; } } while (RT_SUCCESS(rc)); RTDirClose(hDir); } } } else if (RTFS_IS_FILE(objInfo.Attr.fMode)) { rc = addEntry(pcszSrcPath, &pcszDstPath[cchDstBase], fFlags); } else if (RTFS_IS_SYMLINK(objInfo.Attr.fMode)) { if (fFlags & DNDURILIST_FLAGS_RESOLVE_SYMLINKS) { char *pszSrc = RTPathRealDup(pcszSrcPath); if (pszSrc) { rc = RTPathQueryInfo(pszSrc, &objInfo, RTFSOBJATTRADD_NOTHING); if (RT_SUCCESS(rc)) { if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode)) { LogFlowFunc(("Symlink to directory\n")); rc = appendPathRecursive(pszSrc, pcszDstPath, pcszDstBase, cchDstBase, fFlags); } else if (RTFS_IS_FILE(objInfo.Attr.fMode)) { LogFlowFunc(("Symlink to file\n")); rc = addEntry(pszSrc, &pcszDstPath[cchDstBase], fFlags); } else rc = VERR_NOT_SUPPORTED; } RTStrFree(pszSrc); } else rc = VERR_NO_MEMORY; } } else rc = VERR_NOT_SUPPORTED; } LogFlowFuncLeaveRC(rc); return rc; }
int DnDURIList::appendPathRecursive(const char *pcszPath, size_t cbBaseLen, uint32_t fFlags) { AssertPtrReturn(pcszPath, VERR_INVALID_POINTER); RTFSOBJINFO objInfo; int rc = RTPathQueryInfo(pcszPath, &objInfo, RTFSOBJATTRADD_NOTHING); if (RT_FAILURE(rc)) return rc; /* * These are the types we currently support. Symlinks are not directly * supported. First the guest could be an OS which doesn't support it and * second the symlink could point to a file which is out of the base tree. * Both things are hard to support. For now we just copy the target file in * this case. */ if (!( RTFS_IS_DIRECTORY(objInfo.Attr.fMode) || RTFS_IS_FILE(objInfo.Attr.fMode) || RTFS_IS_SYMLINK(objInfo.Attr.fMode))) return VINF_SUCCESS; uint64_t cbSize = 0; rc = RTFileQuerySize(pcszPath, &cbSize); if (rc == VERR_IS_A_DIRECTORY) rc = VINF_SUCCESS; if (RT_FAILURE(rc)) return rc; m_lstTree.append(DnDURIObject( RTFS_IS_DIRECTORY(objInfo.Attr.fMode) ? DnDURIObject::Directory : DnDURIObject::File, pcszPath, &pcszPath[cbBaseLen], objInfo.Attr.fMode, cbSize)); m_cbTotal += cbSize; #ifdef DEBUG_andy LogFlowFunc(("strSrcPath=%s, strDstPath=%s, fMode=0x%x, cbSize=%RU64, cbTotal=%zu\n", pcszPath, &pcszPath[cbBaseLen], objInfo.Attr.fMode, cbSize, m_cbTotal)); #endif PRTDIR hDir; /* We have to try to open even symlinks, cause they could * be symlinks to directories. */ rc = RTDirOpen(&hDir, pcszPath); /* The following error happens when this was a symlink * to an file or a regular file. */ if ( rc == VERR_PATH_NOT_FOUND || rc == VERR_NOT_A_DIRECTORY) return VINF_SUCCESS; if (RT_FAILURE(rc)) return rc; while (RT_SUCCESS(rc)) { RTDIRENTRY DirEntry; rc = RTDirRead(hDir, &DirEntry, NULL); if (RT_FAILURE(rc)) { if (rc == VERR_NO_MORE_FILES) rc = VINF_SUCCESS; break; } switch (DirEntry.enmType) { case RTDIRENTRYTYPE_DIRECTORY: { /* Skip "." and ".." entries. */ if ( RTStrCmp(DirEntry.szName, ".") == 0 || RTStrCmp(DirEntry.szName, "..") == 0) break; char *pszRecDir = RTPathJoinA(pcszPath, DirEntry.szName); if (pszRecDir) { rc = appendPathRecursive(pszRecDir, cbBaseLen, fFlags); RTStrFree(pszRecDir); } else rc = VERR_NO_MEMORY; break; } case RTDIRENTRYTYPE_SYMLINK: case RTDIRENTRYTYPE_FILE: { char *pszNewFile = RTPathJoinA(pcszPath, DirEntry.szName); if (pszNewFile) { /* We need the size and the mode of the file. */ RTFSOBJINFO objInfo1; rc = RTPathQueryInfo(pszNewFile, &objInfo1, RTFSOBJATTRADD_NOTHING); if (RT_FAILURE(rc)) return rc; rc = RTFileQuerySize(pszNewFile, &cbSize); if (rc == VERR_IS_A_DIRECTORY) /* Happens for symlinks. */ rc = VINF_SUCCESS; if (RT_FAILURE(rc)) break; if (RTFS_IS_FILE(objInfo.Attr.fMode)) { m_lstTree.append(DnDURIObject(DnDURIObject::File, pszNewFile, &pszNewFile[cbBaseLen], objInfo1.Attr.fMode, cbSize)); m_cbTotal += cbSize; } else /* Handle symlink directories. */ rc = appendPathRecursive(pszNewFile, cbBaseLen, fFlags); #ifdef DEBUG_andy LogFlowFunc(("strSrcPath=%s, strDstPath=%s, fMode=0x%x, cbSize=%RU64, cbTotal=%zu\n", pszNewFile, &pszNewFile[cbBaseLen], objInfo1.Attr.fMode, cbSize, m_cbTotal)); #endif RTStrFree(pszNewFile); } else rc = VERR_NO_MEMORY; break; } default: break; } } RTDirClose(hDir); return rc; }
/** * Recursion worker for RTDirRemoveRecursive. * * @returns IPRT status code. * @param pszBuf The path buffer. Contains the abs path to the * directory to recurse into. Trailing slash. * @param cchDir The length of the directory we're cursing into, * including the trailing slash. * @param pDirEntry The dir entry buffer. (Shared to save stack.) * @param pObjInfo The object info buffer. (ditto) */ static int rtDirRemoveRecursiveSub(char *pszBuf, size_t cchDir, PRTDIRENTRY pDirEntry, PRTFSOBJINFO pObjInfo) { AssertReturn(RTPATH_IS_SLASH(pszBuf[cchDir - 1]), VERR_INTERNAL_ERROR_4); /* * Enumerate the directory content and dispose of it. */ PRTDIR pDir; int rc = RTDirOpen(&pDir, pszBuf); if (RT_FAILURE(rc)) return rc; while (RT_SUCCESS(rc = RTDirRead(pDir, pDirEntry, NULL))) { if ( pDirEntry->szName[0] != '.' || pDirEntry->cbName > 2 || ( pDirEntry->cbName == 2 && pDirEntry->szName[1] != '.') ) { /* Construct the full name of the entry. */ if (cchDir + pDirEntry->cbName + 1 /* dir slash */ >= RTPATH_MAX) { rc = VERR_FILENAME_TOO_LONG; break; } memcpy(&pszBuf[cchDir], pDirEntry->szName, pDirEntry->cbName + 1); /* Deal with the unknown type. */ if (pDirEntry->enmType == RTDIRENTRYTYPE_UNKNOWN) { rc = RTPathQueryInfoEx(pszBuf, pObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK); if (RT_SUCCESS(rc) && RTFS_IS_DIRECTORY(pObjInfo->Attr.fMode)) pDirEntry->enmType = RTDIRENTRYTYPE_DIRECTORY; else if (RT_SUCCESS(rc) && RTFS_IS_FILE(pObjInfo->Attr.fMode)) pDirEntry->enmType = RTDIRENTRYTYPE_FILE; else if (RT_SUCCESS(rc) && RTFS_IS_SYMLINK(pObjInfo->Attr.fMode)) pDirEntry->enmType = RTDIRENTRYTYPE_SYMLINK; } /* Try the delete the fs object. */ switch (pDirEntry->enmType) { case RTDIRENTRYTYPE_FILE: rc = RTFileDelete(pszBuf); break; case RTDIRENTRYTYPE_DIRECTORY: { size_t cchSubDir = cchDir + pDirEntry->cbName; pszBuf[cchSubDir++] = '/'; pszBuf[cchSubDir] = '\0'; rc = rtDirRemoveRecursiveSub(pszBuf, cchSubDir, pDirEntry, pObjInfo); if (RT_SUCCESS(rc)) { pszBuf[cchSubDir] = '\0'; rc = RTDirRemove(pszBuf); } break; } //case RTDIRENTRYTYPE_SYMLINK: // rc = RTSymlinkDelete(pszBuf, 0); // break; default: /** @todo not implemented yet. */ rc = VINF_SUCCESS; break; } if (RT_FAILURE(rc)) break; } } if (rc == VERR_NO_MORE_FILES) rc = VINF_SUCCESS; RTDirClose(pDir); return rc; }
int DnDHGSendDataMessage::buildFileTree(const char *pcszPath, size_t cbBaseLen) { RTFSOBJINFO objInfo; int rc = RTPathQueryInfo(pcszPath, &objInfo, RTFSOBJATTRADD_NOTHING); if (RT_FAILURE(rc)) return rc; /* These are the types we currently support. Symlinks are not directly * supported. First the guest could be an OS which doesn't support it and * second the symlink could point to a file which is out of the base tree. * Both things are hard to support. For now we just copy the target file in * this case. */ if (!( RTFS_IS_DIRECTORY(objInfo.Attr.fMode) || RTFS_IS_FILE(objInfo.Attr.fMode) || RTFS_IS_SYMLINK(objInfo.Attr.fMode))) return VINF_SUCCESS; uint64_t cbSize = 0; rc = RTFileQuerySize(pcszPath, &cbSize); if (rc == VERR_IS_A_DIRECTORY) rc = VINF_SUCCESS; if (RT_FAILURE(rc)) return rc; m_uriList.append(PathEntry(pcszPath, &pcszPath[cbBaseLen], objInfo.Attr.fMode, cbSize)); m_cbAll += cbSize; DO(("cbFile: %u\n", cbSize)); PRTDIR hDir; /* We have to try to open even symlinks, cause they could be symlinks * to directories. */ rc = RTDirOpen(&hDir, pcszPath); /* The following error happens when this was a symlink to an file or a * regular file. */ if (rc == VERR_PATH_NOT_FOUND) return VINF_SUCCESS; if (RT_FAILURE(rc)) return rc; while (RT_SUCCESS(rc)) { RTDIRENTRY DirEntry; rc = RTDirRead(hDir, &DirEntry, NULL); if (RT_FAILURE(rc)) { if (rc == VERR_NO_MORE_FILES) rc = VINF_SUCCESS; break; } switch (DirEntry.enmType) { case RTDIRENTRYTYPE_DIRECTORY: { /* Skip "." and ".." entries. */ if ( RTStrCmp(DirEntry.szName, ".") == 0 || RTStrCmp(DirEntry.szName, "..") == 0) break; if (char *pszRecDir = RTStrAPrintf2("%s%c%s", pcszPath, RTPATH_DELIMITER, DirEntry.szName)) { rc = buildFileTree(pszRecDir, cbBaseLen); RTStrFree(pszRecDir); } else rc = VERR_NO_MEMORY; break; } case RTDIRENTRYTYPE_SYMLINK: case RTDIRENTRYTYPE_FILE: { if (char *pszNewFile = RTStrAPrintf2("%s%c%s", pcszPath, RTPATH_DELIMITER, DirEntry.szName)) { /* We need the size and the mode of the file. */ RTFSOBJINFO objInfo1; rc = RTPathQueryInfo(pszNewFile, &objInfo1, RTFSOBJATTRADD_NOTHING); if (RT_FAILURE(rc)) return rc; rc = RTFileQuerySize(pszNewFile, &cbSize); if (RT_FAILURE(rc)) break; m_uriList.append(PathEntry(pszNewFile, &pszNewFile[cbBaseLen], objInfo1.Attr.fMode, cbSize)); m_cbAll += cbSize; RTStrFree(pszNewFile); } else rc = VERR_NO_MEMORY; break; } default: break; } } RTDirClose(hDir); return rc; }
HRESULT VFSExplorer::i_updateFS(TaskVFSExplorer *aTask) { LogFlowFuncEnter(); AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS); HRESULT rc = S_OK; std::list<VFSExplorer::Data::DirEntry> fileList; char *pszPath = NULL; PRTDIR pDir = NULL; try { int vrc = RTDirOpen(&pDir, m->strPath.c_str()); if (RT_FAILURE(vrc)) throw setError(VBOX_E_FILE_ERROR, tr ("Can't open directory '%s' (%Rrc)"), pszPath, vrc); if (aTask->progress) aTask->progress->SetCurrentOperationProgress(33); RTDIRENTRYEX entry; while (RT_SUCCESS(vrc)) { vrc = RTDirReadEx(pDir, &entry, NULL, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK); if (RT_SUCCESS(vrc)) { Utf8Str name(entry.szName); if ( name != "." && name != "..") fileList.push_back(VFSExplorer::Data::DirEntry(name, i_RTToVFSFileType(entry.Info.Attr.fMode), entry.Info.cbObject, entry.Info.Attr.fMode & (RTFS_UNIX_IRWXU | RTFS_UNIX_IRWXG | RTFS_UNIX_IRWXO))); } } if (aTask->progress) aTask->progress->SetCurrentOperationProgress(66); } catch(HRESULT aRC) { rc = aRC; } /* Clean up */ if (pszPath) RTStrFree(pszPath); if (pDir) RTDirClose(pDir); if (aTask->progress) aTask->progress->SetCurrentOperationProgress(99); /* Assign the result on success (this clears the old list) */ if (rc == S_OK) m->entryList.assign(fileList.begin(), fileList.end()); aTask->rc = rc; if (!aTask->progress.isNull()) aTask->progress->i_notifyComplete(rc); LogFlowFunc(("rc=%Rhrc\n", rc)); LogFlowFuncLeave(); return VINF_SUCCESS; }
/** * Recursively delete a directory. * * @returns IPRT status code, errors go via rtPathRmError. * @param pOpts The RM options. * @param pszPath Pointer to a writable buffer holding the path to * the directory. * @param cchPath The length of the path (avoid strlen). * @param pDirEntry Pointer to a directory entry buffer that is * RTPATHRM_DIR_MAX_ENTRY_SIZE bytes big. */ static int rtPathRmRecursive(PRTPATHRMCMDOPTS pOpts, char *pszPath, size_t cchPath, PRTDIRENTRYEX pDirEntry) { /* * Make sure the path ends with a slash. */ if (!cchPath || !RTPATH_IS_SLASH(pszPath[cchPath - 1])) { if (cchPath + 1 >= RTPATH_MAX) return rtPathRmError(pOpts, pszPath, VERR_BUFFER_OVERFLOW, "Buffer overflow fixing up '%s'.\n", pszPath); pszPath[cchPath++] = RTPATH_SLASH; pszPath[cchPath] = '\0'; } /* * Traverse the directory. */ PRTDIR hDir; int rc = RTDirOpen(&hDir, pszPath); if (RT_FAILURE(rc)) return rtPathRmError(pOpts, pszPath, rc, "Error opening directory '%s': %Rrc", pszPath, rc); int rcRet = VINF_SUCCESS; for (;;) { /* * Read the next entry, constructing an full path for it. */ size_t cbEntry = RTPATHRM_DIR_MAX_ENTRY_SIZE; rc = RTDirReadEx(hDir, pDirEntry, &cbEntry, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK); if (rc == VERR_NO_MORE_FILES) { /* * Reached the end of the directory. */ pszPath[cchPath] = '\0'; rc = RTDirClose(hDir); if (RT_FAILURE(rc)) return rtPathRmError(pOpts, pszPath, rc, "Error closing directory '%s': %Rrc", pszPath, rc); /* Delete the directory. */ int rc2 = rtPathRmOneDir(pOpts, pszPath); if (RT_FAILURE(rc2) && RT_SUCCESS(rcRet)) return rc2; return rcRet; } if (RT_FAILURE(rc)) { rc = rtPathRmError(pOpts, pszPath, rc, "Error reading directory '%s': %Rrc", pszPath, rc); break; } /* Skip '.' and '..'. */ if ( pDirEntry->szName[0] == '.' && ( pDirEntry->cbName == 1 || ( pDirEntry->cbName == 2 && pDirEntry->szName[1] == '.'))) continue; /* Construct full path. */ if (cchPath + pDirEntry->cbName >= RTPATH_MAX) { pszPath[cchPath] = '\0'; rc = rtPathRmError(pOpts, pszPath, VERR_BUFFER_OVERFLOW, "Path buffer overflow in directory '%s'.", pszPath); break; } memcpy(pszPath + cchPath, pDirEntry->szName, pDirEntry->cbName + 1); /* * Take action according to the type. */ switch (pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK) { case RTFS_TYPE_FILE: rc = rtPathRmOneFile(pOpts, pszPath, &pDirEntry->Info); break; case RTFS_TYPE_DIRECTORY: rc = rtPathRmRecursive(pOpts, pszPath, cchPath + pDirEntry->cbName, pDirEntry); break; case RTFS_TYPE_SYMLINK: rc = rtPathRmOneSymlink(pOpts, pszPath); break; case RTFS_TYPE_FIFO: case RTFS_TYPE_DEV_CHAR: case RTFS_TYPE_DEV_BLOCK: case RTFS_TYPE_SOCKET: rc = rtPathRmOneFile(pOpts, pszPath, &pDirEntry->Info); break; case RTFS_TYPE_WHITEOUT: default: rc = rtPathRmError(pOpts, pszPath, VERR_UNEXPECTED_FS_OBJ_TYPE, "Object '%s' has an unknown file type: %o\n", pszPath, pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK); break; } if (RT_FAILURE(rc) && RT_SUCCESS(rcRet)) rcRet = rc; } /* * Some error occured, close and return. */ RTDirClose(hDir); return rc; }
static ssize_t rtLinuxFindDevicePathRecursive(dev_t DevNum, RTFMODE fMode, const char *pszBasePath, char *pszBuf, size_t cchBuf) { /* * Check assumptions made by the code below. */ size_t const cchBasePath = strlen(pszBasePath); AssertReturnStmt(cchBasePath < RTPATH_MAX - 10U, errno = ENAMETOOLONG, -1); ssize_t rcRet; PRTDIR pDir; int rc = RTDirOpen(&pDir, pszBasePath); if (RT_SUCCESS(rc)) { char szPath[RTPATH_MAX]; /** @todo 4K per recursion - can easily be optimized away by passing it along pszBasePath and only remember the length. */ memcpy(szPath, pszBasePath, cchBasePath + 1); for (;;) { RTDIRENTRYEX Entry; rc = RTDirReadEx(pDir, &Entry, NULL, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK); if (RT_FAILURE(rc)) { errno = rc == VERR_NO_MORE_FILES ? ENOENT : rc == VERR_BUFFER_OVERFLOW ? EOVERFLOW : EIO; rcRet = -1; break; } if (RTFS_IS_SYMLINK(Entry.Info.Attr.fMode)) continue; /* Do the matching. */ if ( Entry.Info.Attr.u.Unix.Device == DevNum && (Entry.Info.Attr.fMode & RTFS_TYPE_MASK) == fMode) { rcRet = rtLinuxConstructPath(pszBuf, cchBuf, pszBasePath, "%s", Entry.szName); break; } /* Recurse into subdirectories. */ if (!RTFS_IS_DIRECTORY(Entry.Info.Attr.fMode)) continue; if (Entry.szName[0] == '.') continue; szPath[cchBasePath] = '\0'; rc = RTPathAppend(szPath, sizeof(szPath) - 1, Entry.szName); /* -1: for slash */ if (RT_FAILURE(rc)) { errno = ENAMETOOLONG; rcRet = -1; break; } strcat(&szPath[cchBasePath], "/"); rcRet = rtLinuxFindDevicePathRecursive(DevNum, fMode, szPath, pszBuf, cchBuf); if (rcRet >= 0 || errno != ENOENT) break; } RTDirClose(pDir); } else { rcRet = -1; errno = RTErrConvertToErrno(rc); } return rcRet; }