libwreport  3.40
sys.h
1 #ifndef WREPORT_SYS_H
2 #define WREPORT_SYS_H
3 
11 #include <dirent.h>
12 #include <fcntl.h>
13 #include <filesystem>
14 #include <iterator>
15 #include <memory>
16 #include <string>
17 #include <sys/resource.h>
18 #include <sys/stat.h>
19 #include <sys/time.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22 
23 namespace wreport {
24 namespace sys {
25 
32 std::filesystem::path with_suffix(const std::filesystem::path& path,
33  const std::string& suffix);
34 
40 std::unique_ptr<struct stat> stat(const char* pathname);
41 
47 std::unique_ptr<struct stat> stat(const std::string& pathname);
48 
54 std::unique_ptr<struct stat> stat(const std::filesystem::path& path);
55 
60 void stat(const char* pathname, struct stat& st);
61 
66 void stat(const std::string& pathname, struct stat& st);
67 
72 void stat(const std::filesystem::path& path, struct stat& st);
73 
79 [[deprecated("Use std::filesystem::is_directory")]] bool
80 isdir(const std::string& pathname);
81 
83 [[deprecated("Use std::filesystem::is_block_file")]] bool
84 isblk(const std::string& pathname);
85 
87 [[deprecated("Use std::filesystem::is_character_file")]] bool
88 ischr(const std::string& pathname);
89 
91 [[deprecated("Use std::filesystem::is_fifo")]] bool
92 isfifo(const std::string& pathname);
93 
95 [[deprecated("Use std::filesystem::is_symlink")]] bool
96 islnk(const std::string& pathname);
97 
99 [[deprecated("Use std::filesystem::is_regular_file")]] bool
100 isreg(const std::string& pathname);
101 
103 [[deprecated("Use std::filesystem::is_socket")]] bool
104 issock(const std::string& pathname);
105 
107 time_t timestamp(const std::filesystem::path& file);
108 
110 time_t timestamp(const std::filesystem::path& file, time_t def);
111 
113 size_t size(const std::filesystem::path& file);
114 
116 size_t size(const std::filesystem::path& file, size_t def);
117 
119 ino_t inode(const std::filesystem::path& file);
120 
122 ino_t inode(const std::filesystem::path& file, ino_t def);
123 
125 bool access(const std::filesystem::path& s, int m);
126 
128 [[deprecated("Use std::filesystem::exists")]] bool exists(const std::string& s);
129 
131 [[deprecated("Use std::filesystem::current_path")]] std::string getcwd();
132 
134 [[deprecated("Use std::filesystem::current_path")]] void
135 chdir(const std::string& dir);
136 
138 void chroot(const std::filesystem::path& dir);
139 
141 mode_t umask(mode_t mask);
142 
144 [[deprecated("Use std::filesystem::canonical")]] std::string
145 abspath(const std::string& pathname);
146 
152 class MMap
153 {
154  void* addr;
155  size_t length;
156 
157 public:
158  MMap(const MMap&) = delete;
159  MMap(MMap&&);
160  MMap(void* addr, size_t length);
161  ~MMap();
162 
163  MMap& operator=(const MMap&) = delete;
164  MMap& operator=(MMap&&);
165 
166  size_t size() const { return length; }
167 
168  void munmap();
169 
170  template <typename T> operator const T*() const
171  {
172  return reinterpret_cast<const T*>(addr);
173  }
174 
175  template <typename T> operator T*() const
176  {
177  return reinterpret_cast<T*>(addr);
178  }
179 };
180 
193 {
194 protected:
195  int fd = -1;
196 
197 public:
198  FileDescriptor();
200  explicit FileDescriptor(int fd);
201  virtual ~FileDescriptor();
202 
203  // We can copy at the FileDescriptor level because the destructor does not
204  // close fd
205  FileDescriptor(const FileDescriptor& o) = default;
206  FileDescriptor& operator=(const FileDescriptor& o) = default;
207 
215  [[noreturn]] virtual void throw_error(const char* desc);
216 
224  [[noreturn]] virtual void throw_runtime_error(const char* desc);
225 
227  bool is_open() const;
228 
234  void close();
235 
236  void fstat(struct stat& st);
237  void fchmod(mode_t mode);
238 
239  void futimens(const ::timespec ts[2]);
240 
241  void fsync();
242  void fdatasync();
243 
244  int dup();
245 
246  size_t read(void* buf, size_t count);
247 
255  bool read_all_or_retry(void* buf, size_t count);
256 
261  void read_all_or_throw(void* buf, size_t count);
262 
263  size_t write(const void* buf, size_t count);
264 
265  template <typename Container> size_t write(const Container& c)
266  {
267  return write(c.data(), c.size() * sizeof(Container::value_type));
268  }
269 
271  void write_all_or_retry(const void* buf, size_t count);
272 
273  template <typename Container> void write_all_or_retry(const Container& c)
274  {
275  write_all_or_retry(c.data(),
276  c.size() * sizeof(typename Container::value_type));
277  }
278 
283  void write_all_or_throw(const void* buf, size_t count);
284 
285  template <typename Container> void write_all_or_throw(const Container& c)
286  {
287  write_all_or_throw(c.data(),
288  c.size() * sizeof(typename Container::value_type));
289  }
290 
291  off_t lseek(off_t offset, int whence = SEEK_SET);
292 
293  size_t pread(void* buf, size_t count, off_t offset);
294  size_t pwrite(const void* buf, size_t count, off_t offset);
295 
296  template <typename Container>
297  size_t pwrite(const Container& c, off_t offset)
298  {
299  return pwrite(c.data(),
300  c.size() * sizeof(typename Container::value_type),
301  offset);
302  }
303 
304  void ftruncate(off_t length);
305 
306  MMap mmap(size_t length, int prot, int flags, off_t offset = 0);
307 
314  bool ofd_setlk(::flock&);
315 
325  bool ofd_setlkw(::flock&, bool retry_on_signal = true);
326 
332  bool ofd_getlk(::flock&);
333 
335  int getfl();
336 
338  void setfl(int flags);
339 
340  operator int() const { return fd; }
341 };
342 
347 {
348 protected:
349  FileDescriptor fd;
350  ::timespec ts[2];
351 
352 public:
353  explicit PreserveFileTimes(FileDescriptor fd);
355 };
356 
361 {
362 protected:
363  std::filesystem::path path_;
364 
365 public:
366  NamedFileDescriptor(int fd, const std::filesystem::path& path);
369 
370  // We can copy at the NamedFileDescriptor level because the destructor does
371  // not close fd
372  NamedFileDescriptor(const NamedFileDescriptor& o) = default;
373  NamedFileDescriptor& operator=(const NamedFileDescriptor& o) = default;
374 
375  [[noreturn]] virtual void throw_error(const char* desc) override;
376  [[noreturn]] virtual void throw_runtime_error(const char* desc) override;
377 
379  [[deprecated("use path() instead")]] std::string name() const
380  {
381  return path_.string();
382  }
383  const std::filesystem::path& path() const { return path_; }
384 };
385 
390 {
391  using NamedFileDescriptor::NamedFileDescriptor;
392 
395 
404 
406  operator=(const ManagedNamedFileDescriptor&) = delete;
408 };
409 
414 {
418  struct iterator
419  {
420  using iterator_category = std::input_iterator_tag;
421  using value_type = ::dirent;
422  using difference_type = int;
423  using pointer = ::dirent*;
424  using reference = ::dirent&;
425 
426  Path* path = nullptr;
427  DIR* dir = nullptr;
428  ::dirent* cur_entry = nullptr;
429 
430  // End iterator
431  iterator();
432  // Start iteration on dir
433  explicit iterator(Path& dir);
434  iterator(iterator&) = delete;
435  iterator(iterator&& o) : dir(o.dir), cur_entry(o.cur_entry)
436  {
437  o.dir = nullptr;
438  o.cur_entry = nullptr;
439  }
440  ~iterator();
441  iterator& operator=(iterator&) = delete;
442  iterator& operator=(iterator&&) = delete;
443 
444  bool operator==(const iterator& i) const;
445  bool operator!=(const iterator& i) const;
446  ::dirent& operator*() const { return *cur_entry; }
447  ::dirent* operator->() const { return cur_entry; }
448  iterator& operator++();
449 
451  bool isdir() const;
452 
454  bool isblk() const;
455 
457  bool ischr() const;
458 
460  bool isfifo() const;
461 
463  bool islnk() const;
464 
466  bool isreg() const;
467 
469  bool issock() const;
470 
472  Path open_path(int flags = 0) const;
473  };
474 
475  using ManagedNamedFileDescriptor::ManagedNamedFileDescriptor;
476 
480  explicit Path(const std::filesystem::path& pathname, int flags = 0,
481  mode_t mode = 0777);
485  Path(Path& parent, const char* pathname, int flags = 0, mode_t mode = 0777);
486  Path(const Path&) = delete;
487  Path(Path&&) = default;
488  Path& operator=(const Path&) = delete;
489  Path& operator=(Path&&) = default;
490 
492  void open(int flags, mode_t mode = 0777);
493 
494  DIR* fdopendir();
495 
497  iterator begin();
498 
500  iterator end();
501 
502  int openat(const char* pathname, int flags, mode_t mode = 0777);
503 
505  int openat_ifexists(const char* pathname, int flags, mode_t mode = 0777);
506 
507  bool faccessat(const char* pathname, int mode, int flags = 0);
508 
509  void fstatat(const char* pathname, struct stat& st);
510 
512  bool fstatat_ifexists(const char* pathname, struct stat& st);
513 
515  void lstatat(const char* pathname, struct stat& st);
516 
518  bool lstatat_ifexists(const char* pathname, struct stat& st);
519 
520  void unlinkat(const char* pathname);
521 
522  void mkdirat(const char* pathname, mode_t mode = 0777);
523 
525  void rmdirat(const char* pathname);
526 
527  void symlinkat(const char* target, const char* linkpath);
528 
529  std::string readlinkat(const char* pathname);
530 
536  void rmtree();
537 
538  static std::string mkdtemp(const std::filesystem::path& prefix);
539  [[deprecated(
540  "Use mkdtemp(const std::filesystem::path&)")]] static std::string
541  mkdtemp(const std::string& prefix);
542  static std::string mkdtemp(const char* prefix);
543  static std::string mkdtemp(char* pathname_template);
544 };
545 
550 {
551 public:
552  using ManagedNamedFileDescriptor::ManagedNamedFileDescriptor;
553 
554  File(File&&) = default;
555  File(const File&) = delete;
556 
560  explicit File(const std::filesystem::path& path);
561  explicit File(const char* path);
562  [[deprecated("Use File(const std::filesystem::path&)")]] explicit File(
563  const std::string& path);
564 
566  File(const std::filesystem::path& path, int flags, mode_t mode = 0777);
567 
568  File& operator=(const File&) = delete;
569  File& operator=(File&&) = default;
570 
572  void open(int flags, mode_t mode = 0777);
573 
578  bool open_ifexists(int flags, mode_t mode = 0777);
579 
580  static File mkstemp(const std::filesystem::path& prefix);
581  [[deprecated("Use mkstemp(const std::filesysten::path&)")]] static File
582  mkstemp(const std::string& prefix);
583  static File mkstemp(const char* prefix);
584  static File mkstemp(char* pathname_template);
585 };
586 
592 class Tempfile : public File
593 {
594 protected:
595  bool m_unlink_on_exit = true;
596 
597 public:
598  Tempfile();
599  explicit Tempfile(const std::filesystem::path& prefix);
600  [[deprecated("Use Tempfile(const std::string&)")]] explicit Tempfile(
601  const std::string& prefix);
602  explicit Tempfile(const char* prefix);
603  ~Tempfile();
604 
606  void unlink_on_exit(bool val);
607 
609  void unlink();
610 };
611 
618 class Tempdir : public Path
619 {
620 protected:
621  bool m_rmtree_on_exit = true;
622 
623 public:
624  Tempdir();
625  explicit Tempdir(const std::filesystem::path& prefix);
626  [[deprecated(
627  "Use Tempdir(const "
628  "std::filesystem::path&)")]] explicit Tempdir(const std::string&
629  prefix);
630  explicit Tempdir(const char* prefix);
631  ~Tempdir();
632 
634  void rmtree_on_exit(bool val);
635 };
636 
638 std::string read_file(const std::filesystem::path& file);
639 [[deprecated("Use read_file(const std::filesystem::path&)")]] std::string
640 read_file(const std::string& file);
641 std::string read_file(const char* file);
642 
649 void write_file(const std::filesystem::path& file, const std::string& data,
650  mode_t mode = 0777);
651 [[deprecated("Use write_file(const std::filesystem::path&, …)")]] void
652 write_file(const std::string& file, const std::string& data,
653  mode_t mode = 0777);
654 void write_file(const char* file, const std::string& data, mode_t mode = 0777);
655 
662 void write_file(const std::filesystem::path& file, const void* data,
663  size_t size, mode_t mode = 0777);
664 [[deprecated("Use write_file(const std::filesystem::path&, …)")]] void
665 write_file(const std::string& file, const void* data, size_t size,
666  mode_t mode = 0777);
667 void write_file(const char* file, const void* data, size_t size,
668  mode_t mode = 0777);
669 
679 void write_file_atomically(const std::filesystem::path& file,
680  const std::string& data, mode_t mode = 0777);
681 [[deprecated(
682  "Use write_file_atomically(const std::filesystem::path&, …)")]] void
683 write_file_atomically(const std::string& file, const std::string& data,
684  mode_t mode = 0777);
685 void write_file_atomically(const char* file, const std::string& data,
686  mode_t mode = 0777);
687 
697 void write_file_atomically(const std::filesystem::path& file, const void* data,
698  size_t size, mode_t mode = 0777);
699 [[deprecated(
700  "Use write_file_atomically(const std::filesystem::path&, …)")]] void
701 write_file_atomically(const std::string& file, const void* data, size_t size,
702  mode_t mode = 0777);
703 
704 #if 0
705 // Create a temporary directory based on a template.
706 std::string mkdtemp(std::string templ);
707 
710 void mkFilePath(const std::string& file);
711 #endif
712 
718 [[deprecated("use std::filesystem::remove")]] bool
719 unlink_ifexists(const char* file);
720 [[deprecated("use std::filesystem::remove")]] bool
721 unlink_ifexists(const std::string& file);
722 [[deprecated("use std::filesystem::remove")]] bool
723 unlink_ifexists(const std::filesystem::path& file);
724 
730 bool rename_ifexists(const std::filesystem::path& src,
731  const std::filesystem::path& dst);
732 
741 [[deprecated("use std::filesystem::create_directory")]] bool
742 mkdir_ifmissing(const std::filesystem::path& path);
743 
750 [[deprecated("use std::filesystem::create_directories")]] bool
751 makedirs(const std::filesystem::path& path);
752 
760 std::filesystem::path which(const std::string& name);
761 
763 void unlink(const std::filesystem::path& pathname);
764 
766 void rmdir(const std::filesystem::path& pathname);
767 
769 void rmtree(const std::filesystem::path& pathname);
770 
776 bool rmtree_ifexists(const std::filesystem::path& pathname);
777 [[deprecated("use rmtree_ifexists(const std::filesystem::path&)")]] bool
778 rmtree_ifexists(const std::string& pathname);
779 bool rmtree_ifexists(const char* pathname);
780 
787 [[deprecated("use std::filesystem::rename")]] void
788 rename(const std::string& src_pathname, const std::string& dst_pathname);
789 
795 void touch(const std::filesystem::path& pathname, time_t ts);
796 
802 bool touch_ifexists(const std::filesystem::path& pathname, time_t ts);
803 
807 void clock_gettime(::clockid_t clk_id, ::timespec& ts);
808 
812 unsigned long long timesec_elapsed(const ::timespec& begin,
813  const ::timespec& until);
814 
818 struct Clock
819 {
820  ::clockid_t clk_id;
821  ::timespec ts;
822 
826  explicit Clock(::clockid_t clk_id);
827 
832  unsigned long long elapsed();
833 };
834 
839 void getrlimit(int resource, ::rlimit& rlim);
841 
843 void setrlimit(int resource, const ::rlimit& rlim);
844 
847 {
848  int resource;
849  ::rlimit orig;
850 
851  OverrideRlimit(int resource, rlim_t rlim);
852  ~OverrideRlimit();
853 
855  void set(rlim_t rlim);
856 };
857 
860 {
861  std::string name;
862  bool was_set = false;
863  std::string orig_value;
864 
865  // Unset the variable
866  explicit OverrideEnvironment(const std::string& name);
867  // Set the variable to the given value
868  OverrideEnvironment(const std::string& name, const std::string& value);
870 };
871 
873 template <typename T = char> class TempBuffer
874 {
875  T* buffer = nullptr;
876 
877 public:
878  explicit TempBuffer(size_t size) : buffer(new T[size]) {}
879  ~TempBuffer() { delete[] buffer; }
880  TempBuffer(const TempBuffer&) = delete;
881  TempBuffer(TempBuffer&&) = delete;
882  TempBuffer& operator=(const TempBuffer&) = delete;
883  TempBuffer& operator=(TempBuffer&&) = delete;
884 
885  T* data() { return buffer; }
886  const T* data() const { return buffer; }
887  operator T*() { return buffer; }
888  operator const T*() const { return buffer; }
889 };
890 
892 void breakpoint();
893 
894 } // namespace sys
895 } // namespace wreport
896 
897 #endif
virtual void throw_error(const char *desc)
Throw an exception based on errno and the given message.
std::string name() const
Return the file pathname.
Definition: sys.h:379
Clock(::clockid_t clk_id)
Initialize ts with the value of the given clock.
bool open_ifexists(int flags, mode_t mode=0777)
Wrap open(2) and return false instead of throwing an exception if open fails with ENOENT...
void unlink()
Unlink the file right now.
RAII mechanism to save restore file times at the end of some file operations.
Definition: sys.h:346
bool read_all_or_retry(void *buf, size_t count)
Read count bytes into bufr, retrying partial reads, stopping at EOF.
Wraps a mmapped memory area, unmapping it on destruction.
Definition: sys.h:152
bool is_open() const
Check if the file descriptor is open (that is, if it is not -1)
bool ofd_setlk(::flock &)
Open file description locks F_OFD_SETLK operation.
virtual void throw_runtime_error(const char *desc) override
Throw a runtime_error unrelated from errno.
void close()
Close the file descriptor, setting its value to -1.
Common operations on file descriptors.
Definition: sys.h:192
File in the file system.
Definition: sys.h:549
void write_all_or_throw(const void *buf, size_t count)
Write all the data in buf, throwing runtime_error in case of a partial write.
int getfl()
Get open flags for the file.
bool ofd_setlkw(::flock &, bool retry_on_signal=true)
Open file description locks F_OFD_SETLKW operation.
virtual void throw_runtime_error(const char *desc)
Throw a runtime_error unrelated from errno.
Override an environment variable for the duration of this object.
Definition: sys.h:859
iterator begin()
Begin iterator on all directory entries.
Path open_path(int flags=0) const
Return a Path object for this entry.
File descriptor with a name.
Definition: sys.h:360
void unlink_on_exit(bool val)
Change the unlink-on-exit behaviour.
RAII local memory buffer.
Definition: sys.h:873
void lstatat(const char *pathname, struct stat &st)
fstatat with the AT_SYMLINK_NOFOLLOW flag set
void write_all_or_retry(const void *buf, size_t count)
Write all the data in buf, retrying partial writes.
Iterator for directory entries.
Definition: sys.h:418
void rmtree_on_exit(bool val)
Change the rmtree-on-exit behaviour.
File descriptor that gets automatically closed in the object destructor.
Definition: sys.h:389
void open(int flags, mode_t mode=0777)
Wrapper around open(2)
Open a temporary directory.
Definition: sys.h:618
void setfl(int flags)
Set open flags for the file.
void open(int flags, mode_t mode=0777)
Wrapper around open(2) with flags | O_PATH.
Override a soft resource limit during the lifetime of the object.
Definition: sys.h:846
void read_all_or_throw(void *buf, size_t count)
Read all the data into buf, throwing runtime_error in case of a partial read.
iterator end()
End iterator on all directory entries.
String functions.
Definition: benchmark.h:13
unsigned long long elapsed()
Return the number of nanoseconds elapsed since the last time ts was updated.
void rmtree()
Delete the directory pointed to by this Path, with all its contents.
Path(const std::filesystem::path &pathname, int flags=0, mode_t mode=0777)
Open the given pathname with flags | O_PATH.
~ManagedNamedFileDescriptor()
The destructor closes the file descriptor, but does not check errors on ::close().
bool ofd_getlk(::flock &)
Open file description locks F_OFD_GETLK operation.
int openat_ifexists(const char *pathname, int flags, mode_t mode=0777)
Same as openat, but returns -1 if the file does not exist.
bool fstatat_ifexists(const char *pathname, struct stat &st)
fstatat, but in case of ENOENT returns false instead of throwing
bool lstatat_ifexists(const char *pathname, struct stat &st)
lstatat, but in case of ENOENT returns false instead of throwing
virtual void throw_error(const char *desc) override
Throw an exception based on errno and the given message.
Access to clock_gettime.
Definition: sys.h:818
Open a temporary file.
Definition: sys.h:592
Wrap a path on the file system opened with O_PATH.
Definition: sys.h:413
void rmdirat(const char *pathname)
unlinkat with the AT_REMOVEDIR flag set