mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-29 04:09:13 +00:00
LibFileSystem: Port to Windows
This commit is contained in:
parent
d87144fde2
commit
33e7d6121b
Notes:
github-actions[bot]
2024-11-19 22:18:12 +00:00
Author: https://github.com/stasoid
Commit: 33e7d6121b
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2189
Reviewed-by: https://github.com/ADKaster ✅
2 changed files with 65 additions and 38 deletions
|
@ -1,7 +1,12 @@
|
||||||
set(SOURCES
|
set (SOURCES FileSystem.cpp)
|
||||||
FileSystem.cpp
|
if (NOT WIN32)
|
||||||
TempFile.cpp
|
list(APPEND SOURCES TempFile.cpp)
|
||||||
)
|
endif()
|
||||||
|
|
||||||
serenity_lib(LibFileSystem filesystem)
|
serenity_lib(LibFileSystem filesystem)
|
||||||
target_link_libraries(LibFileSystem PRIVATE LibCoreMinimal)
|
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()
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <LibCore/DirIterator.h>
|
#include <LibCore/DirIterator.h>
|
||||||
#include <LibCore/System.h>
|
#include <LibCore/System.h>
|
||||||
#include <LibFileSystem/FileSystem.h>
|
#include <LibFileSystem/FileSystem.h>
|
||||||
|
#include <dirent.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
#if !defined(AK_OS_IOS) && defined(AK_OS_BSD_GENERIC)
|
#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)
|
ErrorOr<ByteString> absolute_path(StringView path)
|
||||||
{
|
{
|
||||||
|
#ifndef AK_OS_WINDOWS
|
||||||
if (exists(path))
|
if (exists(path))
|
||||||
return real_path(path);
|
return real_path(path);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (path.starts_with("/"sv))
|
if (LexicalPath::is_absolute_path(path))
|
||||||
return LexicalPath::canonicalized_path(path);
|
return LexicalPath::canonicalized_path(path);
|
||||||
|
|
||||||
auto working_directory = TRY(current_working_directory());
|
auto working_directory = TRY(current_working_directory());
|
||||||
return LexicalPath::absolute_path(working_directory, path);
|
return LexicalPath::absolute_path(working_directory, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef AK_OS_WINDOWS
|
||||||
ErrorOr<ByteString> real_path(StringView path)
|
ErrorOr<ByteString> real_path(StringView path)
|
||||||
{
|
{
|
||||||
if (path.is_null())
|
if (path.is_null())
|
||||||
|
@ -56,6 +60,13 @@ ErrorOr<ByteString> real_path(StringView path)
|
||||||
|
|
||||||
return ByteString { real_path, strlen(real_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)
|
bool exists(StringView path)
|
||||||
{
|
{
|
||||||
|
@ -103,6 +114,16 @@ bool is_directory(int fd)
|
||||||
return S_ISDIR(st.st_mode);
|
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)
|
bool is_link(StringView path)
|
||||||
{
|
{
|
||||||
auto st_or_error = Core::System::lstat(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)) {
|
if (has_flag(preserve_mode, PreserveMode::Timestamps)) {
|
||||||
struct timespec times[2] = {
|
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_atimespec,
|
||||||
source_stat.st_mtimespec,
|
source_stat.st_mtimespec,
|
||||||
#else
|
# else
|
||||||
source_stat.st_atim,
|
source_stat.st_atim,
|
||||||
source_stat.st_mtim,
|
source_stat.st_mtim,
|
||||||
#endif
|
# endif
|
||||||
};
|
};
|
||||||
TRY(Core::System::utimensat(AT_FDCWD, destination_path, times, 0));
|
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)) {
|
if (has_flag(preserve_mode, PreserveMode::Timestamps)) {
|
||||||
struct timespec times[2] = {
|
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_atimespec,
|
||||||
source_stat.st_mtimespec,
|
source_stat.st_mtimespec,
|
||||||
#else
|
# else
|
||||||
source_stat.st_atim,
|
source_stat.st_atim,
|
||||||
source_stat.st_mtim,
|
source_stat.st_mtim,
|
||||||
#endif
|
# endif
|
||||||
};
|
};
|
||||||
TRY(Core::System::utimensat(AT_FDCWD, destination_path, times, 0));
|
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);
|
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)
|
ErrorOr<void> remove(StringView path, RecursionMode mode)
|
||||||
{
|
{
|
||||||
if (is_directory(path) && mode == RecursionMode::Allowed) {
|
if (is_directory(path) && mode == RecursionMode::Allowed) {
|
||||||
|
@ -314,31 +363,4 @@ ErrorOr<off_t> size_from_fstat(int fd)
|
||||||
return st.st_size;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue