return tl::make_unexpected(fmt::format("cannot open file {}: {}", fname, ::strerror(errno)));
}
- if (!rspamd_file_lock(fd, FALSE)) {
+ if (!rspamd_file_lock(fd, TRUE)) {
close(fd);
return tl::make_unexpected(fmt::format("cannot lock file {}: {}", fname, ::strerror(errno)));
}
- auto ret = raii_locked_file{fd};
+ auto ret = raii_locked_file{fname, fd, false};
if (fstat(ret.fd, &ret.st) == -1) {
return tl::make_unexpected(fmt::format("cannot stat file {}: {}", fname, ::strerror(errno)));
raii_locked_file::~raii_locked_file()
{
if (fd != -1) {
+ if (temp) {
+ (void)unlink(fname.c_str());
+ }
(void) rspamd_file_unlock(fd, FALSE);
close(fd);
}
return tl::make_unexpected(fmt::format("cannot create file {}: {}", fname, ::strerror(errno)));
}
- if (!rspamd_file_lock(fd, FALSE)) {
+ if (!rspamd_file_lock(fd, TRUE)) {
close(fd);
return tl::make_unexpected(fmt::format("cannot lock file {}: {}", fname, ::strerror(errno)));
}
- auto ret = raii_locked_file{fd};
+ auto ret = raii_locked_file{fname, fd, false};
+
+ if (fstat(ret.fd, &ret.st) == -1) {
+ return tl::make_unexpected(fmt::format("cannot stat file {}: {}", fname, ::strerror(errno)));
+ }
+
+ return ret;
+}
+
+auto raii_locked_file::create_temp(const char *fname, int flags, int perms) -> tl::expected<raii_locked_file, std::string>
+{
+ int oflags = flags;
+#ifdef O_CLOEXEC
+ oflags |= O_CLOEXEC | O_CREAT | O_EXCL;
+#endif
+ auto fd = ::open(fname, oflags, perms);
+
+ if (fd == -1) {
+ return tl::make_unexpected(fmt::format("cannot create file {}: {}", fname, ::strerror(errno)));
+ }
+
+ if (!rspamd_file_lock(fd, TRUE)) {
+ close(fd);
+ return tl::make_unexpected(fmt::format("cannot lock file {}: {}", fname, ::strerror(errno)));
+ }
+
+ auto ret = raii_locked_file{fname, fd, true};
if (fstat(ret.fd, &ret.st) == -1) {
return tl::make_unexpected(fmt::format("cannot stat file {}: {}", fname, ::strerror(errno)));
TEST_CASE("create and delete file") {
auto fname = random_fname();
{
- auto raii_locked_file = raii_locked_file::open(fname.c_str(), O_RDONLY);
+ auto raii_locked_file = raii_locked_file::create_temp(fname.c_str(), O_RDONLY, 00600);
CHECK(raii_locked_file.has_value());
CHECK(::access(fname.c_str(), R_OK) == 0);
}
CHECK(errno == ENOENT);
// Create one more time
{
- auto raii_locked_file = raii_locked_file::open(fname.c_str(), O_RDONLY);
+ auto raii_locked_file = raii_locked_file::create_temp(fname.c_str(), O_RDONLY, 00600);
CHECK(raii_locked_file.has_value());
CHECK(::access(fname.c_str(), R_OK) == 0);
}
TEST_CASE("check lock") {
auto fname = random_fname();
{
- auto raii_locked_file = raii_locked_file::open(fname.c_str(), O_RDONLY);
+ auto raii_locked_file = raii_locked_file::create_temp(fname.c_str(), O_RDONLY, 00600);
CHECK(raii_locked_file.has_value());
CHECK(::access(fname.c_str(), R_OK) == 0);
auto raii_locked_file2 = raii_locked_file::open(fname.c_str(), O_RDONLY);
static auto open(const char *fname, int flags) -> tl::expected<raii_locked_file, std::string>;
static auto create(const char *fname, int flags, int perms) -> tl::expected<raii_locked_file, std::string>;
+ static auto create_temp(const char *fname, int flags, int perms) -> tl::expected<raii_locked_file, std::string>;
- auto get_fd() const -> int
- {
+ auto get_fd() const -> int {
return fd;
}
- auto get_stat() const -> const struct stat&
- {
+ auto get_stat() const -> const struct stat& {
return st;
};
raii_locked_file& operator=(raii_locked_file &&other) noexcept {
std::swap(fd, other.fd);
+ std::swap(temp, other.temp);
+ std::swap(fname, other.fname);
std::swap(st, other.st);
return *this;
raii_locked_file(const raii_locked_file &other) = delete;
private:
int fd;
+ bool temp;
+ std::string fname;
struct stat st;
- explicit raii_locked_file(int _fd) : fd(_fd) {}
+ explicit raii_locked_file(const char *_fname, int _fd, bool _temp) : fd(_fd), temp(_temp), fname(_fname) {}
};
/**