LibCore: Implement File::can_delete_or_move()

Besides from a general check if a file's directory has write
permissions, this also checks if the directory has set a sticky bit,
meaning that only file owners and the directory owner can remove or move
files in such directory. It's being used in /tmp for example.
This commit is contained in:
Karol Kosek 2022-08-31 22:07:16 +02:00 committed by Linus Groh
parent 8cfd445c23
commit b810f7f88a
2 changed files with 28 additions and 0 deletions

View file

@ -202,6 +202,33 @@ bool File::looks_like_shared_library(DeprecatedString const& filename)
return filename.ends_with(".so"sv) || filename.contains(".so."sv);
}
bool File::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;
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;
}
bool File::exists(StringView filename)
{
return !Core::System::stat(filename).is_error();

View file

@ -53,6 +53,7 @@ public:
static ErrorOr<size_t> size(DeprecatedString const& filename);
static DeprecatedString current_working_directory();
static DeprecatedString absolute_path(DeprecatedString const& path);
static bool can_delete_or_move(StringView path);
enum class RecursionMode {
Allowed,