forked from OctaForge/libostd
add APIs for checking file types and permissions
This commit is contained in:
parent
f395562734
commit
0d0655b09e
173
ostd/path.hh
173
ostd/path.hh
|
@ -21,7 +21,7 @@
|
||||||
#ifndef OSTD_PATH_HH
|
#ifndef OSTD_PATH_HH
|
||||||
#define OSTD_PATH_HH
|
#define OSTD_PATH_HH
|
||||||
|
|
||||||
#include <string.h>
|
#include <cstdint>
|
||||||
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
@ -696,6 +696,177 @@ namespace fs {
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
enum class file_type {
|
||||||
|
none = 0,
|
||||||
|
not_found,
|
||||||
|
regular,
|
||||||
|
directory,
|
||||||
|
symlink,
|
||||||
|
block,
|
||||||
|
character,
|
||||||
|
fifo,
|
||||||
|
socket,
|
||||||
|
unknown
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class perms {
|
||||||
|
/* occupies 12 bits */
|
||||||
|
none = 0,
|
||||||
|
owner_read = 0400,
|
||||||
|
owner_write = 0200,
|
||||||
|
owner_exec = 0100,
|
||||||
|
owner_all = 0700,
|
||||||
|
group_read = 040,
|
||||||
|
group_write = 020,
|
||||||
|
group_exec = 010,
|
||||||
|
group_all = 070,
|
||||||
|
others_read = 04,
|
||||||
|
others_write = 02,
|
||||||
|
others_exec = 01,
|
||||||
|
others_all = 07,
|
||||||
|
all = 0777,
|
||||||
|
set_uid = 04000,
|
||||||
|
set_gid = 02000,
|
||||||
|
sticky_bit = 01000,
|
||||||
|
mask = 07777,
|
||||||
|
|
||||||
|
unknown = 0xFFFF
|
||||||
|
};
|
||||||
|
|
||||||
|
inline perms operator|(perms a, perms b) {
|
||||||
|
return perms(int(a) | int(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline perms operator&(perms a, perms b) {
|
||||||
|
return perms(int(a) & int(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline perms operator^(perms a, perms b) {
|
||||||
|
return perms(int(a) ^ int(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline perms operator~(perms v) {
|
||||||
|
return perms(~int(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline perms &operator|=(perms &a, perms b) {
|
||||||
|
a = (a | b);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline perms &operator&=(perms &a, perms b) {
|
||||||
|
a = (a & b);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline perms &operator^=(perms &a, perms b) {
|
||||||
|
a = (a ^ b);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct file_status {
|
||||||
|
private:
|
||||||
|
using UT = std::uint_least32_t;
|
||||||
|
UT p_val;
|
||||||
|
|
||||||
|
public:
|
||||||
|
file_status() noexcept: file_status(file_type::none) {}
|
||||||
|
file_status(file_type type, perms permissions = perms::unknown) noexcept:
|
||||||
|
p_val(UT(permissions) | (UT(type) << 16))
|
||||||
|
{}
|
||||||
|
|
||||||
|
file_type type() const noexcept {
|
||||||
|
return file_type(p_val >> 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void type(file_type type) noexcept {
|
||||||
|
p_val = ((p_val & 0xFFFF) | (UT(type) << 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
perms permissions() const noexcept {
|
||||||
|
return perms(p_val & 0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void permissions(perms perm) noexcept {
|
||||||
|
p_val = ((p_val & ~UT(0xFFFF)) | UT(perm));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
OSTD_EXPORT file_status status(path const &p);
|
||||||
|
OSTD_EXPORT file_status symlink_status(path const &p);
|
||||||
|
|
||||||
|
inline bool is_block_file(file_status st) {
|
||||||
|
return st.type() == file_type::block;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_block_file(path const &p) {
|
||||||
|
return is_block_file(status(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_character_file(file_status st) {
|
||||||
|
return st.type() == file_type::character;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_character_file(path const &p) {
|
||||||
|
return is_character_file(status(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_directory(file_status st) {
|
||||||
|
return st.type() == file_type::directory;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_directory(path const &p) {
|
||||||
|
return is_directory(status(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_regular_file(file_status st) {
|
||||||
|
return st.type() == file_type::regular;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_regular_file(path const &p) {
|
||||||
|
return is_regular_file(status(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_fifo(file_status st) {
|
||||||
|
return st.type() == file_type::fifo;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_fifo(path const &p) {
|
||||||
|
return is_fifo(status(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_symlink(file_status st) {
|
||||||
|
return st.type() == file_type::symlink;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_symlink(path const &p) {
|
||||||
|
return is_symlink(status(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_socket(file_status st) {
|
||||||
|
return st.type() == file_type::socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_socket(path const &p) {
|
||||||
|
return is_socket(status(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_other(file_status st) {
|
||||||
|
return st.type() == file_type::unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_other(path const &p) {
|
||||||
|
return is_other(status(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool status_known(file_status st) {
|
||||||
|
return st.type() != file_type::none;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool status_known(path const &p) {
|
||||||
|
return status_known(status(p));
|
||||||
|
}
|
||||||
|
|
||||||
struct directory_entry {
|
struct directory_entry {
|
||||||
directory_entry() {}
|
directory_entry() {}
|
||||||
directory_entry(ostd::path const &p): p_path(p) {}
|
directory_entry(ostd::path const &p): p_path(p) {}
|
||||||
|
|
|
@ -9,6 +9,75 @@
|
||||||
|
|
||||||
#include "ostd/path.hh"
|
#include "ostd/path.hh"
|
||||||
|
|
||||||
|
namespace ostd {
|
||||||
|
namespace fs {
|
||||||
|
|
||||||
|
static perms mode_to_perms(mode_t mode) {
|
||||||
|
perms ret = perms::none;
|
||||||
|
switch (mode & S_IRWXU) {
|
||||||
|
case S_IRUSR: ret |= perms::owner_read;
|
||||||
|
case S_IWUSR: ret |= perms::owner_write;
|
||||||
|
case S_IXUSR: ret |= perms::owner_exec;
|
||||||
|
case S_IRWXU: ret |= perms::owner_all;
|
||||||
|
}
|
||||||
|
switch (mode & S_IRWXG) {
|
||||||
|
case S_IRGRP: ret |= perms::group_read;
|
||||||
|
case S_IWGRP: ret |= perms::group_write;
|
||||||
|
case S_IXGRP: ret |= perms::group_exec;
|
||||||
|
case S_IRWXG: ret |= perms::group_all;
|
||||||
|
}
|
||||||
|
switch (mode & S_IRWXO) {
|
||||||
|
case S_IROTH: ret |= perms::others_read;
|
||||||
|
case S_IWOTH: ret |= perms::others_write;
|
||||||
|
case S_IXOTH: ret |= perms::others_exec;
|
||||||
|
case S_IRWXO: ret |= perms::others_all;
|
||||||
|
}
|
||||||
|
if (mode & S_ISUID) {
|
||||||
|
ret |= perms::set_uid;
|
||||||
|
}
|
||||||
|
if (mode & S_ISGID) {
|
||||||
|
ret |= perms::set_gid;
|
||||||
|
}
|
||||||
|
if (mode & S_ISVTX) {
|
||||||
|
ret |= perms::sticky_bit;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static file_type mode_to_type(mode_t mode) {
|
||||||
|
switch (mode & S_IFMT) {
|
||||||
|
case S_IFBLK: return file_type::block;
|
||||||
|
case S_IFCHR: return file_type::character;
|
||||||
|
case S_IFIFO: return file_type::fifo;
|
||||||
|
case S_IFREG: return file_type::regular;
|
||||||
|
case S_IFDIR: return file_type::directory;
|
||||||
|
case S_IFLNK: return file_type::symlink;
|
||||||
|
case S_IFSOCK: return file_type::socket;
|
||||||
|
}
|
||||||
|
return file_type::unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSTD_EXPORT file_status status(path const &p) {
|
||||||
|
struct stat sb;
|
||||||
|
if (stat(p.string().data(), &sb) < 0) {
|
||||||
|
/* FIXME: throw */
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
return file_status{mode_to_type(sb.st_mode), mode_to_perms(sb.st_mode)};
|
||||||
|
}
|
||||||
|
|
||||||
|
OSTD_EXPORT file_status symlink_status(path const &p) {
|
||||||
|
struct stat sb;
|
||||||
|
if (lstat(p.string().data(), &sb) < 0) {
|
||||||
|
/* FIXME: throw */
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
return file_status{mode_to_type(sb.st_mode), mode_to_perms(sb.st_mode)};
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace fs */
|
||||||
|
} /* namespace ostd */
|
||||||
|
|
||||||
namespace ostd {
|
namespace ostd {
|
||||||
namespace fs {
|
namespace fs {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
@ -81,12 +150,7 @@ OSTD_EXPORT void rdir_range_impl::read_next() {
|
||||||
if (p_handles.empty()) {
|
if (p_handles.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct stat sb;
|
if (is_directory(p_current.path())) {
|
||||||
if (stat(p_current.path().string().data(), &sb) < 0) {
|
|
||||||
/* FIXME: throw */
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
if (S_ISDIR(sb.st_mode)) {
|
|
||||||
/* directory, recurse into it and if it contains stuff, return */
|
/* directory, recurse into it and if it contains stuff, return */
|
||||||
DIR *nd = opendir(p_current.path().string().data());
|
DIR *nd = opendir(p_current.path().string().data());
|
||||||
if (!nd) {
|
if (!nd) {
|
||||||
|
|
Loading…
Reference in a new issue