mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 16:33:02 -05:00
240 lines
6.6 KiB
C
240 lines
6.6 KiB
C
/**
|
|
* @file memfs-main.c
|
|
*
|
|
* @copyright 2015-2017 Bill Zissimopoulos
|
|
*/
|
|
/*
|
|
* This file is part of WinFsp.
|
|
*
|
|
* You can redistribute it and/or modify it under the terms of the GNU
|
|
* General Public License version 3 as published by the Free Software
|
|
* Foundation.
|
|
*
|
|
* Licensees holding a valid commercial license may use this file in
|
|
* accordance with the commercial license agreement provided with the
|
|
* software.
|
|
*/
|
|
|
|
#include <winfsp/winfsp.h>
|
|
#include "memfs.h"
|
|
|
|
#define PROGNAME "memfs"
|
|
|
|
#define info(format, ...) FspServiceLog(EVENTLOG_INFORMATION_TYPE, format, __VA_ARGS__)
|
|
#define warn(format, ...) FspServiceLog(EVENTLOG_WARNING_TYPE, format, __VA_ARGS__)
|
|
#define fail(format, ...) FspServiceLog(EVENTLOG_ERROR_TYPE, format, __VA_ARGS__)
|
|
|
|
#define argtos(v) if (arge > ++argp) v = *argp; else goto usage
|
|
#define argtol(v) if (arge > ++argp) v = wcstol_deflt(*argp, v); else goto usage
|
|
|
|
static ULONG wcstol_deflt(wchar_t *w, ULONG deflt)
|
|
{
|
|
wchar_t *endp;
|
|
ULONG ul = wcstol(w, &endp, 0);
|
|
return L'\0' != w[0] && L'\0' == *endp ? ul : deflt;
|
|
}
|
|
|
|
NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
|
{
|
|
wchar_t **argp, **arge;
|
|
ULONG DebugFlags = 0;
|
|
PWSTR DebugLogFile = 0;
|
|
ULONG CaseInsensitiveFlags = 0;
|
|
ULONG Flags = MemfsDisk;
|
|
ULONG FileInfoTimeout = INFINITE;
|
|
ULONG MaxFileNodes = 1024;
|
|
ULONG MaxFileSize = 16 * 1024 * 1024;
|
|
|
|
ULONG SlowioMaxDelay = 0; // From -M : maximum delay in milliseconds
|
|
ULONG SlowioPercentDelay = 0; // From -D : percent of IO to slow down
|
|
ULONG SlowioRarefyDelay = 12; // From -R : adjust the rarity of long delays
|
|
|
|
PWSTR FileSystemName = 0;
|
|
PWSTR MountPoint = 0;
|
|
PWSTR VolumePrefix = 0;
|
|
PWSTR RootSddl = 0;
|
|
HANDLE DebugLogHandle = INVALID_HANDLE_VALUE;
|
|
MEMFS *Memfs = 0;
|
|
NTSTATUS Result;
|
|
|
|
for (argp = argv + 1, arge = argv + argc; arge > argp; argp++)
|
|
{
|
|
if (L'-' != argp[0][0])
|
|
break;
|
|
switch (argp[0][1])
|
|
{
|
|
case L'?':
|
|
goto usage;
|
|
case L'd':
|
|
argtol(DebugFlags);
|
|
break;
|
|
case L'D':
|
|
argtos(DebugLogFile);
|
|
break;
|
|
case L'F':
|
|
argtos(FileSystemName);
|
|
break;
|
|
case L'i':
|
|
CaseInsensitiveFlags = MemfsCaseInsensitive;
|
|
break;
|
|
case L'm':
|
|
argtos(MountPoint);
|
|
break;
|
|
case L'M':
|
|
argtol(SlowioMaxDelay);
|
|
break;
|
|
case L'n':
|
|
argtol(MaxFileNodes);
|
|
break;
|
|
case L'P':
|
|
argtol(SlowioPercentDelay);
|
|
break;
|
|
case L'R':
|
|
argtol(SlowioRarefyDelay);
|
|
break;
|
|
case L'S':
|
|
argtos(RootSddl);
|
|
break;
|
|
case L's':
|
|
argtol(MaxFileSize);
|
|
break;
|
|
case L't':
|
|
argtol(FileInfoTimeout);
|
|
break;
|
|
case L'u':
|
|
argtos(VolumePrefix);
|
|
if (0 != VolumePrefix && L'\0' != VolumePrefix[0])
|
|
Flags = MemfsNet;
|
|
break;
|
|
default:
|
|
goto usage;
|
|
}
|
|
}
|
|
|
|
if (arge > argp)
|
|
goto usage;
|
|
|
|
if (MemfsDisk == Flags && 0 == MountPoint)
|
|
goto usage;
|
|
|
|
if (0 != DebugLogFile)
|
|
{
|
|
if (0 == wcscmp(L"-", DebugLogFile))
|
|
DebugLogHandle = GetStdHandle(STD_ERROR_HANDLE);
|
|
else
|
|
DebugLogHandle = CreateFileW(
|
|
DebugLogFile,
|
|
FILE_APPEND_DATA,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
0,
|
|
OPEN_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
0);
|
|
if (INVALID_HANDLE_VALUE == DebugLogHandle)
|
|
{
|
|
fail(L"cannot open debug log file");
|
|
goto usage;
|
|
}
|
|
|
|
FspDebugLogSetHandle(DebugLogHandle);
|
|
}
|
|
|
|
Result = MemfsCreateFunnel(
|
|
CaseInsensitiveFlags | Flags,
|
|
FileInfoTimeout,
|
|
MaxFileNodes,
|
|
MaxFileSize,
|
|
|
|
SlowioMaxDelay,
|
|
SlowioPercentDelay,
|
|
SlowioRarefyDelay,
|
|
|
|
FileSystemName,
|
|
VolumePrefix,
|
|
RootSddl,
|
|
&Memfs);
|
|
if (!NT_SUCCESS(Result))
|
|
{
|
|
fail(L"cannot create MEMFS");
|
|
goto exit;
|
|
}
|
|
|
|
FspFileSystemSetDebugLog(MemfsFileSystem(Memfs), DebugFlags);
|
|
|
|
if (0 != MountPoint && L'\0' != MountPoint[0])
|
|
{
|
|
Result = FspFileSystemSetMountPoint(MemfsFileSystem(Memfs),
|
|
L'*' == MountPoint[0] && L'\0' == MountPoint[1] ? 0 : MountPoint);
|
|
if (!NT_SUCCESS(Result))
|
|
{
|
|
fail(L"cannot mount MEMFS");
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
Result = MemfsStart(Memfs);
|
|
if (!NT_SUCCESS(Result))
|
|
{
|
|
fail(L"cannot start MEMFS");
|
|
goto exit;
|
|
}
|
|
|
|
MountPoint = FspFileSystemMountPoint(MemfsFileSystem(Memfs));
|
|
|
|
info(L"%s -t %ld -n %ld -s %ld%s%s%s%s%s%s",
|
|
L"" PROGNAME, FileInfoTimeout, MaxFileNodes, MaxFileSize,
|
|
RootSddl ? L" -S " : L"", RootSddl ? RootSddl : L"",
|
|
0 != VolumePrefix && L'\0' != VolumePrefix[0] ? L" -u " : L"",
|
|
0 != VolumePrefix && L'\0' != VolumePrefix[0] ? VolumePrefix : L"",
|
|
MountPoint ? L" -m " : L"", MountPoint ? MountPoint : L"");
|
|
|
|
Service->UserContext = Memfs;
|
|
Result = STATUS_SUCCESS;
|
|
|
|
exit:
|
|
if (!NT_SUCCESS(Result) && 0 != Memfs)
|
|
MemfsDelete(Memfs);
|
|
|
|
return Result;
|
|
|
|
usage:
|
|
static wchar_t usage[] = L""
|
|
"usage: %s OPTIONS\n"
|
|
"\n"
|
|
"options:\n"
|
|
" -d DebugFlags [-1: enable all debug logs]\n"
|
|
" -D DebugLogFile [file path; use - for stderr]\n"
|
|
" -i [case insensitive file system]\n"
|
|
" -t FileInfoTimeout [millis]\n"
|
|
" -n MaxFileNodes\n"
|
|
" -s MaxFileSize [bytes]\n"
|
|
|
|
" -M MaxDelay [maximum slow IO delay in millis]\n"
|
|
" -P PercentDelay [percent of IO to make slow IO\n"
|
|
" -R RarefyDelay [adjust the rarity of slow IO\n"
|
|
|
|
" -F FileSystemName\n"
|
|
" -S RootSddl [file rights: FA, etc; NO generic rights: GA, etc.]\n"
|
|
" -u \\Server\\Share [UNC prefix (single backslash)]\n"
|
|
" -m MountPoint [X:|* (required if no UNC prefix)]\n";
|
|
|
|
fail(usage, L"" PROGNAME);
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
NTSTATUS SvcStop(FSP_SERVICE *Service)
|
|
{
|
|
MEMFS *Memfs = Service->UserContext;
|
|
|
|
MemfsStop(Memfs);
|
|
MemfsDelete(Memfs);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
int wmain(int argc, wchar_t **argv)
|
|
{
|
|
return FspServiceRun(L"" PROGNAME, SvcStart, SvcStop, 0);
|
|
}
|