Пример #1
0
static
BOOLEAN
PvfsSysIsEmptyDir(
    PSTR pszDirname
)
{
    NTSTATUS ntError = STATUS_SUCCESS;
    BOOLEAN isEmptyDir = TRUE;
    DIR *pDir = NULL;
    struct dirent *pDirEntry = NULL;
    struct dirent dirEntry = { 0 };

    ntError = PvfsSysOpenDir(pszDirname, &pDir);
    BAIL_ON_NT_STATUS(ntError);

    for (ntError = PvfsSysReadDir(pDir, &dirEntry, &pDirEntry);
            pDirEntry;
            ntError = PvfsSysReadDir(pDir, &dirEntry, &pDirEntry))
    {
        /* First check the error return */
        BAIL_ON_NT_STATUS(ntError);

        if (!LwRtlCStringIsEqual(pDirEntry->d_name, ".", FALSE) &&
                !LwRtlCStringIsEqual(pDirEntry->d_name, "..", FALSE))
        {
            isEmptyDir = FALSE;
            break;
        }
    }

error:
    if (pDir)
    {
        PvfsSysCloseDir(pDir);
    }

    return NT_SUCCESS(ntError) ? isEmptyDir : FALSE;
}
Пример #2
0
static
NTSTATUS
PvfsSysRemoveDir(
    PSTR pszDirname
)
{
    NTSTATUS ntError = STATUS_SUCCESS;
    DIR *pDir = NULL;
    struct dirent *pDirEntry = NULL;
    struct dirent dirEntry = { 0 };
    PSTR pszPath = NULL;
    PVFS_STAT streamDirStat = { 0 };

    ntError = PvfsSysOpenDir(pszDirname, &pDir);
    BAIL_ON_NT_STATUS(ntError);

    for (ntError = PvfsSysReadDir(pDir, &dirEntry, &pDirEntry);
            pDirEntry;
            ntError = PvfsSysReadDir(pDir, &dirEntry, &pDirEntry))
    {
        /* First check the error return */
        BAIL_ON_NT_STATUS(ntError);

        memset(&streamDirStat, 0, sizeof(PVFS_STAT));
        if (pszPath)
        {
            LwRtlCStringFree(&pszPath);
        }

        ntError = LwRtlCStringAllocatePrintf(
                      &pszPath,
                      "%s/%s",
                      pszDirname,
                      pDirEntry->d_name);
        BAIL_ON_NT_STATUS(ntError);

        ntError = PvfsSysStat(pszPath, &streamDirStat);
        if (ntError == STATUS_SUCCESS)
        {
            if(S_ISDIR(streamDirStat.s_mode))
            {
                if (!LwRtlCStringIsEqual(pDirEntry->d_name, ".", FALSE) &&
                        !LwRtlCStringIsEqual(pDirEntry->d_name, "..", FALSE))
                {
                    ntError = PvfsSysRemoveDir(pszPath);
                    BAIL_ON_NT_STATUS(ntError);
                }
            }
            else
            {
                ntError = PvfsSysRemove(pszPath);
                BAIL_ON_NT_STATUS(ntError);
            }
        }
        else
        {
            // Squash the error is the stream directory did not exist
            ntError = STATUS_SUCCESS;
        }
    }

    ntError = PvfsSysCloseDir(pDir);
    BAIL_ON_NT_STATUS(ntError);
    pDir = NULL;

    ntError = PvfsSysRemove(pszDirname);
    BAIL_ON_NT_STATUS(ntError);

error:
    if (pszPath)
    {
        LwRtlCStringFree(&pszPath);
    }

    if (pDir)
    {
        PvfsSysCloseDir(pDir);
    }

    return ntError;
}
Пример #3
0
static NTSTATUS
PvfsResolvePath(
    PSTR *ppszResolvedPath,
    PCSTR pszLookupPath
    )
{
    NTSTATUS ntError = STATUS_SUCCESS;
    PSTR pszCursor = NULL;
    PSTR pszComponent = NULL;
    PSTR pszPath = NULL;
    PVFS_STAT Stat = {0};
    PSTR pszResolvedPath = NULL;
    PSTR pszResWorkingPath = NULL;
    PSTR pszWorkingPath = NULL;
    DWORD Length = PATH_MAX;
    DIR *pDir = NULL;
    struct dirent *pDirEntry = NULL;

    if (*pszLookupPath != '/') {
        ntError = STATUS_INVALID_PARAMETER;
        BAIL_ON_NT_STATUS(ntError);
    }

    ntError = RTL_ALLOCATE(&pszResolvedPath, CHAR, Length);
    BAIL_ON_NT_STATUS(ntError);

    ntError = RTL_ALLOCATE(&pszWorkingPath, CHAR, PATH_MAX);
    BAIL_ON_NT_STATUS(ntError);

    ntError = RtlCStringDuplicate(&pszPath, pszLookupPath);
    BAIL_ON_NT_STATUS(ntError);

    pszComponent = pszPath + 1;

    while (pszComponent && (Length > 0))
    {
        pDir = NULL;

        if ((pszCursor = strchr(pszComponent, '/')) != NULL) {
            *pszCursor = '\0';
        }

        snprintf(pszWorkingPath, PATH_MAX-1, "%s/%s",
                 pszResolvedPath, pszComponent);

        /* Try cache first */

        ntError = PvfsPathCacheLookup(&pszResWorkingPath, pszWorkingPath);
        if(ntError == STATUS_SUCCESS)
        {
            strncpy(pszResolvedPath, pszResWorkingPath, PATH_MAX-1);
            Length = PATH_MAX - RtlCStringNumChars(pszResolvedPath);
            RtlCStringFree(&pszResWorkingPath);
        }

        /* Maybe an exact match on disk? */

        else if (PvfsSysStat(pszWorkingPath, &Stat) == STATUS_SUCCESS)
        {
            strncpy(pszResolvedPath, pszWorkingPath, PATH_MAX-1);
            Length = PATH_MAX - RtlCStringNumChars(pszResolvedPath);
            RtlCStringFree(&pszResWorkingPath);

            ntError = PvfsPathCacheAdd(pszResolvedPath);
            BAIL_ON_NT_STATUS(ntError);
        }

        /* Do the work ourselves */

        else
        {
            /* Enumerate directory entries and look for a match */

            ntError = PvfsSysOpenDir(pszResolvedPath, &pDir);
            if (ntError == STATUS_NOT_A_DIRECTORY)
            {
                ntError = STATUS_OBJECT_PATH_NOT_FOUND;
            }
            BAIL_ON_NT_STATUS(ntError);

            for(ntError = PvfsSysReadDir(pDir, &pDirEntry);
                pDirEntry;
                ntError = PvfsSysReadDir(pDir, &pDirEntry))
            {
                /* First check the error return */
                BAIL_ON_NT_STATUS(ntError);

                if (RtlCStringIsEqual(pszComponent, pDirEntry->d_name, FALSE)) {
                    break;
                }
            }

            /* Did we find a match? */

            if (!pDirEntry) {
                /* Return code depends on whether the last component was
                   not found or if an intermediate component was invalid */

                if (pszCursor == NULL)
                {
                    ntError = STATUS_OBJECT_NAME_NOT_FOUND;
                }
                else
                {
                    ntError = STATUS_OBJECT_PATH_NOT_FOUND;
                }

                BAIL_ON_NT_STATUS(ntError);
            }

            strncat(pszResolvedPath, "/", Length-1);
            Length -= 1;
            strncat(pszResolvedPath, pDirEntry->d_name, Length-1);
            Length -= RtlCStringNumChars(pDirEntry->d_name);

            ntError = PvfsSysCloseDir(pDir);
            pDir = NULL;
            BAIL_ON_NT_STATUS(ntError);

            ntError = PvfsPathCacheAdd(pszResolvedPath);
            BAIL_ON_NT_STATUS(ntError);

        }

        /* Cleanup for next loop */


        if (pszCursor) {
            *pszCursor = '/';
        }

        if ((pszComponent = strchr(pszComponent, '/')) != NULL) {
            pszComponent++;
        }
    }

    /* Did we finish? */

    if ((Length <= 0) && (pszComponent != NULL)) {
        ntError = STATUS_NAME_TOO_LONG;
        BAIL_ON_NT_STATUS(ntError);
    }

    *ppszResolvedPath = pszResolvedPath;
    pszResolvedPath = NULL;

    ntError = STATUS_SUCCESS;

cleanup:
    RtlCStringFree(&pszPath);
    RtlCStringFree(&pszWorkingPath);
    RtlCStringFree(&pszResWorkingPath);
    RtlCStringFree(&pszResolvedPath);

    if (pDir) {
        PvfsSysCloseDir(pDir);
    }

    return ntError;

error:
    goto cleanup;
}
Пример #4
0
NTSTATUS
PvfsSysOpenByFileName(
    OUT int *pFd,
    OUT PBOOLEAN pbCreateOwnerFile,
    IN PPVFS_FILE_NAME pFileName,
    IN int iFlags,
    IN mode_t Mode
)
{
    NTSTATUS ntError = STATUS_SUCCESS;
    int fd = -1;
    int unixerr = 0;
    PSTR pszFilename = NULL;
    PVFS_STAT Stat = {0};
    int Ownerfd = -1;
    PSTR pszStreamDirectoryName = NULL;
    PSTR pszMetadataPath = NULL;
    BOOLEAN bCreateOwnerFile = FALSE;

    // Need make sure the object (file/directory) exists
    // Before non-default stream objects can be created
    if (!PvfsIsDefaultStreamName(pFileName))
    {
        ntError = PvfsSysStat(pFileName->FileName, &Stat);
        if (LW_STATUS_OBJECT_NAME_NOT_FOUND == ntError)
        {
            ntError = PvfsSysOpen(
                          &Ownerfd,
                          pFileName->FileName,
                          iFlags,
                          Mode);
            if (STATUS_SUCCESS == ntError)
            {
                bCreateOwnerFile = TRUE;
            }
        }
        BAIL_ON_NT_STATUS(ntError);

        ntError = PvfsLookupStreamDirectoryPath(&pszStreamDirectoryName,
                                                pFileName);
        BAIL_ON_NT_STATUS(ntError);

        ntError = PvfsFileDirname(&pszMetadataPath,
                                  pszStreamDirectoryName);
        BAIL_ON_NT_STATUS(ntError);

        ntError = PvfsSysOpenDir(pszMetadataPath, NULL);
        if (LW_STATUS_OBJECT_NAME_NOT_FOUND == ntError)
        {
            // create meta data directory
            ntError = PvfsSysMkDir(
                          pszMetadataPath,
                          (mode_t)gPvfsDriverConfig.CreateDirectoryMode);
            BAIL_ON_NT_STATUS(ntError);
        }
        BAIL_ON_NT_STATUS(ntError);

        ntError = PvfsSysOpenDir(pszStreamDirectoryName, NULL);
        if (LW_STATUS_OBJECT_NAME_NOT_FOUND == ntError)
        {
            // create stream directory for an object
            ntError = PvfsSysMkDir(
                          pszStreamDirectoryName,
                          (mode_t)gPvfsDriverConfig.CreateDirectoryMode);
            BAIL_ON_NT_STATUS(ntError);
        }
        BAIL_ON_NT_STATUS(ntError);

        ntError = LwRtlCStringAllocatePrintf(
                      &pszFilename,
                      "%s/%s",
                      pszStreamDirectoryName,
                      PvfsGetCStringBaseStreamName(pFileName));
        BAIL_ON_NT_STATUS(ntError);
    }
    else
    {
        ntError = LwRtlCStringDuplicate(&pszFilename,
                                        PvfsGetCStringBaseFileName(pFileName));
        BAIL_ON_NT_STATUS(ntError);
    }

    if ((fd = open(pszFilename, iFlags, Mode)) == -1) {
        PVFS_BAIL_ON_UNIX_ERROR(unixerr, ntError);
    }

    *pFd = fd;
    *pbCreateOwnerFile = bCreateOwnerFile;

cleanup:

    if (pszFilename)
    {
        LwRtlCStringFree(&pszFilename);
    }
    if (pszStreamDirectoryName)
    {
        LwRtlCStringFree(&pszStreamDirectoryName);
    }
    if (pszMetadataPath)
    {
        LwRtlCStringFree(&pszMetadataPath);
    }

    if (Ownerfd != -1)
    {
        PvfsSysClose(Ownerfd);
    }

    return ntError;

error:
    if (fd != -1)
    {
        PvfsSysClose(fd);
    }

    goto cleanup;
}
Пример #5
0
NTSTATUS
PvfsEnumerateDirectory(
    PPVFS_CCB pCcb,
    PIO_MATCH_FILE_SPEC pFileSpec,
    LONG Count,
    BOOLEAN bRescan
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    DIR *pDir = NULL;
    struct dirent *pDirEntry = NULL;
    struct dirent dirEntry = { 0 };
    PSTR pszPattern = NULL;
    BOOLEAN bCaseSensitive = FALSE;
    PSTR pszDiskFilename = NULL;
    PVFS_STAT Stat = { 0 };
    PSTR pszResolvedDirname = NULL;
    PSTR pszResolvedFilename = NULL;

    if (Count == 0)
    {
        ntError = STATUS_INVALID_PARAMETER;
        BAIL_ON_NT_STATUS(ntError);
    }

    ntError = AllocateCStringFileSpec(&pszPattern, pFileSpec);
    BAIL_ON_NT_STATUS(ntError);

    if (bRescan)
    {
        if (pCcb->pDirContext->pDir)
        {
            PvfsSysCloseDir(pCcb->pDirContext->pDir);

        }
        PvfsFreeDirectoryContext(pCcb->pDirContext);
        pCcb->pDirContext = NULL;

        ntError = PvfsAllocateMemory(
                      (PVOID)&pCcb->pDirContext,
                      sizeof(PVFS_DIRECTORY_CONTEXT),
                      TRUE);
        BAIL_ON_NT_STATUS(ntError);

        pCcb->pDirContext->bScanned = FALSE;
    }


    if (!pCcb->pDirContext->bScanned)
    {
        if (!strchr(pszPattern, '?') && !strchr(pszPattern, '*'))
        {
            // A single file name match is the equivalent of a Windows Stat()
            ntError = PvfsLookupFile(
                          &pszDiskFilename,
                          &Stat,
                          pCcb->pScb->pOwnerFcb->pszFilename,
                          pszPattern,
                          pFileSpec->Options & IO_NAME_OPTION_CASE_SENSITIVE);
            BAIL_ON_NT_STATUS(ntError);

            ntError = PvfsFileSplitPath(
                          &pszResolvedDirname,
                          &pszResolvedFilename,
                          pszDiskFilename);
            BAIL_ON_NT_STATUS(ntError);

            if (IsSetFlag(pCcb->Flags, PVFS_CCB_FLAG_ENABLE_ABE))
            {
                ntError = PvfsAccessCheckFileEnumerate(
                              pCcb,
                              pszResolvedFilename);
                BAIL_ON_NT_STATUS(ntError);
            }

            ntError = PvfsDirContextAddEntry(
                          pCcb->pDirContext,
                          pszResolvedFilename);
            BAIL_ON_NT_STATUS(ntError);

            pCcb->pDirContext->bScanned = TRUE;

            // Success
            goto cleanup;
        }
        else
        {
            // Prepare to enumerate the entire directory
            ntError = PvfsSysOpenDir(
                          pCcb->pScb->pOwnerFcb->pszFilename,
                          &pCcb->pDirContext->pDir);
            BAIL_ON_NT_STATUS(ntError);

            pCcb->pDirContext->bScanned = TRUE;
        }
    }

    /* Loop to read entries */

    pDir = pCcb->pDirContext->pDir;

    /* -1 means to fill in whatever you can including current and
       parent directory entries */

    if (Count == -1)
    {
        /* Always add '.' and '..' first if thet match */

        if (PvfsWildcardMatch(".", pszPattern, FALSE))
        {
            ntError = PvfsDirContextAddEntry(pCcb->pDirContext, ".");
            BAIL_ON_NT_STATUS(ntError);
        }
        if (PvfsWildcardMatch("..", pszPattern, FALSE))
        {
            ntError = PvfsDirContextAddEntry(pCcb->pDirContext, "..");
            BAIL_ON_NT_STATUS(ntError);
        }
    }

    /* Loop through directory entries */

    for(ntError = PvfsSysReadDir(pDir, &dirEntry, &pDirEntry);
        pDirEntry && ((Count == -1) || (pCcb->pDirContext->dwNumEntries < Count));
        ntError = PvfsSysReadDir(pDir, &dirEntry, &pDirEntry))
    {
        /* First check the error return */
        BAIL_ON_NT_STATUS(ntError);

        /* We've already added the "." and ".." directories */

        if (RtlCStringIsEqual(pDirEntry->d_name, ".", FALSE) ||
            RtlCStringIsEqual(pDirEntry->d_name, "..", FALSE))
        {
            continue;
        }

        if (PvfsWildcardMatch(pDirEntry->d_name, pszPattern, bCaseSensitive))
        {
            if (IsSetFlag(pCcb->Flags, PVFS_CCB_FLAG_ENABLE_ABE))
            {
                ntError = PvfsAccessCheckFileEnumerate(
                              pCcb,
                              pDirEntry->d_name);
                if (ntError != STATUS_SUCCESS)
                {
                    continue;
                }
            }

            ntError = PvfsDirContextAddEntry(pCcb->pDirContext, pDirEntry->d_name);
            BAIL_ON_NT_STATUS(ntError);
        }
    }

    /* Bail if there were no matches */

    if (pCcb->pDirContext->dwNumEntries == 0) {
        ntError = STATUS_NO_SUCH_FILE;
        BAIL_ON_NT_STATUS(ntError);
    }

cleanup:
    RtlCStringFree(&pszResolvedFilename);
    RtlCStringFree(&pszResolvedDirname);
    RtlCStringFree(&pszDiskFilename);
    RtlCStringFree(&pszPattern);

    return ntError;

error:
    goto cleanup;
}