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
23namespace wreport {
24namespace sys {
25
32std::filesystem::path with_suffix(const std::filesystem::path& path, const std::string& suffix);
33
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 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
100time_t timestamp(const std::filesystem::path& file);
101
103time_t timestamp(const std::filesystem::path& file, time_t def);
104
106size_t size(const std::filesystem::path& file);
107
109size_t size(const std::filesystem::path& file, size_t def);
110
112ino_t inode(const std::filesystem::path& file);
113
115ino_t inode(const std::filesystem::path& file, ino_t def);
116
118bool 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
130void chroot(const std::filesystem::path& dir);
131
133mode_t umask(mode_t mask);
134
136[[deprecated("Use std::filesystem::canonical")]] std::string abspath(const std::string& pathname);
137
143class MMap
144{
145 void* addr;
146 size_t length;
147
148public:
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{
181protected:
182 int fd = -1;
183
184public:
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{
335protected:
337 ::timespec ts[2];
338
339public:
342};
343
344
345
350{
351protected:
352 std::filesystem::path path_;
353
354public:
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{
537public:
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
577class Tempfile : public File
578{
579protected:
580 bool m_unlink_on_exit = true;
581
582public:
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
603class Tempdir : public Path
604{
605protected:
606 bool m_rmtree_on_exit = true;
607
608public:
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
620std::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);
622std::string read_file(const char* file);
623
630void 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);
632void write_file(const char* file, const std::string& data, mode_t mode=0777);
633
640void 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);
642void write_file(const char* file, const void* data, size_t size, mode_t mode=0777);
643
653void 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);
655void write_file_atomically(const char* file, const std::string& data, mode_t mode=0777);
656
666void 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.
671std::string mkdtemp(std::string templ);
672
675void 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
692bool 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
719std::filesystem::path which(const std::string& name);
720
722void unlink(const std::filesystem::path& pathname);
723
725void rmdir(const std::filesystem::path& pathname);
726
728void rmtree(const std::filesystem::path& pathname);
729
735bool rmtree_ifexists(const std::filesystem::path& pathname);
736[[deprecated("use rmtree_ifexists(const std::filesystem::path&)")]] bool rmtree_ifexists(const std::string& pathname);
737bool 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
750void touch(const std::filesystem::path& pathname, time_t ts);
751
755void clock_gettime(::clockid_t clk_id, ::timespec& ts);
756
760unsigned long long timesec_elapsed(const ::timespec& begin, const ::timespec& until);
761
765struct 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
787void getrlimit(int resource, ::rlimit& rlim);
788
790void setrlimit(int resource, const ::rlimit& rlim);
791
794{
795 int resource;
796 ::rlimit orig;
797
798 OverrideRlimit(int resource, rlim_t rlim);
800
802 void set(rlim_t rlim);
803};
804
805
807template<typename T = char>
809{
810 T* buffer = nullptr;
811
812public:
813 explicit TempBuffer(size_t size)
814 : buffer(new T[size])
815 {
816 }
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.