From a91e5b01ab918afe7d49467ca38732c84ad7d901 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Sun, 29 Jan 2017 10:29:37 -0800 Subject: [PATCH] tst: passthrough-fuse: windows-posix layer --- tst/passthrough-fuse/passthrough-fuse.c | 3 +- tst/passthrough-fuse/winposix.c | 287 ++++++++++++++++++++++++ tst/passthrough-fuse/winposix.h | 34 +-- 3 files changed, 310 insertions(+), 14 deletions(-) diff --git a/tst/passthrough-fuse/passthrough-fuse.c b/tst/passthrough-fuse/passthrough-fuse.c index 4d6c53cf..b0d2f9d3 100644 --- a/tst/passthrough-fuse/passthrough-fuse.c +++ b/tst/passthrough-fuse/passthrough-fuse.c @@ -16,6 +16,7 @@ */ #include +#include #include #include #include @@ -195,7 +196,7 @@ static int ptfs_create(const char *path, fuse_mode_t mode, struct fuse_file_info ptfs_impl_fullpath(path); int fd; - return -1 != (fd = creat(path, mode)) ? (fi->fh = fd, 0) : -errno; + return -1 != (fd = open(path, O_CREAT | O_EXCL, mode)) ? (fi->fh = fd, 0) : -errno; } static int ptfs_ftruncate(const char *path, fuse_off_t off, struct fuse_file_info *fi) diff --git a/tst/passthrough-fuse/winposix.c b/tst/passthrough-fuse/winposix.c index 4351ab6d..b733bfb7 100644 --- a/tst/passthrough-fuse/winposix.c +++ b/tst/passthrough-fuse/winposix.c @@ -15,5 +15,292 @@ * software. */ +#include +#include #include #include "winposix.h" + +static int maperror(int winerrno); + +char *realpath(const char *path, char *resolved) +{ + char *result; + + HANDLE h = CreateFileA(path, + FILE_READ_ATTRIBUTES, 0, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); + + if (INVALID_HANDLE_VALUE == h) + { + errno = maperror(GetLastError()); + return 0; + } + + if (0 == resolved) + { + result = malloc(PATH_MAX); /* sets errno */ + if (0 == result) + return 0; + } + else + result = resolved; + + if (PATH_MAX < GetFinalPathNameByHandleA(h, resolved, PATH_MAX, 0)) + { + if (result != resolved) + free(result); + errno = EINVAL; + result = 0; + } + + CloseHandle(h); + + return result; +} + +int statvfs(const char *path, struct fuse_statvfs *stbuf) +{ + char root[PATH_MAX]; + DWORD + VolumeSerialNumber, + MaxComponentLength, + SectorsPerCluster, + BytesPerSector, + NumberOfFreeClusters, + TotalNumberOfClusters; + + if (!GetVolumePathNameA(path, root, PATH_MAX) || + !GetVolumeInformationA(root, 0, 0, &VolumeSerialNumber, &MaxComponentLength, 0, 0, 0) || + !GetDiskFreeSpaceA(root, &SectorsPerCluster, &BytesPerSector, + &NumberOfFreeClusters, &TotalNumberOfClusters)) + { + errno = maperror(GetLastError()); + return -1; + } + + memset(stbuf, 0, sizeof *stbuf); + stbuf->f_bsize = SectorsPerCluster * BytesPerSector; + stbuf->f_frsize = BytesPerSector; + stbuf->f_blocks = TotalNumberOfClusters; + stbuf->f_bfree = NumberOfFreeClusters; + stbuf->f_bavail = TotalNumberOfClusters; + stbuf->f_fsid = VolumeSerialNumber; + stbuf->f_namemax = MaxComponentLength; + + return -1; +} + +int open(const char *path, int oflag, ...) +{ + static DWORD da[] = { GENERIC_READ, GENERIC_WRITE, GENERIC_READ | GENERIC_WRITE, 0 }; + static DWORD cd[] = { OPEN_EXISTING, OPEN_ALWAYS, TRUNCATE_EXISTING, CREATE_ALWAYS }; + DWORD DesiredAccess = 0 == (oflag & _O_APPEND) ? + da[oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)] : + (da[oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)] & ~FILE_WRITE_DATA) | FILE_APPEND_DATA; + DWORD CreationDisposition = (_O_CREAT | _O_EXCL) == (oflag & (_O_CREAT | _O_EXCL)) ? + CREATE_NEW : + cd[(oflag & (_O_CREAT | _O_TRUNC)) >> 8]; + + HANDLE h = CreateFileA(path, + DesiredAccess, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, + CreationDisposition, FILE_ATTRIBUTE_NORMAL, 0); + + if (INVALID_HANDLE_VALUE == h) + { + errno = maperror(GetLastError()); + return -1; + } + + return (int)(intptr_t)h; +} + +int fstat(int fd, struct fuse_stat *stbuf) +{ + return -1; +} + +int ftruncate(int fd, fuse_off_t size) +{ + return -1; +} + +int pread(int fd, void *buf, size_t nbyte, fuse_off_t offset) +{ + return -1; +} + +int pwrite(int fd, const void *buf, size_t nbyte, fuse_off_t offset) +{ + return -1; +} + +int fsync(int fd) +{ + return -1; +} + +int close(int fd) +{ + return -1; +} + +int lstat(const char *path, struct fuse_stat *stbuf) +{ + return -1; +} + +int chmod(const char *path, fuse_mode_t mode) +{ + return -1; +} + +int lchown(const char *path, fuse_uid_t uid, fuse_gid_t gid) +{ + return -1; +} + +int truncate(const char *path, fuse_off_t size) +{ + return -1; +} + +int utime(const char *path, const struct fuse_utimbuf *timbuf) +{ + return -1; +} + +int unlink(const char *path) +{ + return -1; +} + +int rename(const char *oldpath, const char *newpath) +{ + return -1; +} + +int mkdir(const char *path, fuse_mode_t mode) +{ + return -1; +} + +int rmdir(const char *path) +{ + return -1; +} + +DIR *opendir(const char *path) +{ + return 0; +} + +struct dirent *readdir(DIR *dirp) +{ + return 0; +} + +int closedir(DIR *dp) +{ + return -1; +} + +static int maperror(int winerrno) +{ + switch (winerrno) + { + case ERROR_INVALID_FUNCTION: + return EINVAL; + case ERROR_FILE_NOT_FOUND: + return ENOENT; + case ERROR_PATH_NOT_FOUND: + return ENOENT; + case ERROR_TOO_MANY_OPEN_FILES: + return EMFILE; + case ERROR_ACCESS_DENIED: + return EACCES; + case ERROR_INVALID_HANDLE: + return EBADF; + case ERROR_ARENA_TRASHED: + return ENOMEM; + case ERROR_NOT_ENOUGH_MEMORY: + return ENOMEM; + case ERROR_INVALID_BLOCK: + return ENOMEM; + case ERROR_BAD_ENVIRONMENT: + return E2BIG; + case ERROR_BAD_FORMAT: + return ENOEXEC; + case ERROR_INVALID_ACCESS: + return EINVAL; + case ERROR_INVALID_DATA: + return EINVAL; + case ERROR_INVALID_DRIVE: + return ENOENT; + case ERROR_CURRENT_DIRECTORY: + return EACCES; + case ERROR_NOT_SAME_DEVICE: + return EXDEV; + case ERROR_NO_MORE_FILES: + return ENOENT; + case ERROR_LOCK_VIOLATION: + return EACCES; + case ERROR_BAD_NETPATH: + return ENOENT; + case ERROR_NETWORK_ACCESS_DENIED: + return EACCES; + case ERROR_BAD_NET_NAME: + return ENOENT; + case ERROR_FILE_EXISTS: + return EEXIST; + case ERROR_CANNOT_MAKE: + return EACCES; + case ERROR_FAIL_I24: + return EACCES; + case ERROR_INVALID_PARAMETER: + return EINVAL; + case ERROR_NO_PROC_SLOTS: + return EAGAIN; + case ERROR_DRIVE_LOCKED: + return EACCES; + case ERROR_BROKEN_PIPE: + return EPIPE; + case ERROR_DISK_FULL: + return ENOSPC; + case ERROR_INVALID_TARGET_HANDLE: + return EBADF; + case ERROR_WAIT_NO_CHILDREN: + return ECHILD; + case ERROR_CHILD_NOT_COMPLETE: + return ECHILD; + case ERROR_DIRECT_ACCESS_HANDLE: + return EBADF; + case ERROR_NEGATIVE_SEEK: + return EINVAL; + case ERROR_SEEK_ON_DEVICE: + return EACCES; + case ERROR_DIR_NOT_EMPTY: + return ENOTEMPTY; + case ERROR_NOT_LOCKED: + return EACCES; + case ERROR_BAD_PATHNAME: + return ENOENT; + case ERROR_MAX_THRDS_REACHED: + return EAGAIN; + case ERROR_LOCK_FAILED: + return EACCES; + case ERROR_ALREADY_EXISTS: + return EEXIST; + case ERROR_FILENAME_EXCED_RANGE: + return ENOENT; + case ERROR_NESTING_NOT_ALLOWED: + return EAGAIN; + case ERROR_NOT_ENOUGH_QUOTA: + return ENOMEM; + default: + if (ERROR_WRITE_PROTECT <= winerrno && winerrno <= ERROR_SHARING_BUFFER_EXCEEDED) + return EACCES; + else if (ERROR_INVALID_STARTING_CODESEG <= winerrno && winerrno <= ERROR_INFLOOP_IN_RELOC_CHAIN) + return ENOEXEC; + else + return EINVAL; + } +} diff --git a/tst/passthrough-fuse/winposix.h b/tst/passthrough-fuse/winposix.h index 0aaec01d..86b5ff21 100644 --- a/tst/passthrough-fuse/winposix.h +++ b/tst/passthrough-fuse/winposix.h @@ -18,6 +18,14 @@ #ifndef WINPOSIX_H_INCLUDED #define WINPOSIX_H_INCLUDED +#define O_RDONLY _O_RDONLY +#define O_WRONLY _O_WRONLY +#define O_RDWR _O_RDWR +#define O_APPEND _O_APPEND +#define O_CREAT _O_CREAT +#define O_EXCL _O_EXCL +#define O_TRUNC _O_TRUNC + #define PATH_MAX 1024 typedef struct _DIR DIR; @@ -26,28 +34,28 @@ struct dirent char d_name[255]; }; -char *realpath(const char *path, char *resolved_path); +char *realpath(const char *path, char *resolved); -int statvfs(const char *path, struct fuse_statvfs *buf); +int statvfs(const char *path, struct fuse_statvfs *stbuf); -int mkdir(const char *path, fuse_mode_t mode); -int rmdir(const char *path); +int open(const char *path, int oflag, ...); +int fstat(int fd, struct fuse_stat *stbuf); +int ftruncate(int fd, fuse_off_t size); +int pread(int fd, void *buf, size_t nbyte, fuse_off_t offset); +int pwrite(int fd, const void *buf, size_t nbyte, fuse_off_t offset); +int fsync(int fd); +int close(int fd); -int unlink(const char *path); int lstat(const char *path, struct fuse_stat *stbuf); int chmod(const char *path, fuse_mode_t mode); int lchown(const char *path, fuse_uid_t uid, fuse_gid_t gid); int truncate(const char *path, fuse_off_t size); int utime(const char *path, const struct fuse_utimbuf *timbuf); +int unlink(const char *path); +int rename(const char *oldpath, const char *newpath); -int creat(const char *path, fuse_mode_t mode); -int open(const char *path, int oflag); -int fstat(int fd, struct fuse_stat *stbuf); -int ftruncate(int fd, fuse_off_t size);; -int pread(int fd, void *buf, size_t nbyte, fuse_off_t offset); -int pwrite(int fd, const void *buf, size_t nbyte, fuse_off_t offset); -int fsync(int fd); -int close(int fd); +int mkdir(const char *path, fuse_mode_t mode); +int rmdir(const char *path); DIR *opendir(const char *path); struct dirent *readdir(DIR *dirp);