uvw  2.12.1
fs.h
1 #ifndef UVW_FS_INCLUDE_H
2 #define UVW_FS_INCLUDE_H
3 
4 #include <chrono>
5 #include <memory>
6 #include <string>
7 #include <utility>
8 #include <uv.h>
9 #include "loop.h"
10 #include "request.hpp"
11 #include "util.h"
12 
13 namespace uvw {
14 
15 namespace details {
16 
17 enum class UVFsType : std::underlying_type_t<uv_fs_type> {
18  UNKNOWN = UV_FS_UNKNOWN,
19  CUSTOM = UV_FS_CUSTOM,
20  OPEN = UV_FS_OPEN,
21  CLOSE = UV_FS_CLOSE,
22  READ = UV_FS_READ,
23  WRITE = UV_FS_WRITE,
24  SENDFILE = UV_FS_SENDFILE,
25  STAT = UV_FS_STAT,
26  LSTAT = UV_FS_LSTAT,
27  FSTAT = UV_FS_FSTAT,
28  FTRUNCATE = UV_FS_FTRUNCATE,
29  UTIME = UV_FS_UTIME,
30  FUTIME = UV_FS_FUTIME,
31  ACCESS = UV_FS_ACCESS,
32  CHMOD = UV_FS_CHMOD,
33  FCHMOD = UV_FS_FCHMOD,
34  FSYNC = UV_FS_FSYNC,
35  FDATASYNC = UV_FS_FDATASYNC,
36  UNLINK = UV_FS_UNLINK,
37  RMDIR = UV_FS_RMDIR,
38  MKDIR = UV_FS_MKDIR,
39  MKDTEMP = UV_FS_MKDTEMP,
40  RENAME = UV_FS_RENAME,
41  SCANDIR = UV_FS_SCANDIR,
42  LINK = UV_FS_LINK,
43  SYMLINK = UV_FS_SYMLINK,
44  READLINK = UV_FS_READLINK,
45  CHOWN = UV_FS_CHOWN,
46  FCHOWN = UV_FS_FCHOWN,
47  REALPATH = UV_FS_REALPATH,
48  COPYFILE = UV_FS_COPYFILE,
49  LCHOWN = UV_FS_LCHOWN,
50  OPENDIR = UV_FS_OPENDIR,
51  READDIR = UV_FS_READDIR,
52  CLOSEDIR = UV_FS_CLOSEDIR,
53  STATFS = UV_FS_STATFS,
54  MKSTEMP = UV_FS_MKSTEMP,
55  LUTIME = UV_FS_LUTIME
56 };
57 
58 enum class UVDirentTypeT : std::underlying_type_t<uv_dirent_type_t> {
59  UNKNOWN = UV_DIRENT_UNKNOWN,
60  FILE = UV_DIRENT_FILE,
61  DIR = UV_DIRENT_DIR,
62  LINK = UV_DIRENT_LINK,
63  FIFO = UV_DIRENT_FIFO,
64  SOCKET = UV_DIRENT_SOCKET,
65  CHAR = UV_DIRENT_CHAR,
66  BLOCK = UV_DIRENT_BLOCK
67 };
68 
69 enum class UVFileOpenFlags : int {
70  APPEND = UV_FS_O_APPEND,
71  CREAT = UV_FS_O_CREAT,
72  DIRECT = UV_FS_O_DIRECT,
73  DIRECTORY = UV_FS_O_DIRECTORY,
74  DSYNC = UV_FS_O_DSYNC,
75  EXCL = UV_FS_O_EXCL,
76  EXLOCK = UV_FS_O_EXLOCK,
77  FILEMAP = UV_FS_O_FILEMAP,
78  NOATIME = UV_FS_O_NOATIME,
79  NOCTTY = UV_FS_O_NOCTTY,
80  NOFOLLOW = UV_FS_O_NOFOLLOW,
81  NONBLOCK = UV_FS_O_NONBLOCK,
82  RANDOM = UV_FS_O_RANDOM,
83  RDONLY = UV_FS_O_RDONLY,
84  RDWR = UV_FS_O_RDWR,
85  SEQUENTIAL = UV_FS_O_SEQUENTIAL,
86  SHORT_LIVED = UV_FS_O_SHORT_LIVED,
87  SYMLINK = UV_FS_O_SYMLINK,
88  SYNC = UV_FS_O_SYNC,
89  TEMPORARY = UV_FS_O_TEMPORARY,
90  TRUNC = UV_FS_O_TRUNC,
91  WRONLY = UV_FS_O_WRONLY
92 };
93 
94 enum class UVCopyFileFlags : int {
95  EXCL = UV_FS_COPYFILE_EXCL,
96  FICLONE = UV_FS_COPYFILE_FICLONE,
97  FICLONE_FORCE = UV_FS_COPYFILE_FICLONE_FORCE
98 };
99 
100 enum class UVSymLinkFlags : int {
101  DIR = UV_FS_SYMLINK_DIR,
102  JUNCTION = UV_FS_SYMLINK_JUNCTION
103 };
104 
105 } // namespace details
106 
158 template<details::UVFsType e>
159 struct FsEvent {
160  FsEvent(const char *pathname) noexcept
161  : path{pathname} {}
162 
163  const char *path;
164 };
165 
172 template<>
173 struct FsEvent<details::UVFsType::READ> {
174  FsEvent(const char *pathname, std::unique_ptr<const char[]> buf, std::size_t sz) noexcept
175  : path{pathname}, data{std::move(buf)}, size{sz} {}
176 
177  const char *path;
178  std::unique_ptr<const char[]> data;
179  std::size_t size;
180 };
181 
188 template<>
189 struct FsEvent<details::UVFsType::WRITE> {
190  FsEvent(const char *pathname, std::size_t sz) noexcept
191  : path{pathname}, size{sz} {}
192 
193  const char *path;
194  std::size_t size;
195 };
196 
203 template<>
204 struct FsEvent<details::UVFsType::SENDFILE> {
205  FsEvent(const char *pathname, std::size_t sz) noexcept
206  : path{pathname}, size{sz} {}
207 
208  const char *path;
209  std::size_t size;
210 };
211 
218 template<>
219 struct FsEvent<details::UVFsType::STAT> {
220  FsEvent(const char *pathname, Stat curr) noexcept
221  : path{pathname}, stat{std::move(curr)} {}
222 
223  const char *path;
225 };
226 
233 template<>
234 struct FsEvent<details::UVFsType::FSTAT> {
235  FsEvent(const char *pathname, Stat curr) noexcept
236  : path{pathname}, stat{std::move(curr)} {}
237 
238  const char *path;
240 };
241 
248 template<>
249 struct FsEvent<details::UVFsType::LSTAT> {
250  FsEvent(const char *pathname, Stat curr) noexcept
251  : path{pathname}, stat{std::move(curr)} {}
252 
253  const char *path;
255 };
256 
263 template<>
264 struct FsEvent<details::UVFsType::STATFS> {
265  FsEvent(const char *pathname, Statfs curr) noexcept
266  : path{pathname}, statfs{std::move(curr)} {}
267 
268  const char *path;
270 };
271 
278 template<>
279 struct FsEvent<details::UVFsType::MKSTEMP> {
280  FsEvent(const char *pathname, std::size_t desc) noexcept
281  : path{pathname}, descriptor{desc} {}
282 
283  const char *path;
284  std::size_t descriptor;
285 };
286 
293 template<>
294 struct FsEvent<details::UVFsType::SCANDIR> {
295  FsEvent(const char *pathname, std::size_t sz) noexcept
296  : path{pathname}, size{sz} {}
297 
298  const char *path;
299  std::size_t size;
300 };
301 
308 template<>
309 struct FsEvent<details::UVFsType::READLINK> {
310  explicit FsEvent(const char *pathname, const char *buf, std::size_t sz) noexcept
311  : path{pathname}, data{buf}, size{sz} {}
312 
313  const char *path;
314  const char *data;
315  std::size_t size;
316 };
317 
324 template<>
325 struct FsEvent<details::UVFsType::READDIR> {
326  using EntryType = details::UVDirentTypeT;
327 
328  FsEvent(const char *name, EntryType type, bool eos) noexcept
329  : name{name}, type{type}, eos{eos} {}
330 
331  const char *name;
332  EntryType type;
333  bool eos;
334 };
335 
341 template<typename T>
342 class FsRequest: public Request<T, uv_fs_t> {
343 protected:
344  template<details::UVFsType e>
345  static void fsGenericCallback(uv_fs_t *req) {
346  if(auto ptr = Request<T, uv_fs_t>::reserve(req); req->result < 0) {
347  ptr->publish(ErrorEvent{req->result});
348  } else {
349  ptr->publish(FsEvent<e>{req->path});
350  }
351  }
352 
353  template<details::UVFsType e>
354  static void fsResultCallback(uv_fs_t *req) {
355  if(auto ptr = Request<T, uv_fs_t>::reserve(req); req->result < 0) {
356  ptr->publish(ErrorEvent{req->result});
357  } else {
358  ptr->publish(FsEvent<e>{req->path, static_cast<std::size_t>(req->result)});
359  }
360  }
361 
362  template<details::UVFsType e>
363  static void fsStatCallback(uv_fs_t *req) {
364  if(auto ptr = Request<T, uv_fs_t>::reserve(req); req->result < 0) {
365  ptr->publish(ErrorEvent{req->result});
366  } else {
367  ptr->publish(FsEvent<e>{req->path, req->statbuf});
368  }
369  }
370 
371  static void fsStatfsCallback(uv_fs_t *req) {
372  if(auto ptr = Request<T, uv_fs_t>::reserve(req); req->result < 0) {
373  ptr->publish(ErrorEvent{req->result});
374  } else {
375  ptr->publish(FsEvent<Type::STATFS>{req->path, *static_cast<Statfs *>(req->ptr)});
376  }
377  }
378 
379  template<typename... Args>
380  void cleanupAndInvoke(Args &&...args) {
381  uv_fs_req_cleanup(this->get());
382  this->invoke(std::forward<Args>(args)...);
383  }
384 
385  template<typename F, typename... Args>
386  void cleanupAndInvokeSync(F &&f, Args &&...args) {
387  uv_fs_req_cleanup(this->get());
388  std::forward<F>(f)(std::forward<Args>(args)..., nullptr);
389  }
390 
391 public:
392  using Time = std::chrono::duration<double>;
393  using Type = details::UVFsType;
394  using EntryType = details::UVDirentTypeT;
395 
397 };
398 
411 class FileReq final: public FsRequest<FileReq> {
412  static constexpr uv_file BAD_FD = -1;
413 
414  static void fsOpenCallback(uv_fs_t *req);
415  static void fsCloseCallback(uv_fs_t *req);
416  static void fsReadCallback(uv_fs_t *req);
417 
418 public:
419  using FileOpen = details::UVFileOpenFlags;
420 
421  using FsRequest::FsRequest;
422 
423  ~FileReq() noexcept;
424 
431  void close();
432 
437  bool closeSync();
438 
478  void open(const std::string &path, Flags<FileOpen> flags, int mode);
479 
517  bool openSync(const std::string &path, Flags<FileOpen> flags, int mode);
518 
528  void read(int64_t offset, unsigned int len);
529 
542  std::pair<bool, std::pair<std::unique_ptr<const char[]>, std::size_t>> readSync(int64_t offset, unsigned int len);
543 
557  void write(std::unique_ptr<char[]> buf, unsigned int len, int64_t offset);
558 
572  void write(char *buf, unsigned int len, int64_t offset);
573 
585  std::pair<bool, std::size_t> writeSync(std::unique_ptr<char[]> buf, unsigned int len, int64_t offset);
586 
593  void stat();
594 
602  std::pair<bool, Stat> statSync();
603 
610  void sync();
611 
616  bool syncSync();
617 
624  void datasync();
625 
630  bool datasyncSync();
631 
640  void truncate(int64_t offset);
641 
647  bool truncateSync(int64_t offset);
648 
659  void sendfile(FileHandle out, int64_t offset, std::size_t length);
660 
672  std::pair<bool, std::size_t> sendfileSync(FileHandle out, int64_t offset, std::size_t length);
673 
682  void chmod(int mode);
683 
689  bool chmodSync(int mode);
690 
702  void futime(Time atime, Time mtime);
703 
712  bool futimeSync(Time atime, Time mtime);
713 
723  void chown(Uid uid, Gid gid);
724 
731  bool chownSync(Uid uid, Gid gid);
732 
741  operator FileHandle() const noexcept;
742 
743 private:
744  std::unique_ptr<char[]> current{nullptr};
745  uv_buf_t buffer{};
746  uv_file file{BAD_FD};
747 };
748 
761 class FsReq final: public FsRequest<FsReq> {
762  static void fsReadlinkCallback(uv_fs_t *req);
763  static void fsReaddirCallback(uv_fs_t *req);
764 
765 public:
766  using CopyFile = details::UVCopyFileFlags;
767  using SymLink = details::UVSymLinkFlags;
768 
769  using FsRequest::FsRequest;
770 
771  ~FsReq() noexcept;
772 
781  void unlink(const std::string &path);
782 
788  bool unlinkSync(const std::string &path);
789 
799  void mkdir(const std::string &path, int mode);
800 
807  bool mkdirSync(const std::string &path, int mode);
808 
817  void mkdtemp(const std::string &tpl);
818 
828  std::pair<bool, const char *> mkdtempSync(const std::string &tpl);
829 
838  void mkstemp(const std::string &tpl);
839 
860  std::pair<bool, std::pair<std::string, std::size_t>> mkstempSync(const std::string &tpl);
861 
874  void lutime(const std::string &path, Time atime, Time mtime);
875 
885  bool lutimeSync(const std::string &path, Time atime, Time mtime);
886 
895  void rmdir(const std::string &path);
896 
902  bool rmdirSync(const std::string &path);
903 
913  void scandir(const std::string &path, int flags);
914 
925  std::pair<bool, std::size_t> scandirSync(const std::string &path, int flags);
926 
956  std::pair<bool, std::pair<EntryType, const char *>> scandirNext();
957 
966  void stat(const std::string &path);
967 
977  std::pair<bool, Stat> statSync(const std::string &path);
978 
987  void lstat(const std::string &path);
988 
998  std::pair<bool, Stat> lstatSync(const std::string &path);
999 
1011  void statfs(const std::string &path);
1012 
1025  std::pair<bool, Statfs> statfsSync(const std::string &path);
1026 
1036  void rename(const std::string &old, const std::string &path);
1037 
1044  bool renameSync(const std::string &old, const std::string &path);
1045 
1075  void copyfile(const std::string &old, const std::string &path, Flags<CopyFile> flags = Flags<CopyFile>{});
1076 
1096  bool copyfileSync(const std::string &old, const std::string &path, Flags<CopyFile> flags = Flags<CopyFile>{});
1097 
1107  void access(const std::string &path, int mode);
1108 
1115  bool accessSync(const std::string &path, int mode);
1116 
1126  void chmod(const std::string &path, int mode);
1127 
1134  bool chmodSync(const std::string &path, int mode);
1135 
1148  void utime(const std::string &path, Time atime, Time mtime);
1149 
1159  bool utimeSync(const std::string &path, Time atime, Time mtime);
1160 
1170  void link(const std::string &old, const std::string &path);
1171 
1178  bool linkSync(const std::string &old, const std::string &path);
1179 
1197  void symlink(const std::string &old, const std::string &path, Flags<SymLink> flags = Flags<SymLink>{});
1198 
1214  bool symlinkSync(const std::string &old, const std::string &path, Flags<SymLink> flags = Flags<SymLink>{});
1215 
1224  void readlink(const std::string &path);
1225 
1237  std::pair<bool, std::pair<const char *, std::size_t>> readlinkSync(const std::string &path);
1238 
1247  void realpath(const std::string &path);
1248 
1258  std::pair<bool, const char *> realpathSync(const std::string &path);
1259 
1270  void chown(const std::string &path, Uid uid, Gid gid);
1271 
1279  bool chownSync(const std::string &path, Uid uid, Gid gid);
1280 
1291  void lchown(const std::string &path, Uid uid, Gid gid);
1292 
1300  bool lchownSync(const std::string &path, Uid uid, Gid gid);
1301 
1314  void opendir(const std::string &path);
1315 
1326  bool opendirSync(const std::string &path);
1327 
1337  void closedir();
1338 
1348 
1359  void readdir();
1360 
1394  std::pair<bool, std::pair<EntryType, const char *>> readdirSync();
1395 
1396 private:
1397  uv_dirent_t dirents[1];
1398 };
1399 
1401 struct FsHelper {
1412  static OSFileDescriptor handle(FileHandle file) noexcept;
1413 
1424  static FileHandle open(OSFileDescriptor descriptor) noexcept;
1425 };
1426 
1427 } // namespace uvw
1428 
1429 #ifndef UVW_AS_LIB
1430 # include "fs.cpp"
1431 #endif
1432 
1433 #endif // UVW_FS_INCLUDE_H
The FileReq request.
Definition: fs.h:411
std::pair< bool, std::size_t > sendfileSync(FileHandle out, int64_t offset, std::size_t length)
Sync sendfile.
void futime(Time atime, Time mtime)
Async futime.
bool truncateSync(int64_t offset)
Sync ftruncate.
void truncate(int64_t offset)
Async ftruncate.
void datasync()
Async fdatasync.
void chmod(int mode)
Async fchmod.
bool chmodSync(int mode)
Sync fchmod.
bool futimeSync(Time atime, Time mtime)
Sync futime.
std::pair< bool, std::size_t > writeSync(std::unique_ptr< char[]> buf, unsigned int len, int64_t offset)
Sync write.
std::pair< bool, std::pair< std::unique_ptr< const char[]>, std::size_t > > readSync(int64_t offset, unsigned int len)
Sync read.
void open(const std::string &path, Flags< FileOpen > flags, int mode)
Async open.
void chown(Uid uid, Gid gid)
Async fchown.
bool syncSync()
Sync fsync.
bool closeSync()
Sync close.
std::pair< bool, Stat > statSync()
Sync fstat.
void sync()
Async fsync.
bool chownSync(Uid uid, Gid gid)
Sync fchown.
void close()
Async close.
void stat()
Async fstat.
bool datasyncSync()
Sync fdatasync.
void sendfile(FileHandle out, int64_t offset, std::size_t length)
Async sendfile.
void read(int64_t offset, unsigned int len)
Async read.
void write(char *buf, unsigned int len, int64_t offset)
Async write.
void write(std::unique_ptr< char[]> buf, unsigned int len, int64_t offset)
Async write.
bool openSync(const std::string &path, Flags< FileOpen > flags, int mode)
Sync open.
Utility class to handle flags.
Definition: util.h:80
The FsReq request.
Definition: fs.h:761
bool closedirSync()
Closes synchronously a directory stream.
void readdir()
Iterates asynchronously over a directory stream one entry at a time.
void access(const std::string &path, int mode)
Async access.
void link(const std::string &old, const std::string &path)
Async link.
bool chownSync(const std::string &path, Uid uid, Gid gid)
Sync chown.
void copyfile(const std::string &old, const std::string &path, Flags< CopyFile > flags=Flags< CopyFile >{})
Copies a file asynchronously from a path to a new one.
void mkstemp(const std::string &tpl)
Async mkstemp.
bool copyfileSync(const std::string &old, const std::string &path, Flags< CopyFile > flags=Flags< CopyFile >{})
Copies a file synchronously from a path to a new one.
void statfs(const std::string &path)
Async statfs.
bool rmdirSync(const std::string &path)
Sync rmdir.
void closedir()
Closes asynchronously a directory stream.
std::pair< bool, const char * > realpathSync(const std::string &path)
Sync realpath.
bool symlinkSync(const std::string &old, const std::string &path, Flags< SymLink > flags=Flags< SymLink >{})
Sync symlink.
void chmod(const std::string &path, int mode)
Async chmod.
std::pair< bool, Statfs > statfsSync(const std::string &path)
Sync statfs.
void symlink(const std::string &old, const std::string &path, Flags< SymLink > flags=Flags< SymLink >{})
Async symlink.
std::pair< bool, std::pair< EntryType, const char * > > scandirNext()
Gets entries populated with the next directory entry data.
bool lchownSync(const std::string &path, Uid uid, Gid gid)
Sync lchown.
void readlink(const std::string &path)
Async readlink.
std::pair< bool, Stat > statSync(const std::string &path)
Sync stat.
bool lutimeSync(const std::string &path, Time atime, Time mtime)
Sync lutime.
void scandir(const std::string &path, int flags)
Async scandir.
bool utimeSync(const std::string &path, Time atime, Time mtime)
Sync utime.
void lchown(const std::string &path, Uid uid, Gid gid)
Async lchown.
void unlink(const std::string &path)
Async unlink.
void mkdtemp(const std::string &tpl)
Async mktemp.
void rename(const std::string &old, const std::string &path)
Async rename.
std::pair< bool, Stat > lstatSync(const std::string &path)
Sync lstat.
std::pair< bool, std::pair< std::string, std::size_t > > mkstempSync(const std::string &tpl)
Sync mkstemp.
void utime(const std::string &path, Time atime, Time mtime)
Async utime.
bool mkdirSync(const std::string &path, int mode)
Sync mkdir.
std::pair< bool, const char * > mkdtempSync(const std::string &tpl)
Sync mktemp.
void chown(const std::string &path, Uid uid, Gid gid)
Async chown.
void stat(const std::string &path)
Async stat.
void lutime(const std::string &path, Time atime, Time mtime)
Async lutime.
void opendir(const std::string &path)
Opens a path asynchronously as a directory stream.
bool renameSync(const std::string &old, const std::string &path)
Sync rename.
bool linkSync(const std::string &old, const std::string &path)
Sync link.
std::pair< bool, std::size_t > scandirSync(const std::string &path, int flags)
Sync scandir.
void lstat(const std::string &path)
Async lstat.
bool opendirSync(const std::string &path)
Opens a path synchronously as a directory stream.
void mkdir(const std::string &path, int mode)
Async mkdir.
bool unlinkSync(const std::string &path)
Sync unlink.
std::pair< bool, std::pair< EntryType, const char * > > readdirSync()
Iterates synchronously over a directory stream one entry at a time.
std::pair< bool, std::pair< const char *, std::size_t > > readlinkSync(const std::string &path)
Sync readlink.
void rmdir(const std::string &path)
Async rmdir.
bool chmodSync(const std::string &path, int mode)
Sync chmod.
void realpath(const std::string &path)
Async realpath.
bool accessSync(const std::string &path, int mode)
Sync access.
Base class for FsReq and/or FileReq.
Definition: fs.h:342
Request base class.
Definition: request.hpp:18
uvw default namespace.
Definition: async.h:8
uv_uid_t Uid
Definition: util.h:217
details::UVTypeWrapper< uv_file > FileHandle
Definition: util.h:205
uv_statfs_t Statfs
Definition: util.h:216
uv_gid_t Gid
Definition: util.h:218
static constexpr std::uint32_t type() noexcept
Returns a numerical identifier for a given type.
Definition: type_info.hpp:54
uv_stat_t Stat
Definition: util.h:215
details::UVTypeWrapper< uv_os_fd_t > OSFileDescriptor
Definition: util.h:207
The ErrorEvent event.
Definition: emitter.h:23
std::unique_ptr< const char[]> data
Definition: fs.h:178
Default FsEvent event.
Definition: fs.h:159
const char * path
Definition: fs.h:163
Helper functions.
Definition: fs.h:1401
static OSFileDescriptor handle(FileHandle file) noexcept
Gets the OS dependent handle.
static FileHandle open(OSFileDescriptor descriptor) noexcept
Gets the file descriptor.