-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
mil_tools/os/FileDescriptor.cpp: Add file descriptor class for file/p…
…ty/pipes
- Loading branch information
Showing
7 changed files
with
271 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* | ||
* os.hpp - High-level OS utilities | ||
*/ | ||
#pragma once | ||
|
||
#include <fcntl.h> | ||
#include <pty.h> | ||
#include <string.h> | ||
#include <unistd.h> | ||
|
||
#include <stdexcept> | ||
#include <string> | ||
#include <tuple> | ||
#include <vector> | ||
|
||
#include "mil_tools/os/FileDescriptor.hpp" | ||
|
||
namespace mil_tools::os | ||
{ | ||
/// Opens a file | ||
FileDescriptor open(std::string const& filename, int flags); | ||
/// Open a new pseudo-terminal pair (master, slave) | ||
std::tuple<FileDescriptor, FileDescriptor> openpty(); | ||
/// Closes a file descriptor | ||
void close(int fd); | ||
/// Reads a certain number of bytes from a file descriptor | ||
std::vector<char> read(int fd, size_t count); | ||
/// Writes a string to a file descriptor | ||
void write(int fd, std::vector<char> const& data); | ||
void write(int fd, std::string const& data); | ||
}; // namespace mil_tools::os |
45 changes: 45 additions & 0 deletions
45
src/mil_common/mil_tools/include/mil_tools/os/FileDescriptor.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
#pragma once | ||
|
||
#include <string.h> | ||
|
||
#include <stdexcept> | ||
#include <string> | ||
#include <tuple> | ||
#include <vector> | ||
|
||
namespace mil_tools::os | ||
{ | ||
class FileDescriptor | ||
{ | ||
private: | ||
int fd_; | ||
|
||
public: | ||
FileDescriptor() : fd_(-1) | ||
{ | ||
} | ||
explicit FileDescriptor(int fd) : fd_(fd) | ||
{ | ||
} | ||
~FileDescriptor(); | ||
inline int get() const | ||
{ | ||
return fd_; | ||
}; | ||
inline bool valid() const | ||
{ | ||
return fd_ >= 0; | ||
}; | ||
explicit operator int() const; | ||
FileDescriptor(FileDescriptor const&) = delete; | ||
FileDescriptor& operator=(FileDescriptor const&) = delete; | ||
FileDescriptor(FileDescriptor&& other); | ||
FileDescriptor& operator=(FileDescriptor&& other); | ||
void close(); | ||
std::vector<char> read(int size); | ||
std::string read_as_string(int size); | ||
void write(std::string const& data); | ||
void write(std::vector<char> const& data); | ||
}; | ||
|
||
} // namespace mil_tools::os |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
#include "mil_tools/os.hpp" | ||
|
||
#include "mil_tools/os/FileDescriptor.hpp" | ||
|
||
namespace mil_tools::os | ||
{ | ||
std::tuple<FileDescriptor, FileDescriptor> openpty() | ||
{ | ||
int master = -1, slave = -1; | ||
if (::openpty(&master, &slave, nullptr, nullptr, nullptr) == -1) | ||
{ | ||
throw std::runtime_error("openpty failed: " + std::string(strerror(errno))); | ||
} | ||
if (grantpt(master) < 0) | ||
{ | ||
throw std::runtime_error("grantpt failed: " + std::string(strerror(errno))); | ||
} | ||
if (unlockpt(master) < 0) | ||
{ | ||
throw std::runtime_error("unlockpt failed: " + std::string(strerror(errno))); | ||
} | ||
return { FileDescriptor(master), FileDescriptor(slave) }; | ||
} | ||
|
||
void close(int fd) | ||
{ | ||
if (::close(fd) == -1) | ||
{ | ||
throw std::runtime_error("close failed: " + std::string(strerror(errno))); | ||
} | ||
} | ||
|
||
std::vector<char> read(int fd, size_t count) | ||
{ | ||
std::vector<char> data(count); | ||
ssize_t n = ::read(fd, data.data(), count); | ||
if (n == -1) | ||
{ | ||
throw std::runtime_error("read failed: " + std::string(strerror(errno))); | ||
} | ||
data.resize(n); | ||
return data; | ||
} | ||
|
||
void write(int fd, std::vector<char> const& data) | ||
{ | ||
ssize_t total_written = 0; | ||
while (total_written < static_cast<ssize_t>(data.size())) | ||
{ | ||
ssize_t n = ::write(fd, data.data() + total_written, data.size() - total_written); | ||
if (n == -1) | ||
{ | ||
throw std::runtime_error("write failed: " + std::string(strerror(errno))); | ||
} | ||
total_written += n; | ||
} | ||
} | ||
|
||
void write(int fd, std::string const& data) | ||
{ | ||
write(fd, std::vector<char>(data.begin(), data.end())); | ||
} | ||
|
||
FileDescriptor open(std::string const& filename, int flags) | ||
{ | ||
auto fd = ::open(filename.c_str(), flags); | ||
if (fd < 0) | ||
{ | ||
throw std::runtime_error("open failed: " + std::string(strerror(errno))); | ||
} | ||
return FileDescriptor(fd); | ||
} | ||
} // namespace mil_tools::os |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
#include "mil_tools/os/FileDescriptor.hpp" | ||
|
||
#include "mil_tools/os.hpp" | ||
|
||
namespace mil_tools::os | ||
{ | ||
FileDescriptor::~FileDescriptor() | ||
{ | ||
close(); | ||
} | ||
|
||
FileDescriptor::operator int() const | ||
{ | ||
return fd_; | ||
}; | ||
|
||
FileDescriptor::FileDescriptor(FileDescriptor&& other) | ||
{ | ||
fd_ = other.fd_; | ||
other.fd_ = -1; | ||
} | ||
|
||
FileDescriptor& FileDescriptor::operator=(FileDescriptor&& other) | ||
{ | ||
if (this != &other) | ||
{ | ||
fd_ = other.fd_; | ||
other.fd_ = -1; | ||
} | ||
return *this; | ||
} | ||
|
||
void FileDescriptor::close() | ||
{ | ||
if (fd_ != -1) | ||
{ | ||
mil_tools::os::close(fd_); | ||
fd_ = -1; | ||
} | ||
} | ||
|
||
std::vector<char> FileDescriptor::read(int size) | ||
{ | ||
return mil_tools::os::read(fd_, size); | ||
} | ||
|
||
std::string FileDescriptor::read_as_string(int size) | ||
{ | ||
std::vector<char> raw = read(size); | ||
return std::string(raw.begin(), raw.end()); | ||
} | ||
|
||
void FileDescriptor::write(std::vector<char> const& data) | ||
{ | ||
mil_tools::os::write(fd_, data); | ||
} | ||
|
||
void FileDescriptor::write(std::string const& data) | ||
{ | ||
mil_tools::os::write(fd_, data); | ||
} | ||
|
||
} // namespace mil_tools::os |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
#include "mil_tools/os.hpp" | ||
|
||
#include <gtest/gtest.h> | ||
|
||
#include <cstdio> | ||
#include <fstream> | ||
#include <iostream> | ||
|
||
#include "mil_tools/fs/path.hpp" | ||
|
||
TEST(mil_tools_os, open) | ||
{ | ||
auto fd_null = mil_tools::os::open("/dev/null", O_RDWR); | ||
EXPECT_TRUE(fd_null.valid()); | ||
fd_null.close(); | ||
EXPECT_FALSE(fd_null.valid()); | ||
auto fd_readme = mil_tools::os::open(mil_tools::fs::path::expanduser("~/mil2/README.md"), O_RDONLY); | ||
EXPECT_EQ(fd_readme.read_as_string(5), "![Col"); | ||
} | ||
|
||
TEST(mil_tools_os, write) | ||
{ | ||
// create file if not eist | ||
std::ofstream(mil_tools::fs::path::expanduser("~/mil2/tmp.txt")); | ||
|
||
// write with fd | ||
std::string filename = mil_tools::fs::path::expanduser("~/mil2/tmp.txt"); | ||
auto fd = mil_tools::os::open(filename, O_RDWR | O_CREAT); | ||
mil_tools::os::write(fd.get(), "hello"); | ||
fd.write(" world"); | ||
fd.close(); | ||
|
||
// check contents | ||
std::ifstream file(filename); | ||
std::string line; | ||
std::getline(file, line); | ||
EXPECT_EQ(line, "hello world"); | ||
file.close(); | ||
|
||
// delete file | ||
std::remove(filename.c_str()); | ||
} | ||
|
||
int main(int argc, char **argv) | ||
{ | ||
testing::InitGoogleTest(&argc, argv); | ||
return RUN_ALL_TESTS(); | ||
} |