libcute 0.1
Loading...
Searching...
No Matches
fd.h
1#pragma once
2#include "macro.h"
3#include "utility.h"
4#include "io/error.h"
5#include <nostd.h>
6#include <stdbool.h>
7#include <stddef.h>
8#include "string/string.h"
9
10#if CU_PLAT_POSIX
11#include <unistd.h>
12#include <errno.h>
13typedef int cu_Handle;
14#define CU_INVALID_HANDLE -1
15#else
16#include <windows.h>
17#include <io.h>
18typedef HANDLE cu_Handle;
19#define CU_INVALID_HANDLE INVALID_HANDLE_VALUE
20#endif
21
22#if CU_PLAT_POSIX
23#define CU_FILE_MAX_PATH_LENGTH 4096
24#else
25#define CU_FILE_MAX_PATH_LENGTH 260
26#endif
27
28#if CU_PLAT_WINDOWS
29#define CU_PATH_SEPARATOR '\\'
30#else
31#define CU_PATH_SEPARATOR '/'
32#endif
33
34typedef enum {
35 CU_FILE_TYPE_UNKNOWN,
36 CU_FILE_TYPE_FILE,
37 CU_FILE_TYPE_DIRECTORY,
38 CU_FILE_TYPE_SYMLINK,
39 CU_FILE_TYPE_NAMED_PIPE,
40 CU_FILE_TYPE_BLOCK_DEVICE,
41 CU_FILE_TYPE_CHAR_DEVICE,
42 CU_FILE_TYPE_SOCKET,
43 CU_FILE_TYPE_DOOR,
44 CU_FILE_TYPE_EVENT_PORT,
45} cu_File_Type;
46
47typedef struct {
48 cu_String path;
49 unsigned long long size;
50 unsigned int mode;
51 cu_File_Type kind;
52 long long atime;
53 long long mtime;
54 long long ctime;
56
57static inline void cu_File_Stat_destroy(cu_File_Stat *stat) {
58 cu_String_destroy(&stat->path);
59 cu_Memory_memset(stat, 0, sizeof(*stat));
60}
61
62#if CU_PLAT_POSIX
63#include <sys/stat.h>
64#include <sys/types.h>
65static inline cu_File_Stat cu_File_Stat_from_handle(cu_Handle handle) {
66 struct stat st;
67 cu_Memory_memset(&st, 0, sizeof(st));
68 cu_File_Stat out;
69 cu_Memory_memset(&out, 0, sizeof(out));
70 if (fstat(handle, &st) != 0) {
71 return out;
72 }
73
74 out.size = (unsigned long long)st.st_size;
75 out.mode = (unsigned int)st.st_mode;
76
77 if (S_ISREG(st.st_mode)) {
78 out.kind = CU_FILE_TYPE_FILE;
79 } else if (S_ISDIR(st.st_mode)) {
80 out.kind = CU_FILE_TYPE_DIRECTORY;
81 } else if (S_ISCHR(st.st_mode)) {
82 out.kind = CU_FILE_TYPE_CHAR_DEVICE;
83 } else if (S_ISBLK(st.st_mode)) {
84 out.kind = CU_FILE_TYPE_BLOCK_DEVICE;
85 } else if (S_ISFIFO(st.st_mode)) {
86 out.kind = CU_FILE_TYPE_NAMED_PIPE;
87 } else if (S_ISLNK(st.st_mode)) {
88 out.kind = CU_FILE_TYPE_SYMLINK;
89#ifdef S_ISSOCK
90 } else if (S_ISSOCK(st.st_mode)) {
91 out.kind = CU_FILE_TYPE_SOCKET;
92#endif
93#ifdef S_IFDOOR
94 } else if ((st.st_mode & S_IFMT) == S_IFDOOR) {
95 out.kind = CU_FILE_TYPE_DOOR;
96#endif
97#ifdef S_IFPORT
98 } else if ((st.st_mode & S_IFMT) == S_IFPORT) {
99 out.kind = CU_FILE_TYPE_EVENT_PORT;
100#endif
101 } else {
102 out.kind = CU_FILE_TYPE_UNKNOWN;
103 }
104
105#ifdef __APPLE__
106 out.atime = (long long)st.st_atimespec.tv_sec * CU_TIME_NS_PER_SEC +
107 st.st_atimespec.tv_nsec;
108 out.mtime = (long long)st.st_mtimespec.tv_sec * CU_TIME_NS_PER_SEC +
109 st.st_mtimespec.tv_nsec;
110 out.ctime = (long long)st.st_ctimespec.tv_sec * CU_TIME_NS_PER_SEC +
111 st.st_ctimespec.tv_nsec;
112#elif defined(_STATBUF_ST_NSEC) && defined(st_atim)
113 out.atime =
114 (long long)st.st_atim.tv_sec * CU_TIME_NS_PER_SEC + st.st_atim.tv_nsec;
115 out.mtime =
116 (long long)st.st_mtim.tv_sec * CU_TIME_NS_PER_SEC + st.st_mtim.tv_nsec;
117 out.ctime =
118 (long long)st.st_ctim.tv_sec * CU_TIME_NS_PER_SEC + st.st_ctim.tv_nsec;
119#elif defined(_STATBUF_ST_NSEC)
120 out.atime = (long long)st.st_atime * CU_TIME_NS_PER_SEC + st.st_atimensec;
121 out.mtime = (long long)st.st_mtime * CU_TIME_NS_PER_SEC + st.st_mtimensec;
122 out.ctime = (long long)st.st_ctime * CU_TIME_NS_PER_SEC + st.st_ctimensec;
123#else
124 out.atime = (long long)st.st_atime * CU_TIME_NS_PER_SEC;
125 out.mtime = (long long)st.st_mtime * CU_TIME_NS_PER_SEC;
126 out.ctime = (long long)st.st_ctime * CU_TIME_NS_PER_SEC;
127#endif
128
129 return out;
130}
131#else
132#include <windows.h>
133static inline cu_File_Stat cu_File_Stat_from_handle(cu_Handle handle) {
134 BY_HANDLE_FILE_INFORMATION info;
135 cu_File_Stat out;
136 cu_Memory_memset(&out, 0, sizeof(out));
137 if (!GetFileInformationByHandle(handle, &info)) {
138 return out;
139 }
140 ULARGE_INTEGER size;
141 size.HighPart = info.nFileSizeHigh;
142 size.LowPart = info.nFileSizeLow;
143
144 out.size = (unsigned long long)size.QuadPart;
145 out.mode = info.dwFileAttributes;
146 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
147 out.kind = CU_FILE_TYPE_DIRECTORY;
148 } else if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
149 out.kind = CU_FILE_TYPE_SYMLINK;
150 } else {
151 out.kind = CU_FILE_TYPE_FILE;
152 }
153
154 out.mtime = cu_Time_filetime_to_unix(info.ftLastWriteTime);
155 out.ctime = cu_Time_filetime_to_unix(info.ftCreationTime);
156 out.atime = cu_Time_filetime_to_unix(info.ftLastAccessTime);
157
158 return out;
159}
160#endif
161
162static inline cu_IoSize_Result cu_Fd_tell(cu_Handle handle) {
163#if CU_PLAT_POSIX
164 off_t pos = lseek(handle, 0, SEEK_CUR);
165 if (pos == (off_t)-1) {
166 return cu_IoSize_Result_error(cu_Io_Error_from_errno(errno));
167 }
168 return cu_IoSize_Result_ok((size_t)pos);
169#else
170 long long pos = _lseeki64(handle, 0, SEEK_CUR);
171 if (pos == -1) {
172 return cu_IoSize_Result_error(cu_Io_Error_from_win32(GetLastError()));
173 }
174 return cu_IoSize_Result_ok((size_t)pos);
175#endif
176}
Definition fd.h:47
Dynamically allocated UTF-8 string.
Definition string.h:24