blob: 56479ce3b1b6dd32eee5b994f0f69353bb6bf4d8 [file] [log] [blame]
John Park33858a32018-09-28 23:05:48 -07001#ifndef AOS_UTIL_FILE_H_
2#define AOS_UTIL_FILE_H_
Brian Silverman61175fb2016-03-13 15:35:56 -04003
James Kuszmaul0625b0d2022-09-21 11:38:48 -07004#include <fcntl.h>
Austin Schuhe3fc0532021-02-07 22:14:22 -08005#include <sys/stat.h>
James Kuszmaul0625b0d2022-09-21 11:38:48 -07006#include <sys/types.h>
davidjevans8b9b52f2021-09-17 08:57:30 -07007
8#include <memory>
Brian Silverman61175fb2016-03-13 15:35:56 -04009#include <string>
James Kuszmaul3ae42262019-11-08 12:33:41 -080010#include <string_view>
Austin Schuhcb108412019-10-13 16:09:54 -070011
James Kuszmaul0625b0d2022-09-21 11:38:48 -070012#include "absl/strings/numbers.h"
davidjevans8b9b52f2021-09-17 08:57:30 -070013#include "absl/types/span.h"
James Kuszmaul0625b0d2022-09-21 11:38:48 -070014#include "aos/scoped/scoped_fd.h"
Brian Silvermana9f2ec92020-10-06 18:00:53 -070015#include "glog/logging.h"
16
Brian Silverman61175fb2016-03-13 15:35:56 -040017namespace aos {
18namespace util {
19
20// Returns the complete contents of filename. LOG(FATAL)s if any errors are
21// encountered.
James Kuszmaul3ae42262019-11-08 12:33:41 -080022::std::string ReadFileToStringOrDie(const std::string_view filename);
Brian Silverman61175fb2016-03-13 15:35:56 -040023
Alex Perrycb7da4b2019-08-28 19:35:56 -070024// Creates filename if it doesn't exist and sets the contents to contents.
James Kuszmaul3ae42262019-11-08 12:33:41 -080025void WriteStringToFileOrDie(const std::string_view filename,
Austin Schuhe3fc0532021-02-07 22:14:22 -080026 const std::string_view contents,
27 mode_t permissions = S_IRWXU);
Alex Perrycb7da4b2019-08-28 19:35:56 -070028
Brian Silvermana9f2ec92020-10-06 18:00:53 -070029// Returns true if it succeeds or false if the filesystem is full.
30bool MkdirPIfSpace(std::string_view path, mode_t mode);
31
32inline void MkdirP(std::string_view path, mode_t mode) {
33 CHECK(MkdirPIfSpace(path, mode));
34}
Austin Schuhfccb2d02020-01-26 16:11:19 -080035
James Kuszmaulf8178092020-05-10 18:46:45 -070036bool PathExists(std::string_view path);
37
Austin Schuhe991fe22020-11-18 16:53:39 -080038// Recursively removes everything in the provided path. Ignores any errors it
39// runs across.
40void UnlinkRecursive(std::string_view path);
41
Austin Schuhe4d1a682021-10-01 15:04:50 -070042enum class FileOptions { kReadable, kWriteable };
43
davidjevans8b9b52f2021-09-17 08:57:30 -070044// Maps file from disk into memory
Austin Schuhe4d1a682021-10-01 15:04:50 -070045std::shared_ptr<absl::Span<uint8_t>> MMapFile(
46 const std::string &path, FileOptions options = FileOptions::kReadable);
davidjevans8b9b52f2021-09-17 08:57:30 -070047
James Kuszmaul0625b0d2022-09-21 11:38:48 -070048// Wrapper to handle reading the contents of a file into a buffer. Meant for
49// situations where the malloc'ing of ReadFileToStringOrDie is inappropriate,
50// but where you still want to read a file.
51template <int kBufferSize = 1024>
52class FileReader {
53 public:
54 FileReader(std::string_view filename)
55 : file_(open(::std::string(filename).c_str(), O_RDONLY)) {
56 PCHECK(file_.get() != -1) << ": opening " << filename;
57 memset(buffer_, 0, kBufferSize);
58 }
59 // Reads the entire contents of the file into the internal buffer and returns
60 // a string_view of it.
61 // Note: The result may not be null-terminated.
62 std::string_view ReadContents() {
63 PCHECK(0 == lseek(file_.get(), 0, SEEK_SET));
64 const ssize_t result = read(file_.get(), buffer_, sizeof(buffer_));
65 PCHECK(result >= 0);
66 return {buffer_, static_cast<size_t>(result)};
67 }
68 // Calls ReadContents() and attempts to convert the result into an integer, or
69 // dies trying.
70 int ReadInt() {
71 int result;
72 std::string_view contents = ReadContents();
73 CHECK(absl::SimpleAtoi(contents, &result))
74 << "Failed to parse \"" << contents << "\" as int.";
75 return result;
76 }
77
78 private:
79 aos::ScopedFD file_;
80 char buffer_[kBufferSize];
81};
82
James Kuszmaulfd43f4e2022-12-16 15:19:35 -080083// Simple interface to allow opening a file for writing and then writing it
84// without any malloc's.
85// TODO(james): It may make sense to add a ReadBytes() interface here that can
86// take a memory buffer to fill, to avoid the templating required by the
87// self-managed buffer of FileReader<>.
88class FileWriter {
89 public:
90 // The result of an individual call to WriteBytes().
91 // Because WriteBytes() may repeatedly call write() when partial writes occur,
92 // it is possible for a non-zero number of bytes to have been written while
93 // still having an error because a late call to write() failed.
94 struct WriteResult {
95 // Total number of bytes successfully written to the file.
96 size_t bytes_written;
97 // If the write was successful (return_code > 0), equal to bytes_written.
98 // Otherwise, equal to the return value of the final call to write.
99 int return_code;
100 };
101
102 FileWriter(std::string_view filename, mode_t permissions = S_IRWXU);
103
104 WriteResult WriteBytes(absl::Span<const uint8_t> bytes);
105 WriteResult WriteBytes(std::string_view bytes);
106 void WriteBytesOrDie(absl::Span<const uint8_t> bytes);
107 void WriteBytesOrDie(std::string_view bytes);
108 int fd() const { return file_.get(); }
109
110 private:
111 aos::ScopedFD file_;
112};
113
Brian Silverman61175fb2016-03-13 15:35:56 -0400114} // namespace util
115} // namespace aos
116
John Park33858a32018-09-28 23:05:48 -0700117#endif // AOS_UTIL_FILE_H_