mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-31 12:08:41 -05:00 
			
		
		
		
	tst: passthrough-fuse: windows-posix layer
This commit is contained in:
		| @@ -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; | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user