/* Editor Settings: expandtabs and use 4 spaces for indentation
* ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: *
* -*- mode: c, c-basic-offset: 4 -*- */
/*
* Copyright Likewise Software 2004-2008
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details. You should have received a copy of the GNU General
* Public License along with this program. If not, see
* .
*
* LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING
* TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT
* WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE
* TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU
* GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU
* HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING
* TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT
* license@likewisesoftware.com
*/
/*
* Copyright (C) Likewise Software. All rights reserved.
*
* Module Name:
*
* main.c
*
* Abstract:
*
* Likewise IO (LWIO)
*
* Test Program for exercising the PVFS driver
*
* Authors: Gerald Carter
*
*/
#include "includes.h"
/***********************************************************************
**********************************************************************/
int
main(
int argc,
char *argv[]
)
{
NTSTATUS ntError = STATUS_UNSUCCESSFUL;
/* Check Arg count */
if (argc <= 1) {
PrintUsage(argv[0]);
ntError = STATUS_INVALID_PARAMETER;
BAIL_ON_NT_STATUS(ntError);
}
/* Process Args */
if (strcmp(argv[1], "-c") == 0)
{
ntError = CopyFileToPvfs(argc-2, argv+2);
}
else if (strcmp(argv[1], "-C") == 0)
{
ntError = CopyFileFromPvfs(argc-2, argv+2);
}
else if (strcmp(argv[1], "--cat") == 0)
{
ntError = CatFileFromPvfs(argv[2]);
}
else if (strcmp(argv[1], "--notify") == 0)
{
ntError = TestReadDirectoryChange(argv[2]);
}
else if (strcmp(argv[1], "-O") == 0)
{
ntError = RequestOplock(argc-2, argv+2);
}
else if (strcmp(argv[1], "-S") == 0)
{
ntError = StatRemoteFile(argv[2]);
}
else if (strcmp(argv[1], "-F") == 0)
{
ntError = SetEndOfFile(argc-2, argv+2);
}
else if (strcmp(argv[1], "-D") == 0)
{
ntError = DeletePath(argv[2]);
}
else if (strcmp(argv[1], "-l") == 0)
{
char *filter = NULL;
if ((argc-2) > 1) {
filter = argv[3];
}
ntError = ListDirectory(argv[2], filter);
}
else if (strcmp(argv[1], "-L") == 0)
{
ntError = LockTest(argv[2]);
}
else if (strcmp(argv[1], "--ls-open-files") == 0)
{
ntError = ListOpenFiles(argv[2]);
}
else if (strcmp(argv[1], "--max-open-files") == 0)
{
ntError = PrintMaxOpenFiles();
}
else
{
PrintUsage(argv[0]);
ntError = STATUS_INVALID_PARAMETER;
}
BAIL_ON_NT_STATUS(ntError);
cleanup:
if (ntError != STATUS_SUCCESS)
{
printf("Final NTSTATUS was %s (%s)\n",
NtStatusToDescription(ntError),
NtStatusToName(ntError));
}
return ntError == STATUS_SUCCESS;
error:
goto cleanup;
}
/***********************************************************************
**********************************************************************/
void
PrintUsage(
char *pszProgName
)
{
fprintf(stderr, "Usage: %s [command options]\n", pszProgName);
fprintf(stderr, "(All pvfs files should be given in the format \"/pvfs/path/...\")\n");
fprintf(stderr, " -c Copy src to the Pvfs dst file\n");
fprintf(stderr, " -C Copy the pvfs src file to the local dst file\n");
fprintf(stderr, " -S Stat a Pvfs path (directory or file)\n");
fprintf(stderr, " -l List the files in a directory\n");
fprintf(stderr, " -F Set the end-of-file\n");
fprintf(stderr, " -D Delete a file or directory using delete-on-close\n");
fprintf(stderr, " -L Locking Tests\n");
fprintf(stderr, " -O Oplock Test\n");
fprintf(stderr, " --ls-open-files List open files\n");
fprintf(stderr, " --max-open-files Print the maximum number of concurrent open fds\n");
fprintf(stderr, "\n");
return;
}
/***********************************************************************
**********************************************************************/
NTSTATUS
CopyFileToPvfs(
int argc,
char *argv[]
)
{
NTSTATUS ntError = STATUS_UNSUCCESSFUL;
IO_FILE_HANDLE hFile = NULL;
IO_STATUS_BLOCK StatusBlock = {0};
IO_FILE_NAME DstFilename = {0};
PSTR pszSrcPath = NULL;
PSTR pszDstPath = NULL;
size_t bytes = 0;
int fd = -1;
BYTE pBuffer[1024];
if (argc != 2)
{
fprintf(stderr, "Missing parameters. Requires and \n");
ntError = STATUS_INVALID_PARAMETER;
BAIL_ON_NT_STATUS(ntError);
}
pszSrcPath = argv[0];
pszDstPath = argv[1];
ntError = RtlWC16StringAllocateFromCString(&DstFilename.FileName, pszDstPath);
BAIL_ON_NT_STATUS(ntError);
/* Open the remote Destination file */
ntError = NtCreateFile(&hFile,
NULL,
&StatusBlock,
&DstFilename,
NULL,
NULL,
FILE_GENERIC_WRITE,
0,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OVERWRITE,
FILE_NON_DIRECTORY_FILE,
NULL,
0,
NULL);
BAIL_ON_NT_STATUS(ntError);
/* Open the local source */
if ((fd = open(pszSrcPath, O_RDONLY, 0)) == -1)
{
fprintf(stderr, "Failed to open local file \"%s\" for copy (%s).\n",
pszDstPath, strerror(errno));
ntError = STATUS_UNSUCCESSFUL;
BAIL_ON_NT_STATUS(ntError);
}
/* Copy the file */
do {
if ((bytes = read(fd, pBuffer, sizeof(pBuffer))) == -1)
{
fprintf(stderr, "Read failed! (%s)\n", strerror(errno));
ntError = STATUS_UNSUCCESSFUL;
BAIL_ON_NT_STATUS(ntError);
}
if (bytes == 0) {
break;
}
ntError = NtWriteFile(hFile,
NULL,
&StatusBlock,
pBuffer,
bytes,
0, 0);
BAIL_ON_NT_STATUS(ntError);
} while (bytes != 0);
close(fd);
ntError = NtCloseFile(hFile);
BAIL_ON_NT_STATUS(ntError);
cleanup:
return ntError;
error:
if (hFile) {
NtCloseFile(hFile);
}
if (fd != -1) {
close(fd);
}
goto cleanup;
}
/***********************************************************************
**********************************************************************/
NTSTATUS
CopyFileFromPvfs(
int argc,
char *argv[]
)
{
NTSTATUS ntError = STATUS_UNSUCCESSFUL;
IO_FILE_HANDLE hFile = NULL;
IO_STATUS_BLOCK StatusBlock = {0};
IO_FILE_NAME SrcFilename = {0};
PSTR pszSrcPath = NULL;
PSTR pszDstPath = NULL;
size_t bytes = 0;
int fd = -1;
BYTE pBuffer[1024];
if (argc != 2)
{
fprintf(stderr, "Missing parameters. Requires and \n");
ntError = STATUS_INVALID_PARAMETER;
BAIL_ON_NT_STATUS(ntError);
}
pszSrcPath = argv[0];
pszDstPath = argv[1];
ntError = RtlWC16StringAllocateFromCString(&SrcFilename.FileName, pszSrcPath);
BAIL_ON_NT_STATUS(ntError);
/* Open the remote source file */
ntError = NtCreateFile(&hFile,
NULL,
&StatusBlock,
&SrcFilename,
NULL,
NULL,
FILE_GENERIC_READ,
0,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE,
NULL,
0,
NULL);
BAIL_ON_NT_STATUS(ntError);
/* Open the local destination */
if ((fd = open(pszDstPath, O_WRONLY | O_TRUNC | O_CREAT, 0666)) == -1)
{
fprintf(stderr, "Failed to open local file \"%s\" for copy (%s).\n",
pszDstPath, strerror(errno));
ntError = STATUS_UNSUCCESSFUL;
BAIL_ON_NT_STATUS(ntError);
}
/* Copy the file */
do {
ntError = NtReadFile(hFile,
NULL,
&StatusBlock,
pBuffer,
sizeof(pBuffer),
NULL, NULL);
BAIL_ON_NT_STATUS(ntError);
if (StatusBlock.BytesTransferred == 0) {
break;
}
if ((bytes = write(fd, pBuffer, StatusBlock.BytesTransferred)) == -1)
{
fprintf(stderr, "Write failed! (%s)\n", strerror(errno));
ntError = STATUS_UNSUCCESSFUL;
BAIL_ON_NT_STATUS(ntError);
}
} while (bytes != 0);
close(fd);
ntError = NtCloseFile(hFile);
BAIL_ON_NT_STATUS(ntError);
cleanup:
return ntError;
error:
if (hFile) {
NtCloseFile(hFile);
}
if (fd != -1) {
close(fd);
}
goto cleanup;
}
/***********************************************************************
**********************************************************************/
NTSTATUS
CatFileFromPvfs(
char *pszFilename
)
{
NTSTATUS ntError = STATUS_UNSUCCESSFUL;
IO_FILE_HANDLE hFile = NULL;
IO_STATUS_BLOCK StatusBlock = {0};
IO_FILE_NAME SrcFilename = {0};
size_t bytes = 0;
int fd = -1;
BYTE pBuffer[1024];
ntError = RtlWC16StringAllocateFromCString(&SrcFilename.FileName, pszFilename);
BAIL_ON_NT_STATUS(ntError);
/* Open the remote source file */
ntError = NtCreateFile(&hFile,
NULL,
&StatusBlock,
&SrcFilename,
NULL,
NULL,
FILE_GENERIC_READ,
0,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE,
NULL,
0,
NULL);
BAIL_ON_NT_STATUS(ntError);
/* Read the file */
do {
ntError = NtReadFile(hFile,
NULL,
&StatusBlock,
pBuffer,
sizeof(pBuffer),
NULL, NULL);
if (ntError == STATUS_END_OF_FILE) {
ntError = STATUS_SUCCESS;
break;
}
BAIL_ON_NT_STATUS(ntError);
if (StatusBlock.BytesTransferred == 0) {
break;
}
if ((bytes = write(1, pBuffer, StatusBlock.BytesTransferred)) == -1)
{
fprintf(stderr, "Write failed! (%s)\n", strerror(errno));
ntError = STATUS_UNSUCCESSFUL;
BAIL_ON_NT_STATUS(ntError);
}
} while (bytes != 0);
ntError = NtCloseFile(hFile);
BAIL_ON_NT_STATUS(ntError);
cleanup:
return ntError;
error:
if (hFile) {
NtCloseFile(hFile);
}
if (fd != -1) {
close(fd);
}
goto cleanup;
}
/***********************************************************************
**********************************************************************/
NTSTATUS
StatRemoteFile(
char *pszFilename
)
{
NTSTATUS ntError = STATUS_UNSUCCESSFUL;
FILE_BASIC_INFORMATION FileBasicInfo = {0};
FILE_STANDARD_INFORMATION FileStdInfo = {0};
FILE_INTERNAL_INFORMATION FileInternalInfo = {0};
IO_FILE_NAME Filename = {0};
IO_FILE_HANDLE hFile = NULL;
IO_STATUS_BLOCK StatusBlock = {0};
ntError = RtlWC16StringAllocateFromCString(&Filename.FileName,
pszFilename);
BAIL_ON_NT_STATUS(ntError);
ntError = NtCreateFile(&hFile,
NULL,
&StatusBlock,
&Filename,
NULL,
NULL,
FILE_GENERIC_READ,
0,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE,
NULL,
0,
NULL);
BAIL_ON_NT_STATUS(ntError);
ntError = NtQueryInformationFile(hFile,
NULL,
&StatusBlock,
&FileBasicInfo,
sizeof(FileBasicInfo),
FileBasicInformation);
BAIL_ON_NT_STATUS(ntError);
ntError = NtQueryInformationFile(hFile,
NULL,
&StatusBlock,
&FileStdInfo,
sizeof(FileStdInfo),
FileStandardInformation);
BAIL_ON_NT_STATUS(ntError);
ntError = NtQueryInformationFile(hFile,
NULL,
&StatusBlock,
&FileInternalInfo,
sizeof(FileInternalInfo),
FileInternalInformation);
BAIL_ON_NT_STATUS(ntError);
ntError = NtCloseFile(hFile);
BAIL_ON_NT_STATUS(ntError);
printf("Filename: %s\n", pszFilename);
printf("CreationTime: %lld\n", (long long) FileBasicInfo.CreationTime);
printf("Last Access Time: %lld\n", (long long) FileBasicInfo.LastAccessTime);
printf("Last Modification: %lld\n", (long long) FileBasicInfo.LastWriteTime);
printf("Change Time: %lld\n", (long long) FileBasicInfo.ChangeTime);
printf("Allocation Size: %lld\n", (long long) FileStdInfo.AllocationSize);
printf("File Size: %lld\n", (long long) FileStdInfo.EndOfFile);
printf("Number of Links: %d\n", FileStdInfo.NumberOfLinks);
printf("Is Directory: %s\n", FileStdInfo.Directory ? "yes" : "no");
printf("Pending Delete: %s\n", FileStdInfo.DeletePending ? "yes" : "no");
printf("Attributes: 0x%x\n", FileBasicInfo.FileAttributes);
printf("Index Number: %lld\n", (long long) FileInternalInfo.IndexNumber);
printf("\n");
cleanup:
return ntError;
error:
goto cleanup;
}
/***********************************************************************
**********************************************************************/
VOID
PrintFileBothDirInformation(
PFILE_BOTH_DIR_INFORMATION pFileInfo
)
{
NTSTATUS ntError;
PSTR pszFilename = NULL;
PSTR pszShortFilename = NULL;
ntError = RtlCStringAllocateFromWC16String(&pszFilename,
pFileInfo->FileName);
BAIL_ON_NT_STATUS(ntError);
ntError = RtlCStringAllocateFromWC16String(&pszShortFilename,
pFileInfo->ShortName);
BAIL_ON_NT_STATUS(ntError);
printf("Filename: %s\n", pszFilename);
printf("8.3 Filename: %s\n", pszShortFilename);
printf("CreationTime: %lld\n", (long long) pFileInfo->CreationTime);
printf("Last Access Time: %lld\n", (long long) pFileInfo->LastAccessTime);
printf("Last Modification: %lld\n", (long long) pFileInfo->LastWriteTime);
printf("Change Time: %lld\n", (long long) pFileInfo->ChangeTime);
printf("Allocation Size: %lld\n", (long long) pFileInfo->AllocationSize);
printf("File Size: %lld\n", (long long) pFileInfo->EndOfFile);
printf("Attributes: 0x%x\n", pFileInfo->FileAttributes);
printf("EA Size: %d\n", pFileInfo->EaSize);
printf("\n");
cleanup:
return;
error:
goto cleanup;
}
/***********************************************************************
**********************************************************************/
NTSTATUS
ListDirectory(
char *pszDirectory,
char *pszPattern
)
{
NTSTATUS ntError = STATUS_UNSUCCESSFUL;
IO_FILE_NAME Dirname = {0};
IO_FILE_HANDLE hDir = NULL;
IO_STATUS_BLOCK StatusBlock = {0};
PFILE_BOTH_DIR_INFORMATION pFileInfo = NULL;
PVOID pBuffer = NULL;
DWORD dwBufLen = 0;
IO_MATCH_FILE_SPEC FileSpec = { 0 };
ntError = RtlWC16StringAllocateFromCString(&Dirname.FileName,
pszDirectory);
BAIL_ON_NT_STATUS(ntError);
ntError = NtCreateFile(&hDir,
NULL,
&StatusBlock,
&Dirname,
NULL,
NULL,
FILE_GENERIC_READ,
0,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN,
FILE_DIRECTORY_FILE,
NULL,
0,
NULL);
BAIL_ON_NT_STATUS(ntError);
/* Allocate the buffer. Include space for four files including
256 WCHAR length filename */
dwBufLen = (sizeof(FILE_BOTH_DIR_INFORMATION) + (sizeof(WCHAR)*256)) * 4;
ntError = RTL_ALLOCATE(&pBuffer, VOID, dwBufLen);
BAIL_ON_NT_STATUS(ntError);
if (pszPattern) {
ntError = LwRtlUnicodeStringAllocateFromCString(&FileSpec.Pattern, pszPattern);
BAIL_ON_NT_STATUS(ntError);
}
do
{
memset(pBuffer, 0x0, dwBufLen);
ntError = NtQueryDirectoryFile(hDir,
NULL,
&StatusBlock,
pBuffer,
dwBufLen,
FileBothDirectoryInformation,
FALSE, /* ignored */
pszPattern ? &FileSpec : NULL,
FALSE);
BAIL_ON_NT_STATUS(ntError);
pFileInfo = (PFILE_BOTH_DIR_INFORMATION)pBuffer;
while (pFileInfo != NULL)
{
PrintFileBothDirInformation(pFileInfo);
pFileInfo = (pFileInfo->NextEntryOffset != 0) ?
(PVOID)pFileInfo + pFileInfo->NextEntryOffset :
NULL;
}
} while (NT_SUCCESS(ntError));
ntError = NtCloseFile(hDir);
hDir = (IO_FILE_HANDLE)NULL;
BAIL_ON_NT_STATUS(ntError);
cleanup:
if (Dirname.FileName) {
RtlMemoryFree(Dirname.FileName);
}
return ntError;
error:
if (hDir) {
NtCloseFile(hDir);
}
goto cleanup;
}
/***********************************************************************
**********************************************************************/
NTSTATUS
DeletePath(
char *pszPath
)
{
NTSTATUS ntError = STATUS_UNSUCCESSFUL;
BAIL_ON_NT_STATUS(ntError);
cleanup:
return ntError;
error:
goto cleanup;
}
/***********************************************************************
**********************************************************************/
NTSTATUS
SetEndOfFile(
int argc,
char *argv[]
)
{
NTSTATUS ntError = STATUS_UNSUCCESSFUL;
FILE_BASIC_INFORMATION FileBasicInfo = {0};
FILE_STANDARD_INFORMATION FileStdInfo = {0};
FILE_INTERNAL_INFORMATION FileInternalInfo = {0};
FILE_END_OF_FILE_INFORMATION FileEndOfFileInfo = {0};
IO_FILE_NAME Filename = {0};
IO_FILE_HANDLE hFile = NULL;
IO_STATUS_BLOCK StatusBlock = {0};
LONG64 EndOfFile = 0;
PSTR pszFilename = NULL;
char *p = NULL;
if (argc != 2)
{
fprintf(stderr, "Missing parameters. Requires and \n");
ntError = STATUS_INVALID_PARAMETER;
BAIL_ON_NT_STATUS(ntError);
}
pszFilename = argv[0];
EndOfFile = strtol(argv[1], &p, 10);
ntError = RtlWC16StringAllocateFromCString(&Filename.FileName,
pszFilename);
BAIL_ON_NT_STATUS(ntError);
ntError = NtCreateFile(&hFile,
NULL,
&StatusBlock,
&Filename,
NULL,
NULL,
FILE_GENERIC_WRITE,
0,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN_IF,
FILE_NON_DIRECTORY_FILE,
NULL,
0,
NULL);
BAIL_ON_NT_STATUS(ntError);
FileEndOfFileInfo.EndOfFile = EndOfFile;
ntError = NtSetInformationFile(hFile,
NULL,
&StatusBlock,
&FileEndOfFileInfo,
sizeof(FileEndOfFileInfo),
FileEndOfFileInformation);
BAIL_ON_NT_STATUS(ntError);
ntError = NtQueryInformationFile(hFile,
NULL,
&StatusBlock,
&FileBasicInfo,
sizeof(FileBasicInfo),
FileBasicInformation);
BAIL_ON_NT_STATUS(ntError);
ntError = NtQueryInformationFile(hFile,
NULL,
&StatusBlock,
&FileStdInfo,
sizeof(FileStdInfo),
FileStandardInformation);
BAIL_ON_NT_STATUS(ntError);
ntError = NtQueryInformationFile(hFile,
NULL,
&StatusBlock,
&FileInternalInfo,
sizeof(FileInternalInfo),
FileInternalInformation);
BAIL_ON_NT_STATUS(ntError);
ntError = NtCloseFile(hFile);
BAIL_ON_NT_STATUS(ntError);
printf("Filename: %s\n", pszFilename);
printf("CreationTime: %lld\n", (long long) FileBasicInfo.CreationTime);
printf("Last Access Time: %lld\n", (long long) FileBasicInfo.LastAccessTime);
printf("Last Modification: %lld\n", (long long) FileBasicInfo.LastWriteTime);
printf("Change Time: %lld\n", (long long) FileBasicInfo.ChangeTime);
printf("Allocation Size: %lld\n", (long long) FileStdInfo.AllocationSize);
printf("File Size: %lld\n", (long long) FileStdInfo.EndOfFile);
printf("Number of Links: %d\n", FileStdInfo.NumberOfLinks);
printf("Is Directory: %s\n", FileStdInfo.Directory ? "yes" : "no");
printf("Pending Delete: %s\n", FileStdInfo.DeletePending ? "yes" : "no");
printf("Attributes: 0x%x\n", FileBasicInfo.FileAttributes);
printf("Index Number: %lld\n", (long long) FileInternalInfo.IndexNumber);
printf("\n");
cleanup:
return ntError;
error:
goto cleanup;
}
/***********************************************************************
**********************************************************************/
NTSTATUS
LockTest(
char *pszPath
)
{
NTSTATUS ntError = STATUS_UNSUCCESSFUL;
IO_FILE_NAME Filename = {0};
IO_FILE_HANDLE hFile = NULL;
IO_STATUS_BLOCK StatusBlock = {0};
ntError = RtlWC16StringAllocateFromCString(&Filename.FileName,
pszPath);
BAIL_ON_NT_STATUS(ntError);
ntError = NtCreateFile(&hFile,
NULL,
&StatusBlock,
&Filename,
NULL,
NULL,
FILE_GENERIC_READ,
0,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN_IF,
FILE_NON_DIRECTORY_FILE,
NULL,
0,
NULL);
BAIL_ON_NT_STATUS(ntError);
ntError = NtLockFile(hFile,
NULL,
&StatusBlock,
0, 10, 0,
FALSE,
TRUE);
BAIL_ON_NT_STATUS(ntError);
sleep(5);
ntError = NtUnlockFile(hFile,
NULL,
&StatusBlock,
0, 10, 0);
BAIL_ON_NT_STATUS(ntError);
cleanup:
if (hFile) {
NtCloseFile(hFile);
}
return ntError;
error:
goto cleanup;
}
/***********************************************************************
**********************************************************************/
NTSTATUS
RequestOplock(
int argc,
char *argv[]
)
{
NTSTATUS ntError = STATUS_UNSUCCESSFUL;
PSTR pszFilename = NULL;
IO_FILE_NAME Filename = {0};
IO_FILE_HANDLE hFile = NULL;
IO_STATUS_BLOCK StatusBlock = {0};
IO_FSCTL_OPLOCK_REQUEST_INPUT_BUFFER OplockRequestInput = {0};
IO_FSCTL_OPLOCK_REQUEST_OUTPUT_BUFFER OplockRequestOutput = {0};
IO_FSCTL_OPLOCK_BREAK_ACK_INPUT_BUFFER OplockBreakInput = {0};
IO_FSCTL_OPLOCK_BREAK_ACK_OUTPUT_BUFFER OplockBreakOutput = {0};
ULONG SleepCount = 5;
if (argc != 1)
{
fprintf(stderr, "Missing parameter. Requires \n");
ntError = STATUS_INVALID_PARAMETER;
BAIL_ON_NT_STATUS(ntError);
}
pszFilename = argv[0];
ntError = RtlWC16StringAllocateFromCString(&Filename.FileName, pszFilename);
BAIL_ON_NT_STATUS(ntError);
/* Open the remote source file */
ntError = NtCreateFile(
&hFile,
NULL,
&StatusBlock,
&Filename,
NULL,
NULL,
FILE_GENERIC_READ,
0,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE,
NULL,
0,
NULL);
BAIL_ON_NT_STATUS(ntError);
OplockRequestInput.OplockRequestType = IO_OPLOCK_REQUEST_OPLOCK_BATCH;
ntError = NtFsControlFile(
hFile,
NULL,
&StatusBlock,
IO_FSCTL_OPLOCK_REQUEST,
(PVOID)&OplockRequestInput,
sizeof(OplockRequestInput),
(PVOID)&OplockRequestOutput,
sizeof(OplockRequestOutput));
BAIL_ON_NT_STATUS(ntError);
printf("Oplock broken! (%d)\n", OplockRequestOutput.OplockBreakResult);
OplockBreakInput.Response = IO_OPLOCK_BREAK_ACKNOWLEDGE;
ntError = NtFsControlFile(
hFile,
NULL,
&StatusBlock,
IO_FSCTL_OPLOCK_BREAK_ACK,
(PVOID)&OplockBreakInput,
sizeof(OplockBreakInput),
(PVOID)&OplockBreakOutput,
sizeof(OplockBreakOutput));
BAIL_ON_NT_STATUS(ntError);
printf("Oplock broken!\n");
printf("Sleeping for %d seconds...\n", SleepCount);
sleep(SleepCount);
printf("awake\n");
cleanup:
RtlWC16StringFree(&Filename.FileName);
if (hFile) {
NtCloseFile(hFile);
}
return ntError;
error:
goto cleanup;
}
/***********************************************************************
**********************************************************************/
static
NTSTATUS
PrintOpenFileInfo0(
PVOID pBuffer
);
static
NTSTATUS
PrintOpenFileInfo100(
PVOID pBuffer
);
NTSTATUS
ListOpenFiles(
char *pszInfoLevel
)
{
NTSTATUS ntError = STATUS_UNSUCCESSFUL;
ULONG Level = 0;
PSTR pszString = NULL;
IO_OPEN_FILE_INFO_INPUT_BUFFER InputBuffer = {0};
PVOID pOutputBuffer = NULL;
IO_STATUS_BLOCK Status = {0};
IO_FILE_NAME FileName = {0};
IO_FILE_HANDLE hDevice = (IO_FILE_HANDLE)NULL;
ULONG AllocSize = 4096;
if (pszInfoLevel)
{
Level = strtol(pszInfoLevel, &pszString, 10);
if (pszString != NULL && *pszString != '\0')
{
printf("Invalid infor level (%s)\n", pszInfoLevel);
ntError = STATUS_INVALID_INFO_CLASS;
BAIL_ON_NT_STATUS(ntError);
}
}
ntError = LwRtlWC16StringAllocateFromCString(
&FileName.FileName,
"\\pvfs");
BAIL_ON_NT_STATUS(ntError);
ntError = NtCreateFile(
&hDevice,
NULL,
&Status,
&FileName,
NULL,
NULL,
0,
0,
0,
0,
0,
0,
NULL,
0,
NULL);
BAIL_ON_NT_STATUS(ntError);
InputBuffer.Level = Level;
do
{
ntError = RTL_ALLOCATE(&pOutputBuffer, VOID, AllocSize);
BAIL_ON_NT_STATUS(ntError);
ntError = NtDeviceIoControlFile(
hDevice,
NULL,
&Status,
IO_DEVICE_CTL_OPEN_FILE_INFO,
&InputBuffer,
sizeof(InputBuffer),
pOutputBuffer,
AllocSize);
if (ntError == STATUS_BUFFER_TOO_SMALL)
{
AllocSize *= 2;
RTL_FREE(&pOutputBuffer);
}
} while (ntError == STATUS_BUFFER_TOO_SMALL);
switch(Level)
{
case 0:
ntError = PrintOpenFileInfo0(pOutputBuffer);
break;
case 100:
ntError = PrintOpenFileInfo100(pOutputBuffer);
break;
default:
printf("Don't know how to print OpenFileInfo level %d\n", Level);
ntError = STATUS_INVALID_INFO_CLASS;
}
BAIL_ON_NT_STATUS(ntError);
cleanup:
if (hDevice)
{
NtCloseFile(hDevice);
hDevice = (IO_FILE_HANDLE)NULL;
}
LW_RTL_FREE(&pOutputBuffer);
return ntError;
error:
goto cleanup;
}
/***********************************************************************
**********************************************************************/
static
NTSTATUS
PrintOpenFileInfo0(
PVOID pBuffer
)
{
NTSTATUS ntError = STATUS_UNSUCCESSFUL;
PIO_OPEN_FILE_INFO_0 pInfo0 = (PIO_OPEN_FILE_INFO_0)pBuffer;
PSTR pszFilename = NULL;
ULONG Offset = 0;
printf("Handles Filename\n");
printf("------- ---------\n");
while (pBuffer)
{
pInfo0 = (PIO_OPEN_FILE_INFO_0)(pBuffer + Offset);
LwRtlCStringFree(&pszFilename);
ntError = LwRtlCStringAllocateFromWC16String(
&pszFilename,
(PCWSTR)pInfo0->pwszFileName);
BAIL_ON_NT_STATUS(ntError);
printf("%-4d %s\n", pInfo0->OpenHandleCount, pszFilename);
if (pInfo0->NextEntryOffset != 0)
{
Offset += pInfo0->NextEntryOffset;
}
else
{
pBuffer = NULL;
}
}
cleanup:
return ntError;
error:
goto cleanup;
}
/***********************************************************************
**********************************************************************/
static
NTSTATUS
PrintOpenFileInfo100(
PVOID pBuffer
)
{
NTSTATUS ntError = STATUS_UNSUCCESSFUL;
PIO_OPEN_FILE_INFO_100 pInfo100 = (PIO_OPEN_FILE_INFO_100)pBuffer;
PSTR pszFilename = NULL;
ULONG Offset = 0;
printf("Handles Delete Filename\n");
printf("------- ------ ---------\n");
while (pBuffer)
{
pInfo100 = (PIO_OPEN_FILE_INFO_100)(pBuffer + Offset);
LwRtlCStringFree(&pszFilename);
ntError = LwRtlCStringAllocateFromWC16String(
&pszFilename,
(PCWSTR)pInfo100->pwszFileName);
BAIL_ON_NT_STATUS(ntError);
printf("%-4d %-6s %s\n",
pInfo100->OpenHandleCount,
pInfo100->bDeleteOnClose ? "Yes" : "No",
pszFilename);
if (pInfo100->NextEntryOffset != 0)
{
Offset += pInfo100->NextEntryOffset;
}
else
{
pBuffer = NULL;
}
}
cleanup:
return ntError;
error:
goto cleanup;
}
/***********************************************************************
**********************************************************************/
#define NOTIFY_BUFFER_SIZE 1024
NTSTATUS
TestReadDirectoryChange(
char *pszFilename
)
{
NTSTATUS ntError = STATUS_UNSUCCESSFUL;
IO_FILE_HANDLE hFile = NULL;
IO_STATUS_BLOCK StatusBlock = {0};
IO_FILE_NAME SrcFilename = {0};
BYTE pBuffer[NOTIFY_BUFFER_SIZE];
PFILE_NOTIFY_INFORMATION pChange = NULL;
PSTR pszNotifyFilename = NULL;
ntError = RtlWC16StringAllocateFromCString(&SrcFilename.FileName, pszFilename);
BAIL_ON_NT_STATUS(ntError);
/* Open the remote source file */
ntError = NtCreateFile(&hFile,
NULL,
&StatusBlock,
&SrcFilename,
NULL,
NULL,
FILE_GENERIC_READ,
0,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN,
FILE_DIRECTORY_FILE,
NULL,
0,
NULL);
BAIL_ON_NT_STATUS(ntError);
ntError = NtReadDirectoryChangeFile(
hFile,
NULL,
&StatusBlock,
pBuffer,
NOTIFY_BUFFER_SIZE,
FILE_NOTIFY_CHANGE_NAME,
TRUE,
NULL);
BAIL_ON_NT_STATUS(ntError);
pChange = (PFILE_NOTIFY_INFORMATION)pBuffer;
ntError = LwRtlCStringAllocateFromWC16String(
&pszNotifyFilename,
pChange->FileName);
printf("%s (Action = %d)\n", pszNotifyFilename, pChange->Action);
ntError = NtCloseFile(hFile);
BAIL_ON_NT_STATUS(ntError);
cleanup:
LwRtlCStringFree(&pszNotifyFilename);
return ntError;
error:
if (hFile) {
NtCloseFile(hFile);
}
goto cleanup;
}
/***********************************************************************
**********************************************************************/
#define MAX_OPEN_FILE_TEST 0x00010000
NTSTATUS
PrintMaxOpenFiles(
VOID
)
{
NTSTATUS ntError = STATUS_UNSUCCESSFUL;
IO_FILE_HANDLE hFileArray[MAX_OPEN_FILE_TEST];
IO_STATUS_BLOCK StatusBlock = {0};
IO_FILE_NAME SrcFilename = {0};
int i = 0;
NTSTATUS savedStatus = STATUS_SUCCESS;
ntError = LwRtlWC16StringAllocateFromCString(
&SrcFilename.FileName,
"/pvfs/tmp/max_open_file_test");
BAIL_ON_NT_STATUS(ntError);
for (i=0; i=0; i--)
{
NtCloseFile(hFileArray[i]);
}
RtlWC16StringFree(&SrcFilename.FileName);
ntError = savedStatus;
cleanup:
return ntError;
error:
goto cleanup;
}
/*
local variables:
mode: c
c-basic-offset: 4
indent-tabs-mode: nil
tab-width: 4
end:
*/