tst: passthrough-fuse: windows-posix layer

This commit is contained in:
Bill Zissimopoulos 2017-01-29 12:34:28 -08:00
parent a91e5b01ab
commit c252382204
3 changed files with 219 additions and 36 deletions

View File

@ -161,20 +161,20 @@ static int ptfs_opendir(const char *path, struct fuse_file_info *fi)
{
ptfs_impl_fullpath(path);
DIR *dp;
return 0 != (dp = opendir(path)) ? (fi->fh = (intptr_t)dp, 0) : -errno;
DIR *dirp;
return 0 != (dirp = opendir(path)) ? (fi->fh = (intptr_t)dirp, 0) : -errno;
}
static int ptfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, fuse_off_t off,
struct fuse_file_info *fi)
{
DIR *dp = (DIR *)fi->fh;
DIR *dirp = (DIR *)fi->fh;
struct dirent *de;
for (;;)
{
errno = 0;
if (0 == (de = readdir(dp)))
if (0 == (de = readdir(dirp)))
break;
if (0 != filler(buf, de->d_name, 0, 0))
return -ENOMEM;

View File

@ -15,13 +15,41 @@
* software.
*/
/*
* This is a very simple Windows POSIX layer. It handles all the POSIX
* file API's required to implement passthrough-fuse in POSIX, however
* the API handling is rather unsophisticated.
*
* Ways to improve it: use the FspPosix* API's to properly handle
* file names and security.
*/
#include <windows.h>
#include <fcntl.h>
#include <fuse.h>
#include "winposix.h"
struct _DIR
{
HANDLE handle;
struct dirent dirent;
char path[];
};
static int maperror(int winerrno);
static inline void *error0(void)
{
errno = maperror(GetLastError());
return 0;
}
static inline int error(void)
{
errno = maperror(GetLastError());
return -1;
}
char *realpath(const char *path, char *resolved)
{
char *result;
@ -30,10 +58,7 @@ char *realpath(const char *path, char *resolved)
FILE_READ_ATTRIBUTES, 0, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
if (INVALID_HANDLE_VALUE == h)
{
errno = maperror(GetLastError());
return 0;
}
return error0();
if (0 == resolved)
{
@ -46,9 +71,12 @@ char *realpath(const char *path, char *resolved)
if (PATH_MAX < GetFinalPathNameByHandleA(h, resolved, PATH_MAX, 0))
{
int LastError = GetLastError();
if (result != resolved)
free(result);
errno = EINVAL;
errno = maperror(LastError);
result = 0;
}
@ -73,8 +101,7 @@ int statvfs(const char *path, struct fuse_statvfs *stbuf)
!GetDiskFreeSpaceA(root, &SectorsPerCluster, &BytesPerSector,
&NumberOfFreeClusters, &TotalNumberOfClusters))
{
errno = maperror(GetLastError());
return -1;
return error();
}
memset(stbuf, 0, sizeof *stbuf);
@ -101,106 +128,262 @@ int open(const char *path, int oflag, ...)
cd[(oflag & (_O_CREAT | _O_TRUNC)) >> 8];
HANDLE h = CreateFileA(path,
DesiredAccess, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0,
DesiredAccess, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
0/* default security */,
CreationDisposition, FILE_ATTRIBUTE_NORMAL, 0);
if (INVALID_HANDLE_VALUE == h)
{
errno = maperror(GetLastError());
return -1;
}
return error();
return (int)(intptr_t)h;
}
int fstat(int fd, struct fuse_stat *stbuf)
{
return -1;
HANDLE h = (HANDLE)(intptr_t)fd;
BY_HANDLE_FILE_INFORMATION FileInfo;
UINT64 CreationTime, LastAccessTime, LastWriteTime;
if (!GetFileInformationByHandle(h, &FileInfo))
return error();
CreationTime = ((PLARGE_INTEGER)(&FileInfo.ftCreationTime))->QuadPart - 116444736000000000;
LastAccessTime = ((PLARGE_INTEGER)(&FileInfo.ftLastAccessTime))->QuadPart - 116444736000000000;
LastWriteTime = ((PLARGE_INTEGER)(&FileInfo.ftLastWriteTime))->QuadPart - 116444736000000000;
memset(stbuf, 0, sizeof *stbuf);
stbuf->st_mode = 0755 |
((FileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? 0040000/* S_IFDIR */ : 0);
stbuf->st_nlink = 1;
stbuf->st_size = ((UINT64)FileInfo.nFileSizeHigh << 32) | ((UINT64)FileInfo.nFileSizeLow);
stbuf->st_atim.tv_sec = LastAccessTime / 10000000;
stbuf->st_atim.tv_nsec = LastAccessTime % 10000000 * 100;
stbuf->st_mtim.tv_sec = LastWriteTime / 10000000;
stbuf->st_mtim.tv_nsec = LastWriteTime % 10000000 * 100;
stbuf->st_ctim.tv_sec = LastWriteTime / 10000000;
stbuf->st_ctim.tv_nsec = LastWriteTime % 10000000 * 100;
stbuf->st_birthtim.tv_sec = CreationTime / 10000000;
stbuf->st_birthtim.tv_nsec = CreationTime % 10000000 * 100;
return 0;
}
int ftruncate(int fd, fuse_off_t size)
{
return -1;
HANDLE h = (HANDLE)(intptr_t)fd;
FILE_END_OF_FILE_INFO EndOfFileInfo;
EndOfFileInfo.EndOfFile.QuadPart = size;
if (!SetFileInformationByHandle(h, FileEndOfFileInfo, &EndOfFileInfo, sizeof EndOfFileInfo))
return error();
return 0;
}
int pread(int fd, void *buf, size_t nbyte, fuse_off_t offset)
{
return -1;
HANDLE h = (HANDLE)(intptr_t)fd;
OVERLAPPED Overlapped = { 0 };
DWORD BytesTransferred;
Overlapped.Offset = (DWORD)offset;
Overlapped.OffsetHigh = (DWORD)(offset >> 32);
if (!ReadFile(h, buf, (DWORD)nbyte, &BytesTransferred, &Overlapped))
return error();
return BytesTransferred;
}
int pwrite(int fd, const void *buf, size_t nbyte, fuse_off_t offset)
{
return -1;
HANDLE h = (HANDLE)(intptr_t)fd;
OVERLAPPED Overlapped = { 0 };
DWORD BytesTransferred;
Overlapped.Offset = (DWORD)offset;
Overlapped.OffsetHigh = (DWORD)(offset >> 32);
if (!WriteFile(h, buf, (DWORD)nbyte, &BytesTransferred, &Overlapped))
return error();
return BytesTransferred;
}
int fsync(int fd)
{
return -1;
HANDLE h = (HANDLE)(intptr_t)fd;
if (!FlushFileBuffers(h))
return error();
return 0;
}
int close(int fd)
{
return -1;
HANDLE h = (HANDLE)(intptr_t)fd;
if (!CloseHandle(h))
return error();
return 0;
}
int lstat(const char *path, struct fuse_stat *stbuf)
{
return -1;
int res = -1;
int fd;
fd = open(path, O_RDONLY);
if (-1 != fd)
{
res = fstat(fd, stbuf);
close(fd);
}
return res;
}
int chmod(const char *path, fuse_mode_t mode)
{
return -1;
/* we do not support file security */
return 0;
}
int lchown(const char *path, fuse_uid_t uid, fuse_gid_t gid)
{
return -1;
/* we do not support file security */
return 0;
}
int truncate(const char *path, fuse_off_t size)
{
return -1;
int res = -1;
int fd;
fd = open(path, O_WRONLY);
if (-1 != fd)
{
res = ftruncate(fd, size);
close(fd);
}
return res;
}
int utime(const char *path, const struct fuse_utimbuf *timbuf)
{
return -1;
int res = -1;
int fd;
UINT64 LastAccessTime, LastWriteTime;
fd = open(path, O_WRONLY);
if (-1 != fd)
{
LastAccessTime = timbuf->actime * 10000000 + 116444736000000000;
LastWriteTime = timbuf->modtime * 10000000 + 116444736000000000;
res = SetFileTime((HANDLE)(intptr_t)fd,
0, (PFILETIME)&LastAccessTime, (PFILETIME)&LastWriteTime) ? 0 : error();
close(fd);
}
return res;
}
int unlink(const char *path)
{
return -1;
if (!DeleteFileA(path))
return error();
return 0;
}
int rename(const char *oldpath, const char *newpath)
{
return -1;
if (!MoveFileExA(oldpath, newpath, MOVEFILE_REPLACE_EXISTING))
return error();
return 0;
}
int mkdir(const char *path, fuse_mode_t mode)
{
return -1;
if (!CreateDirectoryA(path, 0/* default security */))
return error();
return 0;
}
int rmdir(const char *path)
{
return -1;
if (!RemoveDirectoryA(path))
return error();
return 0;
}
DIR *opendir(const char *path)
{
return 0;
DWORD FileAttributes = GetFileAttributesA(path);
if (INVALID_FILE_ATTRIBUTES == FileAttributes)
return error0();
if (0 == (FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
errno = ENOTDIR;
return 0;
}
size_t pathlen = strlen(path);
if (0 < pathlen && '/' == path[pathlen - 1])
pathlen--;
DIR *dirp = malloc(sizeof *dirp + pathlen + 3); /* sets errno */
if (0 == dirp)
return 0;
memset(dirp, 0, sizeof *dirp);
dirp->handle = INVALID_HANDLE_VALUE;
memcpy(dirp->path, path, pathlen);
dirp->path[pathlen + 0] = '/';
dirp->path[pathlen + 1] = '*';
dirp->path[pathlen + 2] = '\0';
return dirp;
}
struct dirent *readdir(DIR *dirp)
{
return 0;
WIN32_FIND_DATAA FindData;
if (INVALID_HANDLE_VALUE != dirp->handle)
{
dirp->handle = FindFirstFileA(dirp->path, &FindData);
if (INVALID_HANDLE_VALUE == dirp)
return error0();
}
else
{
if (!FindNextFileA(dirp->handle, &FindData))
return error0();
}
strcpy(dirp->dirent.d_name, FindData.cFileName);
return &dirp->dirent;
}
int closedir(DIR *dp)
int closedir(DIR *dirp)
{
return -1;
if (INVALID_HANDLE_VALUE != dirp->handle)
FindClose(dirp->handle);
free(dirp);
return 0;
}
static int maperror(int winerrno)

View File

@ -59,6 +59,6 @@ int rmdir(const char *path);
DIR *opendir(const char *path);
struct dirent *readdir(DIR *dirp);
int closedir(DIR *dp);
int closedir(DIR *dirp);
#endif