Serenity Operating System
at master 133 lines 4.8 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#pragma once 8 9#include <AK/Error.h> 10#include <AK/Span.h> 11#include <AK/Time.h> 12#include <Kernel/FileSystem/DeviceFileTypes.h> 13#include <Kernel/FileSystem/InodeIdentifier.h> 14#include <Kernel/Forward.h> 15#include <Kernel/UnixTypes.h> 16 17namespace Kernel { 18 19class Process; 20 21constexpr u64 encoded_device(MajorNumber major, MinorNumber minor) 22{ 23 return (minor.value() & 0xff) | (major.value() << 8) | ((minor.value() & ~0xff) << 12); 24} 25static inline MajorNumber major_from_encoded_device(dev_t dev) { return (dev & 0xfff00u) >> 8u; } 26static inline MinorNumber minor_from_encoded_device(dev_t dev) { return (dev & 0xffu) | ((dev >> 12u) & 0xfff00u); } 27 28inline bool is_directory(mode_t mode) { return (mode & S_IFMT) == S_IFDIR; } 29inline bool is_character_device(mode_t mode) { return (mode & S_IFMT) == S_IFCHR; } 30inline bool is_block_device(mode_t mode) { return (mode & S_IFMT) == S_IFBLK; } 31inline bool is_regular_file(mode_t mode) { return (mode & S_IFMT) == S_IFREG; } 32inline bool is_fifo(mode_t mode) { return (mode & S_IFMT) == S_IFIFO; } 33inline bool is_symlink(mode_t mode) { return (mode & S_IFMT) == S_IFLNK; } 34inline bool is_socket(mode_t mode) { return (mode & S_IFMT) == S_IFSOCK; } 35inline bool is_sticky(mode_t mode) { return (mode & S_ISVTX) == S_ISVTX; } 36inline bool is_setuid(mode_t mode) { return (mode & S_ISUID) == S_ISUID; } 37inline bool is_setgid(mode_t mode) { return (mode & S_ISGID) == S_ISGID; } 38 39enum class UseEffectiveIDs { 40 Yes, 41 No 42}; 43 44struct InodeMetadata { 45 bool is_valid() const { return inode.is_valid(); } 46 47 bool may_read(Credentials const&, UseEffectiveIDs = UseEffectiveIDs::Yes) const; 48 bool may_write(Credentials const&, UseEffectiveIDs = UseEffectiveIDs::Yes) const; 49 bool may_execute(Credentials const&, UseEffectiveIDs = UseEffectiveIDs::Yes) const; 50 51 bool may_read(UserID u, GroupID g, ReadonlySpan<GroupID> eg) const 52 { 53 if (u == 0) 54 return true; 55 if (uid == u) 56 return (mode & S_IRUSR) == S_IRUSR; 57 if (gid == g || eg.contains_slow(gid)) 58 return (mode & S_IRGRP) == S_IRGRP; 59 return (mode & S_IROTH) == S_IROTH; 60 } 61 62 bool may_write(UserID u, GroupID g, ReadonlySpan<GroupID> eg) const 63 { 64 if (u == 0) 65 return true; 66 if (uid == u) 67 return (mode & S_IWUSR) == S_IWUSR; 68 if (gid == g || eg.contains_slow(gid)) 69 return (mode & S_IWGRP) == S_IWGRP; 70 return (mode & S_IWOTH) == S_IWOTH; 71 } 72 73 bool may_execute(UserID u, GroupID g, ReadonlySpan<GroupID> eg) const 74 { 75 if (u == 0) 76 return true; 77 if (uid == u) 78 return (mode & S_IXUSR) == S_IXUSR; 79 if (gid == g || eg.contains_slow(gid)) 80 return (mode & S_IXGRP) == S_IXGRP; 81 return (mode & S_IXOTH) == S_IXOTH; 82 } 83 84 bool is_directory() const { return Kernel::is_directory(mode); } 85 bool is_character_device() const { return Kernel::is_character_device(mode); } 86 bool is_block_device() const { return Kernel::is_block_device(mode); } 87 bool is_device() const { return is_character_device() || is_block_device(); } 88 bool is_regular_file() const { return Kernel::is_regular_file(mode); } 89 bool is_fifo() const { return Kernel::is_fifo(mode); } 90 bool is_symlink() const { return Kernel::is_symlink(mode); } 91 bool is_socket() const { return Kernel::is_socket(mode); } 92 bool is_sticky() const { return Kernel::is_sticky(mode); } 93 bool is_setuid() const { return Kernel::is_setuid(mode); } 94 bool is_setgid() const { return Kernel::is_setgid(mode); } 95 96 ErrorOr<struct stat> stat() const 97 { 98 if (!is_valid()) 99 return EIO; 100 struct stat buffer = {}; 101 buffer.st_rdev = encoded_device(major_device, minor_device); 102 buffer.st_ino = inode.index().value(); 103 buffer.st_mode = mode; 104 buffer.st_nlink = link_count; 105 buffer.st_uid = uid.value(); 106 buffer.st_gid = gid.value(); 107 buffer.st_dev = 0; // FIXME 108 buffer.st_size = size; 109 buffer.st_blksize = block_size; 110 buffer.st_blocks = block_count; 111 buffer.st_atim = atime.to_timespec(); 112 buffer.st_mtim = mtime.to_timespec(); 113 buffer.st_ctim = ctime.to_timespec(); 114 return buffer; 115 } 116 117 InodeIdentifier inode; 118 off_t size { 0 }; 119 mode_t mode { 0 }; 120 UserID uid { 0 }; 121 GroupID gid { 0 }; 122 nlink_t link_count { 0 }; 123 Time atime {}; 124 Time ctime {}; 125 Time mtime {}; 126 Time dtime {}; 127 blkcnt_t block_count { 0 }; 128 blksize_t block_size { 0 }; 129 MajorNumber major_device { 0 }; 130 MinorNumber minor_device { 0 }; 131}; 132 133}