From a1b3195ddfe33993e2c0050fd7d1ffed6276f11f Mon Sep 17 00:00:00 2001 From: martinfouilleul Date: Fri, 26 May 2023 18:01:44 +0200 Subject: [PATCH] [win32, io, wip] add fstat operation (type/size/perms for now, TODO: times) --- src/platform/win32_io.c | 121 +++++++++++---------- test/files/data/posix_symlink | 1 + test/files/data/{symlink => win32_symlink} | 0 test/files/main.c | 39 +++++-- 4 files changed, 94 insertions(+), 67 deletions(-) create mode 100644 test/files/data/posix_symlink rename test/files/data/{symlink => win32_symlink} (100%) diff --git a/src/platform/win32_io.c b/src/platform/win32_io.c index 5ba82a7..2ca2896 100644 --- a/src/platform/win32_io.c +++ b/src/platform/win32_io.c @@ -160,7 +160,7 @@ io_cmp io_open_at(file_slot* atSlot, io_req* req) DWORD accessFlags = 0; DWORD createFlags = 0; - DWORD attributesFlags = FILE_ATTRIBUTE_NORMAL; + DWORD attributesFlags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS; if(req->openFlags & FILE_OPEN_READ) { @@ -243,53 +243,6 @@ io_cmp io_close(file_slot* slot, io_req* req) return(cmp); } -/* -file_perm io_convert_perm_from_stat(u16 mode) -{ - file_perm perm = mode & 07777; - return(perm); -} - -file_type io_convert_type_from_stat(u16 mode) -{ - file_type type; - switch(mode & S_IFMT) - { - case S_IFIFO: - type = FILE_FIFO; - break; - - case S_IFCHR: - type = FILE_CHARACTER; - break; - - case S_IFDIR: - type = FILE_DIRECTORY; - break; - - case S_IFBLK: - type = FILE_BLOCK; - break; - - case S_IFREG: - type = FILE_REGULAR; - break; - - case S_IFLNK: - type = FILE_SYMLINK; - break; - - case S_IFSOCK: - type = FILE_SOCKET; - break; - - default: - type = FILE_UNKNOWN; - break; - } - return(type); -} - io_cmp io_fstat(file_slot* slot, io_req* req) { io_cmp cmp = {0}; @@ -300,24 +253,72 @@ io_cmp io_fstat(file_slot* slot, io_req* req) } else { - struct stat s; - if(fstat(slot->fd, &s)) + BY_HANDLE_FILE_INFORMATION info; + if(!GetFileInformationByHandle(slot->h, &info)) { - slot->error = io_convert_errno(errno); + slot->error = io_convert_win32_error(GetLastError()); cmp.error = slot->error; } else { file_status* status = (file_status*)req->buffer; - status->perm = io_convert_perm_from_stat(s.st_mode); - status->type = io_convert_type_from_stat(s.st_mode); - status->size = s.st_size; + + status->size = (((u64)info.nFileSizeHigh)<<32) | ((u64)info.nFileSizeLow); + + DWORD attrRegularSet = FILE_ATTRIBUTE_ARCHIVE + | FILE_ATTRIBUTE_COMPRESSED + | FILE_ATTRIBUTE_ENCRYPTED + | FILE_ATTRIBUTE_HIDDEN + | FILE_ATTRIBUTE_NORMAL + | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED + | FILE_ATTRIBUTE_OFFLINE + | FILE_ATTRIBUTE_READONLY + | FILE_ATTRIBUTE_SPARSE_FILE + | FILE_ATTRIBUTE_SYSTEM + | FILE_ATTRIBUTE_TEMPORARY; + + if(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + status->type = MP_FILE_DIRECTORY; + } + else if((info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) + { + FILE_ATTRIBUTE_TAG_INFO tagInfo; + if(!GetFileInformationByHandleEx(slot->h, FileAttributeTagInfo, &tagInfo, sizeof(tagInfo))) + { + slot->error = io_convert_win32_error(GetLastError()); + cmp.error = slot->error; + } + else if(tagInfo.ReparseTag == IO_REPARSE_TAG_SYMLINK) + { + status->type = MP_FILE_SYMLINK; + } + else + { + status->type = MP_FILE_UNKNOWN; + } + } + else if(info.dwFileAttributes & attrRegularSet) + { + status->type = MP_FILE_REGULAR; + } + else + { + //TODO: might want to check for socket/block/character devices? (otoh MS STL impl. doesn't seem to do it) + status->type = MP_FILE_UNKNOWN; + } + + status->perm = MP_FILE_OWNER_READ | MP_FILE_GROUP_READ | MP_FILE_OTHER_READ; + if(!(info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) + { + status->perm = MP_FILE_OWNER_WRITE | MP_FILE_GROUP_WRITE | MP_FILE_OTHER_WRITE; + } + //TODO: times } } return(cmp); } -*/ io_cmp io_pos(file_slot* slot, io_req* req) { @@ -430,7 +431,7 @@ io_cmp io_wait_single_req(io_req* req) cmp.error = IO_ERR_HANDLE; } } - else if(slot->fatal && req->op != IO_OP_CLOSE) + else if(slot->fatal && req->op != IO_OP_CLOSE && req->op != IO_OP_ERROR) { cmp.error = IO_ERR_PREV; } @@ -442,11 +443,11 @@ io_cmp io_wait_single_req(io_req* req) case IO_OP_OPEN_AT: cmp = io_open_at(slot, req); break; -/* + case IO_OP_FSTAT: cmp = io_fstat(slot, req); break; -*/ + case IO_OP_CLOSE: cmp = io_close(slot, req); break; @@ -458,7 +459,7 @@ io_cmp io_wait_single_req(io_req* req) case IO_OP_WRITE: cmp = io_write(slot, req); break; -/* + case IO_OP_POS: cmp = io_pos(slot, req); break; @@ -466,7 +467,7 @@ io_cmp io_wait_single_req(io_req* req) case IO_OP_SEEK: cmp = io_seek(slot, req); break; -*/ + case IO_OP_ERROR: cmp = io_get_error(slot, req); break; diff --git a/test/files/data/posix_symlink b/test/files/data/posix_symlink new file mode 100644 index 0000000..397e107 --- /dev/null +++ b/test/files/data/posix_symlink @@ -0,0 +1 @@ +regular.txt \ No newline at end of file diff --git a/test/files/data/symlink b/test/files/data/win32_symlink similarity index 100% rename from test/files/data/symlink rename to test/files/data/win32_symlink diff --git a/test/files/main.c b/test/files/main.c index 175213a..44c367f 100644 --- a/test/files/main.c +++ b/test/files/main.c @@ -82,6 +82,12 @@ int test_stat_size(str8 path, u64 size) log_info("stat size\n"); file_handle f = file_open(path, 0); + if(file_last_error(f)) + { + log_error("Can't open file\n"); + return(-1); + } + file_status status = file_get_status(f); if(file_last_error(f)) @@ -104,11 +110,22 @@ int test_stat_type(mem_arena* arena, str8 dataDir) { str8 regular = path_append(arena, dataDir, STR8("regular.txt")); str8 dir = path_append(arena, dataDir, STR8("directory")); - str8 link = path_append(arena, dataDir, STR8("symlink")); + + #if PLATFORM_WINDOWS + str8 link = path_append(arena, dataDir, STR8("win32_symlink")); + #else + str8 link = path_append(arena, dataDir, STR8("posix_symlink")); + #endif log_info("stat type, regular\n"); file_handle f = file_open(regular, 0); + if(file_last_error(f)) + { + log_error("Can't open file\n"); + return(-1); + } + file_status status = file_get_status(f); if(file_last_error(f)) { @@ -125,6 +142,12 @@ int test_stat_type(mem_arena* arena, str8 dataDir) log_info("stat type, directory\n"); f = file_open(dir, 0); + if(file_last_error(f)) + { + log_error("Can't open file\n"); + return(-1); + } + status = file_get_status(f); if(file_last_error(f)) { @@ -141,6 +164,12 @@ int test_stat_type(mem_arena* arena, str8 dataDir) log_info("stat type, symlink\n"); f = file_open(link, FILE_OPEN_SYMLINK); + if(file_last_error(f)) + { + log_error("Can't open file\n"); + return(-1); + } + status = file_get_status(f); if(file_last_error(f)) { @@ -161,12 +190,8 @@ int main(int argc, char** argv) { mem_arena* arena = mem_scratch(); - str8 exePath = path_executable(arena); - str8 dirPath = path_slice_directory(exePath); - dirPath = path_append(arena, dirPath, STR8("..")); - - str8 dataDir = path_append(arena, dirPath, STR8("data")); - str8 path = path_append(arena, dirPath, STR8("test.txt")); + str8 dataDir = STR8("./data"); + str8 path = STR8("./test.txt"); str8 test_string = STR8("Hello, world!");