libwreport 3.38
sys.h
1#ifndef WREPORT_SYS_H
2#define WREPORT_SYS_H
3
10
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
179class FileDescriptor
180{
181protected:
182 int fd = -1;
183
184public:
185 FileDescriptor();
186 FileDescriptor(FileDescriptor&& o);
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
333class PreserveFileTimes
334{
335protected:
337 ::timespec ts[2];
338
339public:
340 explicit PreserveFileTimes(FileDescriptor fd);
341 ~PreserveFileTimes();
342};
343
344
345
349class NamedFileDescriptor : public FileDescriptor
350{
351protected:
352 std::filesystem::path path_;
353
354public:
355 NamedFileDescriptor(int fd, const std::filesystem::path& path);
356 NamedFileDescriptor(NamedFileDescriptor&&);
357 NamedFileDescriptor& operator=(NamedFileDescriptor&&);
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
376struct ManagedNamedFileDescriptor : public NamedFileDescriptor
377{
378 using NamedFileDescriptor::NamedFileDescriptor;
379
380 ManagedNamedFileDescriptor(ManagedNamedFileDescriptor&&) = default;
381 ManagedNamedFileDescriptor(const ManagedNamedFileDescriptor&) = delete;
382
391
392 ManagedNamedFileDescriptor& operator=(const ManagedNamedFileDescriptor&) = delete;
393 ManagedNamedFileDescriptor& operator=(ManagedNamedFileDescriptor&&);
394};
395
396
400struct Path : public ManagedNamedFileDescriptor
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
535class File : public ManagedNamedFileDescriptor
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
785
787void getrlimit(int resource, ::rlimit& rlim);
788
790void setrlimit(int resource, const ::rlimit& rlim);
791
793struct OverrideRlimit
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
807template<typename T = char>
808class TempBuffer
809{
810 T* buffer = nullptr;
811
812public:
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.
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: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.
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:406
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.