예제 #1
0
VOID
PvfsFreeCreateContext(
    IN OUT PVOID *ppContext
    )
{
    PPVFS_PENDING_CREATE pCreateCtx = NULL;

    if (ppContext && *ppContext)
    {
        pCreateCtx = (PPVFS_PENDING_CREATE)*ppContext;

        if (pCreateCtx->pIrpContext)
        {
            PvfsReleaseIrpContext(&pCreateCtx->pIrpContext);
        }

        if (pCreateCtx->pCcb)
        {
            PvfsReleaseCCB(pCreateCtx->pCcb);
        }

        if (pCreateCtx->pFcb)
        {
            PvfsReleaseFCB(&pCreateCtx->pFcb);
        }

        RtlCStringFree(&pCreateCtx->pszDiskFilename);
        RtlCStringFree(&pCreateCtx->pszOriginalFilename);

        PVFS_FREE(ppContext);
    }

    return;
}
예제 #2
0
NTSTATUS
LwRtlAnsiStringAllocateFromUnicodeString(
    OUT PANSI_STRING pNewString,
    IN PUNICODE_STRING pString
    )
{
    NTSTATUS status = 0;
    PSTR pszNewString = NULL;
    ANSI_STRING newString = { 0 };

    status = RtlCStringDuplicate(&pszNewString, pszString);
    GOTO_CLEANUP_ON_STATUS(status);

    newString.Buffer = pszNewString;
    pszNewString = 0;
    newString.Length = wc16slen(newString.Buffer) * sizeof(newString.Buffer[0]);
    newString.MaximumLength = newString.Length + sizeof(newString.Buffer[0]);

cleanup:
    if (status)
    {
        RtlCStringFree(&pszNewString);
        RtlAnsiStringFree(&newString);
    }

    *pString = newString;

    return status;
}
예제 #3
0
NTSTATUS
LwRtlAnsiStringAllocateFromCString(
    OUT PANSI_STRING pNewString,
    IN PCSTR pszString
    )
{
    NTSTATUS status = 0;
    PSTR pszNewString = NULL;
    ANSI_STRING newString = { 0 };

    status = RtlCStringDuplicate(&pszNewString, pszString);
    GOTO_CLEANUP_ON_STATUS(status);

    status = LwRtlAnsiStringInitEx(&newString, pszNewString);
    GOTO_CLEANUP_ON_STATUS(status);

    pszNewString = 0;

cleanup:
    if (status)
    {
        RtlCStringFree(&pszNewString);
        RtlAnsiStringFree(&newString);
    }

    *pNewString = newString;

    return status;
}
예제 #4
0
파일: fcb.c 프로젝트: bhanug/likewise-open
static
VOID
PvfsFreeFCB(
    PPVFS_FCB pFcb
    )
{
    if (pFcb)
    {
        LWIO_ASSERT(pFcb->BaseControlBlock.pBucket == NULL);
        LWIO_ASSERT(pFcb->BaseControlBlock.RefCount == 0);

        if (pFcb->pParentFcb)
        {
            PvfsReleaseFCB(&pFcb->pParentFcb);
        }

        RtlCStringFree(&pFcb->pszFilename);

        pthread_rwlock_destroy(&pFcb->rwScbLock);

        PvfsListDestroy(&pFcb->pScbList);
        PvfsListDestroy(&pFcb->pNotifyListIrp);
        PvfsListDestroy(&pFcb->pNotifyListBuffer);

        PvfsDestroyCB(&pFcb->BaseControlBlock);

        PVFS_FREE(&pFcb);

        InterlockedDecrement(&gPvfsDriverState.Counters.Fcb);
    }

    return;
}
예제 #5
0
NTSTATUS
PvfsLookupFile(
    PSTR *ppszDiskPath,
    PCSTR pszDiskDirname,
    PCSTR pszFilename,
    BOOLEAN bCaseSensitive
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    PSTR pszFullPath = NULL;

    ntError = RtlCStringAllocatePrintf(&pszFullPath,
                                       "%s/%s",
                                       pszDiskDirname,
                                       pszFilename);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsLookupPath(ppszDiskPath, pszFullPath, bCaseSensitive);
    BAIL_ON_NT_STATUS(ntError);

cleanup:
    RtlCStringFree(&pszFullPath);

    return ntError;

error:
    goto cleanup;
}
예제 #6
0
VOID
PvfsFreeDirectoryContext(
    PPVFS_DIRECTORY_CONTEXT pDirCtx
    )
{
    int i = 0;

    if (!pDirCtx) {
        return;
    }

    for (i=0; i<pDirCtx->dwNumEntries; i++)
    {
        RtlCStringFree(&pDirCtx->pDirEntries[i].pszFilename);
    }


    PVFS_FREE(&pDirCtx->pDirEntries);
    PVFS_FREE(&pDirCtx);

    return;
}
예제 #7
0
NTSTATUS
PvfsCreate(
    PPVFS_IRP_CONTEXT  pIrpContext
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    FILE_CREATE_OPTIONS CreateOptions = 0;
    BOOLEAN bIsDirectory = FALSE;
    PIRP pIrp = pIrpContext->pIrp;
    PSTR pszFilename = NULL;
    PSTR pszDiskFilename = NULL;
    PVFS_STAT Stat = {0};
    FILE_CREATE_OPTIONS FileDirCombo = (FILE_DIRECTORY_FILE|
                                        FILE_NON_DIRECTORY_FILE);


    /* Check to see if this is a Device Create (i.e. NULL RootFileHandle
       and empty Filename) */

    if (!pIrp->Args.Create.FileName.RootFileHandle &&
        pIrp->Args.Create.FileName.FileName &&
        *pIrp->Args.Create.FileName.FileName == '\0')
    {
        ntError = PvfsCreateDevice(pIrpContext);
        BAIL_ON_NT_STATUS(ntError);

        goto cleanup;
    }

    /* Regular File/Directory Create() */

    CreateOptions = pIrp->Args.Create.CreateOptions;

    if (((CreateOptions & ~FILE_CREATE_OPTIONS_VALID) != 0))
    {
        ntError = STATUS_INVALID_PARAMETER;
        BAIL_ON_NT_STATUS(ntError);
    }

    if ((CreateOptions & FileDirCombo) == FileDirCombo)
    {
        ntError = STATUS_INVALID_PARAMETER;
        BAIL_ON_NT_STATUS(ntError);
    }

    if (CreateOptions & FILE_DIRECTORY_FILE)
    {
        bIsDirectory = TRUE;
    }
    else if (CreateOptions & FILE_NON_DIRECTORY_FILE)
    {
        bIsDirectory = FALSE;
    }
    else
    {
        /* stat() the path and find out if this is a file or directory */

        ntError = PvfsCanonicalPathName(
                      &pszFilename,
                      pIrp->Args.Create.FileName);
        BAIL_ON_NT_STATUS(ntError);

        ntError = PvfsLookupPath(&pszDiskFilename, pszFilename, FALSE);

        /* The path lookup may fail which is ok.  We'll catch whether
           or not this is a real error later on */

        if (ntError == STATUS_SUCCESS)
        {
            ntError = PvfsSysStat(pszDiskFilename, &Stat);

            bIsDirectory = (ntError == STATUS_SUCCESS) ?
                           S_ISDIR(Stat.s_mode) : FALSE;
        }
    }

    if (bIsDirectory)
    {
        pIrp->Args.Create.CreateOptions |= FILE_DIRECTORY_FILE;
        ntError = PvfsCreateDirectory(pIrpContext);
    }
    /* File branch */
    else
    {
        pIrp->Args.Create.CreateOptions |= FILE_NON_DIRECTORY_FILE;
        ntError = PvfsCreateFile(pIrpContext);
    }
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsSetMaximalAccessMask(pIrp);
    BAIL_ON_NT_STATUS(ntError);

cleanup:
    RtlCStringFree(&pszFilename);
    RtlCStringFree(&pszDiskFilename);

    return ntError;

error:
    goto cleanup;
}
예제 #8
0
static NTSTATUS
FillFileIdFullDirInfoBuffer(
    PVOID pBuffer,
    DWORD dwBufLen,
    PSTR pszParent,
    PPVFS_DIRECTORY_ENTRY pEntry,
    PDWORD pdwConsumed
    )
{
    NTSTATUS ntError = STATUS_UNSUCCESSFUL;
    PFILE_ID_FULL_DIR_INFORMATION pFileInfo = (PFILE_ID_FULL_DIR_INFORMATION)pBuffer;
    PWSTR pwszFilename = NULL;
    PSTR pszFullPath = NULL;
    DWORD dwNeeded = 0;
    size_t W16FilenameLen = 0;
    size_t W16FilenameLenBytes = 0;

    /* Check for enough space for static members */

    if (dwBufLen < sizeof(*pFileInfo))
    {
        ntError = STATUS_BUFFER_TOO_SMALL;
        BAIL_ON_NT_STATUS(ntError);
    }

    /* Build the absolute path and stat() it */

    ntError = RtlCStringAllocatePrintf(
                  &pszFullPath,
                  "%s/%s",
                  pszParent,
                  pEntry->pszFilename);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsSysStat(pszFullPath, &pEntry->Stat);
    BAIL_ON_NT_STATUS(ntError);

    ntError = RtlWC16StringAllocateFromCString(
                  &pwszFilename,
                  pEntry->pszFilename);
    BAIL_ON_NT_STATUS(ntError);

    ntError = FillFileIdFullDirInfoStatic(
                  pFileInfo,
                  pwszFilename,
                  &pEntry->Stat);
    BAIL_ON_NT_STATUS(ntError);

    /* We have more information here to fill in the
       file attributes */

    ntError = PvfsGetFilenameAttributes(
                  pszFullPath,
                  &pFileInfo->FileAttributes);
    BAIL_ON_NT_STATUS(ntError);

    /* Save what we have used so far */

    *pdwConsumed = sizeof(*pFileInfo);

    /* Calculate space */

    W16FilenameLen = RtlWC16StringNumChars(pwszFilename);
    W16FilenameLenBytes = W16FilenameLen * sizeof(WCHAR);
    dwNeeded = sizeof(*pFileInfo) + W16FilenameLenBytes;

    /* alignment on 8 byte boundary */

    if (dwNeeded % 8) {
        dwNeeded += 8 - (dwNeeded % 8);
    }

    if (dwNeeded > dwBufLen)
    {
        ntError = STATUS_BUFFER_TOO_SMALL;
        BAIL_ON_NT_STATUS(ntError);
    }

    pFileInfo->FileNameLength = W16FilenameLenBytes;
    memcpy(pFileInfo->FileName, pwszFilename, W16FilenameLenBytes);

    *pdwConsumed = dwNeeded;
    ntError = STATUS_SUCCESS;

cleanup:
    RtlCStringFree(&pszFullPath);
    RtlWC16StringFree(&pwszFilename);

    return ntError;

error:
    goto cleanup;
}
예제 #9
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;
}
예제 #10
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;
}
예제 #11
0
NTSTATUS
PvfsCreateFileSecurity(
    PACCESS_TOKEN pUserToken,
    PPVFS_CCB pCcb,
    PSECURITY_DESCRIPTOR_RELATIVE pSecurityDescriptor,
    BOOLEAN bIsDirectory
    )
{
    NTSTATUS ntError = STATUS_SUCCESS;
    PSTR pszParentPath = NULL;
    PSTR pszBaseFilename = NULL;
    PSECURITY_DESCRIPTOR_RELATIVE pFinalSecDesc = NULL;
    ULONG FinalSecDescLength = 0;
    BYTE ParentSecDescBuffer[SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE];
    ULONG ParentSecDescLength = SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE;
    SECURITY_INFORMATION SecInfoAll = (OWNER_SECURITY_INFORMATION |
                                       GROUP_SECURITY_INFORMATION |
                                       DACL_SECURITY_INFORMATION  |
                                       SACL_SECURITY_INFORMATION);
    BYTE DefaultSecDescBuffer[SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE];
    ULONG DefaultSecDescLength = SECURITY_DESCRIPTOR_RELATIVE_MAX_SIZE;

    LwRtlZeroMemory(ParentSecDescBuffer, ParentSecDescLength);
    LwRtlZeroMemory(DefaultSecDescBuffer, DefaultSecDescLength);

    ntError = PvfsFileSplitPath(
                  &pszParentPath,
                  &pszBaseFilename,
                  pCcb->pszFilename);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsGetSecurityDescriptorFilename(
                  pszParentPath,
                  SecInfoAll,
                  (PSECURITY_DESCRIPTOR_RELATIVE)ParentSecDescBuffer,
                  &ParentSecDescLength);
    BAIL_ON_NT_STATUS(ntError);

    ntError = RtlCreatePrivateObjectSecurityEx(
                  (PSECURITY_DESCRIPTOR_RELATIVE)ParentSecDescBuffer,
                  pSecurityDescriptor,
                  &pFinalSecDesc,
                  &FinalSecDescLength,
                  NULL,
                  bIsDirectory,
                  SEF_DACL_AUTO_INHERIT|SEF_SACL_AUTO_INHERIT,
                  pUserToken,
                  &gPvfsFileGenericMapping);
    BAIL_ON_NT_STATUS(ntError);

    ntError = PvfsSetSecurityDescriptorFile(
                  pCcb,
                  SecInfoAll,
                  pFinalSecDesc,
                  FinalSecDescLength);
    BAIL_ON_NT_STATUS(ntError);

cleanup:
    LW_RTL_FREE(&pFinalSecDesc);
    RtlCStringFree(&pszParentPath);
    RtlCStringFree(&pszBaseFilename);

    return ntError;

error:
    goto cleanup;
}