commit 2cff48e
Devine Lu Linvega
·
2026-06-13 17:24:10 +0000 UTC
parent 3cd350a
Flushing on write cannot be helped
1 files changed,
+91,
-80
+91,
-80
1@@ -641,48 +641,20 @@ mouse_deo_vector(void)
2 #include <string.h>
3
4 typedef struct {
5- FILE *f;
6- DIR *dir;
7+ union {
8+ FILE *f;
9+ DIR *dir;
10+ } h;
11 char *filepath;
12 enum { IDLE,
13 FILE_READ,
14 FILE_WRITE,
15 DIR_READ,
16- DIR_WRITE
17- } state;
18+ DIR_WRITE } state;
19 } UxnFile;
20
21 static UxnFile ufs[2];
22
23-static void
24-make_pathfile(char *pathbuf, const char *filepath, const char *basename)
25-{
26- char c = '/';
27- while(*filepath)
28- c = *filepath++, *pathbuf = c, pathbuf++;
29- if(c != '/')
30- *pathbuf = '/', pathbuf++;
31- while(*basename)
32- *pathbuf = *basename++, pathbuf++;
33- *pathbuf = 0;
34-}
35-
36-static inline unsigned int
37-put_fill(Uint8 *dest, unsigned int len, char c)
38-{
39- memset(dest, c, len);
40- return len;
41-}
42-
43-static inline unsigned int
44-put_size(Uint8 *dest, unsigned int len, unsigned int size)
45-{
46- unsigned int i;
47- for(i = 0, dest += len; i < len; i++, size >>= 4)
48- *(--dest) = "0123456789abcdef"[(Uint8)(size & 0xf)];
49- return len;
50-}
51-
52 static inline unsigned int
53 put_text(Uint8 *dest, const char *text)
54 {
55@@ -696,20 +668,29 @@ put_text(Uint8 *dest, const char *text)
56 static unsigned int
57 put_stat(Uint8 *dest, unsigned int len, unsigned int size, unsigned int err, unsigned int dir, unsigned int capsize)
58 {
59- if(err) return put_fill(dest, len, '!');
60- if(dir) return put_fill(dest, len, '-');
61- if(capsize && size >= 0x10000) return put_fill(dest, len, '?');
62- return put_size(dest, len, size);
63+ unsigned int i;
64+ if(err || dir || (capsize && size >= 0x10000)) {
65+ memset(dest, err ? '!' : dir ? '-' :
66+ '?',
67+ len);
68+ return len;
69+ }
70+ for(i = 0, dest += len; i < len; i++, size >>= 4)
71+ *(--dest) = "0123456789abcdef"[(Uint8)(size & 0xf)];
72+ return len;
73 }
74
75 static unsigned int
76-put_statfile(Uint8 *dest, const char *filepath, const char *basename)
77+put_statfile(Uint8 *dest, char *pathbuf, unsigned int prefix_len, unsigned int cap, const char *basename)
78 {
79 unsigned int err, dir;
80 struct stat st;
81 Uint8 *anchor = dest;
82- char pathbuf[0x200];
83- make_pathfile(pathbuf, filepath, basename);
84+ char *p = pathbuf + prefix_len, *end = pathbuf + cap - 1;
85+ const char *b = basename;
86+ while(*b && p < end)
87+ *p++ = *b++;
88+ *p = 0;
89 err = stat(pathbuf, &st);
90 dir = !err && S_ISDIR(st.st_mode);
91 dest += put_stat(dest, 4, st.st_size, err, dir, 1);
92@@ -724,11 +705,19 @@ put_fdir(Uint8 *dest, unsigned int len, const char *filepath, DIR *dir)
93 {
94 Uint8 *p = dest, *end = dest + len - 1;
95 struct dirent *de;
96+ char pathbuf[0x200];
97+ unsigned int prefix_len = 0;
98+ char c = '/';
99+ const char *fp = filepath;
100+ while(*fp && prefix_len < sizeof pathbuf - 1)
101+ c = *fp++, pathbuf[prefix_len++] = c;
102+ if(c != '/' && prefix_len < sizeof pathbuf - 1)
103+ pathbuf[prefix_len++] = '/';
104 while((de = readdir(dir)) && p < end) {
105 const char *name = de->d_name;
106 if(name[0] == '.' && (!name[1] || (name[1] == '.' && !name[2])))
107 continue;
108- p += put_statfile(p, filepath, name);
109+ p += put_statfile(p, pathbuf, prefix_len, sizeof pathbuf, name);
110 }
111 *p = 0;
112 return p - dest;
113@@ -753,9 +742,9 @@ static unsigned int
114 file_write_dir(const char *p)
115 {
116 char buf[0x200];
117- char *s = buf;
118+ char *s = buf, *end = buf + sizeof buf - 1;
119 unsigned int ok = 1;
120- while(*p && ok) {
121+ while(*p && ok && s < end) {
122 *s++ = *p;
123 if(*p++ == '/') {
124 s[-1] = '\0';
125@@ -763,17 +752,50 @@ file_write_dir(const char *p)
126 s[-1] = '/';
127 }
128 }
129- return ok;
130+ return ok && !*p;
131 }
132
133 static void
134 file_reset(unsigned int id)
135 {
136- if(ufs[id].f != NULL) fclose(ufs[id].f), ufs[id].f = NULL;
137- if(ufs[id].dir != NULL) closedir(ufs[id].dir), ufs[id].dir = NULL;
138+ switch(ufs[id].state) {
139+ case FILE_READ:
140+ case FILE_WRITE: fclose(ufs[id].h.f); break;
141+ case DIR_READ: closedir(ufs[id].h.dir); break;
142+ default: break;
143+ }
144 ufs[id].state = IDLE;
145 }
146
147+static unsigned int
148+file_open(unsigned int id, unsigned int want_write, Uint8 flags)
149+{
150+ UxnFile *u = &ufs[id];
151+ struct stat st;
152+ if(want_write) {
153+ if(u->state == FILE_WRITE || u->state == DIR_WRITE)
154+ return 1;
155+ file_reset(id);
156+ file_write_dir(u->filepath);
157+ if(is_dir_path(u->filepath)) {
158+ u->state = is_dir_real(u->filepath) ? DIR_WRITE : IDLE;
159+ } else if((u->h.f = fopen(u->filepath, (flags & 0x01) ? "ab" : "wb"))) {
160+ u->state = FILE_WRITE;
161+ }
162+ } else {
163+ if(u->state == FILE_READ || u->state == DIR_READ)
164+ return 1;
165+ file_reset(id);
166+ if(stat(u->filepath, &st) == 0 && S_ISDIR(st.st_mode)) {
167+ if((u->h.dir = opendir(u->filepath)))
168+ u->state = DIR_READ;
169+ } else if((u->h.f = fopen(u->filepath, "rb"))) {
170+ u->state = FILE_READ;
171+ }
172+ }
173+ return u->state != IDLE;
174+}
175+
176 static unsigned int
177 file_init(unsigned int id, Uint16 addr)
178 {
179@@ -786,55 +808,35 @@ static unsigned int
180 file_read(unsigned int id, Uint16 addr, unsigned int len)
181 {
182 void *dest = &ram[addr];
183- struct stat st;
184 unsigned int n;
185 if(ufs[id].filepath == 0)
186 return 0;
187 if(addr + len > 0x10000)
188 len = 0x10000 - addr;
189- if(ufs[id].state != FILE_READ && ufs[id].state != DIR_READ) {
190- file_reset(id);
191- if(stat(ufs[id].filepath, &st) == 0 && S_ISDIR(st.st_mode)) {
192- if((ufs[id].dir = opendir(ufs[id].filepath)) != NULL)
193- ufs[id].state = DIR_READ;
194- } else if((ufs[id].f = fopen(ufs[id].filepath, "rb")) != NULL) {
195- ufs[id].state = FILE_READ;
196- }
197- }
198- if(ufs[id].state == FILE_READ) {
199- n = fread(dest, 1, len, ufs[id].f);
200- if(n == 0) file_reset(id);
201- return n;
202- }
203- if(ufs[id].state == DIR_READ) {
204- n = put_fdir(dest, len, ufs[id].filepath, ufs[id].dir);
205- if(n == 0) file_reset(id);
206- return n;
207- }
208- return 0;
209+ if(!file_open(id, 0, 0))
210+ return 0;
211+ if(ufs[id].state == FILE_READ)
212+ n = fread(dest, 1, len, ufs[id].h.f);
213+ else
214+ n = put_fdir(dest, len, ufs[id].filepath, ufs[id].h.dir);
215+ if(n == 0) file_reset(id);
216+ return n;
217 }
218
219 static unsigned int
220 file_write(unsigned int id, Uint16 addr, unsigned int len, Uint8 flags)
221 {
222- unsigned int ret = 0;
223 if(ufs[id].filepath == 0)
224 return 0;
225 if(addr + len > 0x10000)
226 len = 0x10000 - addr;
227- if(ufs[id].state != FILE_WRITE && ufs[id].state != DIR_WRITE) {
228- file_reset(id);
229- file_write_dir(ufs[id].filepath);
230- if(is_dir_path(ufs[id].filepath))
231- ufs[id].state = DIR_WRITE;
232- else if((ufs[id].f = fopen(ufs[id].filepath, (flags & 0x01) ? "ab" : "wb")) != NULL)
233- ufs[id].state = FILE_WRITE;
234+ if(!file_open(id, 1, flags))
235+ return 0;
236+ if(ufs[id].state == FILE_WRITE) {
237+ unsigned int ret = fwrite(&ram[addr], 1, len, ufs[id].h.f);
238+ return (ret > 0 && fflush(ufs[id].h.f) != 0) ? 0 : ret;
239 }
240- if(ufs[id].state == FILE_WRITE)
241- ret = fwrite(&ram[addr], 1, len, ufs[id].f);
242- if(ufs[id].state == DIR_WRITE)
243- ret = is_dir_real(ufs[id].filepath);
244- return ret;
245+ return is_dir_real(ufs[id].filepath);
246 }
247
248 static unsigned int
249@@ -1115,6 +1117,15 @@ emu_restart(unsigned int soft)
250 uxn_eval(0x100);
251 }
252
253+static inline unsigned int
254+put_size(Uint8 *dest, unsigned int len, unsigned int size)
255+{
256+ unsigned int i;
257+ for(i = 0, dest += len; i < len; i++, size >>= 4)
258+ *(--dest) = "0123456789abcdef"[(Uint8)(size & 0xf)];
259+ return len;
260+}
261+
262 static void
263 emu_screenshot(void)
264 {