Start proper stream support.
This commit is contained in:
parent
5183aa821a
commit
e3e03dc31f
34 changed files with 421 additions and 402 deletions
|
@ -13,9 +13,12 @@ g++ $SOURCE_DIR/main.cpp \
|
||||||
$CORE_SRC_DIR/data_structures/String.cpp \
|
$CORE_SRC_DIR/data_structures/String.cpp \
|
||||||
$CORE_SRC_DIR/filesystem/FileSystemPath.cpp \
|
$CORE_SRC_DIR/filesystem/FileSystemPath.cpp \
|
||||||
$CORE_SRC_DIR/filesystem/File.cpp \
|
$CORE_SRC_DIR/filesystem/File.cpp \
|
||||||
|
$CORE_SRC_DIR/filesystem/FileFormats.cpp \
|
||||||
|
$CORE_SRC_DIR/filesystem/posix/FilePosixImpl.cpp \
|
||||||
$CORE_SRC_DIR/filesystem/Directory.cpp \
|
$CORE_SRC_DIR/filesystem/Directory.cpp \
|
||||||
$CORE_SRC_DIR/logging/ConsoleLogger.cpp \
|
$CORE_SRC_DIR/logging/ConsoleLogger.cpp \
|
||||||
$CORE_SRC_DIR/logging/Logger.cpp \
|
$CORE_SRC_DIR/logging/Logger.cpp \
|
||||||
|
$CORE_SRC_DIR/system/process/Process.cpp \
|
||||||
$CORE_SRC_DIR/time/Time.cpp \
|
$CORE_SRC_DIR/time/Time.cpp \
|
||||||
-o builder -g -fno-exceptions -fno-rtti \
|
-o builder -g -fno-exceptions -fno-rtti \
|
||||||
-I$CORE_SRC_DIR/base_types \
|
-I$CORE_SRC_DIR/base_types \
|
||||||
|
@ -23,6 +26,7 @@ g++ $SOURCE_DIR/main.cpp \
|
||||||
-I$CORE_SRC_DIR/data_structures \
|
-I$CORE_SRC_DIR/data_structures \
|
||||||
-I$CORE_SRC_DIR/encoding \
|
-I$CORE_SRC_DIR/encoding \
|
||||||
-I$CORE_SRC_DIR/filesystem \
|
-I$CORE_SRC_DIR/filesystem \
|
||||||
|
-I$CORE_SRC_DIR/filesystem/posix \
|
||||||
-I$CORE_SRC_DIR/logging \
|
-I$CORE_SRC_DIR/logging \
|
||||||
-I$CORE_SRC_DIR/memory \
|
-I$CORE_SRC_DIR/memory \
|
||||||
-I$CORE_SRC_DIR/system/process \
|
-I$CORE_SRC_DIR/system/process \
|
||||||
|
|
|
@ -10,14 +10,14 @@ public:
|
||||||
|
|
||||||
BuildLibrary(const FileSystemPath& build_config);
|
BuildLibrary(const FileSystemPath& build_config);
|
||||||
|
|
||||||
Status scan();
|
|
||||||
|
|
||||||
const Vector<FileSystemPath>& get_sources() const;
|
const Vector<FileSystemPath>& get_sources() const;
|
||||||
|
|
||||||
const Vector<FileSystemPath>& get_include_dirs() const;
|
const Vector<FileSystemPath>& get_include_dirs() const;
|
||||||
|
|
||||||
const String& get_name() const;
|
const String& get_name() const;
|
||||||
|
|
||||||
|
Status scan();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FileSystemPath m_build_config;
|
FileSystemPath m_build_config;
|
||||||
Vector<FileSystemPath> m_sources;
|
Vector<FileSystemPath> m_sources;
|
||||||
|
|
|
@ -25,6 +25,13 @@ Status::Status(const Error& err)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Status Status::with_errno(const String& prefix_msg)
|
||||||
|
{
|
||||||
|
Status ret;
|
||||||
|
ret.on_errno(prefix_msg);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void Status::on_errno(const String& prefix_msg)
|
void Status::on_errno(const String& prefix_msg)
|
||||||
{
|
{
|
||||||
String errno_msg(::strerror(errno));
|
String errno_msg(::strerror(errno));
|
||||||
|
|
|
@ -48,6 +48,8 @@ public:
|
||||||
|
|
||||||
Status(const Error& err);
|
Status(const Error& err);
|
||||||
|
|
||||||
|
static Status with_errno(const String& prefix_msg);
|
||||||
|
|
||||||
void on_errno(const String& prefix_msg);
|
void on_errno(const String& prefix_msg);
|
||||||
|
|
||||||
const Error& error() const;
|
const Error& error() const;
|
||||||
|
|
|
@ -146,6 +146,17 @@ void String::to_bytes(Vector<Byte>& bytes) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t String::length(const char* arr)
|
||||||
|
{
|
||||||
|
size_t len{0};
|
||||||
|
while(*arr != '\0')
|
||||||
|
{
|
||||||
|
arr++;
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
void String::append(const Vector<Byte>& data)
|
void String::append(const Vector<Byte>& data)
|
||||||
{
|
{
|
||||||
if (data.empty())
|
if (data.empty())
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "Vector.h"
|
#include "Vector.h"
|
||||||
#include "Pair.h"
|
#include "Pair.h"
|
||||||
#include "Index.h"
|
#include "Index.h"
|
||||||
#include "ByteTypes.h"
|
#include "Byte.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
@ -29,6 +29,8 @@ public:
|
||||||
using erasePredicate = std::function<bool(char)>;
|
using erasePredicate = std::function<bool(char)>;
|
||||||
void eraseIf(erasePredicate func);
|
void eraseIf(erasePredicate func);
|
||||||
|
|
||||||
|
static size_t length(const char* arr);
|
||||||
|
|
||||||
bool is_whitespace() const;
|
bool is_whitespace() const;
|
||||||
|
|
||||||
void push_back(char c);
|
void push_back(char c);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ByteTypes.h"
|
#include "Byte.h"
|
||||||
#include "String.h"
|
#include "String.h"
|
||||||
|
|
||||||
class Bits
|
class Bits
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ByteTypes.h"
|
#include "Byte.h"
|
||||||
|
|
||||||
#include "String.h"
|
#include "String.h"
|
||||||
#include "Vector.h"
|
#include "Vector.h"
|
||||||
|
|
31
src/base/core/filesystem/BinaryFile.cpp
Normal file
31
src/base/core/filesystem/BinaryFile.cpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#include "BinaryFile.h"
|
||||||
|
|
||||||
|
Status BinaryFile::to_readable(InputStream<Byte>& input,
|
||||||
|
OutputStream<Byte>& output)
|
||||||
|
{
|
||||||
|
String sstr;
|
||||||
|
sstr << "Count | Binary | Decimal | Hex | ASCII \n";
|
||||||
|
|
||||||
|
Byte b{0};
|
||||||
|
while(input.get(b))
|
||||||
|
{
|
||||||
|
unsigned count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
for(const auto byte : buffer)
|
||||||
|
{
|
||||||
|
const auto ascii_val = std::isalpha(byte) ? byte : '.';
|
||||||
|
String hex_sstr;
|
||||||
|
hex_sstr << std::setfill('0') << std::setw(2) << std::hex << static_cast<int>(byte);
|
||||||
|
|
||||||
|
sstr << count << " | " << Bits::toString(byte) << " | " << static_cast<int>(byte) << " | " << hex_sstr.str() << " | " << ascii_val << '\n';
|
||||||
|
if (count % 10 == 0)
|
||||||
|
{
|
||||||
|
sstr << "\n";
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return {};
|
||||||
|
}
|
12
src/base/core/filesystem/BinaryFile.h
Normal file
12
src/base/core/filesystem/BinaryFile.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Stream.h"
|
||||||
|
#include "Byte.h"
|
||||||
|
#include "Error.h"
|
||||||
|
|
||||||
|
class BinaryFile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static Status to_readable(InputStream<Byte>& input,
|
||||||
|
OutputStream<Byte>& output);
|
||||||
|
};
|
|
@ -3,148 +3,10 @@
|
||||||
#include "Char.h"
|
#include "Char.h"
|
||||||
#include "Directory.h"
|
#include "Directory.h"
|
||||||
#include "Result.h"
|
#include "Result.h"
|
||||||
|
#include "FilePosixImpl.h"
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
class FileImpl
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Status do_open(const FileSystemPath& path, File::AccessMode accessMode)
|
|
||||||
{
|
|
||||||
int flags{0};
|
|
||||||
if (accessMode == File::AccessMode::Read)
|
|
||||||
{
|
|
||||||
flags |= O_RDONLY;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
flags |= O_WRONLY;
|
|
||||||
flags |= O_CREAT;
|
|
||||||
}
|
|
||||||
errno = 0;
|
|
||||||
m_fd = ::open(path.str().raw(), flags);
|
|
||||||
if (m_fd < 0)
|
|
||||||
{
|
|
||||||
Status ret;
|
|
||||||
ret.on_errno("Failed to open file with");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (accessMode == File::AccessMode::Read)
|
|
||||||
{
|
|
||||||
m_open_for_read = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_open_for_write = true;
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
Status do_close()
|
|
||||||
{
|
|
||||||
errno = 0;
|
|
||||||
const auto rc = ::close(m_fd);
|
|
||||||
if (rc < 0)
|
|
||||||
{
|
|
||||||
Status ret;
|
|
||||||
ret.on_errno("Failed to close file with");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
m_open_for_read = false;
|
|
||||||
m_open_for_write = false;
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_ok() const
|
|
||||||
{
|
|
||||||
return m_valid;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_open_for_read() const
|
|
||||||
{
|
|
||||||
return m_open_for_read;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_open_for_write() const
|
|
||||||
{
|
|
||||||
return m_open_for_write;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<size_t> do_read(VecBytes& bytes)
|
|
||||||
{
|
|
||||||
errno = 0;
|
|
||||||
const auto rc = ::read(m_fd, bytes.data(), bytes.capacity());
|
|
||||||
if (rc < 0)
|
|
||||||
{
|
|
||||||
const auto msg = _s("Error in read impl | ") + Error::from_errno();
|
|
||||||
return Result<size_t>(Error(msg));
|
|
||||||
}
|
|
||||||
return Result<size_t>(rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<size_t> do_write(const VecBytes& bytes)
|
|
||||||
{
|
|
||||||
errno = 0;
|
|
||||||
const auto rc = ::write(m_fd, bytes.data(), bytes.size());
|
|
||||||
if (rc < 0)
|
|
||||||
{
|
|
||||||
const auto msg = _s("Error in write impl | ") + Error::from_errno();
|
|
||||||
return Result<size_t>(Error(msg));
|
|
||||||
}
|
|
||||||
return Result<size_t>(rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<size_t> do_write(const Vector<char>& bytes, int size = -1)
|
|
||||||
{
|
|
||||||
errno = 0;
|
|
||||||
int rc = 0;
|
|
||||||
if (size > -1)
|
|
||||||
{
|
|
||||||
rc = ::write(m_fd, bytes.data(), size);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rc = ::write(m_fd, bytes.data(), bytes.size());
|
|
||||||
}
|
|
||||||
if (rc < 0)
|
|
||||||
{
|
|
||||||
const auto msg = _s("Error in write impl | ") + Error::from_errno();
|
|
||||||
return Result<size_t>(Error(msg));
|
|
||||||
}
|
|
||||||
return Result<size_t>(rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
Status update_size()
|
|
||||||
{
|
|
||||||
struct stat buf;
|
|
||||||
const auto rc = ::fstat(m_fd, &buf);
|
|
||||||
if (rc != 0)
|
|
||||||
{
|
|
||||||
Status ret;
|
|
||||||
ret.on_errno("Failed to get size with fstat");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
m_size = buf.st_size;
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool m_open_for_write{false};
|
|
||||||
bool m_open_for_read{false};
|
|
||||||
bool m_valid{false};
|
|
||||||
size_t m_size{0};
|
|
||||||
bool m_is_open{false};
|
|
||||||
int m_fd{-1};
|
|
||||||
};
|
|
||||||
|
|
||||||
File::File(const FileSystemPath& path)
|
File::File(const FileSystemPath& path)
|
||||||
: m_impl(Ptr<FileImpl>::create()),
|
: m_impl(Ptr<FilePosixImpl>::create()),
|
||||||
m_path(path)
|
m_path(path)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -154,23 +16,46 @@ File::~File()
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Status File::close()
|
||||||
|
{
|
||||||
|
return m_impl->do_close();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool File::exists() const
|
||||||
|
{
|
||||||
|
return m_path.exists();
|
||||||
|
}
|
||||||
|
|
||||||
String File::getExtension() const
|
String File::getExtension() const
|
||||||
{
|
{
|
||||||
return m_path.extension();
|
return m_path.extension();
|
||||||
}
|
}
|
||||||
|
|
||||||
Status File::readBinary(VecBytes& buffer)
|
FileFormat::Format File::inferFormat() const
|
||||||
{
|
{
|
||||||
auto status = open(AccessMode::Read, true);
|
const auto extension = getExtension();
|
||||||
if (!status.ok())
|
return FileFormat::inferFormat(extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status File::open(AccessMode accessMode)
|
||||||
|
{
|
||||||
|
if (m_path.is_absolute() && !m_path.parent_path().exists())
|
||||||
{
|
{
|
||||||
return status;
|
Directory::create(m_path.parent_path(), true);
|
||||||
|
}
|
||||||
|
return m_impl->do_open(m_path, accessMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status File::read(VecBytes& buffer)
|
||||||
|
{
|
||||||
|
if (const auto rc = open(AccessMode::Read); !rc.ok())
|
||||||
|
{
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = m_impl->update_size();
|
if (const auto rc = m_impl->update_size(); !rc.ok())
|
||||||
if (!status.ok())
|
|
||||||
{
|
{
|
||||||
return status;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.resize(m_impl->m_size);
|
buffer.resize(m_impl->m_size);
|
||||||
|
@ -183,17 +68,15 @@ Status File::readBinary(VecBytes& buffer)
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Status File::readText(String& ret)
|
Status File::read(String& ret)
|
||||||
{
|
{
|
||||||
auto status = open(AccessMode::Read, true);
|
if (const auto rc = open(AccessMode::Read); !rc.ok())
|
||||||
if (!status.ok())
|
|
||||||
{
|
{
|
||||||
return status;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
VecBytes buffer;
|
VecBytes buffer;
|
||||||
status = m_impl->update_size();
|
if (const auto rc = m_impl->update_size(); rc.ok() && m_impl->m_size > 0)
|
||||||
if (status.ok() && m_impl->m_size > 0)
|
|
||||||
{
|
{
|
||||||
buffer.resize(m_impl->m_size);
|
buffer.resize(m_impl->m_size);
|
||||||
const auto result = m_impl->do_read(buffer);
|
const auto result = m_impl->do_read(buffer);
|
||||||
|
@ -232,85 +115,7 @@ Status File::readText(String& ret)
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
String File::dumpBinary()
|
Status File::write(const String& text)
|
||||||
{
|
|
||||||
open(AccessMode::Read);
|
|
||||||
|
|
||||||
String sstr;
|
|
||||||
sstr << "Count | Binary | Decimal | Hex | ASCII \n";
|
|
||||||
|
|
||||||
VecBytes buffer;
|
|
||||||
readBinary(buffer);
|
|
||||||
|
|
||||||
unsigned count = 0;
|
|
||||||
/*
|
|
||||||
for(const auto byte : buffer)
|
|
||||||
{
|
|
||||||
const auto ascii_val = std::isalpha(byte) ? byte : '.';
|
|
||||||
String hex_sstr;
|
|
||||||
hex_sstr << std::setfill('0') << std::setw(2) << std::hex << static_cast<int>(byte);
|
|
||||||
|
|
||||||
sstr << count << " | " << Bits::toString(byte) << " | " << static_cast<int>(byte) << " | " << hex_sstr.str() << " | " << ascii_val << '\n';
|
|
||||||
if (count % 10 == 0)
|
|
||||||
{
|
|
||||||
sstr << "\n";
|
|
||||||
}
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
close();
|
|
||||||
return sstr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Optional<Byte> File::readNextByte()
|
|
||||||
{
|
|
||||||
if (!open(AccessMode::Read).ok())
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_impl->is_ok())
|
|
||||||
{
|
|
||||||
VecBytes buffer(1);
|
|
||||||
m_impl->do_read(buffer);
|
|
||||||
if (buffer[0] == EOF)
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return buffer[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Status File::open(AccessMode accessMode, bool binary)
|
|
||||||
{
|
|
||||||
if (m_path.is_absolute() && !m_path.parent_path().exists())
|
|
||||||
{
|
|
||||||
Directory::create(m_path.parent_path(), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_impl->do_open(m_path, accessMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
Status File::close()
|
|
||||||
{
|
|
||||||
return m_impl->do_close();
|
|
||||||
}
|
|
||||||
|
|
||||||
FileFormat::Format File::inferFormat() const
|
|
||||||
{
|
|
||||||
//const auto extension = getExtension();
|
|
||||||
//return FileFormat::inferFormat(extension);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
Status File::writeText(const String& text)
|
|
||||||
{
|
{
|
||||||
bool had_to_open{false};
|
bool had_to_open{false};
|
||||||
Status status;
|
Status status;
|
||||||
|
@ -334,54 +139,4 @@ Status File::writeText(const String& text)
|
||||||
status = m_impl->do_close();
|
status = m_impl->do_close();
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status File::readLines(Vector<String>& lines)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
if (!pathExists())
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!open(AccessMode::Read))
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
String str;
|
|
||||||
while(std::getline(*mInHandle, str))
|
|
||||||
{
|
|
||||||
content.push_back(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
close();
|
|
||||||
*/
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
Status File::read(String& ret)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
if (!pathExists())
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!open(AccessMode::Read))
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
String buffer;
|
|
||||||
buffer << mInHandle->rdbuf();
|
|
||||||
|
|
||||||
close();
|
|
||||||
*/
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool File::exists() const
|
|
||||||
{
|
|
||||||
return m_path.exists();
|
|
||||||
}
|
|
|
@ -2,20 +2,18 @@
|
||||||
|
|
||||||
#include "FileFormats.h"
|
#include "FileFormats.h"
|
||||||
#include "FileSystemPath.h"
|
#include "FileSystemPath.h"
|
||||||
#include "Optional.h"
|
|
||||||
#include "String.h"
|
#include "String.h"
|
||||||
#include "ByteTypes.h"
|
#include "Byte.h"
|
||||||
#include "Pointer.h"
|
#include "Pointer.h"
|
||||||
|
|
||||||
class FileImpl;
|
class FilePosixImpl;
|
||||||
|
|
||||||
class File
|
class File
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum class AccessMode{
|
enum class AccessMode{
|
||||||
Read,
|
Read,
|
||||||
Write,
|
Write
|
||||||
ReadWrite
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -25,29 +23,26 @@ public:
|
||||||
|
|
||||||
Status close();
|
Status close();
|
||||||
|
|
||||||
String dumpBinary();
|
bool exists() const;
|
||||||
|
|
||||||
|
bool finished() const;
|
||||||
|
|
||||||
String getExtension() const;
|
String getExtension() const;
|
||||||
|
|
||||||
FileFormat::Format inferFormat() const;
|
FileFormat::Format inferFormat() const;
|
||||||
|
|
||||||
Status readText(String& buffer);
|
Status open(AccessMode mode);
|
||||||
|
|
||||||
Status readLines(Vector<String>& lines);
|
Status read(VecBytes& bytes);
|
||||||
|
|
||||||
Status read(String& buffer);
|
Status read(String& buffer);
|
||||||
|
|
||||||
bool exists() const;
|
Status write(const String& buffer);
|
||||||
|
|
||||||
Status open(AccessMode mode, bool binary = false);
|
Status write(const VecBytes& bytes);
|
||||||
|
|
||||||
Status readBinary(VecBytes& bytes);
|
|
||||||
|
|
||||||
Optional<Byte> readNextByte();
|
|
||||||
|
|
||||||
Status writeText(const String& text);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ptr<FileImpl> m_impl;
|
Ptr<FilePosixImpl> m_impl;
|
||||||
FileSystemPath m_path;
|
FileSystemPath m_path;
|
||||||
|
bool mGotEndOfFile{false};
|
||||||
};
|
};
|
||||||
|
|
121
src/base/core/filesystem/posix/FilePosixImpl.cpp
Normal file
121
src/base/core/filesystem/posix/FilePosixImpl.cpp
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
#include "FilePosixImpl.h"
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
Status FilePosixImpl::do_open(const FileSystemPath& path, File::AccessMode accessMode)
|
||||||
|
{
|
||||||
|
int flags{0};
|
||||||
|
if (accessMode == File::AccessMode::Read)
|
||||||
|
{
|
||||||
|
flags |= O_RDONLY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
flags |= O_WRONLY;
|
||||||
|
flags |= O_CREAT;
|
||||||
|
}
|
||||||
|
errno = 0;
|
||||||
|
m_fd = ::open(path.str().raw(), flags);
|
||||||
|
if (m_fd < 0)
|
||||||
|
{
|
||||||
|
return Status::with_errno("Failed to open file with");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accessMode == File::AccessMode::Read)
|
||||||
|
{
|
||||||
|
m_open_for_read = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_open_for_write = true;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Status FilePosixImpl::do_close()
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
if (const auto rc = ::close(m_fd); rc < 0)
|
||||||
|
{
|
||||||
|
Status::with_errno("Failed to close file with");
|
||||||
|
}
|
||||||
|
m_open_for_read = false;
|
||||||
|
m_open_for_write = false;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FilePosixImpl::is_ok() const
|
||||||
|
{
|
||||||
|
return m_valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FilePosixImpl::is_open_for_read() const
|
||||||
|
{
|
||||||
|
return m_open_for_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FilePosixImpl::is_open_for_write() const
|
||||||
|
{
|
||||||
|
return m_open_for_write;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<size_t> FilePosixImpl::do_read(VecBytes& bytes)
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
const auto rc = ::read(m_fd, bytes.data(), bytes.capacity());
|
||||||
|
if (rc < 0)
|
||||||
|
{
|
||||||
|
const auto msg = _s("Error in read impl | ") + Error::from_errno();
|
||||||
|
return Result<size_t>(Error(msg));
|
||||||
|
}
|
||||||
|
return Result<size_t>(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<size_t> FilePosixImpl::do_write(const VecBytes& bytes)
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
const auto rc = ::write(m_fd, bytes.data(), bytes.size());
|
||||||
|
if (rc < 0)
|
||||||
|
{
|
||||||
|
const auto msg = _s("Error in write impl | ") + Error::from_errno();
|
||||||
|
return Result<size_t>(Error(msg));
|
||||||
|
}
|
||||||
|
return Result<size_t>(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<size_t> FilePosixImpl::do_write(const Vector<char>& bytes, int size)
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
int rc = 0;
|
||||||
|
if (size > -1)
|
||||||
|
{
|
||||||
|
rc = ::write(m_fd, bytes.data(), size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = ::write(m_fd, bytes.data(), bytes.size());
|
||||||
|
}
|
||||||
|
if (rc < 0)
|
||||||
|
{
|
||||||
|
const auto msg = _s("Error in write impl | ") + Error::from_errno();
|
||||||
|
return Result<size_t>(Error(msg));
|
||||||
|
}
|
||||||
|
return Result<size_t>(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status FilePosixImpl::update_size()
|
||||||
|
{
|
||||||
|
struct stat buf;
|
||||||
|
if (const auto rc = ::fstat(m_fd, &buf); rc != 0)
|
||||||
|
{
|
||||||
|
return Status::with_errno("Failed to get size with fstat");
|
||||||
|
}
|
||||||
|
m_size = buf.st_size;
|
||||||
|
return {};
|
||||||
|
}
|
34
src/base/core/filesystem/posix/FilePosixImpl.h
Normal file
34
src/base/core/filesystem/posix/FilePosixImpl.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "FileSystemPath.h"
|
||||||
|
#include "File.h"
|
||||||
|
|
||||||
|
class FilePosixImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Status do_open(const FileSystemPath& path,
|
||||||
|
File::AccessMode accessMode);
|
||||||
|
|
||||||
|
Status do_close();
|
||||||
|
|
||||||
|
bool is_ok() const;
|
||||||
|
|
||||||
|
bool is_open_for_read() const;
|
||||||
|
|
||||||
|
bool is_open_for_write() const;
|
||||||
|
|
||||||
|
Result<size_t> do_read(VecBytes& bytes);
|
||||||
|
|
||||||
|
Result<size_t> do_write(const VecBytes& bytes);
|
||||||
|
|
||||||
|
Result<size_t> do_write(const Vector<char>& bytes, int size = -1);
|
||||||
|
|
||||||
|
Status update_size();
|
||||||
|
|
||||||
|
bool m_open_for_write{false};
|
||||||
|
bool m_open_for_read{false};
|
||||||
|
bool m_valid{false};
|
||||||
|
size_t m_size{0};
|
||||||
|
bool m_is_open{false};
|
||||||
|
int m_fd{-1};
|
||||||
|
};
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
Ptr<JsonDocument> JsonParser::read(const FileSystemPath& input_file)
|
Ptr<JsonDocument> JsonParser::read(const FileSystemPath& input_file)
|
||||||
{
|
{
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,12 @@ TomlContent* TomlReader::getContent() const
|
||||||
void TomlReader::read(const FileSystemPath& input_path)
|
void TomlReader::read(const FileSystemPath& input_path)
|
||||||
{
|
{
|
||||||
Vector<String> lines;
|
Vector<String> lines;
|
||||||
File(input_path).readLines(lines);
|
File input_file(input_path);
|
||||||
|
|
||||||
|
String buffer;
|
||||||
|
input_file.read(buffer);
|
||||||
|
buffer.split(lines, '\n');
|
||||||
|
|
||||||
mLastSectionOffset = 0;
|
mLastSectionOffset = 0;
|
||||||
mWorkingTable = mContent->getRootTable();
|
mWorkingTable = mContent->getRootTable();
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "Stream.h"
|
#include "Stream.h"
|
||||||
#include "String.h"
|
#include "String.h"
|
||||||
#include "Optional.h"
|
#include "Optional.h"
|
||||||
#include "ByteTypes.h"
|
#include "Byte.h"
|
||||||
|
|
||||||
class BinaryStream
|
class BinaryStream
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,7 +11,8 @@ Byte BitStream::getCurrentByte()
|
||||||
{
|
{
|
||||||
if (mByteOffset < 0)
|
if (mByteOffset < 0)
|
||||||
{
|
{
|
||||||
readNextByte();
|
Byte buffer;
|
||||||
|
readNextByte(buffer);
|
||||||
}
|
}
|
||||||
return mCurrentByte;
|
return mCurrentByte;
|
||||||
}
|
}
|
||||||
|
@ -109,9 +110,10 @@ void BitStream::writeNBits(DWord data, size_t length)
|
||||||
|
|
||||||
bool BitStream::readNextNBits(size_t n, Byte& buffer)
|
bool BitStream::readNextNBits(size_t n, Byte& buffer)
|
||||||
{
|
{
|
||||||
|
Byte internal_buffer;
|
||||||
if (mByteOffset < 0)
|
if (mByteOffset < 0)
|
||||||
{
|
{
|
||||||
if (!readNextByte())
|
if (!readNextByte(internal_buffer))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -121,7 +123,7 @@ bool BitStream::readNextNBits(size_t n, Byte& buffer)
|
||||||
if (overshoot > 0)
|
if (overshoot > 0)
|
||||||
{
|
{
|
||||||
const auto last_byte = mCurrentByte;
|
const auto last_byte = mCurrentByte;
|
||||||
if (!readNextByte())
|
if (!readNextByte(internal_buffer))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "AbstractChecksumCalculator.h"
|
#include "AbstractChecksumCalculator.h"
|
||||||
#include "ByteTypes.h"
|
#include "Byte.h"
|
||||||
#include "String.h"
|
#include "String.h"
|
||||||
#include "Optional.h"
|
#include "Optional.h"
|
||||||
#include "Pair.h"
|
#include "Pair.h"
|
||||||
|
@ -27,7 +27,7 @@ public:
|
||||||
|
|
||||||
virtual bool readNextNBits(size_t n, Byte& buffer);
|
virtual bool readNextNBits(size_t n, Byte& buffer);
|
||||||
|
|
||||||
virtual Optional<Byte> readNextByte() = 0;
|
virtual bool readNextByte(Byte& ret) = 0;
|
||||||
|
|
||||||
virtual void writeNBits(DWord data, size_t length);
|
virtual void writeNBits(DWord data, size_t length);
|
||||||
|
|
||||||
|
|
|
@ -30,17 +30,18 @@ void BufferBitStream::peekNextNBytes(size_t n, VecBytes& ret) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<uint8_t> BufferBitStream::readNextByte()
|
bool BufferBitStream::readNextByte(Byte& byte)
|
||||||
{
|
{
|
||||||
if (mByteOffset + 1 == static_cast<int>(mBuffer.size()))
|
if (mByteOffset + 1 == static_cast<int>(mBuffer.size()))
|
||||||
{
|
{
|
||||||
return {};
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mByteOffset++;
|
mByteOffset++;
|
||||||
mCurrentByte = mBuffer[mByteOffset];
|
mCurrentByte = mBuffer[mByteOffset];
|
||||||
return mCurrentByte;
|
byte = mCurrentByte;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,9 +50,9 @@ void BufferBitStream::setBuffer(const VecBytes& data)
|
||||||
mBuffer = data;
|
mBuffer = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BufferBitStream::writeByte(uint8_t data, bool checkOverflow)
|
void BufferBitStream::writeByte(Byte data, bool checkOverflow)
|
||||||
{
|
{
|
||||||
uint8_t out_byte{0};
|
Byte out_byte{0};
|
||||||
if (checkOverflow && mBitOffset > 0)
|
if (checkOverflow && mBitOffset > 0)
|
||||||
{
|
{
|
||||||
out_byte = Bits::getLowerNBits(mCurrentByte, mBitOffset);
|
out_byte = Bits::getLowerNBits(mCurrentByte, mBitOffset);
|
||||||
|
|
|
@ -11,13 +11,13 @@ public:
|
||||||
|
|
||||||
void peekNextNBytes(size_t n, VecBytes& bytes) const override;
|
void peekNextNBytes(size_t n, VecBytes& bytes) const override;
|
||||||
|
|
||||||
Optional<uint8_t> readNextByte() override;
|
bool readNextByte(Byte& byte) override;
|
||||||
|
|
||||||
void reset() override;
|
void reset() override;
|
||||||
|
|
||||||
void setBuffer(const VecBytes& data);
|
void setBuffer(const VecBytes& data);
|
||||||
|
|
||||||
void writeByte(uint8_t data, bool checkOverflow = true) override;
|
void writeByte(Byte data, bool checkOverflow = true) override;
|
||||||
|
|
||||||
void writeBytes(const VecBytes& data) override;
|
void writeBytes(const VecBytes& data) override;
|
||||||
|
|
||||||
|
|
0
src/base/core/streams/ByteStream.cpp
Normal file
0
src/base/core/streams/ByteStream.cpp
Normal file
11
src/base/core/streams/ByteStream.h
Normal file
11
src/base/core/streams/ByteStream.h
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Stream.h"
|
||||||
|
#include "String.h"
|
||||||
|
|
||||||
|
using OutputByteStream = OutputByteStream<Byte>;
|
||||||
|
|
||||||
|
inline void operator<<(OutputByteStream& stream, const char* string)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -1,11 +1,32 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ByteTypes.h"
|
#include "Byte.h"
|
||||||
#include "Stream.h"
|
#include "Stream.h"
|
||||||
#include "FileSystemPath.h"
|
#include "FileSystemPath.h"
|
||||||
|
#include "File.h"
|
||||||
|
|
||||||
class InputFileStream : public InputStream<Byte>
|
class InputFileStream : public InputStream<Byte>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
InputFileStream(const FileSystemPath& path)
|
||||||
|
: File(path)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool good() const override
|
||||||
|
{
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get(T& item) = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void finished()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
File mFile;
|
||||||
|
Status mStatus;
|
||||||
};
|
};
|
|
@ -16,15 +16,16 @@ void InputBitStream::peekNextNBytes(size_t, VecBytes&) const
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<Byte> InputBitStream::readNextByte()
|
bool InputBitStream::readNextByte(Byte& buffer)
|
||||||
{
|
{
|
||||||
if (mStream->good())
|
if (mStream->good())
|
||||||
{
|
{
|
||||||
return static_cast<Byte>(mStream->get());
|
buffer = static_cast<Byte>(mStream->get());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return {};
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include "BitStream.h"
|
#include "BitStream.h"
|
||||||
#include "Stream.h"
|
#include "Stream.h"
|
||||||
#include "ByteTypes.h"
|
#include "Byte.h"
|
||||||
|
|
||||||
class InputBitStream : public BitStream
|
class InputBitStream : public BitStream
|
||||||
{
|
{
|
||||||
|
@ -12,13 +12,12 @@ class InputBitStream : public BitStream
|
||||||
|
|
||||||
void peekNextNBytes(size_t n, VecBytes& bytes) const override;
|
void peekNextNBytes(size_t n, VecBytes& bytes) const override;
|
||||||
|
|
||||||
Optional<Byte> readNextByte() override;
|
bool readNextByte(Byte& buffer) override;
|
||||||
|
|
||||||
void writeByte(Byte data, bool checkOverflow = true) override;
|
void writeByte(Byte data, bool checkOverflow = true) override;
|
||||||
|
|
||||||
void writeBytes(const VecBytes&) override
|
void writeBytes(const VecBytes&) override
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -17,12 +17,12 @@ void OutputBitStream::peekNextNBytes(size_t, VecBytes&) const
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<uint8_t> OutputBitStream::readNextByte()
|
bool OutputBitStream::readNextByte(Byte& buffer)
|
||||||
{
|
{
|
||||||
return {};
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OutputBitStream::writeByte(uint8_t data, bool)
|
void OutputBitStream::writeByte(Byte data, bool)
|
||||||
{
|
{
|
||||||
//(*mStream) << data;
|
//(*mStream) << data;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include "BitStream.h"
|
#include "BitStream.h"
|
||||||
#include "Stream.h"
|
#include "Stream.h"
|
||||||
#include "ByteTypes.h"
|
#include "Byte.h"
|
||||||
|
|
||||||
class OutputBitStream : public BitStream
|
class OutputBitStream : public BitStream
|
||||||
{
|
{
|
||||||
|
@ -13,7 +13,7 @@ public:
|
||||||
|
|
||||||
void peekNextNBytes(size_t n, VecBytes& bytes) const override;
|
void peekNextNBytes(size_t n, VecBytes& bytes) const override;
|
||||||
|
|
||||||
Optional<Byte> readNextByte() override;
|
bool readNextByte(Byte& buffer) override;
|
||||||
|
|
||||||
void writeByte(Byte data, bool checkOverflow = true) override;
|
void writeByte(Byte data, bool checkOverflow = true) override;
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,6 @@ public:
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool get(T& item) = 0;
|
virtual bool get(T& item) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
70
src/base/core/system/process/Process.cpp
Normal file
70
src/base/core/system/process/Process.cpp
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
#include "Process.h"
|
||||||
|
|
||||||
|
#include "Logger.h"
|
||||||
|
#include "File.h"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
Status Process::launch(const String& command,
|
||||||
|
const Vector<String>& args)
|
||||||
|
{
|
||||||
|
const auto pid = fork();
|
||||||
|
if (pid < 0)
|
||||||
|
{
|
||||||
|
ON_ERRNO("Failed to fork");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid == 0)
|
||||||
|
{
|
||||||
|
char* exe_args[args.size()+2];
|
||||||
|
exe_args[0] = const_cast<char*>(command.raw());
|
||||||
|
for(size_t idx = 1; idx<args.size()+1; idx++)
|
||||||
|
{
|
||||||
|
//LOG_INFO(args[idx-1]);
|
||||||
|
exe_args[idx] = const_cast<char*>(args[idx-1].raw());
|
||||||
|
}
|
||||||
|
exe_args[args.size()+1] = nullptr;
|
||||||
|
errno = 0;
|
||||||
|
auto rc = execv(command.raw(), exe_args);
|
||||||
|
if (rc != 0)
|
||||||
|
{
|
||||||
|
LOG_ERROR("External proc failed: " << Error::from_errno());
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
auto rc = wait(&status);
|
||||||
|
if (rc < 0)
|
||||||
|
{
|
||||||
|
ON_ERRNO("Failed to wait");
|
||||||
|
}
|
||||||
|
if (!WIFEXITED(status))
|
||||||
|
{
|
||||||
|
return Status(Error("Process child did not termintate normally"));
|
||||||
|
}
|
||||||
|
if (WEXITSTATUS(status) != EXIT_SUCCESS)
|
||||||
|
{
|
||||||
|
return Status(Error("Process child terminated with failure"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<String> Process::get_self_name()
|
||||||
|
{
|
||||||
|
FileSystemPath path(String("/proc/self/cmdline"));
|
||||||
|
File sys_file(path);
|
||||||
|
|
||||||
|
Result<String> ret;
|
||||||
|
const auto rc = sys_file.read(ret.value());
|
||||||
|
if (!rc.ok())
|
||||||
|
{
|
||||||
|
ret.on_error(rc.error());
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -1,77 +1,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "String.h"
|
#include "String.h"
|
||||||
|
|
||||||
#include "File.h"
|
|
||||||
#include "Result.h"
|
#include "Result.h"
|
||||||
#include "Logger.h"
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
class Process
|
class Process
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static Result<String> get_self_name();
|
||||||
|
|
||||||
static Status launch(const String& command,
|
static Status launch(const String& command,
|
||||||
const Vector<String>& args)
|
const Vector<String>& args);
|
||||||
{
|
|
||||||
const auto pid = fork();
|
|
||||||
if (pid < 0)
|
|
||||||
{
|
|
||||||
ON_ERRNO("Failed to fork");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pid == 0)
|
|
||||||
{
|
|
||||||
char* exe_args[args.size()+2];
|
|
||||||
exe_args[0] = const_cast<char*>(command.raw());
|
|
||||||
for(size_t idx = 1; idx<args.size()+1; idx++)
|
|
||||||
{
|
|
||||||
//LOG_INFO(args[idx-1]);
|
|
||||||
exe_args[idx] = const_cast<char*>(args[idx-1].raw());
|
|
||||||
}
|
|
||||||
exe_args[args.size()+1] = nullptr;
|
|
||||||
errno = 0;
|
|
||||||
auto rc = execv(command.raw(), exe_args);
|
|
||||||
if (rc != 0)
|
|
||||||
{
|
|
||||||
LOG_ERROR("External proc failed: " << Error::from_errno());
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
auto rc = wait(&status);
|
|
||||||
if (rc < 0)
|
|
||||||
{
|
|
||||||
ON_ERRNO("Failed to wait");
|
|
||||||
}
|
|
||||||
if (!WIFEXITED(status))
|
|
||||||
{
|
|
||||||
return Status(Error("Process child did not termintate normally"));
|
|
||||||
}
|
|
||||||
if (WEXITSTATUS(status) != EXIT_SUCCESS)
|
|
||||||
{
|
|
||||||
return Status(Error("Process child terminated with failure"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
static Result<String> get_self_name()
|
|
||||||
{
|
|
||||||
FileSystemPath path(String("/proc/self/cmdline"));
|
|
||||||
File sys_file(path);
|
|
||||||
|
|
||||||
Result<String> ret;
|
|
||||||
const auto rc = sys_file.readText(ret.value());
|
|
||||||
if (!rc.ok())
|
|
||||||
{
|
|
||||||
ret.on_error(rc.error());
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
};
|
};
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ByteTypes.h"
|
#include "Byte.h"
|
||||||
|
|
||||||
#include "String.h"
|
#include "String.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
|
@ -6,6 +6,7 @@ g++ $SCRIPT_DIR/test_runner.cpp \
|
||||||
$CORE_SRC_DIR/system/process/CommandLineArgs.cpp \
|
$CORE_SRC_DIR/system/process/CommandLineArgs.cpp \
|
||||||
$CORE_SRC_DIR/base_types/Error.cpp \
|
$CORE_SRC_DIR/base_types/Error.cpp \
|
||||||
$CORE_SRC_DIR/base_types/Index.cpp \
|
$CORE_SRC_DIR/base_types/Index.cpp \
|
||||||
|
$CORE_SRC_DIR/base_types/Char.cpp \
|
||||||
$CORE_SRC_DIR/data_structures/String.cpp \
|
$CORE_SRC_DIR/data_structures/String.cpp \
|
||||||
$CORE_SRC_DIR/filesystem/FileSystemPath.cpp \
|
$CORE_SRC_DIR/filesystem/FileSystemPath.cpp \
|
||||||
$CORE_SRC_DIR/logging/Logger.cpp \
|
$CORE_SRC_DIR/logging/Logger.cpp \
|
||||||
|
|
Loading…
Reference in a new issue