Elaboradar  0.1
sys.h
1 #ifndef RADARELAB_UTILS_SYS_H
2 #define RADARELAB_UTILS_SYS_H
3 
11 #include <string>
12 #include <memory>
13 #include <iterator>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <sys/time.h>
17 #include <sys/resource.h>
18 #include <unistd.h>
19 #include <dirent.h>
20 #include <fcntl.h>
21 
22 namespace radarelab {
23 namespace utils {
24 namespace sys {
25 
31 std::unique_ptr<struct stat> stat(const std::string& pathname);
32 
37 void stat(const std::string& pathname, struct stat& st);
38 
44 bool isdir(const std::string& pathname);
45 
47 bool isblk(const std::string& pathname);
48 
50 bool ischr(const std::string& pathname);
51 
53 bool isfifo(const std::string& pathname);
54 
56 bool islnk(const std::string& pathname);
57 
59 bool isreg(const std::string& pathname);
60 
62 bool issock(const std::string& pathname);
63 
65 time_t timestamp(const std::string& file);
66 
68 time_t timestamp(const std::string& file, time_t def);
69 
71 size_t size(const std::string& file);
72 
74 size_t size(const std::string& file, size_t def);
75 
77 ino_t inode(const std::string& file);
78 
80 ino_t inode(const std::string& file, ino_t def);
81 
83 bool access(const std::string& s, int m);
84 
86 bool exists(const std::string& s);
87 
89 std::string getcwd();
90 
92 void chdir(const std::string& dir);
93 
95 void chroot(const std::string& dir);
96 
98 mode_t umask(mode_t mask);
99 
101 std::string abspath(const std::string& pathname);
102 
108 class MMap
109 {
110  void* addr;
111  size_t length;
112 
113 public:
114  MMap(const MMap&) = delete;
115  MMap(MMap&&);
116  MMap(void* addr, size_t length);
117  ~MMap();
118 
119  MMap& operator=(const MMap&) = delete;
120  MMap& operator=(MMap&&);
121 
122  size_t size() const { return length; }
123 
124  void munmap();
125 
126  template<typename T>
127  operator const T*() const { return reinterpret_cast<const T*>(addr); }
128 
129  template<typename T>
130  operator T*() const { return reinterpret_cast<T*>(addr); }
131 };
132 
145 {
146 protected:
147  int fd = -1;
148 
149 public:
150  FileDescriptor();
152  FileDescriptor(int fd);
153  virtual ~FileDescriptor();
154 
155  // We can copy at the FileDescriptor level because the destructor does not
156  // close fd
157  FileDescriptor(const FileDescriptor& o) = default;
158  FileDescriptor& operator=(const FileDescriptor& o) = default;
159 
167  [[noreturn]] virtual void throw_error(const char* desc);
168 
176  [[noreturn]] virtual void throw_runtime_error(const char* desc);
177 
179  bool is_open() const;
180 
186  void close();
187 
188  void fstat(struct stat& st);
189  void fchmod(mode_t mode);
190 
191  void futimens(const struct ::timespec ts[2]);
192 
193  void fsync();
194  void fdatasync();
195 
196  int dup();
197 
198  size_t read(void* buf, size_t count);
199 
207  bool read_all_or_retry(void* buf, size_t count);
208 
213  void read_all_or_throw(void* buf, size_t count);
214 
215  size_t write(const void* buf, size_t count);
216 
217  template<typename Container>
218  size_t write(const Container& c)
219  {
220  return write(c.data(), c.size() * sizeof(Container::value_type));
221  }
222 
224  void write_all_or_retry(const void* buf, size_t count);
225 
226  template<typename Container>
227  void write_all_or_retry(const Container& c)
228  {
229  write_all_or_retry(c.data(), c.size() * sizeof(typename Container::value_type));
230  }
231 
236  void write_all_or_throw(const void* buf, size_t count);
237 
238  template<typename Container>
239  void write_all_or_throw(const Container& c)
240  {
241  write_all_or_throw(c.data(), c.size() * sizeof(typename Container::value_type));
242  }
243 
244  off_t lseek(off_t offset, int whence=SEEK_SET);
245 
246  size_t pread(void* buf, size_t count, off_t offset);
247  size_t pwrite(const void* buf, size_t count, off_t offset);
248 
249  template<typename Container>
250  size_t pwrite(const Container& c, off_t offset)
251  {
252  return pwrite(c.data(), c.size() * sizeof(typename Container::value_type), offset);
253  }
254 
255  void ftruncate(off_t length);
256 
257  MMap mmap(size_t length, int prot, int flags, off_t offset=0);
258 
265  bool ofd_setlk(struct ::flock&);
266 
276  bool ofd_setlkw(struct ::flock&, bool retry_on_signal=true);
277 
283  bool ofd_getlk(struct ::flock&);
284 
286  int getfl();
287 
289  void setfl(int flags);
290 
291  operator int() const { return fd; }
292 };
293 
294 
299 {
300 protected:
301  FileDescriptor fd;
302  struct ::timespec ts[2];
303 
304 public:
307 };
308 
309 
310 
315 {
316 protected:
317  std::string pathname;
318 
319 public:
320  NamedFileDescriptor(int fd, const std::string& pathname);
323 
324  // We can copy at the NamedFileDescriptor level because the destructor does not
325  // close fd
326  NamedFileDescriptor(const NamedFileDescriptor& o) = default;
327  NamedFileDescriptor& operator=(const NamedFileDescriptor& o) = default;
328 
329  [[noreturn]] virtual void throw_error(const char* desc);
330  [[noreturn]] virtual void throw_runtime_error(const char* desc);
331 
333  const std::string& name() const { return pathname; }
334 };
335 
336 
341 {
342  using NamedFileDescriptor::NamedFileDescriptor;
343 
346 
355 
356  ManagedNamedFileDescriptor& operator=(const ManagedNamedFileDescriptor&) = delete;
358 };
359 
360 
365 {
369  struct iterator
370  {
371  using iterator_category = std::input_iterator_tag;
372  using value_type = struct dirent;
373  using difference_type = int;
374  using pointer = struct dirent*;
375  using reference = struct dirent&;
376 
377  Path* path = nullptr;
378  DIR* dir = nullptr;
379  struct dirent* cur_entry = nullptr;
380 
381  // End iterator
382  iterator();
383  // Start iteration on dir
384  iterator(Path& dir);
385  iterator(iterator&) = delete;
386  iterator(iterator&& o)
387  : dir(o.dir), cur_entry(o.cur_entry)
388  {
389  o.dir = nullptr;
390  o.cur_entry = nullptr;
391  }
392  ~iterator();
393  iterator& operator=(iterator&) = delete;
394  iterator& operator=(iterator&&) = delete;
395 
396  bool operator==(const iterator& i) const;
397  bool operator!=(const iterator& i) const;
398  struct dirent& operator*() const { return *cur_entry; }
399  struct dirent* operator->() const { return cur_entry; }
400  void operator++();
401 
403  bool isdir() const;
404 
406  bool isblk() const;
407 
409  bool ischr() const;
410 
412  bool isfifo() const;
413 
415  bool islnk() const;
416 
418  bool isreg() const;
419 
421  bool issock() const;
422 
424  Path open_path(int flags=0) const;
425  };
426 
427  using ManagedNamedFileDescriptor::ManagedNamedFileDescriptor;
428 
432  Path(const char* pathname, int flags=0, mode_t mode=0777);
436  Path(const std::string& pathname, int flags=0, mode_t mode=0777);
440  Path(Path& parent, const char* pathname, int flags=0, mode_t mode=0777);
441  Path(const Path&) = delete;
442  Path(Path&&) = default;
443  Path& operator=(const Path&) = delete;
444  Path& operator=(Path&&) = default;
445 
447  void open(int flags, mode_t mode=0777);
448 
449  DIR* fdopendir();
450 
453 
456 
457  int openat(const char* pathname, int flags, mode_t mode=0777);
458 
460  int openat_ifexists(const char* pathname, int flags, mode_t mode=0777);
461 
462  bool faccessat(const char* pathname, int mode, int flags=0);
463 
464  void fstatat(const char* pathname, struct stat& st);
465 
467  bool fstatat_ifexists(const char* pathname, struct stat& st);
468 
470  void lstatat(const char* pathname, struct stat& st);
471 
473  bool lstatat_ifexists(const char* pathname, struct stat& st);
474 
475  void unlinkat(const char* pathname);
476 
477  void mkdirat(const char* pathname, mode_t mode=0777);
478 
480  void rmdirat(const char* pathname);
481 
482  void symlinkat(const char* target, const char* linkpath);
483 
484  std::string readlinkat(const char* pathname);
485 
491  void rmtree();
492 
493  static std::string mkdtemp(const std::string& prefix);
494  static std::string mkdtemp(const char* prefix);
495  static std::string mkdtemp(char* pathname_template);
496 };
497 
498 
503 {
504 public:
505  using ManagedNamedFileDescriptor::ManagedNamedFileDescriptor;
506 
507  File(File&&) = default;
508  File(const File&) = delete;
509 
513  File(const std::string& pathname);
514 
516  File(const std::string& pathname, int flags, mode_t mode=0777);
517 
518  File& operator=(const File&) = delete;
519  File& operator=(File&&) = default;
520 
522  void open(int flags, mode_t mode=0777);
523 
528  bool open_ifexists(int flags, mode_t mode=0777);
529 
530  static File mkstemp(const std::string& prefix);
531  static File mkstemp(const char* prefix);
532  static File mkstemp(char* pathname_template);
533 };
534 
535 
541 class Tempfile : public File
542 {
543 protected:
544  bool m_unlink_on_exit = true;
545 
546 public:
547  Tempfile();
548  Tempfile(const std::string& prefix);
549  Tempfile(const char* prefix);
550  ~Tempfile();
551 
553  void unlink_on_exit(bool val);
554 
556  void unlink();
557 };
558 
559 
566 class Tempdir : public Path
567 {
568 protected:
569  bool m_rmtree_on_exit = true;
570 
571 public:
572  Tempdir();
573  Tempdir(const std::string& prefix);
574  Tempdir(const char* prefix);
575  ~Tempdir();
576 
578  void rmtree_on_exit(bool val);
579 };
580 
581 
583 std::string read_file(const std::string &file);
584 
591 void write_file(const std::string& file, const std::string& data, mode_t mode=0777);
592 
599 void write_file(const std::string& file, const void* data, size_t size, mode_t mode=0777);
600 
610 void write_file_atomically(const std::string& file, const std::string& data, mode_t mode=0777);
611 
621 void write_file_atomically(const std::string& file, const void* data, size_t size, mode_t mode=0777);
622 
623 #if 0
624 // Create a temporary directory based on a template.
625 std::string mkdtemp(std::string templ);
626 
629 void mkFilePath(const std::string& file);
630 #endif
631 
637 bool unlink_ifexists(const std::string& file);
638 
644 bool rename_ifexists(const std::string& src, const std::string& dst);
645 
654 bool mkdir_ifmissing(const char* pathname, mode_t mode=0777);
655 
656 bool mkdir_ifmissing(const std::string& pathname, mode_t mode=0777);
657 
664 bool makedirs(const std::string& pathname, mode_t=0777);
665 
673 std::string which(const std::string& name);
674 
676 void unlink(const std::string& pathname);
677 
679 void rmdir(const std::string& pathname);
680 
682 void rmtree(const std::string& pathname);
683 
689 bool rmtree_ifexists(const std::string& pathname);
690 
697 void rename(const std::string& src_pathname, const std::string& dst_pathname);
698 
702 void touch(const std::string& pathname, time_t ts);
703 
707 void clock_gettime(::clockid_t clk_id, struct ::timespec& ts);
708 
712 unsigned long long timesec_elapsed(const struct ::timespec& begin, const struct ::timespec& until);
713 
717 struct Clock
718 {
719  ::clockid_t clk_id;
720  struct ::timespec ts;
721 
725  Clock(::clockid_t clk_id);
726 
731  unsigned long long elapsed();
732 };
733 
739 void getrlimit(int resource, struct ::rlimit& rlim);
740 
742 void setrlimit(int resource, const struct ::rlimit& rlim);
743 
746 {
747  int resource;
748  struct ::rlimit orig;
749 
750  OverrideRlimit(int resource, rlim_t rlim);
751  ~OverrideRlimit();
752 
754  void set(rlim_t rlim);
755 };
756 
757 }
758 }
759 }
760 
761 #endif
void close()
Close the file descriptor, setting its value to -1.
bool ofd_setlk(struct ::flock &)
Open file description locks F_OFD_SETLK operation.
bool ofd_setlkw(struct ::flock &, bool retry_on_signal=true)
Open file description locks F_OFD_SETLKW operation.
void write_all_or_retry(const void *buf, size_t count)
Write all the data in buf, retrying partial writes.
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.
void setfl(int flags)
Set open flags for the file.
int getfl()
Get open flags for the file.
virtual void throw_error(const char *desc)
Throw an exception based on errno and the given message.
bool is_open() const
Check if the file descriptor is open (that is, if it is not -1)
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.
bool read_all_or_retry(void *buf, size_t count)
Read count bytes into bufr, retrying partial reads, stopping at EOF.
virtual void throw_runtime_error(const char *desc)
Throw a runtime_error unrelated from errno.
bool ofd_getlk(struct ::flock &)
Open file description locks F_OFD_GETLK operation.
Common operations on file descriptors.
Definition: sys.h:145
File(const std::string &pathname)
Create an unopened File object for the given pathname.
File(const std::string &pathname, int flags, mode_t mode=0777)
Wrapper around open(2)
void open(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 in the file system.
Definition: sys.h:503
Wraps a mmapped memory area, unmapping it on destruction.
Definition: sys.h:109
const std::string & name() const
Return the file pathname.
Definition: sys.h:333
virtual void throw_error(const char *desc)
Throw an exception based on errno and the given message.
virtual void throw_runtime_error(const char *desc)
Throw a runtime_error unrelated from errno.
File descriptor with a name.
Definition: sys.h:315
RAII mechanism to save restore file times at the end of some file operations.
Definition: sys.h:299
void rmtree_on_exit(bool val)
Change the rmtree-on-exit behaviour.
Open a temporary directory.
Definition: sys.h:567
void unlink_on_exit(bool val)
Change the unlink-on-exit behaviour.
void unlink()
Unlink the file right now.
Open a temporary file.
Definition: sys.h:542
String functions.
Definition: cart.cpp:4
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.
Access to clock_gettime.
Definition: sys.h:718
~ManagedNamedFileDescriptor()
The destructor closes the file descriptor, but does not check errors on ::close().
File descriptor that gets automatically closed in the object destructor.
Definition: sys.h:341
void set(rlim_t rlim)
Change the limit value again.
Override a soft resource limit during the lifetime of the object.
Definition: sys.h:746
Path open_path(int flags=0) const
Return a Path object for this entry.
Iterator for directory entries.
Definition: sys.h:370
Path(const char *pathname, int flags=0, mode_t mode=0777)
Open the given pathname with flags | O_PATH.
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 rmtree()
Delete the directory pointed to by this Path, with all its contents.
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
iterator end()
End iterator on all directory entries.
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
iterator begin()
Begin iterator on all directory entries.
void open(int flags, mode_t mode=0777)
Wrapper around open(2) with flags | O_PATH.
Path(const std::string &pathname, int flags=0, mode_t mode=0777)
Open the given pathname with flags | O_PATH.
Path(Path &parent, const char *pathname, int flags=0, mode_t mode=0777)
Open the given pathname calling parent.openat, with flags | O_PATH.
Wrap a path on the file system opened with O_PATH.
Definition: sys.h:365