From: Steinar H. Gunderson Date: Fri, 19 Feb 2021 17:42:12 +0000 (+0100) Subject: Support filesystems that do not support O_TMPFILE, even on Linux. X-Git-Tag: 1.1.5~2 X-Git-Url: https://git.sesse.net/?p=plocate;a=commitdiff_plain;h=2ce489a666c51d516b1a1b40cd420397350c8f9f Support filesystems that do not support O_TMPFILE, even on Linux. Evidently, overlayfs does not support O_TMPFILE. Reported by Daniel Lewart. --- diff --git a/database-builder.cpp b/database-builder.cpp index da52cdb..75b05f6 100644 --- a/database-builder.cpp +++ b/database-builder.cpp @@ -485,24 +485,26 @@ DatabaseBuilder::DatabaseBuilder(const char *outfile, gid_t owner, int block_siz if (path.empty()) { path = "."; } + int fd = -1; #ifdef O_TMPFILE - int fd = open(path.c_str(), O_WRONLY | O_TMPFILE, 0640); - if (fd == -1) { + fd = open(path.c_str(), O_WRONLY | O_TMPFILE, 0640); + if (fd == -1 && errno != EOPNOTSUPP) { perror(path.c_str()); exit(1); } -#else - temp_filename = string(outfile) + ".XXXXXX"; - int fd = mkstemp(&temp_filename[0]); +#endif if (fd == -1) { - perror(temp_filename.c_str()); - exit(1); - } - if (fchmod(fd, 0640) == -1) { - perror("fchmod"); - exit(1); + temp_filename = string(outfile) + ".XXXXXX"; + fd = mkstemp(&temp_filename[0]); + if (fd == -1) { + perror(temp_filename.c_str()); + exit(1); + } + if (fchmod(fd, 0640) == -1) { + perror("fchmod"); + exit(1); + } } -#endif if (owner != (gid_t)-1) { if (fchown(fd, (uid_t)-1, owner) == -1) { @@ -679,22 +681,24 @@ void DatabaseBuilder::finish_corpus() fseek(outfp, 0, SEEK_SET); fwrite(&hdr, sizeof(hdr), 1, outfp); + if (!temp_filename.empty()) { + if (rename(temp_filename.c_str(), outfile.c_str()) == -1) { + perror("rename"); + exit(1); + } + } else { #ifdef O_TMPFILE - // Give the file a proper name, making it visible in the file system. - // TODO: It would be nice to be able to do this atomically, like with rename. - unlink(outfile.c_str()); - char procpath[256]; - snprintf(procpath, sizeof(procpath), "/proc/self/fd/%d", fileno(outfp)); - if (linkat(AT_FDCWD, procpath, AT_FDCWD, outfile.c_str(), AT_SYMLINK_FOLLOW) == -1) { - perror("linkat"); - exit(1); - } -#else - if (rename(temp_filename.c_str(), outfile.c_str()) == -1) { - perror("rename"); - exit(1); - } + // Give the file a proper name, making it visible in the file system. + // TODO: It would be nice to be able to do this atomically, like with rename. + unlink(outfile.c_str()); + char procpath[256]; + snprintf(procpath, sizeof(procpath), "/proc/self/fd/%d", fileno(outfp)); + if (linkat(AT_FDCWD, procpath, AT_FDCWD, outfile.c_str(), AT_SYMLINK_FOLLOW) == -1) { + perror("linkat"); + exit(1); + } #endif + } fclose(outfp); diff --git a/database-builder.h b/database-builder.h index 0c25476..89fbc7c 100644 --- a/database-builder.h +++ b/database-builder.h @@ -81,9 +81,7 @@ public: private: FILE *outfp; std::string outfile; -#ifndef O_TMPFILE std::string temp_filename; -#endif Header hdr; const int block_size; std::chrono::steady_clock::time_point corpus_start;