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
23namespace wreport {
24namespace sys {
25
32std::filesystem::path with_suffix(const std::filesystem::path& path,
33 const std::string& suffix);
34
40std::unique_ptr<struct stat> stat(const char* pathname);
41
47std::unique_ptr<struct stat> stat(const std::string& pathname);
48
54std::unique_ptr<struct stat> stat(const std::filesystem::path& path);
55
60void stat(const char* pathname, struct stat& st);
61
66void stat(const std::string& pathname, struct stat& st);
67
72void stat(const std::filesystem::path& path, struct stat& st);
73
79[[deprecated("Use std::filesystem::is_directory")]] bool
80isdir(const std::string& pathname);
81
83[[deprecated("Use std::filesystem::is_block_file")]] bool
84isblk(const std::string& pathname);
85
87[[deprecated("Use std::filesystem::is_character_file")]] bool
88ischr(const std::string& pathname);
89
91[[deprecated("Use std::filesystem::is_fifo")]] bool
92isfifo(const std::string& pathname);
93
95[[deprecated("Use std::filesystem::is_symlink")]] bool
96islnk(const std::string& pathname);
97
99[[deprecated("Use std::filesystem::is_regular_file")]] bool
100isreg(const std::string& pathname);
101
103[[deprecated("Use std::filesystem::is_socket")]] bool
104issock(const std::string& pathname);
105
107time_t timestamp(const std::filesystem::path& file);
108
110time_t timestamp(const std::filesystem::path& file, time_t def);
111
113size_t size(const std::filesystem::path& file);
114
116size_t size(const std::filesystem::path& file, size_t def);
117
119ino_t inode(const std::filesystem::path& file);
120
122ino_t inode(const std::filesystem::path& file, ino_t def);
123
125bool 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
135chdir(const std::string& dir);
136
138void chroot(const std::filesystem::path& dir);
139
141mode_t umask(mode_t mask);
142
144[[deprecated("Use std::filesystem::canonical")]] std::string
145abspath(const std::string& pathname);
146
152class MMap
153{
154 void* addr;
155 size_t length;
156
157public:
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{
194protected:
195 int fd = -1;
196
197public:
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{
348protected:
350 ::timespec ts[2];
351
352public:
355};
356
361{
362protected:
363 std::filesystem::path path_;
364
365public:
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
498
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{
551public:
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
592class Tempfile : public File
593{
594protected:
595 bool m_unlink_on_exit = true;
596
597public:
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
618class Tempdir : public Path
619{
620protected:
621 bool m_rmtree_on_exit = true;
622
623public:
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
638std::string read_file(const std::filesystem::path& file);
639[[deprecated("Use read_file(const std::filesystem::path&)")]] std::string
640read_file(const std::string& file);
641std::string read_file(const char* file);
642
649void 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
652write_file(const std::string& file, const std::string& data,
653 mode_t mode = 0777);
654void write_file(const char* file, const std::string& data, mode_t mode = 0777);
655
662void 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
665write_file(const std::string& file, const void* data, size_t size,
666 mode_t mode = 0777);
667void write_file(const char* file, const void* data, size_t size,
668 mode_t mode = 0777);
669
679void 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
683write_file_atomically(const std::string& file, const std::string& data,
684 mode_t mode = 0777);
685void write_file_atomically(const char* file, const std::string& data,
686 mode_t mode = 0777);
687
697void 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
701write_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.
706std::string mkdtemp(std::string templ);
707
710void mkFilePath(const std::string& file);
711#endif
712
718[[deprecated("use std::filesystem::remove")]] bool
719unlink_ifexists(const char* file);
720[[deprecated("use std::filesystem::remove")]] bool
721unlink_ifexists(const std::string& file);
722[[deprecated("use std::filesystem::remove")]] bool
723unlink_ifexists(const std::filesystem::path& file);
724
730bool rename_ifexists(const std::filesystem::path& src,
731 const std::filesystem::path& dst);
732
741[[deprecated("use std::filesystem::create_directory")]] bool
742mkdir_ifmissing(const std::filesystem::path& path);
743
750[[deprecated("use std::filesystem::create_directories")]] bool
751makedirs(const std::filesystem::path& path);
752
760std::filesystem::path which(const std::string& name);
761
763void unlink(const std::filesystem::path& pathname);
764
766void rmdir(const std::filesystem::path& pathname);
767
769void rmtree(const std::filesystem::path& pathname);
770
776bool rmtree_ifexists(const std::filesystem::path& pathname);
777[[deprecated("use rmtree_ifexists(const std::filesystem::path&)")]] bool
778rmtree_ifexists(const std::string& pathname);
779bool rmtree_ifexists(const char* pathname);
780
787[[deprecated("use std::filesystem::rename")]] void
788rename(const std::string& src_pathname, const std::string& dst_pathname);
789
795void touch(const std::filesystem::path& pathname, time_t ts);
796
802bool touch_ifexists(const std::filesystem::path& pathname, time_t ts);
803
807void clock_gettime(::clockid_t clk_id, ::timespec& ts);
808
812unsigned long long timesec_elapsed(const ::timespec& begin,
813 const ::timespec& until);
814
818struct 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
840void getrlimit(int resource, ::rlimit& rlim);
841
843void setrlimit(int resource, const ::rlimit& rlim);
844
847{
848 int resource;
849 ::rlimit orig;
850
851 OverrideRlimit(int resource, rlim_t rlim);
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
873template <typename T = char> class TempBuffer
874{
875 T* buffer = nullptr;
876
877public:
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
892void breakpoint();
893
894} // namespace sys
895} // namespace wreport
896
897#endif
Common operations on file descriptors.
Definition sys.h:193
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:550
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:153
File descriptor with a name.
Definition sys.h:361
std::string name() const
Return the file pathname.
Definition sys.h:379
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:347
RAII local memory buffer.
Definition sys.h:874
Open a temporary directory.
Definition sys.h:619
void rmtree_on_exit(bool val)
Change the rmtree-on-exit behaviour.
Open a temporary file.
Definition sys.h:593
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:819
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:390
~ManagedNamedFileDescriptor()
The destructor closes the file descriptor, but does not check errors on close().
Override an environment variable for the duration of this object.
Definition sys.h:860
Override a soft resource limit during the lifetime of the object.
Definition sys.h:847
void set(rlim_t rlim)
Change the limit value again.
Iterator for directory entries.
Definition sys.h:419
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:414
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.