Skip to content

Commit

Permalink
mil_tools/TemporaryFile.hpp: Add TemporaryFile class
Browse files Browse the repository at this point in the history
  • Loading branch information
cbrxyz committed Jan 6, 2025
1 parent 41fe4cd commit 16563f8
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 11 deletions.
7 changes: 7 additions & 0 deletions src/mil_common/mil_tools/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,11 @@ if(BUILD_TESTING)
$<INSTALL_INTERFACE:include>
)
target_link_libraries(${PROJECT_NAME}_os_test ${PROJECT_NAME})

ament_add_gtest(${PROJECT_NAME}_random_test test/random.cpp)
target_include_directories(${PROJECT_NAME}_random_test PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
target_link_libraries(${PROJECT_NAME}_random_test ${PROJECT_NAME})
endif()
87 changes: 87 additions & 0 deletions src/mil_common/mil_tools/include/mil_tools/os/TemporaryFile.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#pragma once

#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

#include <filesystem>
#include <iostream>
#include <string>
#include <vector>

#include "mil_tools/os/FileDescriptor.hpp"
#include "mil_tools/string.hpp"

namespace mil_tools::os
{

class TemporaryFile
{
private:
std::string name_;
std::string tmp_path_ = std::filesystem::temp_directory_path().string();
void create()
{
char* name = path().data();
int raw_fd = mkstemp(name);
if (raw_fd < 0)
{
throw std::runtime_error("Failed to create temporary file " + path() + ": " + strerror(errno));
}
name_ = mil_tools::string::removeprefix(name, tmp_path_);
fd_ = FileDescriptor(raw_fd);
}
FileDescriptor fd_;

public:
TemporaryFile() : name_("tmpXXXXXX")
{
create();
};
explicit TemporaryFile(std::string const& name) : name_(name)
{
create();
};
inline std::string name() const
{
return name_;
}
inline std::string path() const
{
return tmp_path_ + "/" + name_;
}
~TemporaryFile()
{
close();
};
inline bool valid()
{
return fd_.valid();
}
void close()
{
::unlink(path().data());
fd_.close();
};
void write(std::string const& data)
{
fd_.write(data);
fsync(fd_.get());
};
void write(std::vector<char> const& data)
{
fd_.write(data);
fsync(fd_.get());
};
std::string read_as_string(int size)
{
return fd_.read_as_string(size);
};
std::vector<char> read(int size)
{
return fd_.read(size);
};
};

} // namespace mil_tools::os
20 changes: 9 additions & 11 deletions src/mil_common/mil_tools/test/os.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <iostream>

#include "mil_tools/fs/path.hpp"
#include "mil_tools/os/TemporaryFile.hpp"

TEST(mil_tools_os, open)
{
Expand All @@ -21,24 +22,21 @@ TEST(mil_tools_os, open)
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();
mil_tools::os::TemporaryFile tmpfile;
tmpfile.write("hello world");

// check contents
std::ifstream file(filename);
std::ifstream file(tmpfile.path());
assert(file.is_open());
std::string line;
std::getline(file, line);
EXPECT_EQ(line, "hello world");
file.close();
tmpfile.close();

// delete file
std::remove(filename.c_str());
// ensure temp file was actually deleted
file.open(tmpfile.path());
EXPECT_FALSE(file.is_open());
}

int main(int argc, char **argv)
Expand Down

0 comments on commit 16563f8

Please sign in to comment.