mirror of
https://github.com/ksherlock/mpw-shell.git
synced 2025-07-24 21:24:48 +00:00
move cxx stuff into cxx directory
This commit is contained in:
289
cxx/filesystem.cpp
Normal file
289
cxx/filesystem.cpp
Normal file
@@ -0,0 +1,289 @@
|
||||
#include "filesystem.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
namespace filesystem {
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
template<class FX, class... Args>
|
||||
auto syscall(error_code &ec, FX fx, Args&&... args) -> decltype(fx(std::forward<Args>(args)...))
|
||||
{
|
||||
auto rv = fx(std::forward<Args>(args)...);
|
||||
if (rv < 0) {
|
||||
ec = error_code(errno, std::system_category());
|
||||
} else {
|
||||
ec.clear();
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int fs_stat(const path &p, struct stat *buf, error_code &ec) {
|
||||
int rv = stat(p.c_str(), buf);
|
||||
if (rv < 0) {
|
||||
ec = error_code(errno, std::system_category());
|
||||
}
|
||||
else {
|
||||
ec.clear();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
int fs_lstat(const path &p, struct stat *buf, error_code &ec) {
|
||||
int rv = lstat(p.c_str(), buf);
|
||||
if (rv < 0) {
|
||||
ec = error_code(errno, std::system_category());
|
||||
}
|
||||
else {
|
||||
ec.clear();
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
template<class FX>
|
||||
file_status status_common(FX fx, const path& p, error_code& ec) noexcept {
|
||||
|
||||
|
||||
struct stat st;
|
||||
int rv = fx(p, &st, ec);
|
||||
if (rv < 0)
|
||||
{
|
||||
switch (ec.value())
|
||||
{
|
||||
case ENOENT:
|
||||
case ENOTDIR:
|
||||
return file_status(file_type::not_found);
|
||||
|
||||
case EOVERFLOW:
|
||||
return file_status(file_type::unknown);
|
||||
|
||||
//case ENAMETOOLONG: ???
|
||||
// case ELOOP ?
|
||||
|
||||
default:
|
||||
return file_status(file_type::none);
|
||||
}
|
||||
}
|
||||
|
||||
ec.clear();
|
||||
perms prms = static_cast<perms>(st.st_mode & perms::mask);
|
||||
|
||||
if (S_ISREG(st.st_mode))
|
||||
return file_status(file_type::regular, prms);
|
||||
|
||||
if (S_ISDIR(st.st_mode))
|
||||
return file_status(file_type::directory, prms);
|
||||
|
||||
if (S_ISBLK(st.st_mode))
|
||||
return file_status(file_type::block, prms);
|
||||
|
||||
if (S_ISFIFO(st.st_mode))
|
||||
return file_status(file_type::fifo, prms);
|
||||
|
||||
if (S_ISSOCK(st.st_mode))
|
||||
return file_status(file_type::socket, prms);
|
||||
|
||||
return file_status(file_type::unknown, prms);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
file_status status(const path& p) {
|
||||
error_code ec;
|
||||
file_status result = status(p, ec);
|
||||
if (result.type() == file_type::none)
|
||||
throw filesystem_error("filesystem::file_status", p, ec);
|
||||
return result;
|
||||
}
|
||||
|
||||
file_status status(const path& p, error_code& ec) noexcept {
|
||||
|
||||
return status_common(fs_stat, p, ec);
|
||||
/*
|
||||
struct stat st;
|
||||
int rv = stat(p.c_str(), &st);
|
||||
if (rv < 0) {
|
||||
int e = errno;
|
||||
ec = error_code(e, std::system_category());
|
||||
|
||||
switch(e){
|
||||
case ENOENT:
|
||||
case ENOTDIR:
|
||||
return file_status(file_type::not_found);
|
||||
|
||||
case EOVERFLOW:
|
||||
return file_status(file_type::unknown);
|
||||
|
||||
//case ENAMETOOLONG: ???
|
||||
// case ELOOP ?
|
||||
|
||||
default:
|
||||
return file_status(file_type::none);
|
||||
}
|
||||
}
|
||||
|
||||
ec.clear();
|
||||
perms prms = static_cast<perms>(st.st_mode & perms::mask);
|
||||
|
||||
if (S_ISREG(st.st_mode))
|
||||
return file_status(file_type::regular, prms);
|
||||
|
||||
if (S_ISDIR(st.st_mode))
|
||||
return file_status(file_type::directory, prms);
|
||||
|
||||
if (S_ISBLK(st.st_mode))
|
||||
return file_status(file_type::block, prms);
|
||||
|
||||
if (S_ISFIFO(st.st_mode))
|
||||
return file_status(file_type::fifo, prms);
|
||||
|
||||
if (S_ISSOCK(st.st_mode))
|
||||
return file_status(file_type::socket, prms);
|
||||
|
||||
return file_status(file_type::unknown, prms);
|
||||
*/
|
||||
}
|
||||
|
||||
file_status symlink_status(const path& p) {
|
||||
error_code ec;
|
||||
file_status result = symlink_status(p, ec);
|
||||
if (result.type() == file_type::none)
|
||||
throw filesystem_error("filesystem::symlink_status", p, ec);
|
||||
return result;
|
||||
}
|
||||
|
||||
file_status symlink_status(const path& p, error_code& ec) noexcept {
|
||||
|
||||
return status_common(fs_lstat, p, ec);
|
||||
}
|
||||
|
||||
|
||||
uintmax_t file_size(const path& p) {
|
||||
error_code ec;
|
||||
|
||||
struct stat st;
|
||||
//if (fs_stat(p, &st, ec) < 0)
|
||||
if (syscall(ec, ::stat, p.c_str(), &st) < 0)
|
||||
throw filesystem_error("filesystem::file_size", p, ec);
|
||||
|
||||
return st.st_size;
|
||||
|
||||
}
|
||||
|
||||
uintmax_t file_size(const path& p, error_code& ec) noexcept {
|
||||
|
||||
struct stat st;
|
||||
|
||||
//if (fs_stat(p, &st, ec) < 0)
|
||||
if (syscall(ec, ::stat, p.c_str(), &st) < 0)
|
||||
return static_cast<uintmax_t>(-1);
|
||||
|
||||
return st.st_size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool create_directory(const path& p) {
|
||||
error_code ec;
|
||||
bool rv = create_directory(p, ec);
|
||||
if (ec)
|
||||
throw filesystem_error("filesystem::create_directory", p, ec);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool create_directory(const path& p, error_code& ec) noexcept {
|
||||
|
||||
int rv = ::mkdir(p.c_str(), S_IRWXU|S_IRWXG|S_IRWXO);
|
||||
if (rv == 0) {
|
||||
ec.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
int e = errno;
|
||||
error_code tmp;
|
||||
|
||||
// special case -- not an error if the directory already exists.
|
||||
|
||||
if (e == EEXIST && is_directory(p, tmp)) {
|
||||
ec.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
ec = error_code(e, std::system_category());
|
||||
return false;
|
||||
}
|
||||
|
||||
void resize_file(const path& p, uintmax_t new_size) {
|
||||
error_code ec;
|
||||
|
||||
if (syscall(ec, ::truncate, p.c_str(), new_size) < 0)
|
||||
throw filesystem_error("filesystem::create_directory", p, ec);
|
||||
}
|
||||
|
||||
void resize_file(const path& p, uintmax_t new_size, error_code& ec) noexcept {
|
||||
|
||||
syscall(ec, ::truncate, p.c_str(), new_size);
|
||||
|
||||
}
|
||||
|
||||
bool remove(const path& p) {
|
||||
error_code ec;
|
||||
|
||||
if (syscall(ec, ::remove, p.c_str()) < 0)
|
||||
{
|
||||
throw filesystem_error("filesystem::remove", p, ec);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool remove(const path& p, error_code& ec) noexcept {
|
||||
if (syscall(ec, ::remove, p.c_str()) < 0) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
path current_path() {
|
||||
error_code ec;
|
||||
path p = current_path(ec);
|
||||
|
||||
if (ec)
|
||||
throw filesystem_error("filesystem::current_path", ec);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
path current_path(error_code& ec) {
|
||||
|
||||
char *cp;
|
||||
char buffer[PATH_MAX];
|
||||
|
||||
ec.clear();
|
||||
cp = ::getcwd(buffer, sizeof(buffer));
|
||||
if (cp) return path(cp);
|
||||
|
||||
ec = error_code(errno, std::system_category());
|
||||
return path();
|
||||
}
|
||||
|
||||
void current_path(const path& p) {
|
||||
error_code ec;
|
||||
syscall(ec, ::chdir, p.c_str());
|
||||
if (ec)
|
||||
throw filesystem_error("filesystem::current_path", p, ec);
|
||||
}
|
||||
|
||||
void current_path(const path& p, error_code& ec) noexcept {
|
||||
|
||||
syscall(ec, ::chdir, p.c_str());
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user