]> git.lizzy.rs Git - nothing.git/blob - src/system/file.c
(#910) Introduce Lt adapters
[nothing.git] / src / system / file.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <errno.h>
4 #include "system/nth_alloc.h"
5 #ifdef __linux__
6 #include <sys/stat.h>
7 #include <sys/types.h>
8 #elif defined(_WIN32)
9 #include <Windows.h>
10 #define WINDOWS_TICK 10000000
11 #define SEC_TO_UNIX_EPOCH 11644473600LL
12 #endif
13
14 #include "system/stacktrace.h"
15 #include "file.h"
16 #include "lt_adapters.h"
17
18 int last_modified(const char *filepath, time_t *time)
19 {
20     trace_assert(filepath);
21     trace_assert(time);
22
23 #ifdef __linux__
24
25     struct stat attr;
26     if (stat(filepath, &attr) < 0) {
27         // errno is set by stat
28         return -1;
29     }
30     *time = attr.st_mtime;
31     return 0;
32
33 #elif defined(_WIN32)
34
35     // CreateFile opens file (see flag OPEN_EXISTING)
36     HANDLE hFile = CreateFile(
37         filepath,
38         GENERIC_READ,
39         FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
40         NULL,
41         OPEN_EXISTING,
42         0,
43         NULL
44     );
45     if (hFile == INVALID_HANDLE_VALUE) {
46         // TODO(#900): convert GetLastError() to errno
47         // for now let's just assume that file was not found.
48         errno = ENOENT;
49         return -1;
50     }
51     FILETIME filetime = { 0 };
52     BOOL res = GetFileTime(hFile, NULL, NULL, &filetime);
53     CloseHandle(hFile);
54     if (!res) {
55         errno = EPERM;
56         return -1;
57     }
58     unsigned long long mod_time = filetime.dwHighDateTime;
59     mod_time <<= 32;
60     mod_time |= filetime.dwLowDateTime;
61     // Taken from https://stackoverflow.com/a/6161842/1901561
62     *time = mod_time / WINDOWS_TICK - SEC_TO_UNIX_EPOCH;
63     return 0;
64
65 #elif defined(__APPLE__)
66
67     // TODO(#901): implement last_modified for Mac OS X
68     #warning last_modified is not implemented
69     return -1;
70
71 #else
72
73     #error Unsupported OS
74     return -1;
75
76 #endif
77 }
78
79 #ifdef _WIN32
80 struct DIR
81 {
82     HANDLE hFind;
83     WIN32_FIND_DATA data;
84     struct dirent *dirent;
85 };
86
87 DIR *opendir(const char *dirpath)
88 {
89     trace_assert(dirpath);
90
91     char buffer[MAX_PATH];
92     snprintf(buffer, MAX_PATH, "%s\\*", dirpath);
93
94     DIR *dir = nth_calloc(1, sizeof(DIR));
95
96     dir->hFind = FindFirstFile(buffer, &dir->data);
97     if (dir->hFind == INVALID_HANDLE_VALUE) {
98         goto fail;
99     }
100
101     return dir;
102
103 fail:
104     if (dir) {
105         free(dir);
106     }
107
108     return NULL;
109 }
110
111 struct dirent *readdir(DIR *dirp)
112 {
113     trace_assert(dirp);
114
115     if (dirp->dirent == NULL) {
116         dirp->dirent = nth_calloc(1, sizeof(struct dirent));
117     } else {
118         if(!FindNextFile(dirp->hFind, &dirp->data)) {
119             return NULL;
120         }
121     }
122
123     memset(dirp->dirent->d_name, 0, sizeof(dirp->dirent->d_name));
124
125     strncpy(
126         dirp->dirent->d_name,
127         dirp->data.cFileName,
128         sizeof(dirp->dirent->d_name) - 1);
129
130     return dirp->dirent;
131 }
132
133 void closedir(DIR *dirp)
134 {
135     trace_assert(dirp);
136
137     FindClose(dirp->hFind);
138     if (dirp->dirent) {
139         free(dirp->dirent);
140     }
141     free(dirp);
142 }
143
144 #endif