From 6a7b6c77c6c636d2028dd0fb0ec14d50b0cbe027 Mon Sep 17 00:00:00 2001 From: John Oberschelp Date: Sat, 3 Aug 2019 12:22:57 -0700 Subject: [PATCH] Create common.h --- tst/airfs/common.h | 212 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 tst/airfs/common.h diff --git a/tst/airfs/common.h b/tst/airfs/common.h new file mode 100644 index 00000000..57adff35 --- /dev/null +++ b/tst/airfs/common.h @@ -0,0 +1,212 @@ +/** + * @file common.h + * + * @copyright 2015-2019 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 software + * in accordance with the commercial license agreement provided in + * conjunction with the software. The terms and conditions of any such + * commercial license agreement shall govern, supersede, and render + * ineffective any application of the GPLv3 license to this software, + * notwithstanding of any reference thereto in the software or + * associated repository. + */ +/* + * Airfs is based on Memfs with changes contributed by John Oberschelp. + * The contributed changes are under joint copyright by Bill Zissimopoulos + * and John Oberschelp per the Contributor Agreement found at the + * root of this project. + */ + +#include +#include +#include +#include +#include + +#define PROGNAME "airfs" +#define ROUND_UP( bytes, units ) (((bytes) + (units) - 1) / (units) * (units)) +#define ROUND_DOWN( bytes, units ) (((bytes) ) / (units) * (units)) +#define MINIMUM_ALLOCSIZE 196 +#define MAXIMUM_ALLOCSIZE ROUND_DOWN(10*1024*1024, MINIMUM_ALLOCSIZE) +#define SECTOR_SIZE 512 +#define SECTORS_PER_ALLOCATION_UNIT 1 +#define ALLOCATION_UNIT ( SECTOR_SIZE * SECTORS_PER_ALLOCATION_UNIT ) +#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 AIRFS_MAX_PATH 512 +#define FILEBLOCK_OVERHEAD 40 // size of ( P + E + L + R + FileOffset ) = 8 * 5 = 40 +#define ARG_TO_S(v) if (arge > ++argp) v = *argp; else goto usage +#define ARG_TO_4(v) if (arge > ++argp) v = (int32_t) wcstoll_default(*argp, v); else goto usage +#define ARG_TO_8(v) if (arge > ++argp) v = wcstoll_default(*argp, v); else goto usage + +enum StorageFileAccessType {ZERO=0,READ,WRITE}; +enum Neighbor {LT=-2,LE=-1,EQ=0,GE=1,GT=2}; + +struct NODE; +typedef NODE* NODE_; + +typedef int CompareFunction (void* key, NODE_); + +inline NTSTATUS GetLastErrorAsStatus() +{ + return FspNtStatusFromWin32(GetLastError()); +} + +inline UINT64 SystemTime() +{ + FILETIME FileTime; + GetSystemTimeAsFileTime(&FileTime); + return ((PLARGE_INTEGER)&FileTime)->QuadPart; +} + +static int64_t wcstoll_default(wchar_t *w, int64_t deflt) +{ + wchar_t *endp; + int64_t i = wcstoll(w, &endp, 0); + return L'\0' != w[0] && L'\0' == *endp ? i : deflt; +} + +////////////////////////////////////////////////////////////////////// +// +// Where Class: This class manages an offset within our memory-mapped +// volume to another location within our memory-mapped volume. Because it is +// a self-relative offset, this delta is constant regardless of where in +// memory the file system is mapped, so we can always reoptain its address. +// A delta of 0 is the special case for "null". +// + +template class Where +{ + int64_t delta; + + public: + + Where() = default; + ~Where() = default; + Where(T t) : delta( t ?( (char*)t -(char*)this ):0) {} + Where(Where& w) : delta( w.delta?( ((char*)&w+w.delta)-(char*)this ):0) {} + + operator bool () { return delta != 0; } + operator T () { return (T) ( delta?( (char*)this+delta ):0); } + T operator -> () { return (T) ( delta?( (char*)this+delta ):0); } + operator void* () { return (void*)( delta?( (char*)this+delta ):0); } + + bool operator == (Where& rhs) { return (char*)this+delta == (char*)&rhs+rhs.delta; } + bool operator != (Where& rhs) { return (char*)this+delta != (char*)&rhs+rhs.delta; } + bool operator == (T rhs) { return (char*)this+delta == (char*)rhs; } + bool operator != (T rhs) { return (char*)this+delta != (char*)rhs; } + + Where& operator = (Where& rhs) { delta = rhs.delta?( ((char*)&rhs+rhs.delta) - ((char*)this) ):0; return *this; } + Where& operator = (void* rhs) { delta = rhs ?( (char*)rhs - ((char*)this) ):0; return *this; } + + char* Address () { return (char*)this+delta; } +}; + +////////////////////////////////////////////////////////////////////// +// +// The header for an Airfs volume +// + +typedef struct +{ + char Signature[8]; // Airfs\0\0\0 + char MapFormatVersion[4]; // Major.Minor.Patch.Build + char filler[4]; + Where Root; + Where Available; + UINT64 VolumeSize; + UINT64 FreeSize; + WCHAR VolumeLabel[32]; + UINT16 VolumeLabelLength; + UINT16 filler1,filler2,filler3; + UINT32 CaseInsensitive; + UINT32 filler4; + WCHAR MapName[256]; + WCHAR VolumeName[256]; // Use "" for a memory-only page file. + int64_t VolumeLength; + FSP_FSCTL_VOLUME_PARAMS VolumeParams; + FSP_FILE_SYSTEM *FileSystem; + HANDLE MapFileHandle; + HANDLE MapHandle; +} AIRFS, *AIRFS_; + +////////////////////////////////////////////////////////////////////// +// +// Information per file or directory +// +struct NODE +{ + Where P,L,R,E; // Sorted sibling tree: Parent, Left, Right, and Equal + union + { + Where Name; + int64_t FileOffset; + }; + Where Parent; + Where Children; + FSP_FSCTL_FILE_INFO FileInfo; + uint64_t SecurityDescriptorSize; + Where SecurityDescriptor; + Where FileBlocks; + uint64_t ReparseDataSize; + Where ReparseData; + volatile LONG RefCount; + Where Streams; + BOOLEAN IsAStream; +}; + +////////////////////////////////////////////////////////////////////// + +class SpinLock +{ + LONG C; // Counter + HANDLE S; // Semaphore + + public: + + SpinLock() { C = 0; S = CreateSemaphore(NULL, 0, 1, NULL); } + ~SpinLock() { CloseHandle(S); } + + void Acquire() { if (_InterlockedIncrement(&C) > 1) WaitForSingleObject(S, INFINITE); } + void Release() { if (_InterlockedDecrement(&C) > 0) ReleaseSemaphore(S, 1, NULL); } +}; + +////////////////////////////////////////////////////////////////////// + +void Airprint (const char * format, ...); + +int SizeCmp (void* key, NODE_); +int ExactNameCmp (void* key, NODE_); +int CaselessNameCmp (void* key, NODE_); + +NODE_ Find (Where &root, void* key, CompareFunction); +NODE_ Near (Where &root, void* key, CompareFunction, Neighbor); +void Attach (Where &root, NODE_ attach, CompareFunction, void* key); +void Detach (Where &root, NODE_ detach); +NODE_ First (NODE_ start); +NODE_ Last (NODE_ start); +NODE_ Next (NODE_); +NODE_ Prev (NODE_); + +NTSTATUS StorageStartup (AIRFS_ &, WCHAR* MapName, WCHAR* VolumeName, int64_t Length); +NTSTATUS StorageShutdown (AIRFS_); +void* StorageAllocate (AIRFS_ Airfs, int64_t RequestedSize); +void* StorageReallocate (AIRFS_ Airfs, void* Reallocate, int64_t RequestedSize); +void StorageFree (AIRFS_ Airfs, void* Release); +NTSTATUS StorageSetFileCapacity (AIRFS_, NODE_, int64_t MinimumRequiredCapacity); +void StorageAccessFile (StorageFileAccessType, NODE_, int64_t Offset, int64_t NumBytes, char* Address); + +static_assert(AIRFS_MAX_PATH > MAX_PATH, "AIRFS_MAX_PATH must be greater than MAX_PATH."); +static_assert(sizeof NODE + sizeof int32_t == MINIMUM_ALLOCSIZE, "MINIMUM_ALLOCSIZE should be 196."); + +////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////