Browse Source

LibFileSystem: Port to Windows

stasoid 8 months ago
parent
commit
33e7d6121b
2 changed files with 65 additions and 38 deletions
  1. 9 4
      Libraries/LibFileSystem/CMakeLists.txt
  2. 56 34
      Libraries/LibFileSystem/FileSystem.cpp

+ 9 - 4
Libraries/LibFileSystem/CMakeLists.txt

@@ -1,7 +1,12 @@
-set(SOURCES
-    FileSystem.cpp
-    TempFile.cpp
-)
+set (SOURCES FileSystem.cpp)
+if (NOT WIN32)
+   list(APPEND SOURCES TempFile.cpp)
+endif()
 
 serenity_lib(LibFileSystem filesystem)
 target_link_libraries(LibFileSystem PRIVATE LibCoreMinimal)
+
+if (WIN32)
+    find_path(DIRENT_INCLUDE_DIR dirent.h REQUIRED)
+    target_include_directories(LibFileSystem PRIVATE ${DIRENT_INCLUDE_DIR})
+endif()

+ 56 - 34
Libraries/LibFileSystem/FileSystem.cpp

@@ -10,6 +10,7 @@
 #include <LibCore/DirIterator.h>
 #include <LibCore/System.h>
 #include <LibFileSystem/FileSystem.h>
+#include <dirent.h>
 #include <limits.h>
 
 #if !defined(AK_OS_IOS) && defined(AK_OS_BSD_GENERIC)
@@ -32,16 +33,19 @@ ErrorOr<ByteString> current_working_directory()
 
 ErrorOr<ByteString> absolute_path(StringView path)
 {
+#ifndef AK_OS_WINDOWS
     if (exists(path))
         return real_path(path);
+#endif
 
-    if (path.starts_with("/"sv))
+    if (LexicalPath::is_absolute_path(path))
         return LexicalPath::canonicalized_path(path);
 
     auto working_directory = TRY(current_working_directory());
     return LexicalPath::absolute_path(working_directory, path);
 }
 
+#ifndef AK_OS_WINDOWS
 ErrorOr<ByteString> real_path(StringView path)
 {
     if (path.is_null())
@@ -56,6 +60,13 @@ ErrorOr<ByteString> real_path(StringView path)
 
     return ByteString { real_path, strlen(real_path) };
 }
+#else
+// NOTE: real_path on Windows does not resolve symlinks
+ErrorOr<ByteString> real_path(StringView path)
+{
+    return absolute_path(path);
+}
+#endif
 
 bool exists(StringView path)
 {
@@ -103,6 +114,16 @@ bool is_directory(int fd)
     return S_ISDIR(st.st_mode);
 }
 
+#ifdef AK_OS_WINDOWS
+bool is_link(StringView path)
+{
+    ByteString string_path = path;
+    auto attr = GetFileAttributes(string_path.characters());
+    if (attr == INVALID_FILE_ATTRIBUTES)
+        return false;
+    return attr & FILE_ATTRIBUTE_REPARSE_POINT;
+}
+#else
 bool is_link(StringView path)
 {
     auto st_or_error = Core::System::lstat(path);
@@ -178,13 +199,13 @@ ErrorOr<void> copy_file(StringView destination_path, StringView source_path, str
 
     if (has_flag(preserve_mode, PreserveMode::Timestamps)) {
         struct timespec times[2] = {
-#if defined(AK_OS_MACOS) || defined(AK_OS_IOS)
+#    if defined(AK_OS_MACOS) || defined(AK_OS_IOS)
             source_stat.st_atimespec,
             source_stat.st_mtimespec,
-#else
+#    else
             source_stat.st_atim,
             source_stat.st_mtim,
-#endif
+#    endif
         };
         TRY(Core::System::utimensat(AT_FDCWD, destination_path, times, 0));
     }
@@ -226,13 +247,13 @@ ErrorOr<void> copy_directory(StringView destination_path, StringView source_path
 
     if (has_flag(preserve_mode, PreserveMode::Timestamps)) {
         struct timespec times[2] = {
-#if defined(AK_OS_MACOS) || defined(AK_OS_IOS)
+#    if defined(AK_OS_MACOS) || defined(AK_OS_IOS)
             source_stat.st_atimespec,
             source_stat.st_mtimespec,
-#else
+#    else
             source_stat.st_atim,
             source_stat.st_mtim,
-#endif
+#    endif
         };
         TRY(Core::System::utimensat(AT_FDCWD, destination_path, times, 0));
     }
@@ -284,6 +305,34 @@ ErrorOr<void> move_file(StringView destination_path, StringView source_path, Pre
     return Core::System::unlink(source_path);
 }
 
+bool can_delete_or_move(StringView path)
+{
+    VERIFY(!path.is_empty());
+    auto directory = LexicalPath::dirname(path);
+    auto directory_has_write_access = !Core::System::access(directory, W_OK).is_error();
+    if (!directory_has_write_access)
+        return false;
+
+    auto stat_or_empty = [](StringView path) {
+        auto stat_or_error = Core::System::stat(path);
+        if (stat_or_error.is_error()) {
+            struct stat stat { };
+            return stat;
+        }
+        return stat_or_error.release_value();
+    };
+
+    auto directory_stat = stat_or_empty(directory);
+    bool is_directory_sticky = (directory_stat.st_mode & S_ISVTX) != 0;
+    if (!is_directory_sticky)
+        return true;
+
+    // Directory is sticky, only the file owner, directory owner, and root can modify (rename, remove) it.
+    auto user_id = geteuid();
+    return user_id == 0 || directory_stat.st_uid == user_id || stat_or_empty(path).st_uid == user_id;
+}
+#endif // !AK_OS_WINDOWS
+
 ErrorOr<void> remove(StringView path, RecursionMode mode)
 {
     if (is_directory(path) && mode == RecursionMode::Allowed) {
@@ -314,31 +363,4 @@ ErrorOr<off_t> size_from_fstat(int fd)
     return st.st_size;
 }
 
-bool can_delete_or_move(StringView path)
-{
-    VERIFY(!path.is_empty());
-    auto directory = LexicalPath::dirname(path);
-    auto directory_has_write_access = !Core::System::access(directory, W_OK).is_error();
-    if (!directory_has_write_access)
-        return false;
-
-    auto stat_or_empty = [](StringView path) {
-        auto stat_or_error = Core::System::stat(path);
-        if (stat_or_error.is_error()) {
-            struct stat stat { };
-            return stat;
-        }
-        return stat_or_error.release_value();
-    };
-
-    auto directory_stat = stat_or_empty(directory);
-    bool is_directory_sticky = (directory_stat.st_mode & S_ISVTX) != 0;
-    if (!is_directory_sticky)
-        return true;
-
-    // Directory is sticky, only the file owner, directory owner, and root can modify (rename, remove) it.
-    auto user_id = geteuid();
-    return user_id == 0 || directory_stat.st_uid == user_id || stat_or_empty(path).st_uid == user_id;
-}
-
 }