libwreport 3.40
sys.h
1#ifndef WREPORT_SYS_H
2#define WREPORT_SYS_H
3
10
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
192class FileDescriptor
193{
194protected:
195 int fd = -1;
196
197public:
198 FileDescriptor();
199 FileDescriptor(FileDescriptor&& o);
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
346class PreserveFileTimes
347{
348protected:
350 ::timespec ts[2];
351
352public:
353 explicit PreserveFileTimes(FileDescriptor fd);
354 ~PreserveFileTimes();
355};
356
360class NamedFileDescriptor : public FileDescriptor
361{
362protected:
363 std::filesystem::path path_;
364
365public:
366 NamedFileDescriptor(int fd, const std::filesystem::path& path);
367 NamedFileDescriptor(NamedFileDescriptor&&);
368 NamedFileDescriptor& operator=(NamedFileDescriptor&&);
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
389struct ManagedNamedFileDescriptor : public NamedFileDescriptor
390{
391 using NamedFileDescriptor::NamedFileDescriptor;
392
393 ManagedNamedFileDescriptor(ManagedNamedFileDescriptor&&) = default;
394 ManagedNamedFileDescriptor(const ManagedNamedFileDescriptor&) = delete;
395
404
405 ManagedNamedFileDescriptor&
406 operator=(const ManagedNamedFileDescriptor&) = delete;
407 ManagedNamedFileDescriptor& operator=(ManagedNamedFileDescriptor&&);
408};
409
413struct Path : public ManagedNamedFileDescriptor
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
549class File : public ManagedNamedFileDescriptor
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
838
840void getrlimit(int resource, ::rlimit& rlim);
841
843void setrlimit(int resource, const ::rlimit& rlim);
844
846struct OverrideRlimit
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
859struct OverrideEnvironment
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);
869 ~OverrideEnvironment();
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.
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.
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.
void rmtree_on_exit(bool val)
Change the rmtree-on-exit behaviour.
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
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.
~ManagedNamedFileDescriptor()
The destructor closes the file descriptor, but does not check errors on close().
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.
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.