int DnDHGSendDataMessage::currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) { if (!m_pNextPathMsg) return VERR_NO_DATA; /* Fill the data out of our current queued message. */ int rc = m_pNextPathMsg->currentMessage(uMsg, cParms, paParms); /* Has this message more data to deliver? */ if (!m_pNextPathMsg->isMessageWaiting()) { delete m_pNextPathMsg; m_pNextPathMsg = NULL; } /* File/directory data to send? */ if (!m_pNextPathMsg) { if (m_lstURI.IsEmpty()) return rc; /* Create new messages based on our internal path list. Currently * this could be directories or regular files. */ const DnDURIObject &nextObj = m_lstURI.First(); try { uint32_t fMode = nextObj.GetMode(); LogFlowFunc(("Processing srcPath=%s, dstPath=%s, fMode=0x%x, cbSize=%RU32, fIsDir=%RTbool, fIsFile=%RTbool\n", nextObj.GetSourcePath().c_str(), nextObj.GetDestPath().c_str(), fMode, nextObj.GetSize(), RTFS_IS_DIRECTORY(fMode), RTFS_IS_FILE(fMode))); if (RTFS_IS_DIRECTORY(fMode)) m_pNextPathMsg = new DnDHGSendDirPrivate(nextObj, &DnDHGSendDataMessage::progressCallback /* pfnProgressCallback */, this /* pvProgressUser */); else if (RTFS_IS_FILE(fMode)) m_pNextPathMsg = new DnDHGSendFilePrivate(nextObj, &DnDHGSendDataMessage::progressCallback /* pfnProgressCallback */, this /* pvProgressUser */); else AssertMsgFailedReturn(("fMode=0x%x is not supported for srcPath=%s, dstPath=%s\n", fMode, nextObj.GetSourcePath().c_str(), nextObj.GetDestPath().c_str()), VERR_NO_DATA); m_lstURI.RemoveFirst(); } catch(std::bad_alloc &) { rc = VERR_NO_MEMORY; } } return rc; }
RTDECL(int) RTDirQueryUnknownTypeEx(const char *pszComposedName, bool fFollowSymlinks, RTDIRENTRYTYPE *penmType, PRTFSOBJINFO pObjInfo) { int rc = RTPathQueryInfoEx(pszComposedName, pObjInfo, RTFSOBJATTRADD_NOTHING, fFollowSymlinks ? RTPATH_F_FOLLOW_LINK : RTPATH_F_ON_LINK); if (RT_FAILURE(rc)) return rc; if (RTFS_IS_DIRECTORY(pObjInfo->Attr.fMode)) *penmType = RTDIRENTRYTYPE_DIRECTORY; else if (RTFS_IS_FILE(pObjInfo->Attr.fMode)) *penmType = RTDIRENTRYTYPE_FILE; else if (RTFS_IS_SYMLINK(pObjInfo->Attr.fMode)) *penmType = RTDIRENTRYTYPE_SYMLINK; else if (RTFS_IS_FIFO(pObjInfo->Attr.fMode)) *penmType = RTDIRENTRYTYPE_FIFO; else if (RTFS_IS_DEV_CHAR(pObjInfo->Attr.fMode)) *penmType = RTDIRENTRYTYPE_DEV_CHAR; else if (RTFS_IS_DEV_BLOCK(pObjInfo->Attr.fMode)) *penmType = RTDIRENTRYTYPE_DEV_BLOCK; else if (RTFS_IS_SOCKET(pObjInfo->Attr.fMode)) *penmType = RTDIRENTRYTYPE_SOCKET; else if (RTFS_IS_WHITEOUT(pObjInfo->Attr.fMode)) *penmType = RTDIRENTRYTYPE_WHITEOUT; else *penmType = RTDIRENTRYTYPE_UNKNOWN; return VINF_SUCCESS; }
/** * Convert host VFS object mode flags into guest ones. * * @param fHostMode Host flags * * @return Guest flags */ mode_t vboxvfs_h2g_mode_inernal(RTFMODE fHostMode) { mode_t fGuestMode = 0; fGuestMode = /* Owner */ ((fHostMode & RTFS_UNIX_IRUSR) ? S_IRUSR : 0 ) | ((fHostMode & RTFS_UNIX_IWUSR) ? S_IWUSR : 0 ) | ((fHostMode & RTFS_UNIX_IXUSR) ? S_IXUSR : 0 ) | /* Group */ ((fHostMode & RTFS_UNIX_IRGRP) ? S_IRGRP : 0 ) | ((fHostMode & RTFS_UNIX_IWGRP) ? S_IWGRP : 0 ) | ((fHostMode & RTFS_UNIX_IXGRP) ? S_IXGRP : 0 ) | /* Other */ ((fHostMode & RTFS_UNIX_IROTH) ? S_IROTH : 0 ) | ((fHostMode & RTFS_UNIX_IWOTH) ? S_IWOTH : 0 ) | ((fHostMode & RTFS_UNIX_IXOTH) ? S_IXOTH : 0 ) | /* SUID, SGID, SVTXT */ ((fHostMode & RTFS_UNIX_ISUID) ? S_ISUID : 0 ) | ((fHostMode & RTFS_UNIX_ISGID) ? S_ISGID : 0 ) | ((fHostMode & RTFS_UNIX_ISTXT) ? S_ISVTX : 0 ) | /* VFS object types */ ((RTFS_IS_FIFO(fHostMode)) ? S_IFIFO : 0 ) | ((RTFS_IS_DEV_CHAR(fHostMode)) ? S_IFCHR : 0 ) | ((RTFS_IS_DIRECTORY(fHostMode)) ? S_IFDIR : 0 ) | ((RTFS_IS_DEV_BLOCK(fHostMode)) ? S_IFBLK : 0 ) | ((RTFS_IS_FILE(fHostMode)) ? S_IFREG : 0 ) | ((RTFS_IS_SYMLINK(fHostMode)) ? S_IFLNK : 0 ) | ((RTFS_IS_SOCKET(fHostMode)) ? S_IFSOCK : 0 ); return fGuestMode; }
int DnDHGSendDataMessage::currentMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) { if (!m_pNextPathMsg) return VERR_NO_DATA; /* Fill the data out of our current queued message. */ int rc = m_pNextPathMsg->currentMessage(uMsg, cParms, paParms); /* Has this message more data to deliver? */ if (!m_pNextPathMsg->isMessageWaiting()) { delete m_pNextPathMsg; m_pNextPathMsg = NULL; } /* File data to send? */ if (!m_pNextPathMsg) { if (m_uriList.isEmpty()) return rc; /* Create new messages based on our internal path list. Currently * this could be directories or regular files. */ PathEntry nextPath = m_uriList.first(); if (RTFS_IS_DIRECTORY(nextPath.m_fMode)) m_pNextPathMsg = new DnDHGSendDirPrivate(nextPath.m_strGuestPath, nextPath.m_fMode, nextPath.m_cbSize, &DnDHGSendDataMessage::progressCallback, this); else if (RTFS_IS_FILE(nextPath.m_fMode)) m_pNextPathMsg = new DnDHGSendFilePrivate(nextPath.m_strHostPath, nextPath.m_strGuestPath, nextPath.m_fMode, nextPath.m_cbSize, &DnDHGSendDataMessage::progressCallback, this); else AssertMsgFailedReturn(("type '%d' is not supported for path '%s'", nextPath.m_fMode, nextPath.m_strHostPath.c_str()), VERR_NO_DATA); m_uriList.removeFirst(); } return rc; }
RTDECL(bool) RTFileExists(const char *pszPath) { RTFSOBJINFO ObjInfo; int rc = RTPathQueryInfoEx(pszPath, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_FOLLOW_LINK); bool fRc = RT_SUCCESS(rc) && RTFS_IS_FILE(ObjInfo.Attr.fMode) && !(ObjInfo.Attr.fMode & (RTFS_DOS_NT_DEVICE | RTFS_DOS_NT_REPARSE_POINT)); /* paranoia */ LogFlow(("RTFileExists(%p:{%s}): returns %RTbool (%Rrc)\n", pszPath, pszPath, fRc, rc)); return fRc; }
/** * Reads the extension pack descriptor. * * @returns NULL on success, pointer to an error message on failure (caller * deletes it). * @param a_pszDir The directory containing the description file. * @param a_pExtPackDesc Where to store the extension pack descriptor. * @param a_pObjInfo Where to store the object info for the file (unix * attribs). Optional. */ RTCString *VBoxExtPackLoadDesc(const char *a_pszDir, PVBOXEXTPACKDESC a_pExtPackDesc, PRTFSOBJINFO a_pObjInfo) { vboxExtPackClearDesc(a_pExtPackDesc); /* * Validate, open and parse the XML file. */ char szFilePath[RTPATH_MAX]; int vrc = RTPathJoin(szFilePath, sizeof(szFilePath), a_pszDir, VBOX_EXTPACK_DESCRIPTION_NAME); if (RT_FAILURE(vrc)) return new RTCString("RTPathJoin failed with %Rrc", vrc); RTFSOBJINFO ObjInfo; vrc = RTPathQueryInfoEx(szFilePath, &ObjInfo, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK); if (RT_FAILURE(vrc)) return &(new RTCString())->printf("RTPathQueryInfoEx failed with %Rrc", vrc); if (a_pObjInfo) *a_pObjInfo = ObjInfo; if (!RTFS_IS_FILE(ObjInfo.Attr.fMode)) { if (RTFS_IS_SYMLINK(ObjInfo.Attr.fMode)) return new RTCString("The XML file is symlinked, that is not allowed"); return &(new RTCString)->printf("The XML file is not a file (fMode=%#x)", ObjInfo.Attr.fMode); } xml::Document Doc; { xml::XmlFileParser Parser; try { Parser.read(szFilePath, Doc); } catch (xml::XmlError Err) { return new RTCString(Err.what()); } } /* * Hand the xml doc over to the common code. */ return vboxExtPackLoadDescFromDoc(&Doc, a_pExtPackDesc); }
RTDECL(int) RTFileQuerySize(const char *pszPath, uint64_t *pcbFile) { RTFSOBJINFO ObjInfo; int rc = RTPathQueryInfoEx(pszPath, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_FOLLOW_LINK); if (RT_SUCCESS(rc)) { if (RTFS_IS_FILE(ObjInfo.Attr.fMode)) { *pcbFile = ObjInfo.cbObject; LogFlow(("RTFileQuerySize(%p:{%s}): returns %Rrc (%#RX64)\n", pszPath, pszPath, rc, *pcbFile)); return rc; } if (RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode)) rc = VERR_IS_A_DIRECTORY; else rc = VERR_FILE_NOT_FOUND; /** @todo VERR_NOT_A_FILE... */ } LogFlow(("RTFileQuerySize(%p:{%s}): returns %Rrc\n", pszPath, pszPath, rc)); return rc; }
/** * Convert SHFLDIRINFO to struct dirent and copy it back to user. */ static int vboxvfs_vnode_readdir_copy_data(ino_t index, SHFLDIRINFO *Info, struct uio *uio, int *numdirent) { struct dirent entry; int rc; entry.d_ino = index; entry.d_reclen = (__uint16_t)sizeof(entry); /* Detect dir entry type */ if (RTFS_IS_DIRECTORY(Info->Info.Attr.fMode)) entry.d_type = DT_DIR; else if (RTFS_IS_FILE(Info->Info.Attr.fMode)) entry.d_type = DT_REG; else { PDEBUG("Unknown type of host file: mode 0x%X", (int)Info->Info.Attr.fMode); return ENOTSUP; } entry.d_namlen = (__uint8_t)min(sizeof(entry.d_name), Info->name.u16Size); memcpy(entry.d_name, Info->name.String.utf8, entry.d_namlen); rc = uiomove((char *)&entry, sizeof(entry), uio); if (rc == 0) { uio_setoffset(uio, index * sizeof(struct dirent)); *numdirent = (int)index; PDEBUG("discovered entry: '%s' (%d bytes), item #%d", entry.d_name, (int)entry.d_namlen, (int)index); } else { PDEBUG("Failed to return dirent data item #%d (%d)", (int)index, rc); } return rc; }
/** * Validates a file in an extension pack. * * @returns VBox status code, failures with message. * @param pszName The name of the file. * @param hVfsObj The VFS object. * @param pszError Where to store an error message on failure. * @param cbError The size of the buffer @a pszError points to. */ static int vboxExtPackValidateMemberFile(const char *pszName, RTVFSOBJ hVfsObj, char *pszError, size_t cbError) { int rc = vboxExtPackValidateMemberName(pszName, pszError, cbError); if (RT_SUCCESS(rc)) { RTFSOBJINFO ObjInfo; rc = RTVfsObjQueryInfo(hVfsObj, &ObjInfo, RTFSOBJATTRADD_NOTHING); if (RT_SUCCESS(rc)) { if (ObjInfo.cbObject >= 9*_1G64) rc = vboxExtPackReturnError(VERR_OUT_OF_RANGE, pszError, cbError, "'%s': too large (%'RU64 bytes)", pszName, (uint64_t)ObjInfo.cbObject); if (!RTFS_IS_FILE(ObjInfo.Attr.fMode)) rc = vboxExtPackReturnError(VERR_NOT_A_FILE, pszError, cbError, "The alleged file '%s' has a mode mask stating otherwise (%RTfmode)", pszName, ObjInfo.Attr.fMode); } else vboxExtPackSetError(pszError, cbError, "RTVfsObjQueryInfo failed on '%s': %Rrc", pszName, rc); } return rc; }
static void test1Worker(RTTEST hTest, const char *pszBaseDir, const char *pszTarget, RTSYMLINKTYPE enmType, bool fDangling) { char szPath1[RTPATH_MAX]; char szPath2[RTPATH_MAX]; size_t cchTarget = strlen(pszTarget); char szPath3[RTPATH_MAX]; RTStrCopy(szPath3, sizeof(szPath3), pszTarget); #ifdef RT_OS_WINDOWS /* see RTSymlinkCreate in symlink-win.cpp */ char c; char *psz = szPath3; while ((c = *psz) != '\0') { if (c == '/') *psz = '\\'; psz++; } #endif /* Create it.*/ RTTESTI_CHECK_RC_OK_RETV(RTPathJoin(szPath1, sizeof(szPath1), pszBaseDir, "tstRTSymlink-link-1")); RTSymlinkDelete(szPath1, 0); /* clean up previous run */ RTTESTI_CHECK_RC_RETV(RTSymlinkCreate(szPath1, pszTarget, RTSYMLINKTYPE_FILE, 0), VINF_SUCCESS); /* Check the predicate functions. */ RTTESTI_CHECK(RTSymlinkExists(szPath1)); RTTESTI_CHECK(RTSymlinkIsDangling(szPath1) == fDangling); /* Read it. */ memset(szPath2, 0xff, sizeof(szPath2)); szPath2[sizeof(szPath2) - 1] = '\0'; RTTESTI_CHECK_RC(RTSymlinkRead(szPath1, szPath2, sizeof(szPath2), 0), VINF_SUCCESS); RTTESTI_CHECK_MSG(strcmp(szPath2, szPath3) == 0, ("got=\"%s\" expected=\"%s\"", szPath2, szPath3)); memset(szPath2, 0xff, sizeof(szPath2)); szPath2[sizeof(szPath2) - 1] = '\0'; RTTESTI_CHECK_RC(RTSymlinkRead(szPath1, szPath2, cchTarget + 1, 0), VINF_SUCCESS); RTTESTI_CHECK_MSG(strcmp(szPath2, szPath3) == 0, ("got=\"%s\" expected=\"%s\"", szPath2, szPath3)); memset(szPath2, 0xff, sizeof(szPath2)); szPath2[sizeof(szPath2) - 1] = '\0'; RTTESTI_CHECK_RC(RTSymlinkRead(szPath1, szPath2, cchTarget, 0), VERR_BUFFER_OVERFLOW); RTTESTI_CHECK_MSG( strncmp(szPath2, szPath3, cchTarget - 1) == 0 && szPath2[cchTarget - 1] == '\0', ("got=\"%s\" expected=\"%.*s\"", szPath2, cchTarget - 1, szPath3)); /* Other APIs that have to handle symlinks carefully. */ int rc; RTFSOBJINFO ObjInfo; RTTESTI_CHECK_RC(rc = RTPathQueryInfo(szPath1, &ObjInfo, RTFSOBJATTRADD_NOTHING), VINF_SUCCESS); if (RT_SUCCESS(rc)) RTTESTI_CHECK(RTFS_IS_SYMLINK(ObjInfo.Attr.fMode)); RTTESTI_CHECK_RC(rc = RTPathQueryInfoEx(szPath1, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK), VINF_SUCCESS); if (RT_SUCCESS(rc)) RTTESTI_CHECK(RTFS_IS_SYMLINK(ObjInfo.Attr.fMode)); if (!fDangling) { RTTESTI_CHECK_RC(rc = RTPathQueryInfoEx(szPath1, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_FOLLOW_LINK), VINF_SUCCESS); if (RT_SUCCESS(rc)) RTTESTI_CHECK(!RTFS_IS_SYMLINK(ObjInfo.Attr.fMode)); else RT_ZERO(ObjInfo); if (enmType == RTSYMLINKTYPE_DIR) { RTTESTI_CHECK(RTDirExists(szPath1)); RTTESTI_CHECK(RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode)); } else if (enmType == RTSYMLINKTYPE_FILE) { RTTESTI_CHECK(RTFileExists(szPath1)); RTTESTI_CHECK(RTFS_IS_FILE(ObjInfo.Attr.fMode)); } /** @todo Check more APIs */ } /* Finally, the removal of the symlink. */ RTTESTI_CHECK_RC(RTSymlinkDelete(szPath1, 0), VINF_SUCCESS); RTTESTI_CHECK_RC(RTSymlinkDelete(szPath1, 0), VERR_FILE_NOT_FOUND); }
/** * Helper function for vboxvfs_vnode_lookup(): create new vnode. */ static int vboxvfs_vnode_lookup_instantinate_vnode(vnode_t parent_vnode, char *entry_name, vnode_t *result_vnode) { /* We need to construct full path to vnode in order to get * vboxvfs_get_info_internal() to understand us! */ char *pszCurDirPath; int cbCurDirPath = MAXPATHLEN; mount_t mp = vnode_mount(parent_vnode); AssertReturn(mp, EINVAL); vnode_t vnode; int rc; pszCurDirPath = (char *)RTMemAllocZ(cbCurDirPath); if (pszCurDirPath) { rc = vn_getpath(parent_vnode, pszCurDirPath, &cbCurDirPath); if (rc == 0 && cbCurDirPath < MAXPATHLEN) { SHFLFSOBJINFO Info; PSHFLSTRING pSHFLPath; /* Add '/' between path parts and truncate name if it is too long */ strncat(pszCurDirPath, "/", 1); strncat(pszCurDirPath, entry_name, MAXPATHLEN - cbCurDirPath - 1); rc = vboxvfs_guest_path_to_shflstring_path_internal(mp, pszCurDirPath, strlen(pszCurDirPath) + 1, &pSHFLPath); if (rc == 0) { rc = vboxvfs_get_info_internal(mp, pSHFLPath, (PSHFLFSOBJINFO)&Info); if (rc == 0) { enum vtype type; if (RTFS_IS_DIRECTORY(Info.Attr.fMode)) type = VDIR; else if (RTFS_IS_FILE (Info.Attr.fMode)) type = VREG; else { PDEBUG("Not supported VFS object (%s) type: mode 0x%X", entry_name, Info.Attr.fMode); RTMemFree(pszCurDirPath); vboxvfs_put_path_internal((void **)&pSHFLPath); return ENOENT; } /* Create new vnode */ rc = vboxvfs_create_vnode_internal(mp, type, parent_vnode, FALSE, pSHFLPath, &vnode); if (rc == 0) { PDEBUG("new vnode object '%s' has been created", entry_name); *result_vnode = vnode; RTMemFree(pszCurDirPath); return 0; } else PDEBUG("Unable to create vnode: %d", rc); } else PDEBUG("Unable to get host object info: %d", rc); vboxvfs_put_path_internal((void **)&pSHFLPath); } else PDEBUG("Unable to convert guest<->host path"); } else PDEBUG("Unable to construct vnode path: %d", rc); RTMemFree(pszCurDirPath); } else { PDEBUG("Unable to allocate memory for path buffer"); rc = ENOMEM; } return rc; }
/** * Validates a standard file. * * Generally all files are * * @returns VBox status code, failure message in @a pszError. * @param pszAdjName The adjusted member name. * @param enmType The VFS object type. * @param phVfsObj The pointer to the VFS object handle variable. * This is both input and output. * @param phVfsFile Where to store the handle to the memorized * file. This is NULL for license files. * @param pszError Where to write an error message on failure. * @param cbError The size of the @a pszError buffer. */ static int VBoxExtPackValidateStandardFile(const char *pszAdjName, RTVFSOBJTYPE enmType, PRTVFSOBJ phVfsObj, PRTVFSFILE phVfsFile, char *pszError, size_t cbError) { int rc; /* * Make sure it's a file and that it isn't too large. */ if (phVfsFile && *phVfsFile != NIL_RTVFSFILE) rc = vboxExtPackReturnError(VERR_DUPLICATE, pszError, cbError, "There can only be one '%s'", pszAdjName); else if (enmType != RTVFSOBJTYPE_IO_STREAM && enmType != RTVFSOBJTYPE_FILE) rc = vboxExtPackReturnError(VERR_NOT_A_FILE, pszError, cbError, "Standard member '%s' is not a file", pszAdjName); else { RTFSOBJINFO ObjInfo; rc = RTVfsObjQueryInfo(*phVfsObj, &ObjInfo, RTFSOBJATTRADD_NOTHING); if (RT_SUCCESS(rc)) { if (!RTFS_IS_FILE(ObjInfo.Attr.fMode)) rc = vboxExtPackReturnError(VERR_NOT_A_FILE, pszError, cbError, "Standard member '%s' is not a file", pszAdjName); else if (ObjInfo.cbObject >= _1M) rc = vboxExtPackReturnError(VERR_OUT_OF_RANGE, pszError, cbError, "Standard member '%s' is too large: %'RU64 bytes (max 1 MB)", pszAdjName, (uint64_t)ObjInfo.cbObject); else { /* * Make an in memory copy of the stream and check that the file * is UTF-8 clean. */ RTVFSIOSTREAM hVfsIos = RTVfsObjToIoStream(*phVfsObj); RTVFSFILE hVfsFile; rc = RTVfsMemorizeIoStreamAsFile(hVfsIos, RTFILE_O_READ, &hVfsFile); if (RT_SUCCESS(rc)) { rc = RTVfsIoStrmValidateUtf8Encoding(hVfsIos, RTVFS_VALIDATE_UTF8_BY_RTC_3629 | RTVFS_VALIDATE_UTF8_NO_NULL, NULL); if (RT_SUCCESS(rc)) { /* * Replace *phVfsObj with the memorized file. */ rc = RTVfsFileSeek(hVfsFile, 0, RTFILE_SEEK_BEGIN, NULL); if (RT_SUCCESS(rc)) { RTVfsObjRelease(*phVfsObj); *phVfsObj = RTVfsObjFromFile(hVfsFile); } else vboxExtPackSetError(pszError, cbError, "RTVfsFileSeek failed on '%s': %Rrc", pszAdjName, rc); } if (phVfsFile && RT_SUCCESS(rc)) *phVfsFile = hVfsFile; else RTVfsFileRelease(hVfsFile); } else vboxExtPackSetError(pszError, cbError, "RTVfsMemorizeIoStreamAsFile failed on '%s': %Rrc", pszAdjName, rc); RTVfsIoStrmRelease(hVfsIos); } } else vboxExtPackSetError(pszError, cbError, "RTVfsObjQueryInfo failed on '%s': %Rrc", pszAdjName, rc); } return rc; }
/** * Creates a UUID mapping for the file. * * @returns IPRT status code. * @param pszCacheFile The path to the file in the cache. * @param pFileUuid The UUID of the file. * @param pszUuidMapDir The UUID map subdirectory in the cache, if this is * wanted, otherwise NULL. * @param pCfg The configuration. */ static int rtDbgSymCacheAddCreateUuidMapping(const char *pszCacheFile, PRTUUID pFileUuid, const char *pszUuidMapDir, PCRTDBGSYMCACHEADDCFG pCfg) { /* * Create the UUID map entry first, deep. */ char szMapPath[RTPATH_MAX]; int rc = RTPathJoin(szMapPath, sizeof(szMapPath) - sizeof("/xxxx/yyyy/xxxx/yyyy/xxxx/zzzzzzzzzzzz") + 1, pCfg->pszCache, pszUuidMapDir); if (RT_FAILURE(rc)) return RTMsgErrorRc(rc, "Error constructing UUID map path (RTPathJoin): %Rrc", rc); size_t cch = strlen(szMapPath); szMapPath[cch] = '-'; rc = RTUuidToStr(pFileUuid, &szMapPath[cch + 2], sizeof(szMapPath) - cch); if (RT_FAILURE(rc)) return RTMsgErrorRc(rc, "Error constructing UUID map path (RTUuidToStr): %Rrc", rc); /* Uppercase the whole lot. */ RTStrToUpper(&szMapPath[cch + 2]); /* Split the first dword in two. */ szMapPath[cch + 1] = szMapPath[cch + 2]; szMapPath[cch + 2] = szMapPath[cch + 3]; szMapPath[cch + 3] = szMapPath[cch + 4]; szMapPath[cch + 4] = szMapPath[cch + 5]; szMapPath[cch + 5] = '-'; /* * Create the directories in the path. */ char chSaved = RTPATH_SLASH; for (unsigned i = 0; i < 6; i++, cch += 5) { Assert(szMapPath[cch] == '-'); szMapPath[cch] = '\0'; if (!RTDirExists(szMapPath)) { rc = RTDirCreate(szMapPath, 0755, RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_NOT_CRITICAL); if (RT_FAILURE(rc)) return RTMsgErrorRc(rc, "RTDirCreate failed on '%s' (UUID map path): %Rrc", szMapPath, rc); } szMapPath[cch] = RTPATH_SLASH; } cch -= 5; /* * Calculate a relative path from there to the actual file. */ char szLinkTarget[RTPATH_MAX]; //szMapPath[cch] = '\0'; rc = RTPathCalcRelative(szLinkTarget, sizeof(szLinkTarget), szMapPath, pszCacheFile); //szMapPath[cch] = RTPATH_SLASH; if (RT_FAILURE(rc)) return RTMsgErrorRc(rc, "Failed to calculate relative path from '%s' to '%s': %Rrc", szMapPath, pszCacheFile, rc); /* * If there is already a link there, check if it matches or whether * perhaps it's target doesn't exist. */ RTFSOBJINFO ObjInfo; rc = RTPathQueryInfoEx(szMapPath, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK); if (RT_SUCCESS(rc)) { if (RTFS_IS_SYMLINK(ObjInfo.Attr.fMode)) { rc = RTPathQueryInfoEx(szMapPath, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_FOLLOW_LINK); if (RT_SUCCESS(rc)) { char *pszCurTarget = NULL; rc = RTSymlinkReadA(szMapPath, &pszCurTarget); if (RT_FAILURE(rc)) return RTMsgErrorRc(rc, "UUID map: failed to read existing symlink '%s': %Rrc", szMapPath, rc); if (RTPathCompare(pszCurTarget, szLinkTarget) == 0) RTMsgInfo("UUID map: existing link '%s' has the same target ('%s').", szMapPath, pszCurTarget); else { RTMsgError("UUID map: Existing mapping '%s' pointing to '%s' insted of '%s'", szMapPath, pszCurTarget, szLinkTarget); rc = VERR_ALREADY_EXISTS; } RTStrFree(pszCurTarget); return rc; } else RTMsgInfo("UUID map: replacing dangling link '%s'", szMapPath); RTSymlinkDelete(szMapPath, 0 /*fFlags*/); } else if (RTFS_IS_FILE(ObjInfo.Attr.fMode)) return RTMsgErrorRc(VERR_IS_A_FILE, "UUID map: found file at '%s', expect symbolic link or nothing.", szMapPath); else if (RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode)) return RTMsgErrorRc(VERR_IS_A_DIRECTORY, "UUID map: found directory at '%s', expect symbolic link or nothing.", szMapPath); else return RTMsgErrorRc(VERR_NOT_SYMLINK, "UUID map: Expected symbolic link or nothing at '%s', found: fMode=%#x", szMapPath, ObjInfo.Attr.fMode); } /* * Create the symbolic link. */ rc = RTSymlinkCreate(szMapPath, szLinkTarget, RTSYMLINKTYPE_FILE, 0); if (RT_FAILURE(rc)) return RTMsgErrorRc(rc, "Failed to create UUID map symlink '%s' to '%s': %Rrc", szMapPath, szLinkTarget, rc); RTMsgInfo("UUID map: %s => %s", szMapPath, szLinkTarget); return VINF_SUCCESS; }
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; }
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; }
int DnDURIList::addEntry(const char *pcszSource, const char *pcszTarget, uint32_t fFlags) { AssertPtrReturn(pcszSource, VERR_INVALID_POINTER); AssertPtrReturn(pcszTarget, VERR_INVALID_POINTER); LogFlowFunc(("pcszSource=%s, pcszTarget=%s, fFlags=0x%x\n", pcszSource, pcszTarget, fFlags)); RTFSOBJINFO objInfo; int rc = RTPathQueryInfo(pcszSource, &objInfo, RTFSOBJATTRADD_NOTHING); if (RT_SUCCESS(rc)) { if (RTFS_IS_FILE(objInfo.Attr.fMode)) { LogFlowFunc(("File '%s' -> '%s' (%RU64 bytes, file mode 0x%x)\n", pcszSource, pcszTarget, (uint64_t)objInfo.cbObject, objInfo.Attr.fMode)); DnDURIObject *pObjFile = new DnDURIObject(DnDURIObject::File, pcszSource, pcszTarget); if (pObjFile) { if (fFlags & DNDURILIST_FLAGS_KEEP_OPEN) /* Shall we keep the file open while being added to this list? */ { /** @todo Add a standard fOpen mode for this list. */ rc = pObjFile->Open(DnDURIObject::Source, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE, objInfo.Attr.fMode); } if (RT_SUCCESS(rc)) { m_lstTree.append(pObjFile); m_cTotal++; m_cbTotal += pObjFile->GetSize(); } else delete pObjFile; } else rc = VERR_NO_MEMORY; } else if (RTFS_IS_DIRECTORY(objInfo.Attr.fMode)) { LogFlowFunc(("Directory '%s' -> '%s' (file mode 0x%x)\n", pcszSource, pcszTarget, objInfo.Attr.fMode)); DnDURIObject *pObjDir = new DnDURIObject(DnDURIObject::Directory, pcszSource, pcszTarget, objInfo.Attr.fMode, 0 /* Size */); if (pObjDir) { m_lstTree.append(pObjDir); /** @todo Add DNDURILIST_FLAGS_KEEP_OPEN handling? */ m_cTotal++; } else rc = VERR_NO_MEMORY; } /* Note: Symlinks already should have been resolved at this point. */ else rc = VERR_NOT_SUPPORTED; } 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; }
/** * 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; }
/** * Figure the type of a file/dir based on path and FS object info. * * @returns The type. * @param pszPath The path to the file/dir. * @param pObjInfo The object information, symlinks followed. */ static RTDBGSYMCACHEFILETYPE rtDbgSymCacheFigureType2(const char *pszPath, PCRTFSOBJINFO pObjInfo) { const char *pszName = RTPathFilename(pszPath); const char *pszExt = RTPathSuffix(pszName); if (pszExt) pszExt++; else pszExt = ""; if ( RTFS_IS_DIRECTORY(pObjInfo->Attr.fMode) || (pObjInfo->Attr.fMode & RTFS_DOS_DIRECTORY)) /** @todo OS X samba reports reparse points in /Volumes/ that we cannot resolve. */ { /* Skip directories shouldn't bother with. */ if ( !RTStrICmp(pszName, ".Trashes") || !RTStrICmp(pszName, ".$RESCYCLE.BIN") || !RTStrICmp(pszName, "System.kext") /* Usually only plugins here, so skip it. */ ) return RTDBGSYMCACHEFILETYPE_IGNORE; /* Directories can also be bundles on the mac. */ if (!RTStrICmp(pszExt, "dSYM")) return RTDBGSYMCACHEFILETYPE_DEBUG_BUNDLE; for (unsigned i = 0; i < RT_ELEMENTS(g_apszBundleSuffixes) - 1; i++) if (!RTStrICmp(pszExt, &g_apszBundleSuffixes[i][1])) return RTDBGSYMCACHEFILETYPE_IMAGE_BUNDLE; return RTDBGSYMCACHEFILETYPE_DIR; } if (!RTFS_IS_FILE(pObjInfo->Attr.fMode)) return RTDBGSYMCACHEFILETYPE_INVALID; /* Select image vs debug info based on extension. */ if ( !RTStrICmp(pszExt, "pdb") || !RTStrICmp(pszExt, "dbg") || !RTStrICmp(pszExt, "sym") || !RTStrICmp(pszExt, "dwo") || !RTStrICmp(pszExt, "dwp") || !RTStrICmp(pszExt, "debug") || !RTStrICmp(pszExt, "dsym") || !RTStrICmp(pszExt, "dwarf") || !RTStrICmp(pszExt, "map") || !RTStrICmp(pszExt, "cv")) return RTDBGSYMCACHEFILETYPE_DEBUG_FILE; /* Filter out a bunch of files which obviously shouldn't be images. */ if ( !RTStrICmp(pszExt, "txt") || !RTStrICmp(pszExt, "html") || !RTStrICmp(pszExt, "htm") || !RTStrICmp(pszExt, "rtf") || !RTStrICmp(pszExt, "zip") || !RTStrICmp(pszExt, "doc") || !RTStrICmp(pszExt, "gz") || !RTStrICmp(pszExt, "bz2") || !RTStrICmp(pszExt, "xz") || !RTStrICmp(pszExt, "kmk") || !RTStrICmp(pszExt, "c") || !RTStrICmp(pszExt, "cpp") || !RTStrICmp(pszExt, "h") || !RTStrICmp(pszExt, "m") || !RTStrICmp(pszExt, "mm") || !RTStrICmp(pszExt, "asm") || !RTStrICmp(pszExt, "S") || !RTStrICmp(pszExt, "inc") || !RTStrICmp(pszExt, "sh") ) return RTDBGSYMCACHEFILETYPE_IGNORE; if ( !RTStrICmp(pszName, "Makefile") || !RTStrICmp(pszName, "GNUmakefile") || !RTStrICmp(pszName, "createsymbolfiles") || !RTStrICmp(pszName, "kgmacros") ) return RTDBGSYMCACHEFILETYPE_IGNORE; return RTDBGSYMCACHEFILETYPE_IMAGE_FILE; }
/** * Worker that removes a file. * * Currently used to delete both regular and special files. * * @returns IPRT status code, errors go via rtPathRmError. * @param pOpts The RM options. * @param pszPath The path to the file. * @param pObjInfo The FS object info for the file. */ static int rtPathRmOneFile(PRTPATHRMCMDOPTS pOpts, const char *pszPath, PRTFSOBJINFO pObjInfo) { int rc; if (pOpts->fVerbose) rtPathRmVerbose(pOpts, pszPath); /* * Wipe the file if requested and possible. */ if (pOpts->fSafeDelete && RTFS_IS_FILE(pObjInfo->Attr.fMode)) { /* Lazy init of the 0xff buffer. */ if (g_ab0xFF[0] != 0xff || g_ab0xFF[sizeof(g_ab0xFF) - 1] != 0xff) memset(g_ab0xFF, 0xff, sizeof(g_ab0xFF)); RTFILE hFile; rc = RTFileOpen(&hFile, pszPath, RTFILE_O_WRITE); if (RT_FAILURE(rc)) return rtPathRmError(pOpts, pszPath, rc, "Opening '%s' for overwriting: %Rrc\n", pszPath, rc); for (unsigned iPass = 0; iPass < 3; iPass++) { uint8_t const *pabFiller = iPass == 1 ? g_abZeros : g_ab0xFF; size_t const cbFiller = iPass == 1 ? sizeof(g_abZeros) : sizeof(g_ab0xFF); rc = RTFileSeek(hFile, 0, RTFILE_SEEK_BEGIN, NULL); if (RT_FAILURE(rc)) { rc = rtPathRmError(pOpts, pszPath, rc, "Error seeking to start of '%s': %Rrc\n", pszPath, rc); break; } for (RTFOFF cbLeft = pObjInfo->cbObject; cbLeft > 0; cbLeft -= cbFiller) { size_t cbToWrite = cbFiller; if (cbLeft < (RTFOFF)cbToWrite) cbToWrite = (size_t)cbLeft; rc = RTFileWrite(hFile, pabFiller, cbToWrite, NULL); if (RT_FAILURE(rc)) { rc = rtPathRmError(pOpts, pszPath, rc, "Error writing to '%s': %Rrc\n", pszPath, rc); break; } } } int rc2 = RTFileClose(hFile); if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) return rtPathRmError(pOpts, pszPath, rc2, "Closing '%s' failed: %Rrc\n", pszPath, rc); if (RT_FAILURE(rc)) return rc; } /* * Remove the file. */ rc = RTFileDelete(pszPath); if (RT_FAILURE(rc)) return rtPathRmError(pOpts, pszPath, rc, RTFS_IS_FILE(pObjInfo->Attr.fMode) ? "Error removing regular file '%s': %Rrc\n" : "Error removing special file '%s': %Rrc\n", pszPath, rc); return rc; }