Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
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;
}
Beispiel #6
0
/**
 * 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;
}
Beispiel #8
0
/**
 * 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;
}
Beispiel #9
0
/**
 * 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);
}
Beispiel #11
0
/**
 * 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;
}
Beispiel #12
0
/**
 * 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;
}
Beispiel #13
0
/**
 * 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;
}
Beispiel #14
0
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;
}
Beispiel #15
0
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;
}
Beispiel #16
0
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;
}
Beispiel #17
0
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;
}
Beispiel #18
0
/**
 * 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;
}
Beispiel #19
0
/**
 * 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;
}