Esempio n. 1
0
/**
 * Constructs a local (unix) domain socket name.
 *
 * @returns IPRT status code.
 * @param   pAddr               The address structure to construct the name in.
 * @param   pcbAddr             Where to return the address size.
 * @param   pszName             The user specified name (valid).
 * @param   fNative             Whether it's a native name or a portable name.
 */
static int rtLocalIpcPosixConstructName(struct sockaddr_un *pAddr, uint8_t *pcbAddr, const char *pszName, bool fNative)
{
    const char *pszNativeName;
    int rc = rtPathToNative(&pszNativeName, pszName, NULL /*pszBasePath not support*/);
    if (RT_SUCCESS(rc))
    {
        size_t cchNativeName = strlen(pszNativeName);
        size_t cbFull = !fNative ? cchNativeName + sizeof(RTLOCALIPC_POSIX_NAME_PREFIX) : cchNativeName + 1;
        if (cbFull <= sizeof(pAddr->sun_path))
        {
            RT_ZERO(*pAddr);
#ifdef RT_OS_OS2 /* Size must be exactly right on OS/2. */
            *pcbAddr = sizeof(*pAddr);
#else
            *pcbAddr = RT_OFFSETOF(struct sockaddr_un, sun_path) + (uint8_t)cbFull;
#endif
#ifdef HAVE_SUN_LEN_MEMBER
            pAddr->sun_len     = *pcbAddr;
#endif
            pAddr->sun_family  = AF_LOCAL;

            if (!fNative)
            {
                memcpy(pAddr->sun_path, RTLOCALIPC_POSIX_NAME_PREFIX, sizeof(RTLOCALIPC_POSIX_NAME_PREFIX) - 1);
                memcpy(&pAddr->sun_path[sizeof(RTLOCALIPC_POSIX_NAME_PREFIX) - 1], pszNativeName, cchNativeName + 1);
            }
            else
                memcpy(pAddr->sun_path, pszNativeName, cchNativeName + 1);
        }
        else
Esempio n. 2
0
RTDECL(bool) RTPathExistsEx(const char *pszPath, uint32_t fFlags)
{
    /*
     * Validate input.
     */
    AssertPtrReturn(pszPath, false);
    AssertReturn(*pszPath, false);
    Assert(RTPATH_F_IS_VALID(fFlags, 0));

    /*
     * Convert the path and check if it exists using stat().
     */
    char const *pszNativePath;
    int rc = rtPathToNative(&pszNativePath, pszPath, NULL);
    if (RT_SUCCESS(rc))
    {
        struct stat Stat;
        if (fFlags & RTPATH_F_FOLLOW_LINK)
            rc = stat(pszNativePath, &Stat);
        else
            rc = lstat(pszNativePath, &Stat);
        if (!rc)
            rc = VINF_SUCCESS;
        else
            rc = VERR_GENERAL_FAILURE;
        rtPathFreeNative(pszNativePath, pszPath);
    }
    return RT_SUCCESS(rc);
}
Esempio n. 3
0
RTR3DECL(int) RTPathSetMode(const char *pszPath, RTFMODE fMode)
{
    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
    AssertReturn(*pszPath, VERR_INVALID_PARAMETER);

    int rc;
    fMode = rtFsModeNormalize(fMode, pszPath, 0);
    if (rtFsModeIsValidPermissions(fMode))
    {
        char const *pszNativePath;
        rc = rtPathToNative(&pszNativePath, pszPath, NULL);
        if (RT_SUCCESS(rc))
        {
            if (chmod(pszNativePath, fMode & RTFS_UNIX_MASK) != 0)
                rc = RTErrConvertFromErrno(errno);
            rtPathFreeNative(pszNativePath, pszPath);
        }
    }
    else
    {
        AssertMsgFailed(("Invalid file mode! %RTfmode\n", fMode));
        rc = VERR_INVALID_FMODE;
    }
    return rc;
}
Esempio n. 4
0
int rtDirNativeOpen(PRTDIR pDir, char *pszPathBuf)
{
    NOREF(pszPathBuf); /* only used on windows */

    /*
     * Convert to a native path and try opendir.
     */
    char const *pszNativePath;
    int rc = rtPathToNative(&pszNativePath, pDir->pszPath, NULL);
    if (RT_SUCCESS(rc))
    {
        pDir->pDir = opendir(pszNativePath);
        if (pDir->pDir)
        {
            /*
             * Init data.
             */
            pDir->fDataUnread = false;
            memset(&pDir->Data, 0, RT_OFFSETOF(RTDIR, Data.d_name)); /* not strictly necessary */
            memset(&pDir->Data.d_name[0], 0, pDir->cbMaxName);
        }
        else
            rc = RTErrConvertFromErrno(errno);

        rtPathFreeNative(pszNativePath, pDir->pszPath);
    }

    return rc;
}
Esempio n. 5
0
RTDECL(int) RTSymlinkDelete(const char *pszSymlink, uint32_t fDelete)
{
    char const *pszNativeSymlink;
    int rc = rtPathToNative(&pszNativeSymlink, pszSymlink, NULL);
    if (RT_SUCCESS(rc))
    {
        struct stat s;
        if (!lstat(pszNativeSymlink, &s))
        {
            if (S_ISLNK(s.st_mode))
            {
                if (unlink(pszNativeSymlink) == 0)
                    rc = VINF_SUCCESS;
                else
                    rc = RTErrConvertFromErrno(errno);
            }
            else
                rc = VERR_NOT_SYMLINK;
        }
        else
            rc = RTErrConvertFromErrno(errno);
        rtPathFreeNative(pszNativeSymlink, pszSymlink);
    }

    LogFlow(("RTSymlinkDelete(%p={%s}, #%x): returns %Rrc\n", pszSymlink, pszSymlink, fDelete, rc));
    return rc;
}
Esempio n. 6
0
RTDECL(bool) RTSymlinkIsDangling(const char *pszSymlink)
{
    bool fRc = false;
    char const *pszNativeSymlink;
    int rc = rtPathToNative(&pszNativeSymlink, pszSymlink, NULL);
    if (RT_SUCCESS(rc))
    {
        struct stat s;
        fRc = !lstat(pszNativeSymlink, &s)
            && S_ISLNK(s.st_mode);
        if (fRc)
        {
            errno = 0;
            fRc = stat(pszNativeSymlink, &s) != 0
               && (   errno == ENOENT
                   || errno == ENOTDIR
                   || errno == ELOOP);
        }

        rtPathFreeNative(pszNativeSymlink, pszSymlink);
    }

    LogFlow(("RTSymlinkIsDangling(%p={%s}): returns %RTbool\n", pszSymlink, pszSymlink, fRc));
    return fRc;
}
int rtDirNativeOpen(PRTDIR pDir, char *pszPathBuf)
{
    NOREF(pszPathBuf); /* only used on windows */

    /*
     * Convert to a native path and try opendir.
     */
    char const *pszNativePath;
    int rc = rtPathToNative(&pszNativePath, pDir->pszPath, NULL);
    if (RT_SUCCESS(rc))
    {
        pDir->pDir = opendir(pszNativePath);
        if (pDir->pDir)
        {
            /*
             * Init data (allocated as all zeros).
             */
            pDir->fDataUnread = false; /* spelling it out */
        }
        else
            rc = RTErrConvertFromErrno(errno);

        rtPathFreeNative(pszNativePath, pDir->pszPath);
    }

    return rc;
}
Esempio n. 8
0
RTDECL(int) RTPathReal(const char *pszPath, char *pszRealPath, size_t cchRealPath)
{
    /*
     * Convert input.
     */
    char const *pszNativePath;
    int rc = rtPathToNative(&pszNativePath, pszPath, NULL);
    if (RT_SUCCESS(rc))
    {
        /*
         * On POSIX platforms the API doesn't take a length parameter, which makes it
         * a little bit more work.
         */
        char szTmpPath[PATH_MAX + 1];
        const char *psz = realpath(pszNativePath, szTmpPath);
        if (psz)
            rc = rtPathFromNativeCopy(pszRealPath, cchRealPath, szTmpPath, NULL);
        else
            rc = RTErrConvertFromErrno(errno);
        rtPathFreeNative(pszNativePath, pszPath);
    }

    LogFlow(("RTPathReal(%p:{%s}, %p:{%s}, %u): returns %Rrc\n", pszPath, pszPath,
             pszRealPath, RT_SUCCESS(rc) ? pszRealPath : "<failed>",  cchRealPath, rc));
    return rc;
}
Esempio n. 9
0
RTR3DECL(int) RTFsQuerySerial(const char *pszFsPath, uint32_t *pu32Serial)
{
    /*
     * Validate input.
     */
    AssertMsgReturn(VALID_PTR(pszFsPath) && *pszFsPath, ("%p", pszFsPath), VERR_INVALID_PARAMETER);
    AssertMsgReturn(VALID_PTR(pu32Serial), ("%p", pu32Serial), VERR_INVALID_PARAMETER);

    /*
     * Convert the path and query the stats.
     * We're simply return the device id.
     */
    char const *pszNativeFsPath;
    int rc = rtPathToNative(&pszNativeFsPath, pszFsPath, NULL);
    if (RT_SUCCESS(rc))
    {
        struct stat Stat;
        if (!stat(pszNativeFsPath, &Stat))
        {
            if (pu32Serial)
                *pu32Serial = (uint32_t)Stat.st_dev;
        }
        else
            rc = RTErrConvertFromErrno(errno);
        rtPathFreeNative(pszNativeFsPath, pszFsPath);
    }
    LogFlow(("RTFsQuerySerial(%p:{%s}, %p:{%RX32}: returns %Rrc\n",
             pszFsPath, pszFsPath, pu32Serial, pu32Serial ? *pu32Serial : 0, rc));
    return rc;
}
Esempio n. 10
0
RTDECL(int) RTSymlinkReadA(const char *pszSymlink, char **ppszTarget)
{
    AssertPtr(ppszTarget);
    char const *pszNativeSymlink;
    int rc = rtPathToNative(&pszNativeSymlink, pszSymlink, NULL);
    if (RT_SUCCESS(rc))
    {
        /* Guess the initial buffer size. */
        ssize_t     cbBuf;
        struct stat s;
        if (!lstat(pszNativeSymlink, &s))
            cbBuf = RT_MIN(RT_ALIGN_Z(s.st_size, 64), 64);
        else
            cbBuf = 1024;

        /* Read loop that grows the buffer. */
        char *pszBuf = NULL;
        for (;;)
        {
            RTMemTmpFree(pszBuf);
            pszBuf = (char *)RTMemTmpAlloc(cbBuf);
            if (pszBuf)
            {
                ssize_t cbReturned = readlink(pszNativeSymlink, pszBuf, cbBuf);
                if (cbReturned >= cbBuf)
                {
                    /* Increase the buffer size and try again */
                    cbBuf *= 2;
                    continue;
                }

                if (cbReturned > 0)
                {
                    pszBuf[cbReturned] = '\0';
                    rc = rtPathFromNativeDup(ppszTarget, pszBuf, pszSymlink);
                }
                else if (errno == EINVAL)
                    rc = VERR_NOT_SYMLINK;
                else
                    rc = RTErrConvertFromErrno(errno);
            }
            else
                rc = VERR_NO_TMP_MEMORY;
            break;
        } /* for loop */

        RTMemTmpFree(pszBuf);
        rtPathFreeNative(pszNativeSymlink, pszSymlink);
    }

    if (RT_SUCCESS(rc))
        LogFlow(("RTSymlinkReadA(%p={%s},%p): returns %Rrc *ppszTarget=%p:{%s}\n", pszSymlink, pszSymlink, ppszTarget, rc, *ppszTarget, *ppszTarget));
    else
        LogFlow(("RTSymlinkReadA(%p={%s},%p): returns %Rrc\n", pszSymlink, pszSymlink, ppszTarget, rc));
    return rc;
}
Esempio n. 11
0
RTDECL(int) RTDirRemove(const char *pszPath)
{
    char const *pszNativePath;
    int rc = rtPathToNative(&pszNativePath, pszPath, NULL);
    if (RT_SUCCESS(rc))
    {
        if (rmdir(pszNativePath))
            rc = RTErrConvertFromErrno(errno);

        rtPathFreeNative(pszNativePath, pszPath);
    }

    LogFlow(("RTDirRemove(%p={%s}): returns %Rrc\n", pszPath, pszPath, rc));
    return rc;
}
Esempio n. 12
0
RTDECL(int) RTSymlinkCreate(const char *pszSymlink, const char *pszTarget, RTSYMLINKTYPE enmType, uint32_t fCreate)
{
    /*
     * Validate the input.
     */
    AssertReturn(enmType > RTSYMLINKTYPE_INVALID && enmType < RTSYMLINKTYPE_END, VERR_INVALID_PARAMETER);
    AssertPtrReturn(pszSymlink, VERR_INVALID_POINTER);
    AssertPtrReturn(pszTarget, VERR_INVALID_POINTER);

    /*
     * Convert the paths.
     */
    char const *pszNativeSymlink;
    int rc = rtPathToNative(&pszNativeSymlink, pszSymlink, NULL);
    if (RT_SUCCESS(rc))
    {
        const char *pszNativeTarget;
        rc = rtPathToNative(&pszNativeTarget, pszTarget, NULL);
        if (RT_SUCCESS(rc))
        {
            /*
             * Create the link.
             */
            if (symlink(pszNativeTarget, pszNativeSymlink) == 0)
                rc = VINF_SUCCESS;
            else
                rc = RTErrConvertFromErrno(errno);

            rtPathFreeNative(pszNativeTarget, pszTarget);
        }
        rtPathFreeNative(pszNativeSymlink, pszSymlink);
    }

    LogFlow(("RTSymlinkCreate(%p={%s}, %p={%s}, %d, %#x): returns %Rrc\n", pszSymlink, pszSymlink, pszTarget, pszTarget, enmType, fCreate, rc));
    return rc;
}
Esempio n. 13
0
RTDECL(bool) RTDirExists(const char *pszPath)
{
    bool fRc = false;
    char const *pszNativePath;
    int rc = rtPathToNative(&pszNativePath, pszPath, NULL);
    if (RT_SUCCESS(rc))
    {
        struct stat s;
        fRc = !stat(pszNativePath, &s)
            && S_ISDIR(s.st_mode);

        rtPathFreeNative(pszNativePath, pszPath);
    }

    LogFlow(("RTDirExists(%p={%s}): returns %RTbool\n", pszPath, pszPath, fRc));
    return fRc;
}
Esempio n. 14
0
RTDECL(bool) RTSymlinkExists(const char *pszSymlink)
{
    bool fRc = false;
    char const *pszNativeSymlink;
    int rc = rtPathToNative(&pszNativeSymlink, pszSymlink, NULL);
    if (RT_SUCCESS(rc))
    {
        struct stat s;
        fRc = !lstat(pszNativeSymlink, &s)
            && S_ISLNK(s.st_mode);

        rtPathFreeNative(pszNativeSymlink, pszSymlink);
    }

    LogFlow(("RTSymlinkExists(%p={%s}): returns %RTbool\n", pszSymlink, pszSymlink, fRc));
    return fRc;
}
Esempio n. 15
0
RTR3DECL(int) RTFsQuerySizes(const char *pszFsPath, RTFOFF *pcbTotal, RTFOFF *pcbFree,
                             uint32_t *pcbBlock, uint32_t *pcbSector)
{
    /*
     * Validate input.
     */
    AssertMsgReturn(VALID_PTR(pszFsPath) && *pszFsPath, ("%p", pszFsPath), VERR_INVALID_PARAMETER);

    /*
     * Convert the path and query the information.
     */
    char const *pszNativeFsPath;
    int rc = rtPathToNative(&pszNativeFsPath, pszFsPath, NULL);
    if (RT_SUCCESS(rc))
    {
        /** @todo I'm not quite sure if statvfs was properly specified by SuS, I have to check my own
         * implementation and FreeBSD before this can eventually be promoted to posix. */
        struct statvfs StatVFS;
        RT_ZERO(StatVFS);
        if (!statvfs(pszNativeFsPath, &StatVFS))
        {
            /*
             * Calc the returned values.
             */
            if (pcbTotal)
                *pcbTotal = (RTFOFF)StatVFS.f_blocks * StatVFS.f_frsize;
            if (pcbFree)
                *pcbFree = (RTFOFF)StatVFS.f_bavail * StatVFS.f_frsize;
            if (pcbBlock)
                *pcbBlock = StatVFS.f_frsize;
            /* no idea how to get the sector... */
            if (pcbSector)
                *pcbSector = 512;
        }
        else
            rc = RTErrConvertFromErrno(errno);
        rtPathFreeNative(pszNativeFsPath, pszFsPath);
    }

    LogFlow(("RTFsQuerySizes(%p:{%s}, %p:{%RTfoff}, %p:{%RTfoff}, %p:{%RX32}, %p:{%RX32}): returns %Rrc\n",
             pszFsPath, pszFsPath, pcbTotal, pcbTotal ? *pcbTotal : 0, pcbFree, pcbFree ? *pcbFree : 0,
             pcbBlock, pcbBlock ? *pcbBlock : 0, pcbSector, pcbSector ? *pcbSector : 0, rc));
    return rc;
}
Esempio n. 16
0
RTR3DECL(int) RTFsQueryProperties(const char *pszFsPath, PRTFSPROPERTIES pProperties)
{
    /*
     * Validate.
     */
    AssertMsgReturn(VALID_PTR(pszFsPath) && *pszFsPath, ("%p", pszFsPath), VERR_INVALID_PARAMETER);
    AssertMsgReturn(VALID_PTR(pProperties), ("%p", pProperties), VERR_INVALID_PARAMETER);

    /*
     * Convert the path and query the information.
     */
    char const *pszNativeFsPath;
    int rc = rtPathToNative(&pszNativeFsPath, pszFsPath, NULL);
    if (RT_SUCCESS(rc))
    {
        struct statvfs StatVFS;
        RT_ZERO(StatVFS);
        if (!statvfs(pszNativeFsPath, &StatVFS))
        {
            /*
             * Calc/fake the returned values.
             */
            pProperties->cbMaxComponent = StatVFS.f_namemax;
#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
            pProperties->fCaseSensitive = false;
#else
            pProperties->fCaseSensitive = true;
#endif
            pProperties->fCompressed = false;
            pProperties->fFileCompression = false;
            pProperties->fReadOnly = !!(StatVFS.f_flag & ST_RDONLY);
            pProperties->fRemote = false;
            pProperties->fSupportsUnicode = true;
        }
        else
            rc = RTErrConvertFromErrno(errno);
        rtPathFreeNative(pszNativeFsPath, pszFsPath);
    }

    LogFlow(("RTFsQueryProperties(%p:{%s}, %p:{.cbMaxComponent=%u, .fReadOnly=%RTbool}): returns %Rrc\n",
             pszFsPath, pszFsPath, pProperties, pProperties->cbMaxComponent, pProperties->fReadOnly, rc));
    return rc;
}
Esempio n. 17
0
RTDECL(int) RTPathSetCurrent(const char *pszPath)
{
    /*
     * Validate input.
     */
    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
    AssertReturn(*pszPath, VERR_INVALID_PARAMETER);

    /*
     * Change the directory.
     */
    char const *pszNativePath;
    int rc = rtPathToNative(&pszNativePath, pszPath, NULL);
    if (RT_SUCCESS(rc))
    {
        if (chdir(pszNativePath))
            rc = RTErrConvertFromErrno(errno);
        rtPathFreeNative(pszNativePath, pszPath);
    }
    return rc;
}
Esempio n. 18
0
RTDECL(int) RTDirCreate(const char *pszPath, RTFMODE fMode, uint32_t fCreate)
{
    int rc;
    fMode = rtFsModeNormalize(fMode, pszPath, 0);
    if (rtFsModeIsValidPermissions(fMode))
    {
        char const *pszNativePath;
        rc = rtPathToNative(&pszNativePath, pszPath, NULL);
        if (RT_SUCCESS(rc))
        {
            if (mkdir(pszNativePath, fMode & RTFS_UNIX_MASK))
            {
                rc = errno;
                bool fVerifyIsDir = true;
#ifdef RT_OS_SOLARIS
                /*
                 * mkdir on nfs mount points has been/is busted in various
                 * during the Nevada development cycle. We've observed:
                 *  - Build 111b (2009.06) returns EACCES.
                 *  - Build ca. 70-80 returns ENOSYS.
                 */
                if (    rc == ENOSYS
                    ||  rc == EACCES)
                {
                    rc = RTErrConvertFromErrno(rc);
                    fVerifyIsDir = false;  /* We'll check if it's a dir ourselves since we're going to stat() anyway. */
                    struct stat st;
                    if (!stat(pszNativePath, &st))
                    {
                        rc = VERR_ALREADY_EXISTS;
                        if (!S_ISDIR(st.st_mode))
                            rc = VERR_IS_A_FILE;
                    }
                }
                else
                    rc = RTErrConvertFromErrno(rc);
#else
                rc = RTErrConvertFromErrno(rc);
#endif
                if (   rc == VERR_ALREADY_EXISTS
                    && fVerifyIsDir == true)
                {
                    /*
                     * Verify that it really exists as a directory.
                     */
                    struct stat st;
                    if (!stat(pszNativePath, &st) && !S_ISDIR(st.st_mode))
                        rc = VERR_IS_A_FILE;
                }
            }
        }

        rtPathFreeNative(pszNativePath, pszPath);
    }
    else
    {
        AssertMsgFailed(("Invalid file mode! %RTfmode\n", fMode));
        rc = VERR_INVALID_FMODE;
    }
    LogFlow(("RTDirCreate(%p={%s}, %RTfmode): returns %Rrc\n", pszPath, pszPath, fMode, rc));
    return rc;
}
Esempio n. 19
0
/**
 * Worker for RTPathRename, RTDirRename, RTFileRename.
 *
 * @returns IPRT status code.
 * @param   pszSrc      The source path.
 * @param   pszDst      The destination path.
 * @param   fRename     The rename flags.
 * @param   fFileType   The filetype. We use the RTFMODE filetypes here. If it's 0,
 *                      anything goes. If it's RTFS_TYPE_DIRECTORY we'll check that the
 *                      source is a directory. If Its RTFS_TYPE_FILE we'll check that it's
 *                      not a directory (we are NOT checking whether it's a file).
 */
DECLHIDDEN(int) rtPathPosixRename(const char *pszSrc, const char *pszDst, unsigned fRename, RTFMODE fFileType)
{
    /*
     * Convert the paths.
     */
    char const *pszNativeSrc;
    int rc = rtPathToNative(&pszNativeSrc, pszSrc, NULL);
    if (RT_SUCCESS(rc))
    {
        char const *pszNativeDst;
        rc = rtPathToNative(&pszNativeDst, pszDst, NULL);
        if (RT_SUCCESS(rc))
        {
            /*
             * Check that the source exists and that any types that's specified matches.
             * We have to check this first to avoid getting errnous VERR_ALREADY_EXISTS
             * errors from the next step.
             *
             * There are race conditions here (perhaps unlikely ones, but still), but I'm
             * afraid there is little with can do to fix that.
             */
            struct stat SrcStat;
            if (lstat(pszNativeSrc, &SrcStat))
                rc = RTErrConvertFromErrno(errno);
            else if (!fFileType)
                rc = VINF_SUCCESS;
            else if (RTFS_IS_DIRECTORY(fFileType))
                rc = S_ISDIR(SrcStat.st_mode) ? VINF_SUCCESS : VERR_NOT_A_DIRECTORY;
            else
                rc = S_ISDIR(SrcStat.st_mode) ? VERR_IS_A_DIRECTORY : VINF_SUCCESS;
            if (RT_SUCCESS(rc))
            {
                bool fSameFile = false;

                /*
                 * Check if the target exists, rename is rather destructive.
                 * We'll have to make sure we don't overwrite the source!
                 * Another race condition btw.
                 */
                struct stat DstStat;
                if (lstat(pszNativeDst, &DstStat))
                    rc = errno == ENOENT ? VINF_SUCCESS : RTErrConvertFromErrno(errno);
                else
                {
                    Assert(SrcStat.st_dev && DstStat.st_dev);
                    Assert(SrcStat.st_ino && DstStat.st_ino);
                    if (    SrcStat.st_dev == DstStat.st_dev
                        &&  SrcStat.st_ino == DstStat.st_ino
                        &&  (SrcStat.st_mode & S_IFMT) == (DstStat.st_mode & S_IFMT))
                    {
                        /*
                         * It's likely that we're talking about the same file here.
                         * We should probably check paths or whatever, but for now this'll have to be enough.
                         */
                        fSameFile = true;
                    }
                    if (fSameFile)
                        rc = VINF_SUCCESS;
                    else if (S_ISDIR(DstStat.st_mode) || !(fRename & RTPATHRENAME_FLAGS_REPLACE))
                        rc = VERR_ALREADY_EXISTS;
                    else
                        rc = VINF_SUCCESS;

                }
                if (RT_SUCCESS(rc))
                {
                    if (!rename(pszNativeSrc, pszNativeDst))
                        rc = VINF_SUCCESS;
                    else if (   (fRename & RTPATHRENAME_FLAGS_REPLACE)
                             && (errno == ENOTDIR || errno == EEXIST))
                    {
                        /*
                         * Check that the destination isn't a directory.
                         * Yet another race condition.
                         */
                        if (rtPathSame(pszNativeSrc, pszNativeDst))
                        {
                            rc = VINF_SUCCESS;
                            Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): appears to be the same file... (errno=%d)\n",
                                 pszSrc, pszDst, fRename, fFileType, errno));
                        }
                        else
                        {
                            if (lstat(pszNativeDst, &DstStat))
                                rc = errno != ENOENT ? RTErrConvertFromErrno(errno) : VINF_SUCCESS;
                            else if (S_ISDIR(DstStat.st_mode))
                                rc = VERR_ALREADY_EXISTS;
                            else
                                rc = VINF_SUCCESS;
                            if (RT_SUCCESS(rc))
                            {
                                if (!unlink(pszNativeDst))
                                {
                                    if (!rename(pszNativeSrc, pszNativeDst))
                                        rc = VINF_SUCCESS;
                                    else
                                    {
                                        rc = RTErrConvertFromErrno(errno);
                                        Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): rename failed rc=%Rrc errno=%d\n",
                                             pszSrc, pszDst, fRename, fFileType, rc, errno));
                                    }
                                }
                                else
                                {
                                    rc = RTErrConvertFromErrno(errno);
                                    Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): failed to unlink dst rc=%Rrc errno=%d\n",
                                         pszSrc, pszDst, fRename, fFileType, rc, errno));
                                }
                            }
                            else
                                Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): dst !dir check failed rc=%Rrc\n",
                                     pszSrc, pszDst, fRename, fFileType, rc));
                        }
                    }
                    else
                    {
                        rc = RTErrConvertFromErrno(errno);
                        if (errno == ENOTDIR)
                            rc = VERR_ALREADY_EXISTS; /* unless somebody is racing us, this is the right interpretation */
                        Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): rename failed rc=%Rrc errno=%d\n",
                             pszSrc, pszDst, fRename, fFileType, rc, errno));
                    }
                }
                else
                    Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): destination check failed rc=%Rrc errno=%d\n",
                         pszSrc, pszDst, fRename, fFileType, rc, errno));
            }
            else
                Log(("rtPathRename('%s', '%s', %#x ,%RTfmode): source type check failed rc=%Rrc errno=%d\n",
                     pszSrc, pszDst, fRename, fFileType, rc, errno));

            rtPathFreeNative(pszNativeDst, pszDst);
        }
        rtPathFreeNative(pszNativeSrc, pszSrc);
    }
    return rc;
}
Esempio n. 20
0
RTR3DECL(int) RTFsQueryType(const char *pszFsPath, PRTFSTYPE penmType)
{
    *penmType = RTFSTYPE_UNKNOWN;

    /*
     * Validate input.
     */
    AssertPtrReturn(pszFsPath, VERR_INVALID_POINTER);
    AssertReturn(*pszFsPath, VERR_INVALID_PARAMETER);

    /*
     * Convert the path and query the stats.
     * We're simply return the device id.
     */
    char const *pszNativeFsPath;
    int rc = rtPathToNative(&pszNativeFsPath, pszFsPath, NULL);
    if (RT_SUCCESS(rc))
    {
        struct stat Stat;
        if (!stat(pszNativeFsPath, &Stat))
        {
#if defined(RT_OS_LINUX)
            FILE *mounted = setmntent("/proc/mounts", "r");
            if (!mounted)
                mounted = setmntent("/etc/mtab", "r");
            if (mounted)
            {
                char            szBuf[1024];
                struct stat     mntStat;
                struct mntent   mntEnt;
                while (getmntent_r(mounted, &mntEnt, szBuf, sizeof(szBuf)))
                {
                    if (!stat(mntEnt.mnt_dir, &mntStat))
                    {
                        if (mntStat.st_dev == Stat.st_dev)
                        {
                            if (!strcmp("ext4", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_EXT4;
                            else if (!strcmp("ext3", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_EXT3;
                            else if (!strcmp("ext2", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_EXT2;
                            else if (!strcmp("jfs", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_JFS;
                            else if (!strcmp("xfs", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_XFS;
                            else if (   !strcmp("vfat", mntEnt.mnt_type)
                                     || !strcmp("msdos", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_FAT;
                            else if (!strcmp("ntfs", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_NTFS;
                            else if (!strcmp("hpfs", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_HPFS;
                            else if (!strcmp("ufs", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_UFS;
                            else if (!strcmp("tmpfs", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_TMPFS;
                            else if (!strcmp("hfsplus", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_HFS;
                            else if (!strcmp("udf", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_UDF;
                            else if (!strcmp("iso9660", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_ISO9660;
                            else if (!strcmp("smbfs", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_SMBFS;
                            else if (!strcmp("cifs", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_CIFS;
                            else if (!strcmp("nfs", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_NFS;
                            else if (!strcmp("nfs4", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_NFS;
                            else if (!strcmp("sysfs", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_SYSFS;
                            else if (!strcmp("proc", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_PROC;
                            else if (   !strcmp("fuse", mntEnt.mnt_type)
                                     || !strncmp("fuse.", mntEnt.mnt_type, 5)
                                     || !strcmp("fuseblk", mntEnt.mnt_type))
                                *penmType = RTFSTYPE_FUSE;
                            else
                            {
                                /* sometimes there are more than one entry for the same partition */
                                continue;
                            }
                            break;
                        }
                    }
                }
                endmntent(mounted);
            }

#elif defined(RT_OS_SOLARIS)
            if (!strcmp("zfs", Stat.st_fstype))
                *penmType = RTFSTYPE_ZFS;
            else if (!strcmp("ufs", Stat.st_fstype))
                *penmType = RTFSTYPE_UFS;
            else if (!strcmp("nfs", Stat.st_fstype))
                *penmType = RTFSTYPE_NFS;

#elif defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD)
            struct statfs statfsBuf;
            if (!statfs(pszNativeFsPath, &statfsBuf))
            {
                if (!strcmp("hfs", statfsBuf.f_fstypename))
                    *penmType = RTFSTYPE_HFS;
                else if (   !strcmp("fat", statfsBuf.f_fstypename)
                         || !strcmp("msdos", statfsBuf.f_fstypename))
                    *penmType = RTFSTYPE_FAT;
                else if (!strcmp("ntfs", statfsBuf.f_fstypename))
                    *penmType = RTFSTYPE_NTFS;
                else if (!strcmp("autofs", statfsBuf.f_fstypename))
                    *penmType = RTFSTYPE_AUTOFS;
                else if (!strcmp("devfs", statfsBuf.f_fstypename))
                    *penmType = RTFSTYPE_DEVFS;
                else if (!strcmp("nfs", statfsBuf.f_fstypename))
                    *penmType = RTFSTYPE_NFS;
                else if (!strcmp("ufs", statfsBuf.f_fstypename))
                    *penmType = RTFSTYPE_UFS;
                else if (!strcmp("zfs", statfsBuf.f_fstypename))
                    *penmType = RTFSTYPE_ZFS;
            }
            else
                rc = RTErrConvertFromErrno(errno);
#endif
        }
        else
            rc = RTErrConvertFromErrno(errno);
        rtPathFreeNative(pszNativeFsPath, pszFsPath);
    }

    return rc;
}
Esempio n. 21
0
RTR3DECL(int) RTPathQueryInfoEx(const char *pszPath, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags)
{
    /*
     * Validate input.
     */
    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
    AssertReturn(*pszPath, VERR_INVALID_PARAMETER);
    AssertPtrReturn(pObjInfo, VERR_INVALID_POINTER);
    AssertMsgReturn(    enmAdditionalAttribs >= RTFSOBJATTRADD_NOTHING
                    &&  enmAdditionalAttribs <= RTFSOBJATTRADD_LAST,
                    ("Invalid enmAdditionalAttribs=%p\n", enmAdditionalAttribs),
                    VERR_INVALID_PARAMETER);
    AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);

    /*
     * Convert the filename.
     */
    char const *pszNativePath;
    int rc = rtPathToNative(&pszNativePath, pszPath, NULL);
    if (RT_SUCCESS(rc))
    {
        struct stat Stat;
        if (fFlags & RTPATH_F_FOLLOW_LINK)
            rc = stat(pszNativePath, &Stat);
        else
            rc = lstat(pszNativePath, &Stat); /** @todo how doesn't have lstat again? */
        if (!rc)
        {
            rtFsConvertStatToObjInfo(pObjInfo, &Stat, pszPath, 0);
            switch (enmAdditionalAttribs)
            {
                case RTFSOBJATTRADD_NOTHING:
                case RTFSOBJATTRADD_UNIX:
                    Assert(pObjInfo->Attr.enmAdditional == RTFSOBJATTRADD_UNIX);
                    break;

                case RTFSOBJATTRADD_UNIX_OWNER:
                    rtFsObjInfoAttrSetUnixOwner(pObjInfo, Stat.st_uid);
                    break;

                case RTFSOBJATTRADD_UNIX_GROUP:
                    rtFsObjInfoAttrSetUnixGroup(pObjInfo, Stat.st_gid);
                    break;

                case RTFSOBJATTRADD_EASIZE:
                    /** @todo Use SGI extended attribute interface to query EA info. */
                    pObjInfo->Attr.enmAdditional          = RTFSOBJATTRADD_EASIZE;
                    pObjInfo->Attr.u.EASize.cb            = 0;
                    break;

                default:
                    AssertMsgFailed(("Impossible!\n"));
                    return VERR_INTERNAL_ERROR;
            }
        }
        else
            rc = RTErrConvertFromErrno(errno);
        rtPathFreeNative(pszNativePath, pszPath);
    }

    LogFlow(("RTPathQueryInfoEx(%p:{%s}, pObjInfo=%p, %d): returns %Rrc\n",
             pszPath, pszPath, pObjInfo, enmAdditionalAttribs, rc));
    return rc;
}
Esempio n. 22
0
RTR3DECL(int) RTPathSetTimesEx(const char *pszPath, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
                               PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime, uint32_t fFlags)
{
    /*
     * Validate input.
     */
    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
    AssertReturn(*pszPath, VERR_INVALID_PARAMETER);
    AssertPtrNullReturn(pAccessTime, VERR_INVALID_POINTER);
    AssertPtrNullReturn(pModificationTime, VERR_INVALID_POINTER);
    AssertPtrNullReturn(pChangeTime, VERR_INVALID_POINTER);
    AssertPtrNullReturn(pBirthTime, VERR_INVALID_POINTER);
    AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);

    /*
     * Convert the paths.
     */
    char const *pszNativePath;
    int rc = rtPathToNative(&pszNativePath, pszPath, NULL);
    if (RT_SUCCESS(rc))
    {
        RTFSOBJINFO ObjInfo;

        /*
         * If it's a no-op, we'll only verify the existance of the file.
         */
        if (!pAccessTime && !pModificationTime)
            rc = RTPathQueryInfoEx(pszPath, &ObjInfo, RTFSOBJATTRADD_NOTHING, fFlags);
        else
        {
            /*
             * Convert the input to timeval, getting the missing one if necessary,
             * and call the API which does the change.
             */
            struct timeval aTimevals[2];
            if (pAccessTime && pModificationTime)
            {
                RTTimeSpecGetTimeval(pAccessTime,       &aTimevals[0]);
                RTTimeSpecGetTimeval(pModificationTime, &aTimevals[1]);
            }
            else
            {
                rc = RTPathQueryInfoEx(pszPath, &ObjInfo, RTFSOBJATTRADD_UNIX, fFlags);
                if (RT_SUCCESS(rc))
                {
                    RTTimeSpecGetTimeval(pAccessTime        ? pAccessTime       : &ObjInfo.AccessTime,       &aTimevals[0]);
                    RTTimeSpecGetTimeval(pModificationTime  ? pModificationTime : &ObjInfo.ModificationTime, &aTimevals[1]);
                }
                else
                    Log(("RTPathSetTimes('%s',%p,%p,,): RTPathQueryInfo failed with %Rrc\n",
                         pszPath, pAccessTime, pModificationTime, rc));
            }
            if (RT_SUCCESS(rc))
            {
                if (fFlags & RTPATH_F_FOLLOW_LINK)
                {
                    if (utimes(pszNativePath, aTimevals))
                        rc = RTErrConvertFromErrno(errno);
                }
#if (defined(RT_OS_DARWIN) && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050) \
 || defined(RT_OS_FREEBSD) \
 || defined(RT_OS_LINUX) \
 || defined(RT_OS_OS2) /** @todo who really has lutimes? */
                else
                {
                    if (lutimes(pszNativePath, aTimevals))
                        rc = RTErrConvertFromErrno(errno);
                }
#else
                else
                {
                    if (pAccessTime && pModificationTime)
                        rc = RTPathQueryInfoEx(pszPath, &ObjInfo, RTFSOBJATTRADD_UNIX, fFlags);
                    if (RT_SUCCESS(rc) && RTFS_IS_SYMLINK(ObjInfo.Attr.fMode))
                        rc = VERR_NS_SYMLINK_SET_TIME;
                    else if (RT_SUCCESS(rc))
                    {
                        if (utimes(pszNativePath, aTimevals))
                            rc = RTErrConvertFromErrno(errno);
                    }
                }
#endif
                if (RT_FAILURE(rc))
                    Log(("RTPathSetTimes('%s',%p,%p,,): failed with %Rrc and errno=%d\n",
                         pszPath, pAccessTime, pModificationTime, rc, errno));
            }
        }
        rtPathFreeNative(pszNativePath, pszPath);
    }