libwreport  3.38
sys.h
1 #ifndef WREPORT_SYS_H
2 #define WREPORT_SYS_H
3 
11 #include <string>
12 #include <memory>
13 #include <iterator>
14 #include <filesystem>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <sys/time.h>
18 #include <sys/resource.h>
19 #include <unistd.h>
20 #include <dirent.h>
21 #include <fcntl.h>
22 
23 namespace wreport {
24 namespace sys {
25 
32 std::filesystem::path with_suffix(const std::filesystem::path& path, const std::string& suffix);
33 
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 isdir(const std::string& pathname);
80 
82 [[deprecated("Use std::filesystem::is_block_file")]] bool isblk(const std::string& pathname);
83 
85 [[deprecated("Use std::filesystem::is_character_file")]] bool ischr(const std::string& pathname);
86 
88 [[deprecated("Use std::filesystem::is_fifo")]] bool isfifo(const std::string& pathname);
89 
91 [[deprecated("Use std::filesystem::is_symlink")]] bool islnk(const std::string& pathname);
92 
94 [[deprecated("Use std::filesystem::is_regular_file")]] bool isreg(const std::string& pathname);
95 
97 [[deprecated("Use std::filesystem::is_socket")]] bool issock(const std::string& pathname);
98 
100 time_t timestamp(const std::filesystem::path& file);
101 
103 time_t timestamp(const std::filesystem::path& file, time_t def);
104 
106 size_t size(const std::filesystem::path& file);
107 
109 size_t size(const std::filesystem::path& file, size_t def);
110 
112 ino_t inode(const std::filesystem::path& file);
113 
115 ino_t inode(const std::filesystem::path& file, ino_t def);
116 
118 bool access(const std::filesystem::path& s, int m);
119 
121 [[deprecated("Use std::filesystem::exists")]] bool exists(const std::string& s);
122 
124 [[deprecated("Use std::filesystem::current_path")]] std::string getcwd();
125 
127 [[deprecated("Use std::filesystem::current_path")]] void chdir(const std::string& dir);
128 
130 void chroot(const std::filesystem::path& dir);
131 
133 mode_t umask(mode_t mask);
134 
136 [[deprecated("Use std::filesystem::canonical")]] std::string abspath(const std::string& pathname);
137 
143 class MMap
144 {
145  void* addr;
146  size_t length;
147 
148 public:
149  MMap(const MMap&) = delete;
150  MMap(MMap&&);
151  MMap(void* addr, size_t length);
152  ~MMap();
153 
154  MMap& operator=(const MMap&) = delete;
155  MMap& operator=(MMap&&);
156 
157  size_t size() const { return length; }
158 
159  void munmap();
160 
161  template<typename T>
162  operator const T*() const { return reinterpret_cast<const T*>(addr); }
163 
164  template<typename T>
165  operator T*() const { return reinterpret_cast<T*>(addr); }
166 };
167 
180 {
181 protected:
182  int fd = -1;
183 
184 public:
185  FileDescriptor();
187  explicit FileDescriptor(int fd);
188  virtual ~FileDescriptor();
189 
190  // We can copy at the FileDescriptor level because the destructor does not
191  // close fd
192  FileDescriptor(const FileDescriptor& o) = default;
193  FileDescriptor& operator=(const FileDescriptor& o) = default;
194 
202  [[noreturn]] virtual void throw_error(const char* desc);
203 
211  [[noreturn]] virtual void throw_runtime_error(const char* desc);
212 
214  bool is_open() const;
215 
221  void close();
222 
223  void fstat(struct stat& st);
224  void fchmod(mode_t mode);
225 
226  void futimens(const ::timespec ts[2]);
227 
228  void fsync();
229  void fdatasync();
230 
231  int dup();
232 
233  size_t read(void* buf, size_t count);
234 
242  bool read_all_or_retry(void* buf, size_t count);
243 
248  void read_all_or_throw(void* buf, size_t count);
249 
250  size_t write(const void* buf, size_t count);
251 
252  template<typename Container>
253  size_t write(const Container& c)
254  {
255  return write(c.data(), c.size() * sizeof(Container::value_type));
256  }
257 
259  void write_all_or_retry(const void* buf, size_t count);
260 
261  template<typename Container>
262  void write_all_or_retry(const Container& c)
263  {
264  write_all_or_retry(c.data(), c.size() * sizeof(typename Container::value_type));
265  }
266 
271  void write_all_or_throw(const void* buf, size_t count);
272 
273  template<typename Container>
274  void write_all_or_throw(const Container& c)
275  {
276  write_all_or_throw(c.data(), c.size() * sizeof(typename Container::value_type));
277  }
278 
279  off_t lseek(off_t offset, int whence=SEEK_SET);
280 
281  size_t pread(void* buf, size_t count, off_t offset);
282  size_t pwrite(const void* buf, size_t count, off_t offset);
283 
284  template<typename Container>
285  size_t pwrite(const Container& c, off_t offset)
286  {
287  return pwrite(c.data(), c.size() * sizeof(typename Container::value_type), offset);
288  }
289 
290  void ftruncate(off_t length);
291 
292  MMap mmap(size_t length, int prot, int flags, off_t offset=0);
293 
300  bool ofd_setlk(::flock&);
301 
311  bool ofd_setlkw(::flock&, bool retry_on_signal=true);
312 
318  bool ofd_getlk(::flock&);
319 
321  int getfl();
322 
324  void setfl(int flags);
325 
326  operator int() const { return fd; }
327 };
328 
329 
334 {
335 protected:
336  FileDescriptor fd;
337  ::timespec ts[2];
338 
339 public:
340  explicit PreserveFileTimes(FileDescriptor fd);
342 };
343 
344 
345 
350 {
351 protected:
352  std::filesystem::path path_;
353 
354 public:
355  NamedFileDescriptor(int fd, const std::filesystem::path& path);
358 
359  // We can copy at the NamedFileDescriptor level because the destructor does not
360  // close fd
361  NamedFileDescriptor(const NamedFileDescriptor& o) = default;
362  NamedFileDescriptor& operator=(const NamedFileDescriptor& o) = default;
363 
364  [[noreturn]] virtual void throw_error(const char* desc) override;
365  [[noreturn]] virtual void throw_runtime_error(const char* desc) override;
366 
368  [[deprecated("use path() instead")]] std::string name() const { return path_.string(); }
369  const std::filesystem::path& path() const { return path_; }
370 };
371 
372 
377 {
378  using NamedFileDescriptor::NamedFileDescriptor;
379 
382 
391 
392  ManagedNamedFileDescriptor& operator=(const ManagedNamedFileDescriptor&) = delete;
394 };
395 
396 
401 {
405  struct iterator
406  {
407  using iterator_category = std::input_iterator_tag;
408  using value_type = ::dirent;
409  using difference_type = int;
410  using pointer = ::dirent*;
411  using reference = ::dirent&;
412 
413  Path* path = nullptr;
414  DIR* dir = nullptr;
415  ::dirent* cur_entry = nullptr;
416 
417  // End iterator
418  iterator();
419  // Start iteration on dir
420  explicit iterator(Path& dir);
421  iterator(iterator&) = delete;
422  iterator(iterator&& o)
423  : dir(o.dir), cur_entry(o.cur_entry)
424  {
425  o.dir = nullptr;
426  o.cur_entry = nullptr;
427  }
428  ~iterator();
429  iterator& operator=(iterator&) = delete;
430  iterator& operator=(iterator&&) = delete;
431 
432  bool operator==(const iterator& i) const;
433  bool operator!=(const iterator& i) const;
434  ::dirent& operator*() const { return *cur_entry; }
435  ::dirent* operator->() const { return cur_entry; }
436  iterator& operator++();
437 
439  bool isdir() const;
440 
442  bool isblk() const;
443 
445  bool ischr() const;
446 
448  bool isfifo() const;
449 
451  bool islnk() const;
452 
454  bool isreg() const;
455 
457  bool issock() const;
458 
460  Path open_path(int flags=0) const;
461  };
462 
463  using ManagedNamedFileDescriptor::ManagedNamedFileDescriptor;
464 
468  explicit Path(const std::filesystem::path& pathname, int flags=0, mode_t mode=0777);
472  Path(Path& parent, const char* pathname, int flags=0, mode_t mode=0777);
473  Path(const Path&) = delete;
474  Path(Path&&) = default;
475  Path& operator=(const Path&) = delete;
476  Path& operator=(Path&&) = default;
477 
479  void open(int flags, mode_t mode=0777);
480 
481  DIR* fdopendir();
482 
485 
488 
489  int openat(const char* pathname, int flags, mode_t mode=0777);
490 
492  int openat_ifexists(const char* pathname, int flags, mode_t mode=0777);
493 
494  bool faccessat(const char* pathname, int mode, int flags=0);
495 
496  void fstatat(const char* pathname, struct stat& st);
497 
499  bool fstatat_ifexists(const char* pathname, struct stat& st);
500 
502  void lstatat(const char* pathname, struct stat& st);
503 
505  bool lstatat_ifexists(const char* pathname, struct stat& st);
506 
507  void unlinkat(const char* pathname);
508 
509  void mkdirat(const char* pathname, mode_t mode=0777);
510 
512  void rmdirat(const char* pathname);
513 
514  void symlinkat(const char* target, const char* linkpath);
515 
516  std::string readlinkat(const char* pathname);
517 
523  void rmtree();
524 
525  static std::string mkdtemp(const std::filesystem::path& prefix);
526  [[deprecated("Use mkdtemp(const std::filesystem::path&)")]] static std::string mkdtemp(const std::string& prefix);
527  static std::string mkdtemp(const char* prefix);
528  static std::string mkdtemp(char* pathname_template);
529 };
530 
531 
536 {
537 public:
538  using ManagedNamedFileDescriptor::ManagedNamedFileDescriptor;
539 
540  File(File&&) = default;
541  File(const File&) = delete;
542 
546  explicit File(const std::filesystem::path& path);
547  explicit File(const char* path);
548  [[deprecated("Use File(const std::filesystem::path&)")]] explicit File(const std::string& path);
549 
551  File(const std::filesystem::path& path, int flags, mode_t mode=0777);
552 
553  File& operator=(const File&) = delete;
554  File& operator=(File&&) = default;
555 
557  void open(int flags, mode_t mode=0777);
558 
563  bool open_ifexists(int flags, mode_t mode=0777);
564 
565  static File mkstemp(const std::filesystem::path& prefix);
566  [[deprecated("Use mkstemp(const std::filesysten::path&)")]] static File mkstemp(const std::string& prefix);
567  static File mkstemp(const char* prefix);
568  static File mkstemp(char* pathname_template);
569 };
570 
571 
577 class Tempfile : public File
578 {
579 protected:
580  bool m_unlink_on_exit = true;
581 
582 public:
583  Tempfile();
584  explicit Tempfile(const std::filesystem::path& prefix);
585  [[deprecated("Use Tempfile(const std::string&)")]] explicit Tempfile(const std::string& prefix);
586  explicit Tempfile(const char* prefix);
587  ~Tempfile();
588 
590  void unlink_on_exit(bool val);
591 
593  void unlink();
594 };
595 
596 
603 class Tempdir : public Path
604 {
605 protected:
606  bool m_rmtree_on_exit = true;
607 
608 public:
609  Tempdir();
610  explicit Tempdir(const std::filesystem::path& prefix);
611  [[deprecated("Use Tempdir(const std::filesystem::path&)")]] explicit Tempdir(const std::string& prefix);
612  explicit Tempdir(const char* prefix);
613  ~Tempdir();
614 
616  void rmtree_on_exit(bool val);
617 };
618 
620 std::string read_file(const std::filesystem::path& file);
621 [[deprecated("Use read_file(const std::filesystem::path&)")]] std::string read_file(const std::string& file);
622 std::string read_file(const char* file);
623 
630 void write_file(const std::filesystem::path& file, const std::string& data, mode_t mode=0777);
631 [[deprecated("Use write_file(const std::filesystem::path&, …)")]] void write_file(const std::string& file, const std::string& data, mode_t mode=0777);
632 void write_file(const char* file, const std::string& data, mode_t mode=0777);
633 
640 void write_file(const std::filesystem::path& file, const void* data, size_t size, mode_t mode=0777);
641 [[deprecated("Use write_file(const std::filesystem::path&, …)")]] void write_file(const std::string& file, const void* data, size_t size, mode_t mode=0777);
642 void write_file(const char* file, const void* data, size_t size, mode_t mode=0777);
643 
653 void write_file_atomically(const std::filesystem::path& file, const std::string& data, mode_t mode=0777);
654 [[deprecated("Use write_file_atomically(const std::filesystem::path&, …)")]] void write_file_atomically(const std::string& file, const std::string& data, mode_t mode=0777);
655 void write_file_atomically(const char* file, const std::string& data, mode_t mode=0777);
656 
666 void write_file_atomically(const std::filesystem::path& file, const void* data, size_t size, mode_t mode=0777);
667 [[deprecated("Use write_file_atomically(const std::filesystem::path&, …)")]] void write_file_atomically(const std::string& file, const void* data, size_t size, mode_t mode=0777);
668 
669 #if 0
670 // Create a temporary directory based on a template.
671 std::string mkdtemp(std::string templ);
672 
675 void mkFilePath(const std::string& file);
676 #endif
677 
683 [[deprecated("use std::filesystem::remove")]] bool unlink_ifexists(const char* file);
684 [[deprecated("use std::filesystem::remove")]] bool unlink_ifexists(const std::string& file);
685 [[deprecated("use std::filesystem::remove")]] bool unlink_ifexists(const std::filesystem::path& file);
686 
692 bool rename_ifexists(const std::filesystem::path& src, const std::filesystem::path& dst);
693 
702 [[deprecated("use std::filesystem::create_directory")]] bool mkdir_ifmissing(const std::filesystem::path& path);
703 
710 [[deprecated("use std::filesystem::create_directories")]] bool makedirs(const std::filesystem::path& path);
711 
719 std::filesystem::path which(const std::string& name);
720 
722 void unlink(const std::filesystem::path& pathname);
723 
725 void rmdir(const std::filesystem::path& pathname);
726 
728 void rmtree(const std::filesystem::path& pathname);
729 
735 bool rmtree_ifexists(const std::filesystem::path& pathname);
736 [[deprecated("use rmtree_ifexists(const std::filesystem::path&)")]] bool rmtree_ifexists(const std::string& pathname);
737 bool rmtree_ifexists(const char* pathname);
738 
745 [[deprecated("use std::filesystem::rename")]] void rename(const std::string& src_pathname, const std::string& dst_pathname);
746 
750 void touch(const std::filesystem::path& pathname, time_t ts);
751 
755 void clock_gettime(::clockid_t clk_id, ::timespec& ts);
756 
760 unsigned long long timesec_elapsed(const ::timespec& begin, const ::timespec& until);
761 
765 struct Clock
766 {
767  ::clockid_t clk_id;
768  ::timespec ts;
769 
773  explicit Clock(::clockid_t clk_id);
774 
779  unsigned long long elapsed();
780 };
781 
787 void getrlimit(int resource, ::rlimit& rlim);
788 
790 void setrlimit(int resource, const ::rlimit& rlim);
791 
794 {
795  int resource;
796  ::rlimit orig;
797 
798  OverrideRlimit(int resource, rlim_t rlim);
799  ~OverrideRlimit();
800 
802  void set(rlim_t rlim);
803 };
804 
805 
807 template<typename T = char>
809 {
810  T* buffer = nullptr;
811 
812 public:
813  explicit TempBuffer(size_t size)
814  : buffer(new T[size])
815  {
816  }
817  ~TempBuffer()
818  {
819  delete[] buffer;
820  }
821  TempBuffer(const TempBuffer&) = delete;
822  TempBuffer(TempBuffer&&) = delete;
823  TempBuffer& operator=(const TempBuffer&) = delete;
824  TempBuffer& operator=(TempBuffer&&) = delete;
825 
826  T* data() { return buffer; }
827  const T* data() const { return buffer; }
828  operator T*() { return buffer; }
829  operator const T*() const { return buffer; }
830 };
831 
832 }
833 }
834 
835 #endif
Common operations on file descriptors.
Definition: sys.h:180
void write_all_or_retry(const void *buf, size_t count)
Write all the data in buf, retrying partial writes.
bool ofd_setlkw(::flock &, bool retry_on_signal=true)
Open file description locks F_OFD_SETLKW operation.
void setfl(int flags)
Set open flags for the file.
bool read_all_or_retry(void *buf, size_t count)
Read count bytes into bufr, retrying partial reads, stopping at EOF.
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.
void close()
Close the file descriptor, setting its value to -1.
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.
bool ofd_setlk(::flock &)
Open file description locks F_OFD_SETLK operation.
int getfl()
Get open flags for the file.
bool is_open() const
Check if the file descriptor is open (that is, if it is not -1)
bool ofd_getlk(::flock &)
Open file description locks F_OFD_GETLK operation.
virtual void throw_runtime_error(const char *desc)
Throw a runtime_error unrelated from errno.
virtual void throw_error(const char *desc)
Throw an exception based on errno and the given message.
File in the file system.
Definition: sys.h:536
void open(int flags, mode_t mode=0777)
Wrapper around open(2)
File(const std::filesystem::path &path, int flags, mode_t mode=0777)
Wrapper around open(2)
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.
File(const std::filesystem::path &path)
Create an unopened File object for the given pathname.
Wraps a mmapped memory area, unmapping it on destruction.
Definition: sys.h:144
File descriptor with a name.
Definition: sys.h:350
std::string name() const
Return the file pathname.
Definition: sys.h:368
virtual void throw_error(const char *desc) override
Throw an exception based on errno and the given message.
virtual void throw_runtime_error(const char *desc) override
Throw a runtime_error unrelated from errno.
RAII mechanism to save restore file times at the end of some file operations.
Definition: sys.h:334
RAII local memory buffer.
Definition: sys.h:809
Open a temporary directory.
Definition: sys.h:604
void rmtree_on_exit(bool val)
Change the rmtree-on-exit behaviour.
Open a temporary file.
Definition: sys.h:578
void unlink_on_exit(bool val)
Change the unlink-on-exit behaviour.
void unlink()
Unlink the file right now.
String functions.
Definition: benchmark.h:13
Access to clock_gettime.
Definition: sys.h:766
Clock(::clockid_t clk_id)
Initialize ts with the value of the given clock.
unsigned long long elapsed()
Return the number of nanoseconds elapsed since the last time ts was updated.
File descriptor that gets automatically closed in the object destructor.
Definition: sys.h:377
~ManagedNamedFileDescriptor()
The destructor closes the file descriptor, but does not check errors on ::close().
Override a soft resource limit during the lifetime of the object.
Definition: sys.h:794
void set(rlim_t rlim)
Change the limit value again.
Iterator for directory entries.
Definition: sys.h:406
Path open_path(int flags=0) const
Return a Path object for this entry.
Wrap a path on the file system opened with O_PATH.
Definition: sys.h:401
Path(const std::filesystem::path &pathname, int flags=0, mode_t mode=0777)
Open the given pathname with flags | O_PATH.
bool lstatat_ifexists(const char *pathname, struct stat &st)
lstatat, but in case of ENOENT returns false instead of throwing
void lstatat(const char *pathname, struct stat &st)
fstatat with the AT_SYMLINK_NOFOLLOW flag set
int openat_ifexists(const char *pathname, int flags, mode_t mode=0777)
Same as openat, but returns -1 if the file does not exist.
void open(int flags, mode_t mode=0777)
Wrapper around open(2) with flags | O_PATH.
iterator begin()
Begin iterator on all directory entries.
bool fstatat_ifexists(const char *pathname, struct stat &st)
fstatat, but in case of ENOENT returns false instead of throwing
void rmdirat(const char *pathname)
unlinkat with the AT_REMOVEDIR flag set
void rmtree()
Delete the directory pointed to by this Path, with all its contents.
iterator end()
End iterator on all directory entries.
Path(Path &parent, const char *pathname, int flags=0, mode_t mode=0777)
Open the given pathname calling parent.openat, with flags | O_PATH.