GCC Code Coverage Report


Directory: src/gate/
File: src/gate/files.c
Date: 2026-09-21 06:26:40
Exec Total Coverage
Lines: 702 887 79.1%
Functions: 57 63 90.5%
Branches: 327 602 54.3%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright (c) 2018-2026, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28 #include "gate/files.h"
29 #include "gate/results.h"
30 #include "gate/atomics.h"
31 #include "gate/debugging.h"
32 #include "gate/utilities.h"
33
34
35 #if defined(GATE_SYS_WIN)
36 # define GATE_CORE_FILES_WINAPI_IMPL 1
37 #elif defined(GATE_SYS_WASM)
38 # define GATE_CORE_FILES_WASM_IMPL 1
39 #elif defined(GATE_SYS_POSIX)
40 # define GATE_CORE_FILES_POSIX_IMPL 1
41 #elif defined(GATE_SYS_DOS)
42 # define GATE_CORE_FILES_DOS_IMPL 1
43 #elif defined(GATE_SYS_EFI)
44 # define GATE_CORE_FILES_EFI_IMPL 1
45 #else
46 # define GATE_CORE_FILES_NO_IMPL 1
47 #endif
48
49 154 static gate_bool_t gate_file_is_hidden_entry(gate_string_t const* path)
50 {
51
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 154 times.
154 if (gate_string_is_empty(path))
52 {
53 return true; /* empty paths are invalid and therefore hidden */
54 }
55 else
56 {
57 154 const gate_size_t path_separator_found = gate_string_char_pos_last(
58 path, gate_file_path_separator_char);
59
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
154 if (path_separator_found == GATE_STR_NPOS)
60 {
61 /* filename only */
62 return gate_string_starts_with_char(path, '.');
63 }
64 else
65 {
66 /* path */
67 154 return path->str[path_separator_found + 1] == '.';
68 }
69 }
70 }
71
72 17 char GATE_CALL gate_file_path_separator_character(void)
73 {
74 17 return gate_file_path_separator_char;
75 }
76
77 433 gate_size_t gate_file_build_path(char* dest, gate_size_t dest_size, char const* path, gate_size_t path_size,
78 char const* subpath, gate_size_t subpath_size)
79 {
80 433 gate_size_t ret = 0;
81 gate_size_t len;
82
83
1/2
✓ Branch 0 taken 461 times.
✗ Branch 1 not taken.
461 while (path_size > 0)
84 {
85
2/2
✓ Branch 0 taken 433 times.
✓ Branch 1 taken 28 times.
461 if (path[path_size - 1] != gate_file_path_separator_char)
86 {
87 433 break;
88 }
89 28 --path_size;
90 }
91
1/2
✓ Branch 0 taken 433 times.
✗ Branch 1 not taken.
433 while (subpath_size > 0)
92 {
93
1/2
✓ Branch 0 taken 433 times.
✗ Branch 1 not taken.
433 if (subpath[0] != gate_file_path_separator_char)
94 {
95 433 break;
96 }
97 ++subpath;
98 --subpath_size;
99 }
100
101 433 ret = gate_str_print_text(dest, dest_size, path, path_size);
102 433 len = gate_str_print_text(&dest[ret], dest_size - ret, &gate_file_path_separator_char, 1);
103 433 ret += len;
104 433 len = gate_str_print_text(&dest[ret], dest_size - ret, subpath, subpath_size);
105 433 ret += len;
106 433 return ret;
107 }
108
109 14 gate_string_t* gate_file_build_path_string(gate_string_t* dest, gate_string_t const* path, gate_string_t const* subpath)
110 {
111 14 gate_string_t* ret = NULL;
112 14 gate_size_t path_len = gate_string_length(path);
113 14 gate_size_t subpath_len = gate_string_length(subpath);
114 14 gate_strbuilder_t builder = GATE_INIT_EMPTY;
115 14 gate_string_t strs[2] = GATE_INIT_EMPTY;
116 gate_result_t result;
117
118 do
119 {
120 14 gate_string_duplicate(&strs[0], path);
121 14 gate_string_duplicate(&strs[1], subpath);
122
123 14 gate_strbuilder_create(&builder, path_len + subpath_len + 2);
124
125 14 result = gate_file_build_path_components(&builder, gate_file_path_separator_char, strs, sizeof(strs) / sizeof(strs[0]));
126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 GATE_BREAK_IF_FAILED(result);
127
128 14 ret = gate_strbuilder_to_string(&builder, dest);
129
130 } while (0);
131
132 14 gate_string_release(&strs[1]);
133 14 gate_string_release(&strs[0]);
134
135 14 gate_strbuilder_release(&builder);
136 14 return ret;
137 }
138
139 14 gate_result_t gate_file_build_path_components(gate_strbuilder_t* builder, char separator_char,
140 gate_string_t const* component_array, gate_size_t component_array_length)
141 {
142 14 gate_result_t ret = GATE_RESULT_OK;
143 gate_size_t ndx;
144 gate_string_t separator;
145
146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (separator_char == 0)
147 {
148 separator_char = gate_file_path_separator_char;
149 }
150
151 14 gate_string_create_static_len(&separator, &separator_char, 1);
152
153
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 14 times.
42 for (ndx = 0; ndx != component_array_length; ++ndx)
154 {
155 28 gate_string_t const* ptr_str = &component_array[ndx];
156 28 gate_size_t pos = 0;
157 28 gate_size_t pos_end = gate_string_find_last_not_of(ptr_str, &separator);
158
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (pos_end == GATE_STR_NPOS)
159 {
160 continue;
161 }
162
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
28 if (ndx != 0)
163 {
164 14 pos = gate_string_find_first_not_of(ptr_str, &separator, 0);
165 14 gate_strbuilder_append_text(builder, &separator_char, 1);
166 }
167 28 gate_strbuilder_append_text(builder, gate_string_ptr(ptr_str, pos), pos_end - pos + 1);
168 }
169 14 return ret;
170 }
171
172 11 gate_result_t gate_file_split_path(gate_string_t const* src_path, gate_string_t* parent_path, gate_string_t* name)
173 {
174 11 char const* ptr = src_path->str;
175 11 gate_size_t len = src_path->length;
176 gate_size_t parent_len;
177
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 while (len > 0)
178 {
179
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1 times.
12 if (ptr[len - 1] != gate_file_path_separator_char)
180 {
181 11 break;
182 }
183 1 --len;
184 }
185
2/2
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 1 times.
136 for (parent_len = len; parent_len > 0; --parent_len)
186 {
187
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 125 times.
135 if (ptr[parent_len - 1] == gate_file_path_separator_char)
188 {
189
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
10 if (parent_path)
190 {
191 7 gate_string_substr(parent_path, src_path, 0, parent_len);
192 }
193
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
10 if (name)
194 {
195 7 gate_string_substr(name, src_path, parent_len, len - parent_len);
196 }
197 10 return GATE_RESULT_OK;
198 }
199 }
200 1 return GATE_RESULT_NOMATCH;
201 }
202
203 1 gate_size_t gate_file_split_path_components(gate_string_t const* src_path, char separator_char,
204 gate_string_t* out_array, gate_size_t out_array_capacity)
205 {
206 1 gate_size_t ret = 0;
207 1 gate_string_t separator = GATE_STRING_INIT_EMPTY;
208 gate_size_t pos;
209 gate_size_t pos_end;
210 1 gate_string_t path = GATE_STRING_INIT_EMPTY;
211
212 do
213 {
214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (separator_char == 0)
215 {
216 separator_char = gate_file_path_separator_char;
217 }
218
219 1 gate_string_create_static_len(&separator, &separator_char, 1);
220 1 pos = gate_string_find_first_not_of(src_path, &separator, 0);
221
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pos == GATE_STR_NPOS)
222 {
223 /* path-less string */
224 ret = 0;
225 break;
226 }
227 1 pos_end = gate_string_find_last_not_of(src_path, &separator);
228 1 gate_string_substr(&path, src_path, pos, pos_end - pos + 1);
229
230 1 pos = 0;
231
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 while (ret < out_array_capacity)
232 {
233 3 pos_end = gate_string_char_pos(&path, separator_char, pos);
234
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
3 if ((pos_end == GATE_STR_NPOS) || (ret == out_array_capacity - 1))
235 {
236 /* last component found */
237 1 gate_string_substr(&out_array[ret], &path, pos, GATE_STR_NPOS);
238 1 ++ret;
239 1 break;
240 }
241
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (pos_end > pos) /* ignore double separator occurences */
242 {
243 2 gate_string_substr(&out_array[ret], &path, pos, pos_end - pos);
244 2 ++ret;
245 }
246 2 pos = pos_end + 1;
247 }
248
249 } while (0);
250
251 1 gate_string_release(&path);
252 1 gate_string_release(&separator);
253
254 1 return ret;
255 }
256
257 2 gate_result_t gate_file_extract_path(char const* src_path, gate_size_t src_path_len,
258 char* name_buffer, gate_size_t name_buffer_len,
259 char* parent_buffer, gate_size_t parent_buffer_len)
260 {
261 2 char const* ptr = src_path;
262 2 gate_size_t len = src_path_len;
263 gate_size_t parent_len;
264
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 while (len > 0)
265 {
266
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (ptr[len - 1] != gate_file_path_separator_char)
267 {
268 2 break;
269 }
270 --len;
271 }
272
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 for (parent_len = len; parent_len > 0; --parent_len)
273 {
274
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
8 if (ptr[parent_len - 1] == gate_file_path_separator_char)
275 {
276
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if (name_buffer && name_buffer_len > 0)
277 {
278 2 gate_str_print_text(name_buffer, name_buffer_len, &ptr[parent_len], len - parent_len);
279 }
280
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 if (parent_buffer && parent_buffer_len > 0)
281 {
282 2 gate_str_print_text(parent_buffer, parent_buffer_len, ptr, parent_len - 1);
283 }
284 2 return GATE_RESULT_OK;
285 }
286 }
287 return GATE_RESULT_NOMATCH;
288 }
289
290 1 gate_result_t gate_file_extract_path_string(gate_string_t const* src_path, gate_string_t* name, gate_string_t* parent)
291 {
292 char namebuffer[GATE_MAX_FILENAME_LENGTH];
293 char parentbuffer[GATE_MAX_FILEPATH_LENGTH];
294 gate_result_t result;
295
296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(src_path != NULL);
297
298 2 result = gate_file_extract_path(
299 1 gate_string_ptr(src_path, 0), gate_string_length(src_path),
300 namebuffer, sizeof(namebuffer),
301 parentbuffer, sizeof(parentbuffer)
302 );
303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_RETURN_IF_FAILED(result);
304
305
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (name != NULL)
306 {
307
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (NULL == gate_string_create(name, namebuffer, gate_str_length_max(namebuffer, sizeof(namebuffer))))
308 {
309 return GATE_RESULT_OUTOFMEMORY;
310 }
311 }
312
313
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (parent != NULL)
314 {
315
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (NULL == gate_string_create(parent, parentbuffer, gate_str_length_max(parentbuffer, sizeof(parentbuffer))))
316 {
317 if (name)
318 {
319 gate_string_release(name);
320 }
321 return GATE_RESULT_OUTOFMEMORY;
322 }
323 }
324 1 return GATE_RESULT_OK;
325 }
326
327 1 static gate_result_t gate_file_copy_internal(gate_string_t const* srcfilepath, gate_string_t const* dstfilepath, gate_enumint_t flags)
328 {
329 gate_result_t ret;
330 char buffer[GATE_MAX_COPYBUFFER_LENGTH];
331 1 gate_file_t src_handle = GATE_FILE_INVALID;
332 1 gate_file_t dst_handle = GATE_FILE_INVALID;
333 gate_size_t bytes_read;
334 gate_size_t bytes_written;
335 gate_size_t bytes_copied;
336
337 do
338 {
339
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!GATE_FLAG_ENABLED(flags, GATE_FILE_COPY_OVERWRITE))
340 {
341 1 ret = gate_file_exists(dstfilepath);
342
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_SUCCEEDED(ret))
343 {
344 ret = GATE_RESULT_ALREADYEXISTS;
345 break;
346 }
347 }
348 1 ret = gate_file_open(srcfilepath, GATE_STREAM_OPEN_READ, &src_handle);
349
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
350 1 ret = gate_file_open(dstfilepath, GATE_STREAM_OPEN_WRITE, &dst_handle);
351
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
352
353
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 while (GATE_SUCCEEDED(ret))
354 {
355 2 bytes_read = 0;
356 2 ret = gate_file_read(src_handle, buffer, sizeof(buffer), &bytes_read);
357
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
358
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (bytes_read == 0)
359 {
360 1 break;
361 }
362 1 bytes_copied = 0;
363
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 while (bytes_copied < bytes_read)
364 {
365 1 ret = gate_file_write(dst_handle, &buffer[bytes_copied], bytes_read - bytes_copied, &bytes_written);
366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
367 1 bytes_copied += bytes_written;
368 }
369 }
370
371 } while (0);
372
373
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (src_handle != GATE_FILE_INVALID)
374 {
375 1 gate_file_close(src_handle);
376 }
377
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (dst_handle != GATE_FILE_INVALID)
378 {
379 1 gate_file_close(dst_handle);
380 }
381 1 return ret;
382 }
383
384 static gate_result_t gate_file_move_internal(gate_string_t const* srcfilepath, gate_string_t const* dstfilepath)
385 {
386 gate_result_t ret;
387 ret = gate_file_copy(srcfilepath, dstfilepath, 0);
388 if (GATE_SUCCEEDED(ret))
389 {
390 ret = gate_file_delete(srcfilepath);
391 }
392 return ret;
393 }
394
395
396 1 static gate_result_t gate_file_copy_list_create_path(gate_string_t const* path)
397 {
398 1 gate_string_t parent = GATE_STRING_INIT_EMPTY;
399 gate_result_t ret;
400 1 ret = gate_file_exists(path);
401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(ret))
402 {
403 ret = gate_file_split_path(path, &parent, NULL);
404 if (GATE_SUCCEEDED(ret))
405 {
406 ret = gate_file_copy_list_create_path(&parent);
407 if (GATE_SUCCEEDED(ret))
408 {
409 ret = gate_file_dir_create(path, GATE_FILE_DIR_CREATE_DEFAULT);
410 }
411 gate_string_release(&parent);
412 }
413 }
414 1 return ret;
415 }
416
417 1 static gate_result_t gate_file_copy_list_entry(gate_string_t const* source, gate_string_t const* dest,
418 gate_set_t* existing_dirs, gate_enumint_t flags)
419 {
420 1 gate_result_t ret = GATE_RESULT_FAILED;
421 1 gate_string_t dest_parent = GATE_STRING_INIT_EMPTY;
422
423 do
424 {
425 1 ret = gate_file_split_path(dest, &dest_parent, NULL);
426
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
427
428
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (!gate_set_iterator_valid(gate_set_get(existing_dirs, &dest_parent)))
429 {
430 1 ret = gate_file_copy_list_create_path(&dest_parent);
431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
432 1 gate_set_add(existing_dirs, &dest_parent);
433 }
434 1 ret = gate_file_copy(source, dest, flags);
435 } while (0);
436
437 1 gate_string_release(&dest_parent);
438 1 return ret;
439 }
440
441 1 gate_result_t gate_file_copy_list(gate_map_t const* path_map, gate_enumint_t flags,
442 gate_file_copy_list_callback callback, void* user_param)
443 {
444 1 gate_result_t ret = GATE_RESULT_FAILED;
445 gate_result_t result;
446 1 gate_set_t existing_dirs = GATE_INIT_EMPTY;
447 gate_map_iterator_t iter;
448 gate_string_t const* source;
449 gate_string_t const* dest;
450 char source_buffer[GATE_MAX_COPYBUFFER_LENGTH];
451 char dest_buffer[GATE_MAX_COPYBUFFER_LENGTH];
452 do
453 {
454
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (NULL == gate_util_stringset_create(&existing_dirs))
455 {
456 ret = GATE_RESULT_OUTOFMEMORY;
457 break;
458 }
459
460 1 ret = GATE_RESULT_OK;
461
2/2
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
2 for (iter = gate_map_first(path_map); gate_map_iterator_valid(iter); iter = gate_map_iterator_next(iter))
462 {
463 1 source = (gate_string_t const*)gate_map_iterator_key(iter);
464 1 dest = (gate_string_t const*)gate_map_iterator_value(iter);
465
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 if (source && dest)
466 {
467 1 result = gate_file_copy_list_entry(source, dest, &existing_dirs, flags);
468
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (callback)
469 {
470 1 gate_string_to_buffer(source, source_buffer, sizeof(source_buffer));
471 1 gate_string_to_buffer(dest, dest_buffer, sizeof(dest_buffer));
472
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!callback(source_buffer, dest_buffer, result, user_param))
473 {
474 break;
475 }
476 }
477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(result))
478 {
479 if (!GATE_FLAG_ENABLED(flags, GATE_FILE_COPY_IGNORE_ERROR))
480 {
481 ret = result;
482 break;
483 }
484 }
485 }
486 }
487 } while (0);
488
489 1 gate_map_destroy(&existing_dirs);
490
491 1 return ret;
492 }
493
494 3 gate_result_t gate_file_dir_delete_recursive(gate_string_t const* dirpath)
495 {
496 gate_result_t result;
497 gate_file_dirreader_t reader;
498 char path[GATE_MAX_FILEPATH_LENGTH];
499 gate_size_t path_len;
500 3 gate_string_t entry = GATE_STRING_INIT_EMPTY;
501
502 do
503 {
504 3 result = gate_file_dir_exists(dirpath);
505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED(result);
506
507 3 result = gate_file_dir_open(dirpath, &reader);
508
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED(result);
509
510
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 3 times.
8 while (0 != (path_len = gate_file_dir_read(&reader, path, sizeof(path), false)))
511 {
512 5 gate_string_create_static_len(&entry, path, path_len);
513 5 result = gate_file_dir_exists(&entry);
514
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (GATE_SUCCEEDED(result))
515 {
516 /* subdirectory */
517 result = gate_file_dir_delete_recursive(&entry);
518 }
519 else
520 {
521 /* file */
522 5 result = gate_file_delete(&entry);
523 }
524 5 gate_string_release(&entry);
525
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 GATE_BREAK_IF_FAILED(result);
526 }
527
528 3 gate_file_dir_close(&reader);
529
530
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED(result);
531
532 3 result = gate_file_dir_delete(dirpath);
533
534 } while (0);
535 3 return result;
536 }
537
538
539
540
541 struct gate_file_find_param
542 {
543 gate_file_filter_t const* filter;
544 gate_file_list_callback_t callback;
545 void* userparam;
546 };
547
548 32 static gate_bool_t GATE_CALL gate_file_find_callback(gate_file_entry_t const* entry, void* userparam)
549 {
550 32 struct gate_file_find_param* param = (struct gate_file_find_param*)userparam;
551 gate_string_t path;
552 32 gate_bool_t ret = true;
553 32 gate_bool_t is_dir = GATE_FLAG_ENABLED(entry->props.attribs, GATE_FILEENTRY_ATTRIB_DIRECTORY);
554
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 if (param->filter)
555 {
556 32 gate_string_create_static(&path, entry->path);
557
558 do
559 {
560
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 if (!gate_string_is_empty(&param->filter->pattern))
561 {
562
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 if (!gate_string_like_one_of(&path, &param->filter->pattern, ';'))
563 {
564 break;
565 }
566 }
567
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 1 times.
32 if (!is_dir)
568 {
569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (param->filter->from_size > 0)
570 {
571 if (entry->props.size < param->filter->from_size)
572 {
573 break;
574 }
575 }
576
1/2
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
31 if (param->filter->to_size != 0)
577 {
578
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (entry->props.size > param->filter->to_size)
579 {
580 break;
581 }
582 }
583 }
584
585
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (entry->props.time_modified < param->filter->from_modified)
586 {
587 break;
588 }
589
2/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
32 if ((param->filter->to_modified != 0) && (entry->props.time_modified > param->filter->to_modified))
590 {
591 break;
592 }
593
594
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (param->filter->from_size > 0)
595 {
596 if (entry->props.size < param->filter->from_size)
597 {
598 break;
599 }
600 }
601
602 32 ret = param->callback(entry, param->userparam);
603
604 } while (0);
605
606
3/4
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 31 times.
32 if (param->filter->recursive && is_dir)
607 {
608 1 gate_file_find(&path, param->filter, param->callback, param->userparam);
609 }
610 }
611 else
612 {
613 ret = param->callback(entry, param->userparam);
614 }
615 32 return ret;
616 }
617
618 2 gate_result_t gate_file_find(gate_string_t const* dirpath, gate_file_filter_t const* filter,
619 gate_file_list_callback_t callback, void* userparam)
620 {
621 struct gate_file_find_param param;
622 2 param.filter = filter;
623 2 param.callback = callback;
624 2 param.userparam = userparam;
625
626 2 return gate_file_list(dirpath, &gate_file_find_callback, &param);
627 }
628
629 11 gate_result_t gate_file_dir_create_all(gate_string_t const* dirpath, gate_enumint_t flags)
630 {
631 gate_result_t ret;
632 11 gate_string_t parent = GATE_STRING_INIT_EMPTY;
633 11 gate_string_t name = GATE_STRING_INIT_EMPTY;
634
635 do
636 {
637 11 ret = gate_file_dir_exists(dirpath);
638
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
11 if (GATE_SUCCEEDED(ret))
639 {
640 /* path does already exist -> nothing to do */
641 9 break;
642 }
643
644 2 ret = gate_file_split_path(dirpath, &parent, &name);
645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
646
647 /* ensure that parents exist */
648 2 ret = gate_file_dir_create_all(&parent, flags);
649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
650
651 /* now try to create the deepest path component */
652 2 ret = gate_file_dir_create(dirpath, flags);
653 } while (0);
654
655 11 gate_string_release(&parent);
656 11 gate_string_release(&name);
657 11 return ret;
658 }
659
660
661 136 gate_result_t gate_file_get_content_buffer(gate_string_t const* filepath, char* content_buffer, gate_size_t* content_buffer_len)
662 {
663 gate_result_t ret;
664 136 gate_file_t filehandle = GATE_FILE_INVALID;
665 136 gate_size_t copied = 0;
666 136 gate_size_t bufferlen = *content_buffer_len;
667 gate_size_t bufferused;
668
669 do
670 {
671
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 124 times.
136 GATE_BREAK_IF_FAILED(ret = gate_file_open(filepath, GATE_STREAM_OPEN_READ, &filehandle));
672
2/2
✓ Branch 0 taken 246 times.
✓ Branch 1 taken 2 times.
248 while (copied < bufferlen)
673 {
674
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 246 times.
246 GATE_BREAK_IF_FAILED(ret = gate_file_read(filehandle, &content_buffer[copied], bufferlen - copied, &bufferused));
675
2/2
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 124 times.
246 if (bufferused == 0) break;
676 124 copied += bufferused;
677 }
678
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 124 times.
124 GATE_BREAK_IF_FAILED(ret);
679
680 /* success case: */
681 124 *content_buffer_len = copied;
682 124 ret = GATE_RESULT_OK;
683 } while (0);
684
685
2/2
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 12 times.
136 if (filehandle != GATE_FILE_INVALID)
686 {
687 124 gate_file_close(filehandle);
688 }
689 136 return ret;
690 }
691
692
693 2 gate_result_t gate_file_get_content(gate_string_t const* filepath, gate_string_t* content_buffer)
694 {
695 gate_result_t ret;
696 2 gate_file_t filehandle = GATE_FILE_INVALID;
697 gate_int64_t filesize;
698 2 gate_int64_t copied = 0;
699 gate_strbuilder_t builder;
700 char buffer[GATE_MAX_COPYBUFFER_LENGTH];
701 gate_size_t bufferused;
702
703 2 gate_strbuilder_create(&builder, 0);
704
705 do
706 {
707
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret = gate_file_open(filepath, GATE_STREAM_OPEN_READ, &filehandle));
708
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret = gate_file_size(filehandle, &filesize));
709
710 2 gate_strbuilder_create(&builder, (gate_size_t)filesize);
711
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 while (copied != filesize)
712 {
713
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret = gate_file_read(filehandle, buffer, sizeof(buffer), &bufferused));
714
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (bufferused == 0) break;
715
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (0 == gate_strbuilder_append_text(&builder, buffer, bufferused))
716 {
717 ret = GATE_RESULT_OUTOFMEMORY;
718 break;
719 }
720 2 copied += bufferused;
721 }
722
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
723
724
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (NULL == gate_strbuilder_to_string(&builder, content_buffer))
725 {
726 ret = GATE_RESULT_OUTOFMEMORY;
727 break;
728 }
729
730 /* success case: */
731 2 ret = GATE_RESULT_OK;
732 } while (0);
733
734
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (filehandle != GATE_FILE_INVALID)
735 {
736 2 gate_file_close(filehandle);
737 }
738 2 gate_strbuilder_release(&builder);
739
740 2 return ret;
741 }
742 1 gate_result_t gate_file_get_content_lines(gate_string_t const* filepath, gate_arraylist_t string_array)
743 {
744 1 gate_result_t ret = GATE_RESULT_FAILED;
745 char buffer[GATE_MAX_COPYBUFFER_LENGTH * 3];
746 gate_size_t bufferused;
747 1 gate_controlstream_t* stream = NULL;
748 gate_string_t line;
749
750 do
751 {
752
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (string_array == NULL)
753 {
754 ret = GATE_RESULT_NULLPOINTER;
755 break;
756 }
757
758 1 ret = gate_file_openstream(filepath, GATE_STREAM_OPEN_READ, &stream);
759
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
760
761
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 while (GATE_SUCCEEDED(ret = gate_stream_read_line((gate_stream_t*)stream, buffer, sizeof(buffer), &bufferused)))
762 {
763
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (bufferused == 0)
764 {
765 1 break;
766 }
767
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (buffer[bufferused - 1] == '\n')
768 {
769 1 --bufferused;
770 }
771
3/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
2 if ((bufferused != 0) && (buffer[bufferused - 1] == '\r'))
772 {
773 1 --bufferused;
774 }
775
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (NULL != gate_string_create(&line, buffer, bufferused))
776 {
777 2 gate_util_stringarray_add(string_array, &line);
778 2 gate_string_release(&line);
779 }
780 }
781 } while (0);
782
783
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (stream != NULL)
784 {
785 1 gate_object_release(stream);
786 }
787 1 return ret;
788 }
789
790 7 static gate_result_t gate_file_write_block(gate_file_t filehandle, gate_string_t const* content_buffer)
791 {
792 7 gate_result_t ret = GATE_RESULT_OK;
793 7 gate_size_t pos = 0;
794 gate_size_t written;
795
796
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 7 times.
14 while (pos < content_buffer->length)
797 {
798 7 ret = gate_file_write(filehandle, &content_buffer->str[pos], content_buffer->length - pos, &written);
799
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 GATE_BREAK_IF_FAILED(ret);
800 7 pos += written;
801 }
802 7 return ret;
803 }
804
805 3 gate_result_t gate_file_set_content(gate_string_t const* filepath, gate_string_t const* content_buffer)
806 {
807 gate_result_t ret;
808 3 gate_file_t filehandle = GATE_FILE_INVALID;
809
810
811 do
812 {
813 3 ret = gate_file_open(filepath, GATE_STREAM_OPEN_WRITE, &filehandle);
814
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 GATE_BREAK_IF_FAILED(ret);
815 3 ret = gate_file_write_block(filehandle, content_buffer);
816 } while (0);
817
818
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (filehandle != GATE_FILE_INVALID)
819 {
820 3 gate_file_close(filehandle);
821 }
822
823 3 return ret;
824 }
825
826 1 gate_result_t gate_file_set_content_buffer(gate_string_t const* filepath, char const* content_buffer, gate_size_t content_buffer_len)
827 {
828 gate_result_t ret;
829 1 gate_string_t text = GATE_STRING_INIT_EMPTY;
830
831 1 gate_string_create_static_len(&text, content_buffer, content_buffer_len);
832 1 ret = gate_file_set_content(filepath, &text);
833 1 gate_string_release(&text);
834
835 1 return ret;
836 }
837
838 1 gate_result_t gate_file_set_content_lines(gate_string_t const* filepath, gate_arraylist_t string_array)
839 {
840 gate_result_t ret;
841 1 gate_file_t filehandle = GATE_FILE_INVALID;
842 1 gate_size_t count = gate_arraylist_length(string_array);
843 gate_size_t index;
844 gate_string_t const* ptr;
845 static gate_string_t const new_line = { GATE_STR_NEWLINE, GATE_STR_NEWLINE_LENGTH, NULL };
846
847 do
848 {
849 1 ret = gate_file_open(filepath, GATE_STREAM_OPEN_WRITE, &filehandle);
850
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
851
852
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 for (index = 0; index != count; ++index)
853 {
854 2 ptr = (gate_string_t const*)gate_arraylist_get(string_array, index);
855 2 ret = gate_file_write_block(filehandle, ptr);
856
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
857 2 ret = gate_file_write_block(filehandle, &new_line);
858
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
859 }
860 } while (0);
861
862
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (filehandle != GATE_FILE_INVALID)
863 {
864 1 gate_file_close(filehandle);
865 }
866
867 1 return ret;
868 }
869
870
871
872 #if defined(GATE_CORE_FILES_WINAPI_IMPL)
873
874 #include "gate/platforms.h"
875 #include "gate/memalloc.h"
876 #include "gate/strings.h"
877
878 #if defined(GATE_COMPILER_MSVC) && !defined(GATE_SYS_WINCE) && !defined(GATE_SYS_WINSTORE)
879 #pragma comment(lib, "Mpr.lib")
880 #endif
881
882 GATE_CORE_API char const gate_file_path_separator_char = '\\';
883 GATE_CORE_API char const* const gate_file_path_separator = "\\";
884
885 #if defined(GATE_SYS_WINSTORE)
886 # define MoveFile(lpExistingFileName, lpNewFileName) MoveFileEx(lpExistingFileName, lpNewFileName, (MOVEFILE_COPY_ALLOWED))
887 #endif
888
889 #if defined(GATE_SYS_WIN16)
890 # include <direct.h>
891 # include <tchar.h>
892
893
894 static DWORD WINAPI GetLogicalDrives()
895 {
896 DWORD ret = 0;
897 int n;
898 UINT tp;
899 for (n = 0; n < 25; ++n)
900 {
901 tp = GetDriveType(n);
902 if (tp != 0)
903 {
904 ret |= (DWORD)(1UL << n);
905 }
906 }
907 return ret;
908 }
909
910 #endif
911
912 typedef WORD GATE_FILEOP_FLAGS;
913
914 typedef struct _GATE_SHFILEOPSTRUCT
915 {
916 HWND hwnd;
917 UINT wFunc;
918 TCHAR const* pFrom; /* terminated by double zero */
919 TCHAR const* pTo; /* terminated by double zero */
920 GATE_FILEOP_FLAGS fFlags;
921 BOOL fAnyOperationsAborted;
922 LPVOID hNameMappings;
923 PCSTR lpszProgressTitle;
924 } GATE_SHFILEOPSTRUCT, * GATE_LPSHFILEOPSTRUCT;
925
926 #if defined(GATE_WIN32_UNICODE)
927 # define shell32_shfileop_name "SHFileOperationW"
928 #else
929 # define shell32_shfileop_name "SHFileOperationA"
930 #endif
931
932 typedef int(WINAPI* shell32_shfileop_t)(GATE_LPSHFILEOPSTRUCT lpFileOp);
933 static shell32_shfileop_t shell32_shfileop = NULL;
934 static gate_atomic_flag_t shell32_shfileop_loaded = GATE_ATOMIC_FLAG_INIT;
935
936 #define GATE_WIN32_SHFILEOP_MOVE 0x0001
937 #define GATE_WIN32_SHFILEOP_COPY 0x0002
938 #define GATE_WIN32_SHFILEOP_DELETE 0x0003
939 #define GATE_WIN32_SHFILEOP_RENAME 0x0004
940
941
942 #ifndef FOF_SILENT
943 #define FOF_SILENT 0x0004
944 #endif
945 #ifndef FOF_NOCONFIRMATION
946 #define FOF_NOCONFIRMATION 0x0010
947 #endif
948 #ifndef FOF_NOCONFIRMMKDIR
949 #define FOF_NOCONFIRMMKDIR 0x0200
950 #endif
951 #ifndef FOF_NOERRORUI
952 #define FOF_NOERRORUI 0x0400
953 #endif
954 #ifndef FOF_NORECURSION
955 #define FOF_NORECURSION 0x1000
956 #endif
957 #ifndef FOF_NO_UI
958 #define FOF_NO_UI (FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR)
959 #endif
960
961 static gate_bool_t load_shell32_shfileop()
962 {
963 HMODULE hmod_shell32 = gate_win32_get_shell_module();
964
965 if (hmod_shell32)
966 {
967 if (!gate_atomic_flag_set(&shell32_shfileop_loaded))
968 {
969 // execute only once:
970 gate_win32_get_proc_address(hmod_shell32, shell32_shfileop_name, &shell32_shfileop);
971 }
972 }
973 return shell32_shfileop != NULL;
974 }
975
976 static gate_bool_t gate_win32_shfileop(unsigned operation, TCHAR const* fromZZ, TCHAR const* toZZ)
977 {
978 GATE_SHFILEOPSTRUCT fileop;
979 int result;
980
981 if (!load_shell32_shfileop())
982 {
983 return false;
984 }
985
986 gate_mem_clear(&fileop, sizeof(fileop));
987 fileop.hwnd = (HWND)NULL;
988 fileop.wFunc = operation;
989 fileop.pFrom = fromZZ;
990 fileop.pTo = toZZ;
991 fileop.fFlags = FOF_NORECURSION | FOF_NO_UI;
992 result = shell32_shfileop(&fileop);
993 return result == 0;
994 }
995
996
997 #if defined(GATE_SYS_WIN16)
998
999 gate_result_t gate_file_open(gate_string_t const* filepath, gate_enumint_t flags, gate_file_t* filehandle)
1000 {
1001 char path[GATE_MAX_FILEPATH_LENGTH];
1002 gate_platform_stream_t ps;
1003 gate_result_t result;
1004
1005 gate_string_to_buffer(filepath, path, sizeof(path));
1006 result = gate_platform_stream_open(path, flags, 0, &ps);
1007 if (GATE_SUCCEEDED(result) && filehandle)
1008 {
1009 *filehandle = (gate_file_t)ps;
1010 }
1011 return result;
1012 }
1013
1014 #else /* !defined(GATE_SYS_WIN16) */
1015
1016
1017 #ifndef SECURITY_WORLD_SID_AUTHORITY
1018 #define SECURITY_WORLD_SID_AUTHORITY {0,0,0,0,0,1}
1019 #endif
1020
1021 #ifndef SECURITY_NT_AUTHORITY
1022 #define SECURITY_NT_AUTHORITY {0,0,0,0,0,5}
1023 #endif
1024
1025 static const SID_IDENTIFIER_AUTHORITY gate_win32_world_sid = { SECURITY_WORLD_SID_AUTHORITY };
1026 static const SID_IDENTIFIER_AUTHORITY gate_win32_nt_sid = { SECURITY_NT_AUTHORITY };
1027
1028 static LPSECURITY_ATTRIBUTES gate_win32_create_security_attribs(
1029 gate_enumint_t flags, LPSECURITY_ATTRIBUTES secattributes,
1030 gate_win32_sidstruct_t* sidowner, gate_win32_sidstruct_t* sidgroup, gate_win32_sidstruct_t* sideveryone,
1031 SECURITY_DESCRIPTOR* secdescr, BYTE* aclBuffer)
1032 {
1033 LPSECURITY_ATTRIBUTES ret = NULL; /* by default or in error cases -> inherit default security descriptor */
1034 gate_bool_t restrictowner = GATE_FLAG_ENABLED(flags, GATE_FILE_OPEN_CREATEOWNERRESTRICTED);
1035 gate_bool_t restrictgroup = GATE_FLAG_ENABLED(flags, GATE_FILE_OPEN_CREATEGROUPRESTRICTED);
1036 gate_bool_t unrestricted = GATE_FLAG_ENABLED(flags, GATE_FILE_OPEN_CREATEUNRESTRICTED);
1037
1038 if (!restrictowner && !restrictgroup && !unrestricted)
1039 {
1040 /* return NULL to inherit default security descriptor */
1041 GATE_UNUSED_ARG(secattributes);
1042 GATE_UNUSED_ARG(sidowner);
1043 GATE_UNUSED_ARG(sidgroup);
1044 GATE_UNUSED_ARG(sideveryone);
1045 GATE_UNUSED_ARG(secdescr);
1046 GATE_UNUSED_ARG(aclBuffer);
1047 }
1048 else
1049 {
1050 #if !defined(GATE_SYS_WINSTORE) && !defined(GATE_SYS_WINCE) && !defined(GATE_SYS_WIN16)
1051 PSID psidAll = (PSID)sideveryone;
1052 PSID psidGroup = (PSID)sidgroup;
1053 PSID psidOwner = (PSID)sidowner;
1054
1055 HANDLE hToken = (HWND)NULL;
1056 HANDLE hProc;
1057 char userBuffer[1024] = { 0 };
1058 PTOKEN_USER pUser = (PTOKEN_USER)&userBuffer[0];
1059 PACL pacl = (PACL)&aclBuffer[0];
1060
1061 DWORD dwLen = sizeof(userBuffer);
1062 DWORD dwACLFlags = GENERIC_READ | GENERIC_WRITE | DELETE | GENERIC_EXECUTE;
1063
1064 do
1065 {
1066 hProc = GetCurrentProcess();
1067
1068 gate_mem_clear(sideveryone, sizeof(gate_win32_sidstruct_t));
1069 sideveryone->Revision = SID_REVISION;
1070 sideveryone->IdentifierAuthority = gate_win32_world_sid;
1071 sideveryone->SubAuthCount = 1;
1072
1073 gate_mem_clear(sidgroup, sizeof(gate_win32_sidstruct_t));
1074 sidgroup->Revision = SID_REVISION;
1075 sidgroup->IdentifierAuthority = gate_win32_nt_sid;
1076 sidgroup->SubAuthCount = 2;
1077 sidgroup->SubAuthorities[0] = SECURITY_BUILTIN_DOMAIN_RID;
1078 sidgroup->SubAuthorities[1] = DOMAIN_ALIAS_RID_USERS;
1079
1080 gate_mem_clear(sidowner, sizeof(gate_win32_sidstruct_t));
1081 sidowner->Revision = SID_REVISION;
1082
1083 /* check, if the platform supports all required functions */
1084 if ((gate_platform.AdvOpenProcessToken == NULL)
1085 || (gate_platform.AdvGetTokenInformation == NULL)
1086 || (gate_platform.AdvInitializeSecurityDescriptor == NULL)
1087 || (gate_platform.AdvInitializeAcl == NULL)
1088 || (gate_platform.AdvAddAccessAllowedAce == NULL)
1089 || (gate_platform.AdvSetSecurityDescriptorDacl == NULL)
1090 )
1091 {
1092 break;
1093 }
1094
1095 if (!gate_platform.AdvOpenProcessToken(hProc, TOKEN_READ, &hToken))
1096 {
1097 break;
1098 }
1099
1100 if (!gate_platform.AdvGetTokenInformation(hToken, TokenUser, &userBuffer[0], sizeof(userBuffer), &dwLen))
1101 {
1102 break;
1103 }
1104
1105 gate_win32_sid_export(pUser->User.Sid, sidowner);
1106
1107 if (!gate_platform.AdvInitializeSecurityDescriptor(secdescr, SECURITY_DESCRIPTOR_REVISION))
1108 {
1109 break;
1110 }
1111 if (!gate_platform.AdvInitializeAcl(pacl, sizeof(aclBuffer), ACL_REVISION))
1112 {
1113 break;
1114 }
1115
1116 if (unrestricted)
1117 {
1118 if (!gate_platform.AdvAddAccessAllowedAce(pacl, ACL_REVISION, dwACLFlags, psidAll))
1119 {
1120 break;
1121 }
1122 }
1123 else
1124 {
1125 if (restrictowner)
1126 {
1127 if (!gate_platform.AdvAddAccessAllowedAce(pacl, ACL_REVISION, dwACLFlags, psidOwner))
1128 {
1129 break;
1130 }
1131 }
1132 if (restrictgroup)
1133 {
1134 if (!gate_platform.AdvAddAccessAllowedAce(pacl, ACL_REVISION, dwACLFlags, psidGroup))
1135 {
1136 break;
1137 }
1138 }
1139 }
1140
1141 if (!gate_platform.AdvSetSecurityDescriptorDacl(secdescr, TRUE, pacl, FALSE))
1142 {
1143 break;
1144 }
1145
1146 secattributes->nLength = sizeof(SECURITY_ATTRIBUTES);
1147 secattributes->bInheritHandle = FALSE;
1148 secattributes->lpSecurityDescriptor = secdescr;
1149
1150 ret = secattributes;
1151 } while (0);
1152
1153 gate_win32_closehandle(hToken);
1154 #endif
1155 }
1156
1157
1158 return ret;
1159 }
1160
1161 gate_result_t gate_file_open(gate_string_t const* filepath, gate_enumint_t flags, gate_file_t* filehandle)
1162 {
1163 TCHAR path[GATE_MAX_FILEPATH_LENGTH];
1164 DWORD accessmode = 0;
1165 DWORD sharemode = 0;
1166 DWORD createdispo = 0;
1167 DWORD fileattribs = FILE_ATTRIBUTE_NORMAL;
1168 gate_bool_t truncate = false;
1169 gate_bool_t append = false;
1170 HANDLE hfile;
1171 gate_result_t ret;
1172 gate_win32_sidstruct_t sideveryone;
1173 gate_win32_sidstruct_t sidowner;
1174 gate_win32_sidstruct_t sidgroup;
1175 LPSECURITY_ATTRIBUTES ptr_secattributes = NULL;
1176 SECURITY_ATTRIBUTES secattributes;
1177 SECURITY_DESCRIPTOR secdescr;
1178 BYTE aclBuffer[1024];
1179
1180 gate_win32_utf8_2_winstr(filepath->str, filepath->length, path, sizeof(path) / sizeof(path[0]));
1181
1182 switch (flags & GATE_STREAM_OPEN_FLAGS_MASK)
1183 {
1184 case GATE_STREAM_OPEN_READ:
1185 {
1186 accessmode = (GENERIC_READ);
1187 sharemode = (FILE_SHARE_READ);
1188 createdispo = (OPEN_EXISTING);
1189 break;
1190 }
1191 case GATE_STREAM_OPEN_WRITE:
1192 {
1193 accessmode = (GENERIC_WRITE);
1194 sharemode = (FILE_SHARE_READ);
1195 createdispo = (CREATE_ALWAYS);
1196 fileattribs = FILE_ATTRIBUTE_ARCHIVE;
1197 truncate = true;
1198 break;
1199 }
1200 case GATE_STREAM_OPEN_READWRITE:
1201 {
1202 accessmode = (GENERIC_READ | GENERIC_WRITE);
1203 sharemode = (FILE_SHARE_READ);
1204 createdispo = (OPEN_ALWAYS);
1205 fileattribs = FILE_ATTRIBUTE_ARCHIVE;
1206 break;
1207 }
1208 case GATE_STREAM_OPEN_APPENDWRITE:
1209 {
1210 accessmode = (GENERIC_WRITE);
1211 sharemode = (FILE_SHARE_READ);
1212 createdispo = (OPEN_ALWAYS);
1213 fileattribs = FILE_ATTRIBUTE_ARCHIVE;
1214 append = true;
1215 break;
1216 }
1217 case GATE_STREAM_OPEN_APPENDREADWRITE:
1218 {
1219 accessmode = (GENERIC_READ | GENERIC_WRITE);
1220 createdispo = (OPEN_ALWAYS);
1221 fileattribs = FILE_ATTRIBUTE_ARCHIVE;
1222 append = true;
1223 break;
1224 }
1225 default:
1226 {
1227 return GATE_RESULT_INVALIDARG;
1228 }
1229 }
1230
1231 sharemode = (FILE_SHARE_READ);
1232 if (GATE_FLAG_ENABLED(flags, GATE_FILE_OPEN_SHARED))
1233 {
1234 sharemode |= FILE_SHARE_WRITE;
1235 }
1236
1237 /* generate a security descriptor for the file, if supported by the platform, otherwise NULL: */
1238 ptr_secattributes = gate_win32_create_security_attribs(flags, &secattributes, &sidowner, &sidgroup, &sideveryone, &secdescr, aclBuffer);
1239
1240 hfile = gate_win32_createfile(path, accessmode, sharemode, createdispo, fileattribs, 0, ptr_secattributes);
1241 if (hfile == (HANDLE)INVALID_HANDLE_VALUE)
1242 {
1243 gate_win32_print_lasterror(&ret, NULL, 0);
1244 return ret;
1245 }
1246
1247 if (truncate)
1248 {
1249 gate_win32_setendoffile(hfile);
1250 }
1251
1252 if (filehandle == NULL)
1253 {
1254 gate_win32_closehandle(hfile);
1255 return GATE_RESULT_OK;
1256 }
1257
1258 *filehandle = (gate_file_t)hfile;
1259
1260 if (append)
1261 {
1262 gate_file_seek(*filehandle, 0, GATE_FILE_SEEK_ORIGIN_END, NULL);
1263 }
1264 return GATE_RESULT_OK;
1265 }
1266 #endif
1267
1268 gate_result_t gate_file_read(gate_file_t filehandle, char* buffer, gate_size_t bufferlength, gate_size_t* bufferused)
1269 {
1270 gate_result_t ret;
1271 DWORD bytesreceived = 0;
1272 HANDLE hfile = (HANDLE)filehandle;
1273 if (gate_win32_readfile(hfile, (LPVOID)buffer, (DWORD)bufferlength, &bytesreceived, NULL))
1274 {
1275 if (bufferused)
1276 {
1277 *bufferused = (gate_size_t)bytesreceived;
1278 }
1279 ret = GATE_RESULT_OK;
1280 }
1281 else
1282 {
1283 gate_win32_print_lasterror(&ret, NULL, 0);
1284 }
1285 return ret;
1286 }
1287 gate_result_t gate_file_write(gate_file_t filehandle, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
1288 {
1289 gate_result_t ret;
1290 DWORD byteswritten = 0;
1291 HANDLE hfile = (HANDLE)filehandle;
1292 if (gate_win32_writefile(hfile, (LPVOID)buffer, (DWORD)bufferlength, &byteswritten, NULL))
1293 {
1294 *written = (gate_size_t)byteswritten;
1295 ret = GATE_RESULT_OK;
1296 }
1297 else
1298 {
1299 gate_win32_print_lasterror(&ret, NULL, 0);
1300 }
1301 return ret;
1302 }
1303 gate_result_t gate_file_flush(gate_file_t filehandle)
1304 {
1305 gate_result_t ret;
1306 if (gate_win32_flushfilebuffers((HANDLE)filehandle))
1307 {
1308 ret = GATE_RESULT_OK;
1309 }
1310 else
1311 {
1312 gate_win32_print_lasterror(&ret, NULL, 0);
1313 }
1314 return ret;
1315 }
1316
1317 gate_result_t gate_file_close(gate_file_t filehandle)
1318 {
1319 gate_result_t ret;
1320 HANDLE hfile = (HANDLE)filehandle;
1321 if (gate_win32_closehandle(hfile))
1322 {
1323 ret = GATE_RESULT_OK;
1324 }
1325 else
1326 {
1327 gate_win32_print_lasterror(&ret, NULL, 0);
1328 }
1329 return ret;
1330 }
1331 gate_result_t gate_file_seek(gate_file_t filehandle, gate_int64_t position, gate_enumint_t origin, gate_int64_t* newposition)
1332 {
1333 HANDLE hfile = (HANDLE)filehandle;
1334 DWORD movemethod = 0;
1335 LARGE_INTEGER li;
1336
1337 gate_win32_write_largeint(position, &li);
1338
1339 switch (origin)
1340 {
1341 case GATE_FILE_SEEK_ORIGIN_BEGIN: movemethod = FILE_BEGIN; break;
1342 case GATE_FILE_SEEK_ORIGIN_CURPOS: movemethod = FILE_CURRENT; break;
1343 case GATE_FILE_SEEK_ORIGIN_END: movemethod = FILE_END; break;
1344 default: return GATE_RESULT_INVALIDARG;
1345 }
1346
1347 if (gate_win32_setfilepointer(hfile, li, &li, movemethod))
1348 {
1349 if (newposition != NULL)
1350 {
1351 gate_win32_read_largeint(&li, newposition);
1352 }
1353 return GATE_RESULT_OK;
1354 }
1355 return GATE_RESULT_FAILED;
1356 }
1357 gate_result_t gate_file_pos(gate_file_t filehandle, gate_int64_t* position)
1358 {
1359 HANDLE hfile = (HANDLE)filehandle;
1360 LARGE_INTEGER li;
1361 gate_win32_write_largeint(0, &li);
1362
1363 if (gate_win32_setfilepointer(hfile, li, &li, FILE_CURRENT))
1364 {
1365 if (position == NULL)
1366 {
1367 return GATE_RESULT_INVALIDARG;
1368 }
1369 gate_win32_read_largeint(&li, position);
1370 return GATE_RESULT_OK;
1371 }
1372 return GATE_RESULT_FAILED;
1373 }
1374 gate_result_t gate_file_size(gate_file_t filehandle, gate_int64_t* size)
1375 {
1376 HANDLE hfile = (HANDLE)filehandle;
1377 LARGE_INTEGER li;
1378 if (gate_win32_getfilesize(hfile, &li))
1379 {
1380 if (size == NULL)
1381 {
1382 return GATE_RESULT_INVALIDARG;
1383 }
1384 gate_win32_read_largeint(&li, size);
1385 return GATE_RESULT_OK;
1386 }
1387 return GATE_RESULT_FAILED;
1388 }
1389
1390 gate_result_t gate_file_truncate(gate_file_t filehandle)
1391 {
1392 gate_result_t ret = GATE_RESULT_FAILED;
1393 HANDLE hfile = (HANDLE)filehandle;
1394 if (gate_win32_setendoffile(hfile))
1395 {
1396 ret = GATE_RESULT_OK;
1397 }
1398 else
1399 {
1400 gate_win32_print_lasterror(&ret, NULL, 0);
1401 }
1402 return ret;
1403 }
1404
1405 static DWORD const default_lock_length_low = 0xffffffff;
1406 #if defined(GATE_WIN32_ANSI)
1407 static DWORD const default_lock_length_high = 0x00000000;
1408 #else
1409 static DWORD const default_lock_length_high = 0x7fffffff;
1410 #endif
1411
1412 #if defined(GATE_SYS_WINCE) || defined(GATE_SYS_WIN16)
1413 #if defined(__MINGW32CE__) || (_WIN32_WCE < 0x500) || defined(GATE_SYS_WIN16)
1414
1415 #ifndef LOCKFILE_EXCLUSIVE_LOCK
1416 #define LOCKFILE_EXCLUSIVE_LOCK 1
1417 #endif
1418
1419 #ifndef LOCKFILE_FAIL_IMMEDIATELY
1420 #define LOCKFILE_FAIL_IMMEDIATELY 2
1421 #endif
1422
1423 #if defined(GATE_COMPILER_MSVC)
1424 #define GATE_FILES_HELPER_API static
1425 #else
1426 #define GATE_FILES_HELPER_API
1427 #endif
1428
1429 GATE_FILES_HELPER_API BOOL LockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh)
1430 {
1431 GATE_UNUSED_ARG(hFile);
1432 GATE_UNUSED_ARG(dwFileOffsetLow);
1433 GATE_UNUSED_ARG(dwFileOffsetHigh);
1434 GATE_UNUSED_ARG(nNumberOfBytesToLockLow);
1435 GATE_UNUSED_ARG(nNumberOfBytesToLockHigh);
1436 return FALSE;
1437 }
1438
1439 GATE_FILES_HELPER_API BOOL LockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved,
1440 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
1441 LPOVERLAPPED lpOverlapped)
1442 {
1443 GATE_UNUSED_ARG(hFile);
1444 GATE_UNUSED_ARG(dwFlags);
1445 GATE_UNUSED_ARG(dwReserved);
1446 GATE_UNUSED_ARG(nNumberOfBytesToLockLow);
1447 GATE_UNUSED_ARG(nNumberOfBytesToLockHigh);
1448 GATE_UNUSED_ARG(lpOverlapped);
1449 return FALSE;
1450 }
1451
1452 GATE_FILES_HELPER_API BOOL UnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh)
1453 {
1454 GATE_UNUSED_ARG(hFile);
1455 GATE_UNUSED_ARG(dwFileOffsetLow);
1456 GATE_UNUSED_ARG(dwFileOffsetHigh);
1457 GATE_UNUSED_ARG(nNumberOfBytesToUnlockLow);
1458 GATE_UNUSED_ARG(nNumberOfBytesToUnlockHigh);
1459 return FALSE;
1460 }
1461
1462 GATE_FILES_HELPER_API BOOL UnlockFileEx(HANDLE hFile, DWORD dwReserved,
1463 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
1464 LPOVERLAPPED lpOverlapped)
1465 {
1466 GATE_UNUSED_ARG(hFile);
1467 GATE_UNUSED_ARG(dwReserved);
1468 GATE_UNUSED_ARG(nNumberOfBytesToLockLow);
1469 GATE_UNUSED_ARG(nNumberOfBytesToLockHigh);
1470 GATE_UNUSED_ARG(lpOverlapped);
1471 return FALSE;
1472 }
1473
1474 #endif
1475 #endif
1476
1477 #ifndef ERROR_LOCK_VIOLATION
1478 #define ERROR_LOCK_VIOLATION 0x21
1479 #endif
1480
1481 gate_result_t gate_file_lock(gate_file_t filehandle, gate_bool_t wait)
1482 {
1483 gate_result_t ret = GATE_RESULT_FAILED;
1484
1485 do
1486 {
1487 HANDLE const hfile = (HANDLE)filehandle;
1488 BOOL succeeded;
1489 gate_int64_t current_pos;
1490 ret = gate_file_pos(filehandle, &current_pos);
1491 GATE_BREAK_IF_FAILED(ret);
1492 #if defined(GATE_WIN32_ANSI)
1493 GATE_UNUSED_ARG(wait);
1494 succeeded = LockFile(hfile, 0, 0, default_lock_length_low, default_lock_length_high);
1495 #else
1496 do
1497 {
1498 OVERLAPPED ov;
1499 DWORD dwFlags = LOCKFILE_EXCLUSIVE_LOCK;
1500
1501 ret = gate_file_seek(filehandle, 0, GATE_FILE_SEEK_ORIGIN_BEGIN, NULL);
1502 GATE_BREAK_IF_FAILED(ret);
1503
1504 gate_mem_clear(&ov, sizeof(ov));
1505 if (!wait)
1506 {
1507 dwFlags |= LOCKFILE_FAIL_IMMEDIATELY;
1508 }
1509
1510 succeeded = LockFileEx(hfile, dwFlags, 0, default_lock_length_low, default_lock_length_high, &ov);
1511 gate_file_seek(filehandle, current_pos, GATE_FILE_SEEK_ORIGIN_BEGIN, NULL);
1512 } while(0);
1513 GATE_BREAK_IF_FAILED(ret);
1514 #endif
1515 if (succeeded)
1516 {
1517 ret = GATE_RESULT_OK;
1518 }
1519 else
1520 {
1521 if (gate_win32_getlasterror() == ERROR_LOCK_VIOLATION)
1522 {
1523 ret = GATE_RESULT_ACCESSDENIED;
1524 }
1525 else
1526 {
1527 gate_win32_print_lasterror(&ret, NULL, 0);
1528 }
1529 }
1530 } while (0);
1531
1532 return ret;
1533 }
1534 gate_result_t gate_file_unlock(gate_file_t filehandle)
1535 {
1536 gate_result_t ret = GATE_RESULT_FAILED;
1537 HANDLE hfile = (HANDLE)filehandle;
1538 gate_int64_t current_pos = 0;
1539 BOOL succeeded;
1540 #if !defined(GATE_WIN32_ANSI)
1541 OVERLAPPED ov;
1542 #endif
1543
1544 do
1545 {
1546 ret = gate_file_pos(filehandle, &current_pos);
1547 GATE_BREAK_IF_FAILED(ret);
1548
1549 #if defined(GATE_WIN32_ANSI)
1550 succeeded = UnlockFile(hfile, 0, 0, default_lock_length_low, default_lock_length_high);
1551 #else
1552 ret = gate_file_seek(filehandle, 0, GATE_FILE_SEEK_ORIGIN_BEGIN, NULL);
1553 GATE_BREAK_IF_FAILED(ret);
1554
1555 gate_mem_clear(&ov, sizeof(ov));
1556 succeeded = UnlockFileEx(hfile, 0, default_lock_length_low, default_lock_length_high, &ov);
1557 #endif
1558 if (succeeded)
1559 {
1560 ret = GATE_RESULT_OK;
1561 }
1562 else
1563 {
1564 gate_win32_print_lasterror(&ret, NULL, 0);
1565 }
1566
1567 gate_file_seek(filehandle, current_pos, GATE_FILE_SEEK_ORIGIN_BEGIN, NULL);
1568 } while (0);
1569
1570 return ret;
1571 }
1572
1573 static gate_bool_t gate_file_is_server_path(LPTSTR path, gate_bool_t stripshare)
1574 {
1575 #if defined(GATE_SYS_WIN16)
1576 GATE_UNUSED_ARG(path);
1577 GATE_UNUSED_ARG(stripshare);
1578 return false;
1579 #else
1580 gate_size_t pathlength = gate_win32_str_len(path);
1581 gate_size_t pos;
1582 if (pathlength < 2)
1583 {
1584 return false;
1585 }
1586 if (gate_win32_str_pos(path, pathlength, _T("\\\\"), 2, 0) != 0)
1587 {
1588 return false;
1589 }
1590
1591 /* path starts with double-backslashes */
1592 if (stripshare)
1593 {
1594 pos = gate_win32_str_pos(path, pathlength, _T("\\"), 1, 2);
1595 if (pos != GATE_STR_NPOS)
1596 {
1597 path[pos] = 0;
1598 }
1599 }
1600 return true;
1601 #endif
1602 }
1603
1604 static gate_bool_t gate_file_is_server_share_path(LPTSTR path, gate_bool_t stripsubpath)
1605 {
1606 #if defined(GATE_SYS_WIN16)
1607 GATE_UNUSED_ARG(path);
1608 GATE_UNUSED_ARG(stripsubpath);
1609 return false;
1610 #else
1611 gate_size_t pathlength = gate_win32_str_len(path);
1612 gate_size_t pos;
1613 gate_size_t shareendpos;
1614 if (pathlength < 2)
1615 {
1616 return false;
1617 }
1618 if (gate_win32_str_pos(path, pathlength, _T("\\\\"), 2, 0) != 0)
1619 {
1620 return false;
1621 }
1622
1623 /* path starts with double-backslashes */
1624
1625 pos = gate_win32_str_pos(path, pathlength, _T("\\"), 1, 2);
1626 if ((pos == GATE_STR_NPOS) || (pos + 1 == pathlength))
1627 {
1628 return false;
1629 }
1630
1631 if (stripsubpath)
1632 {
1633 shareendpos = gate_win32_str_pos(path, pathlength, _T("\\"), 1, pos);
1634 if (shareendpos != GATE_STR_NPOS)
1635 {
1636 path[shareendpos] = 0;
1637 }
1638 }
1639 return true;
1640 #endif
1641 }
1642
1643 static gate_bool_t gate_win32_is_volume_path(TCHAR const* path, gate_size_t path_len)
1644 {
1645 #if defined(GATE_SYS_WINCE)
1646 return (path_len == 1) && (path[0] == '\\');
1647 #else
1648 TCHAR drive;
1649 if ((path_len < 2) || (path_len > 3))
1650 {
1651 return false;
1652 }
1653 if (path[1] != _T(':'))
1654 {
1655 return false;
1656 }
1657 if ((path_len == 3) && (path[2] != _T('\\')))
1658 {
1659 return false;
1660 }
1661 drive = path[0];
1662 return ((drive >= _T('A')) && (drive <= _T('Z')))
1663 || ((drive >= _T('a')) && (drive <= _T('z')));
1664 #endif
1665 }
1666
1667 gate_result_t gate_file_exists(gate_string_t const* filepath)
1668 {
1669 WIN32_FIND_DATA data;
1670 HANDLE hfind;
1671 TCHAR path[GATE_MAX_FILEPATH_LENGTH];
1672 gate_size_t pathlen = gate_win32_utf8_2_winstr(filepath->str, filepath->length, path, sizeof(path) / sizeof(path[0]));
1673 if ((pathlen > 0) && (path[pathlen - 1] == '\\'))
1674 {
1675 --pathlen;
1676 path[pathlen] = 0;
1677 }
1678
1679 if (gate_file_is_server_path(path, false))
1680 {
1681 return GATE_RESULT_OK;
1682 }
1683 if (gate_file_is_server_share_path(path, false))
1684 {
1685 return GATE_RESULT_OK;
1686 }
1687
1688 #if !defined(GATE_SYS_WINCE)
1689 if (gate_win32_is_volume_path(path, pathlen))
1690 {
1691 DWORD drives = GetLogicalDrives();
1692 DWORD drivebit = (DWORD)(1 << (gate_char_uppercase(path[0]) - 'A'));
1693 if ((drives & drivebit) == 0)
1694 {
1695 return GATE_RESULT_NOTAVAILABLE;
1696 }
1697 return GATE_RESULT_OK;
1698 }
1699 #endif
1700
1701 hfind = gate_win32_findfirstfile(&path[0], &data);
1702 if ((HANDLE)INVALID_HANDLE_VALUE == hfind)
1703 {
1704 return GATE_RESULT_NOTAVAILABLE;
1705 }
1706 gate_win32_findclose(hfind);
1707 return GATE_RESULT_OK;
1708 }
1709
1710 gate_result_t gate_file_copy(gate_string_t const* srcfilepath, gate_string_t const* dstfilepath, gate_enumint_t flags)
1711 {
1712 #if defined(GATE_SYS_WIN16)
1713 return gate_file_copy_internal(srcfilepath, dstfilepath, flags);
1714 #else
1715 gate_result_t ret;
1716 if (GATE_FLAG_ENABLED(flags, GATE_FILE_COPY_SIMPLE))
1717 {
1718 ret = gate_file_copy_internal(srcfilepath, dstfilepath, flags);
1719 }
1720 else
1721 {
1722 TCHAR srcpath[GATE_MAX_FILEPATH_LENGTH];
1723 TCHAR dstpath[GATE_MAX_FILEPATH_LENGTH];
1724 const gate_size_t srcpathlen = gate_win32_string_2_winstr(srcfilepath, srcpath, sizeof(srcpath) / sizeof(srcpath[0]));
1725 const gate_size_t dstpathlen = gate_win32_string_2_winstr(dstfilepath, dstpath, sizeof(dstpath) / sizeof(dstpath[0]));
1726
1727 if ((srcpathlen == 0) || (dstpathlen == 0))
1728 {
1729 ret = GATE_RESULT_INVALIDARG;
1730 }
1731 else
1732 {
1733 if (CopyFile(srcpath, dstpath, GATE_FLAG_ENABLED(flags, GATE_FILE_COPY_OVERWRITE) ? TRUE : FALSE))
1734 {
1735 ret = GATE_RESULT_OK;
1736 }
1737 else
1738 {
1739 gate_win32_print_lasterror(&ret, NULL, 0);
1740 }
1741 }
1742 }
1743 return ret;
1744 #endif
1745 }
1746 gate_result_t gate_file_move(gate_string_t const* srcfilepath, gate_string_t const* dstfilepath)
1747 {
1748 #if defined(GATE_SYS_WIN16)
1749 return gate_file_move_internal(srcfilepath, dstfilepath);
1750 #else
1751 gate_result_t ret;
1752 TCHAR srcpath[GATE_MAX_FILEPATH_LENGTH];
1753 TCHAR dstpath[GATE_MAX_FILEPATH_LENGTH];
1754 gate_size_t srcpathlen = gate_win32_string_2_winstr(srcfilepath, srcpath, sizeof(srcpath) / sizeof(srcpath[0]));
1755 gate_size_t dstpathlen = gate_win32_string_2_winstr(dstfilepath, dstpath, sizeof(dstpath) / sizeof(dstpath[0]));
1756
1757 if ((srcpathlen == 0) || (dstpathlen == 0))
1758 {
1759 ret = GATE_RESULT_INVALIDARG;
1760 }
1761 else
1762 {
1763 if (MoveFile(srcpath, dstpath))
1764 {
1765 ret = GATE_RESULT_OK;
1766 }
1767 else
1768 {
1769 gate_win32_print_lasterror(&ret, NULL, 0);
1770 }
1771 }
1772 return ret;
1773 #endif
1774 }
1775
1776 #if defined(GATE_SYS_WIN16)
1777 static BOOL DeleteFile(LPCSTR lpFileName)
1778 {
1779 OFSTRUCT of;
1780 HFILE hf = OpenFile(lpFileName, &of, OF_DELETE);
1781 if (hf == HFILE_ERROR)
1782 {
1783 return FALSE;
1784 }
1785 return TRUE;
1786 }
1787 #endif
1788
1789
1790 gate_result_t gate_file_delete(gate_string_t const* filepath)
1791 {
1792 gate_result_t ret;
1793 TCHAR path[GATE_MAX_FILEPATH_LENGTH];
1794 gate_size_t pathlen = gate_win32_string_2_winstr(filepath, path, sizeof(path) / sizeof(path[0]) - 1);
1795 DWORD dw_error;
1796
1797 if (pathlen == 0)
1798 {
1799 ret = GATE_RESULT_INVALIDARG;
1800 }
1801 else
1802 {
1803 path[pathlen + 1] = 0; /* ensure double zero for shell-file-ops */
1804 if (DeleteFile(path))
1805 {
1806 ret = GATE_RESULT_OK;
1807 }
1808 else
1809 {
1810 dw_error = gate_win32_getlasterror();
1811 gate_win32_print_lasterror_code(dw_error, &ret, NULL, 0);
1812 /* try fallback */
1813 if (gate_win32_shfileop(GATE_WIN32_SHFILEOP_DELETE, path, NULL))
1814 {
1815 ret = GATE_RESULT_OK;
1816 }
1817 else
1818 {
1819 gate_win32_setlasterror(dw_error);
1820 }
1821 }
1822 }
1823 return ret;
1824 }
1825
1826
1827 #ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
1828 #define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE 0x2
1829 #endif
1830
1831 #ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
1832 #define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1
1833 #endif
1834
1835 #ifndef INVALID_FILE_ATTRIBUTES
1836 #define INVALID_FILE_ATTRIBUTES ((DWORD)(-1))
1837 #endif
1838
1839 #if defined(GATE_SYS_WIN16)
1840 static DWORD GetFileAttributes(LPCSTR lpFileName)
1841 {
1842 DWORD ret;
1843 struct _finddata_t fd;
1844 intptr_t h = _findfirst(lpFileName, &fd);
1845 if (h != -1)
1846 {
1847 _findclose(h);
1848 ret = 0;
1849 GATE_FLAG_SET(ret, FILE_ATTRIBUTE_READONLY, GATE_FLAG_ENABLED(fd.attrib, _A_RDONLY));
1850 GATE_FLAG_SET(ret, FILE_ATTRIBUTE_SYSTEM, GATE_FLAG_ENABLED(fd.attrib, _A_SYSTEM));
1851 GATE_FLAG_SET(ret, FILE_ATTRIBUTE_HIDDEN, GATE_FLAG_ENABLED(fd.attrib, _A_HIDDEN));
1852 GATE_FLAG_SET(ret, FILE_ATTRIBUTE_DIRECTORY, GATE_FLAG_ENABLED(fd.attrib, _A_SUBDIR));
1853 GATE_FLAG_SET(ret, FILE_ATTRIBUTE_ARCHIVE, GATE_FLAG_ENABLED(fd.attrib, _A_ARCH));
1854 }
1855 else
1856 {
1857 ret = INVALID_FILE_ATTRIBUTES;
1858 }
1859 return ret;
1860 }
1861 #endif
1862
1863 static gate_size_t gate_file_build_abs_path(gate_string_t const* srcpath, TCHAR* targetpath, gate_size_t targetpathcapacity)
1864 {
1865 TCHAR tmppath[GATE_MAX_FILEPATH_LENGTH];
1866 gate_size_t tmppathlen = gate_win32_string_2_winstr(srcpath, tmppath, sizeof(tmppath) / sizeof(tmppath[0]) - 1);
1867 #if !defined(GATE_SYS_WINCE) && !defined(GATE_SYS_WIN16)
1868 DWORD fulllen = GetFullPathName(tmppath, (DWORD)targetpathcapacity, targetpath, NULL);
1869 if (fulllen != 0)
1870 {
1871 return (gate_size_t)fulllen;
1872 }
1873 else
1874 #endif
1875 {
1876 return gate_win32_winstr_print_text(targetpath, targetpathcapacity, tmppath, tmppathlen);
1877 }
1878 }
1879
1880 gate_result_t gate_file_real_path(gate_string_t const* relativepath, gate_string_t* absolutepath)
1881 {
1882 TCHAR tmppath[GATE_MAX_FILEPATH_LENGTH];
1883 gate_size_t tmppathlen;
1884 if (!relativepath || !absolutepath)
1885 {
1886 return GATE_RESULT_NULLPOINTER;
1887 }
1888
1889 tmppathlen = gate_file_build_abs_path(relativepath, tmppath, sizeof(tmppath) / sizeof(tmppath[0]) - 1);
1890 if (NULL == gate_win32_winstr_2_utf8_string(tmppath, tmppathlen, absolutepath))
1891 {
1892 return GATE_RESULT_OUTOFMEMORY;
1893 }
1894 return GATE_RESULT_OK;
1895 }
1896
1897
1898 gate_result_t gate_file_create_link(gate_string_t const* targetfile, gate_string_t const* linkfile)
1899 {
1900 #if defined(GATE_SYS_WIN16) || defined(GATE_SYS_WINCE)
1901 GATE_UNUSED_ARG(targetfile);
1902 GATE_UNUSED_ARG(linkfile);
1903 return GATE_RESULT_NOTIMPLEMENTED;
1904 #else
1905 gate_result_t ret;
1906 TCHAR targetpath[GATE_MAX_FILEPATH_LENGTH];
1907 TCHAR linkpath[GATE_MAX_FILEPATH_LENGTH];
1908 gate_size_t targetpathlen = gate_file_build_abs_path(targetfile, targetpath, sizeof(targetpath) / sizeof(targetpath[0]));
1909 gate_size_t linkpathlen = gate_win32_string_2_winstr(linkfile, linkpath, sizeof(linkpath) / sizeof(linkpath[0]));
1910 DWORD dwFlags = 0;
1911 DWORD dwAttribs;
1912
1913 do
1914 {
1915 if ((targetpathlen == 0) || (linkpathlen == 0))
1916 {
1917 ret = GATE_RESULT_INVALIDARG;
1918 break;
1919 }
1920
1921 if (gate_platform.Win32CreateSymbolicLink == NULL)
1922 {
1923 /* symbolic-link API not available (pre-Vista) */
1924 ret = GATE_RESULT_NOTSUPPORTED;
1925 break;
1926 }
1927
1928 dwAttribs = GetFileAttributes(targetpath);
1929 if (INVALID_FILE_ATTRIBUTES == dwAttribs)
1930 {
1931 /* target path not available, so we cannot determine the file type */
1932 ret = GATE_RESULT_NOTAVAILABLE;
1933 break;
1934 }
1935
1936 if (GATE_FLAG_ENABLED(dwAttribs, FILE_ATTRIBUTE_DIRECTORY))
1937 {
1938 dwFlags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
1939 }
1940
1941 if (!gate_platform.Win32CreateSymbolicLink(linkpath, targetpath, dwFlags))
1942 {
1943 DWORD lasterr = gate_win32_getlasterror();
1944 if (lasterr == ERROR_PRIVILEGE_NOT_HELD)
1945 {
1946 /* try optional Win10+ support for unpriviledged link-creation */
1947 dwFlags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
1948 if (gate_platform.Win32CreateSymbolicLink(linkpath, targetpath, dwFlags))
1949 {
1950 /* Yay! Win-Devmode is active */
1951 ret = GATE_RESULT_OK;
1952 break;
1953 }
1954 else
1955 {
1956 /* reset error code for proper handling by caller */
1957 gate_win32_setlasterror(lasterr);
1958 }
1959 }
1960 gate_win32_print_lasterror_code(lasterr, &ret, NULL, 0);
1961 break;
1962 }
1963
1964 /* success case reached */
1965 ret = GATE_RESULT_OK;
1966 } while (0);
1967
1968 return ret;
1969 #endif
1970 }
1971
1972 #ifndef FILE_NAME_NORMALIZED
1973 #define FILE_NAME_NORMALIZED 0x00
1974 #endif
1975
1976 #if !defined(GATE_SYS_WIN16)
1977
1978 typedef struct _GATE_REPARSE_DATA_BUFFER {
1979 ULONG ReparseTag;
1980 USHORT ReparseDataLength;
1981 USHORT Reserved;
1982 union {
1983 struct {
1984 USHORT SubstituteNameOffset;
1985 USHORT SubstituteNameLength;
1986 USHORT PrintNameOffset;
1987 USHORT PrintNameLength;
1988 ULONG Flags;
1989 WCHAR PathBuffer[1];
1990 } SymbolicLinkReparseBuffer;
1991 struct {
1992 USHORT SubstituteNameOffset;
1993 USHORT SubstituteNameLength;
1994 USHORT PrintNameOffset;
1995 USHORT PrintNameLength;
1996 WCHAR PathBuffer[1];
1997 } MountPointReparseBuffer;
1998 struct {
1999 UCHAR DataBuffer[1];
2000 } GenericReparseBuffer;
2001 } UnionItems;
2002 } GATE_REPARSE_DATA_BUFFER, * PGATE_REPARSE_DATA_BUFFER;
2003 #endif
2004
2005 #ifndef FILE_DEVICE_FILE_SYSTEM
2006 #define FILE_DEVICE_FILE_SYSTEM 0x00000009
2007 #endif
2008
2009 #ifndef METHOD_BUFFERED
2010 #define METHOD_BUFFERED 0
2011 #endif
2012
2013 #ifndef FILE_ANY_ACCESS
2014 #define FILE_ANY_ACCESS 0
2015 #endif
2016
2017 #ifndef CTL_CODE
2018 #define CTL_CODE( DeviceType, Function, Method, Access ) ( ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) )
2019 #endif
2020
2021 #ifndef FSCTL_GET_REPARSE_POINT
2022 #define FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)
2023 #endif
2024
2025 #ifndef IO_REPARSE_TAG_SYMLINK
2026 #define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
2027 #endif
2028
2029 gate_result_t gate_file_read_link(gate_string_t const* linkfile, gate_string_t* realpath)
2030 {
2031 #if defined(GATE_SYS_WINCE) || defined(GATE_SYS_WIN16)
2032 GATE_UNUSED_ARG(linkfile);
2033 GATE_UNUSED_ARG(realpath);
2034 return GATE_RESULT_NOTIMPLEMENTED;
2035 #else
2036 gate_result_t ret = GATE_RESULT_NOTIMPLEMENTED;
2037 HANDLE hsearch = INVALID_HANDLE_VALUE;
2038 HANDLE hfile = INVALID_HANDLE_VALUE;
2039 TCHAR linkpath[GATE_MAX_FILEPATH_LENGTH] = GATE_INIT_EMPTY;
2040 gate_size_t linkpathlen = gate_win32_string_2_winstr(linkfile, linkpath, sizeof(linkpath) / sizeof(linkpath[0]));
2041 TCHAR targetpath[GATE_MAX_FILEPATH_LENGTH] = GATE_INIT_EMPTY;
2042 DWORD len_used = 0;
2043 BOOL privilege_enabled = FALSE;
2044 gate_bool_t reset_privilege = false;
2045 WIN32_FIND_DATA searchdata = GATE_INIT_EMPTY;
2046 gate_bool_t is_sym_link = true;
2047 DWORD bytes_returned = 0;
2048 GATE_REPARSE_DATA_BUFFER* ptr_reparse_buffer = NULL;
2049
2050 do
2051 {
2052 if (linkpathlen == 0)
2053 {
2054 ret = GATE_RESULT_INVALIDARG;
2055 break;
2056 }
2057 hsearch = gate_win32_findfirstfile(linkpath, &searchdata);
2058 if (INVALID_HANDLE_VALUE != hsearch)
2059 {
2060 switch (searchdata.dwReserved0)
2061 {
2062 case IO_REPARSE_TAG_SYMLINK:
2063 is_sym_link = true;
2064 break;
2065 default:
2066 is_sym_link = false;
2067 break;
2068 }
2069 }
2070
2071 if (gate_platform.Win32GetFinalPathNameByHandle == NULL)
2072 {
2073 ret = GATE_RESULT_NOTSUPPORTED;
2074 break;
2075 }
2076
2077 hfile = gate_win32_createfile(linkpath, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING,
2078 FILE_ATTRIBUTE_NORMAL, 0, NULL);
2079 if ((INVALID_HANDLE_VALUE == hfile) || (NULL == hfile))
2080 {
2081 if (gate_win32_token_privilege_is_enabled(NULL, SE_BACKUP_NAME, &privilege_enabled))
2082 {
2083 if (!privilege_enabled)
2084 {
2085 if (gate_win32_token_privilege_enable(NULL, SE_BACKUP_NAME, TRUE))
2086 {
2087 reset_privilege = true;
2088 }
2089 }
2090 }
2091
2092 hfile = gate_win32_createfile(linkpath, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING,
2093 0, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
2094 if ((INVALID_HANDLE_VALUE == hfile) || (NULL == hfile))
2095 {
2096 gate_win32_print_lasterror(&ret, NULL, 0);
2097 }
2098 else
2099 {
2100 ret = GATE_RESULT_OK;
2101 }
2102 if (reset_privilege)
2103 {
2104 gate_win32_token_privilege_enable(NULL, SE_BACKUP_NAME, FALSE);
2105 }
2106 GATE_BREAK_IF_FAILED(ret);
2107 }
2108
2109 if (is_sym_link)
2110 {
2111 /* get final path name of symlink */
2112 len_used = gate_platform.Win32GetFinalPathNameByHandle(hfile, targetpath, sizeof(targetpath) / sizeof(targetpath[0]), FILE_NAME_NORMALIZED);
2113 if (0 == len_used)
2114 {
2115 gate_win32_print_lasterror(&ret, NULL, 0);
2116 break;
2117 }
2118 else
2119 {
2120 if (NULL == gate_win32_winstr_2_utf8_string(targetpath, len_used, realpath))
2121 {
2122 ret = GATE_RESULT_OUTOFMEMORY;
2123 break;
2124 }
2125 }
2126 }
2127 else
2128 {
2129 /* get reparse point */
2130 ptr_reparse_buffer = (GATE_REPARSE_DATA_BUFFER*)&targetpath[0];
2131 if (!DeviceIoControl(hfile, FSCTL_GET_REPARSE_POINT, NULL, 0, ptr_reparse_buffer, sizeof(targetpath), &bytes_returned, NULL))
2132 {
2133 ret = GATE_RESULT_FAILED;
2134 break;
2135 }
2136
2137 if (NULL == gate_string_create_utf16(realpath,
2138 &ptr_reparse_buffer->UnionItems.MountPointReparseBuffer.PathBuffer[0],
2139 gate_str16_length(&ptr_reparse_buffer->UnionItems.MountPointReparseBuffer.PathBuffer[0])
2140 ))
2141 {
2142 ret = GATE_RESULT_OUTOFMEMORY;
2143 break;
2144 }
2145 }
2146
2147 /* reached SUCCESS case ;) */
2148 ret = GATE_RESULT_OK;
2149 } while (0);
2150
2151 gate_win32_closehandle(hfile);
2152 gate_win32_findclose(hsearch);
2153
2154 return ret;
2155 #endif
2156 }
2157 gate_result_t gate_file_create_hardlink(gate_string_t const* targetfile, gate_string_t const* linkfile)
2158 {
2159 #if defined(GATE_SYS_WIN16)
2160 GATE_UNUSED_ARG(targetfile);
2161 GATE_UNUSED_ARG(linkfile);
2162 return GATE_RESULT_NOTIMPLEMENTED;
2163 #else
2164 gate_result_t ret;
2165 TCHAR targetpath[GATE_MAX_FILEPATH_LENGTH];
2166 TCHAR linkpath[GATE_MAX_FILEPATH_LENGTH];
2167 gate_size_t targetpathlen = gate_win32_string_2_winstr(targetfile, targetpath, sizeof(targetpath) / sizeof(targetpath[0]));
2168 gate_size_t linkpathlen = gate_win32_string_2_winstr(linkfile, linkpath, sizeof(linkpath) / sizeof(linkpath[0]));
2169
2170 if ((targetpathlen == 0) || (linkpathlen == 0))
2171 {
2172 ret = GATE_RESULT_INVALIDARG;
2173 }
2174 else
2175 {
2176 if (gate_platform.Win32CreateHardLink == NULL)
2177 {
2178 ret = GATE_RESULT_NOTSUPPORTED;
2179 }
2180 else
2181 {
2182 if (gate_platform.Win32CreateHardLink(linkpath, targetpath, NULL))
2183 {
2184 ret = GATE_RESULT_OK;
2185 }
2186 else
2187 {
2188 gate_win32_print_lasterror(&ret, NULL, 0);
2189 }
2190 }
2191 }
2192 return ret;
2193 #endif
2194 }
2195
2196
2197 static gate_timestamp_t gate_win32_to_timestamp(FILETIME const* ft)
2198 {
2199 gate_uint64_t tmp = ((gate_uint64_t)ft->dwHighDateTime << 32) | (gate_uint64_t)ft->dwLowDateTime;
2200 tmp /= 10;
2201 return (gate_timestamp_t)tmp;
2202 }
2203
2204 static void gate_win32_convert_timestamp(gate_timestamp_t src, FILETIME* dest)
2205 {
2206 gate_uint64_t tmp = src * 10;
2207 dest->dwHighDateTime = (DWORD)(tmp >> 32);
2208 dest->dwLowDateTime = (DWORD)(tmp & 0xffffffff);
2209 }
2210
2211 gate_result_t gate_file_get_attributes(gate_string_t const* targetfile, gate_enumint_t* attribs, gate_enumint_t* access_bits)
2212 {
2213 gate_result_t ret;
2214 DWORD dwAttribs;
2215 TCHAR targetpath[GATE_MAX_FILEPATH_LENGTH];
2216 gate_size_t targetpathlen = gate_win32_string_2_winstr(targetfile, targetpath, sizeof(targetpath) / sizeof(targetpath[0]));
2217
2218 do
2219 {
2220 if (targetpathlen == 0)
2221 {
2222 ret = GATE_RESULT_INVALIDARG;
2223 break;
2224 }
2225
2226 if (attribs)
2227 {
2228 dwAttribs = GetFileAttributes(targetpath);
2229 if (INVALID_FILE_ATTRIBUTES == dwAttribs)
2230 {
2231 ret = GATE_RESULT_FAILED;
2232 break;
2233 }
2234
2235 if (attribs == NULL)
2236 {
2237 ret = GATE_RESULT_INVALIDARG;
2238 break;
2239 }
2240 *attribs = 0;
2241
2242 if (GATE_FLAG_ENABLED(dwAttribs, FILE_ATTRIBUTE_DIRECTORY))
2243 {
2244 *attribs |= GATE_FILEENTRY_ATTRIB_DIRECTORY;
2245 }
2246 else
2247 {
2248 *attribs |= GATE_FILEENTRY_ATTRIB_FILE;
2249 }
2250 if (GATE_FLAG_ENABLED(dwAttribs, FILE_ATTRIBUTE_ARCHIVE)) *attribs |= GATE_FILEENTRY_ATTRIB_ARCHIVE;
2251 if (GATE_FLAG_ENABLED(dwAttribs, FILE_ATTRIBUTE_HIDDEN)) *attribs |= GATE_FILEENTRY_ATTRIB_HIDDEN;
2252 if (GATE_FLAG_ENABLED(dwAttribs, FILE_ATTRIBUTE_READONLY)) *attribs |= GATE_FILEENTRY_ATTRIB_READONLY;
2253 if (GATE_FLAG_ENABLED(dwAttribs, FILE_ATTRIBUTE_SYSTEM)) *attribs |= GATE_FILEENTRY_ATTRIB_SYSTEM;
2254 if (GATE_FLAG_ENABLED(dwAttribs, FILE_ATTRIBUTE_COMPRESSED)) *attribs |= GATE_FILEENTRY_ATTRIB_COMPRESSED;
2255 if (GATE_FLAG_ENABLED(dwAttribs, FILE_ATTRIBUTE_TEMPORARY)) *attribs |= GATE_FILEENTRY_ATTRIB_TEMP;
2256 if (GATE_FLAG_ENABLED(dwAttribs, FILE_ATTRIBUTE_REPARSE_POINT)) *attribs |= GATE_FILEENTRY_ATTRIB_LINK;
2257
2258 if (gate_file_is_hidden_entry(targetfile))
2259 {
2260 *attribs |= GATE_FILEENTRY_ATTRIB_HIDDEN;
2261 }
2262 }
2263
2264 if (access_bits)
2265 {
2266 *access_bits = 0;
2267 if (gate_string_ends_with_str_ic(targetfile, ".exe"))
2268 {
2269 *access_bits |= (GATE_FILEENTRY_ACCESS_OWNEREXECUTE | GATE_FILEENTRY_ACCESS_GROUPEXECUTE | GATE_FILEENTRY_ACCESS_ALLEXECUTE);
2270 }
2271 }
2272
2273 ret = GATE_RESULT_OK;
2274 } while (0);
2275 return ret;
2276 }
2277
2278
2279 static void gate_win32_update_attribute_flags(DWORD* dwAttribs, gate_enumint_t attribs, gate_enumint_t mask,
2280 gate_enumint_t gate_flag, DWORD win_flag)
2281 {
2282 if (GATE_FLAG_ENABLED(mask, gate_flag))
2283 {
2284 if (GATE_FLAG_ENABLED(attribs, gate_flag))
2285 {
2286 *dwAttribs |= win_flag;
2287 }
2288 else
2289 {
2290 *dwAttribs &= ~win_flag;
2291 }
2292 }
2293 }
2294
2295 #if defined(GATE_SYS_WIN16)
2296
2297 static BOOL SetFileAttributes(LPCSTR lpFileName, DWORD dwFileAttributes)
2298 {
2299 GATE_UNUSED_ARG(lpFileName);
2300 GATE_UNUSED_ARG(dwFileAttributes);
2301 return FALSE;
2302 }
2303
2304 #endif
2305
2306 gate_result_t gate_file_set_attributes(gate_string_t const* targetfile,
2307 gate_enumint_t attribs, gate_enumint_t attribs_mask,
2308 gate_enumint_t access_bits, gate_enumint_t access_mask)
2309 {
2310 gate_result_t ret = GATE_RESULT_OK;
2311 DWORD dwAttribs = 0;
2312 TCHAR targetpath[GATE_MAX_FILEPATH_LENGTH];
2313 gate_size_t targetpathlen = gate_win32_string_2_winstr(targetfile, targetpath, sizeof(targetpath) / sizeof(targetpath[0]));
2314
2315 do
2316 {
2317 if (targetpathlen == 0)
2318 {
2319 ret = GATE_RESULT_INVALIDARG;
2320 break;
2321 }
2322
2323 if (attribs_mask != 0)
2324 {
2325 dwAttribs = GetFileAttributes(targetpath);
2326 if (INVALID_FILE_ATTRIBUTES == dwAttribs)
2327 {
2328 ret = GATE_RESULT_FAILED;
2329 break;
2330 }
2331
2332 gate_win32_update_attribute_flags(&dwAttribs, attribs, attribs_mask, GATE_FILEENTRY_ATTRIB_READONLY, FILE_ATTRIBUTE_READONLY);
2333 gate_win32_update_attribute_flags(&dwAttribs, attribs, attribs_mask, GATE_FILEENTRY_ATTRIB_SYSTEM, FILE_ATTRIBUTE_SYSTEM);
2334 gate_win32_update_attribute_flags(&dwAttribs, attribs, attribs_mask, GATE_FILEENTRY_ATTRIB_HIDDEN, GATE_FILEENTRY_ATTRIB_HIDDEN);
2335 gate_win32_update_attribute_flags(&dwAttribs, attribs, attribs_mask, GATE_FILEENTRY_ATTRIB_ARCHIVE, GATE_FILEENTRY_ATTRIB_ARCHIVE);
2336
2337 if (!SetFileAttributes(targetpath, dwAttribs))
2338 {
2339 ret = GATE_RESULT_FAILED;
2340 break;
2341 }
2342 }
2343
2344 if (access_mask != 0)
2345 {
2346 /* TODO update file ACL */
2347 GATE_UNUSED_ARG(access_bits);
2348 ret = GATE_RESULT_NOTSUPPORTED;
2349 break;
2350 }
2351
2352 } while (0);
2353
2354 return ret;
2355 }
2356
2357 gate_result_t gate_file_get_size(gate_string_t const* targetfile, gate_int64_t* filesize)
2358 {
2359 gate_result_t ret;
2360 TCHAR targetpath[GATE_MAX_FILEPATH_LENGTH];
2361 gate_size_t targetpathlen = gate_win32_string_2_winstr(targetfile, targetpath, sizeof(targetpath) / sizeof(targetpath[0]));
2362 HANDLE hfile = (HANDLE)INVALID_HANDLE_VALUE;
2363 LARGE_INTEGER large_int;
2364 #if defined(GATE_SYS_WINSTORE)
2365 WIN32_FILE_ATTRIBUTE_DATA attrData;
2366 #endif
2367
2368 do
2369 {
2370 if (targetpathlen == 0)
2371 {
2372 ret = GATE_RESULT_INVALIDARG;
2373 break;
2374 }
2375 #if defined(GATE_SYS_WINSTORE)
2376 if (!GetFileAttributesEx(targetpath, GetFileExInfoStandard, &attrData))
2377 {
2378 ret = GATE_RESULT_FAILED;
2379 break;
2380 }
2381 large_int.QuadPart = (LONGLONG)((((gate_uint64_t)attrData.nFileSizeHigh) << 32) + (gate_uint64_t)attrData.nFileSizeLow);
2382 #else /* GATE_SYS_WINSTORE */
2383 hfile = gate_win32_createfile(targetpath, FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING,
2384 0, FILE_FLAG_BACKUP_SEMANTICS, NULL);
2385 if (hfile == (HANDLE)INVALID_HANDLE_VALUE)
2386 {
2387 ret = GATE_RESULT_FAILED;
2388 break;
2389 }
2390 if (!gate_win32_getfilesize(hfile, &large_int))
2391 {
2392 ret = GATE_RESULT_FAILED;
2393 break;
2394 }
2395 #endif /* GATE_SYS_WINSTORE */
2396
2397 if (filesize)
2398 {
2399 gate_win32_read_largeint(&large_int, filesize);
2400 }
2401 ret = GATE_RESULT_OK;
2402 break;
2403
2404 } while (0);
2405
2406 gate_win32_closehandle(hfile);
2407 return ret;
2408 }
2409
2410
2411 gate_result_t gate_file_get_times(gate_string_t const* targetfile, gate_timestamp_t* modified,
2412 gate_timestamp_t* accessed, gate_timestamp_t* created)
2413 {
2414 gate_result_t ret;
2415 TCHAR targetpath[GATE_MAX_FILEPATH_LENGTH];
2416 gate_size_t targetpathlen = gate_win32_string_2_winstr(targetfile, targetpath, sizeof(targetpath) / sizeof(targetpath[0]));
2417 HANDLE hfile = (HANDLE)INVALID_HANDLE_VALUE;
2418 FILETIME ftModified, ftAccessed, ftCreated;
2419 #if defined(GATE_SYS_WINCE)
2420 DWORD dwAttribs = 0;
2421 #endif
2422 #if defined(GATE_SYS_WINSTORE)
2423 WIN32_FILE_ATTRIBUTE_DATA attrData;
2424 #endif
2425
2426 do
2427 {
2428 if (targetpathlen == 0)
2429 {
2430 ret = GATE_RESULT_INVALIDARG;
2431 break;
2432 }
2433 #if defined(GATE_SYS_WINCE)
2434 dwAttribs = GetFileAttributes(targetpath);
2435 if (dwAttribs == 0xFFFFFFFF)
2436 {
2437 ret = GATE_RESULT_FAILED;
2438 break;
2439 }
2440 if (GATE_FLAG_ENABLED(dwAttribs, FILE_ATTRIBUTE_DIRECTORY))
2441 {
2442 if (created) *created = 0;
2443 if (accessed) *accessed = 0;
2444 if (modified) *modified = 0;
2445 ret = GATE_RESULT_OK;
2446 break;
2447 }
2448 #endif
2449
2450 #if defined(GATE_SYS_WINSTORE)
2451 if (!GetFileAttributesEx(targetpath, GetFileExInfoStandard, &attrData))
2452 {
2453 ret = GATE_RESULT_FAILED;
2454 break;
2455 }
2456 ftCreated = attrData.ftCreationTime;
2457 ftAccessed = attrData.ftLastAccessTime;
2458 ftModified = attrData.ftLastWriteTime;
2459 #elif defined(GATE_SYS_WIN16)
2460 ret = GATE_RESULT_NOTSUPPORTED;
2461 #else /* GATE_SYS_WINSTORE */
2462 hfile = gate_win32_createfile(targetpath, FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING,
2463 0, FILE_FLAG_BACKUP_SEMANTICS, NULL);
2464 if (INVALID_HANDLE_VALUE == hfile)
2465 {
2466 ret = GATE_RESULT_FAILED;
2467 break;
2468 }
2469 if (!GetFileTime(hfile, &ftCreated, &ftAccessed, &ftModified))
2470 {
2471 ret = GATE_RESULT_FAILED;
2472 }
2473 else
2474 {
2475 ret = GATE_RESULT_OK;
2476 }
2477 #endif /* GATE_SYS_WINSTORE */
2478 if (created) *created = gate_win32_to_timestamp(&ftCreated);
2479 if (accessed) *accessed = gate_win32_to_timestamp(&ftAccessed);
2480 if (modified) *modified = gate_win32_to_timestamp(&ftModified);
2481
2482 } while (0);
2483
2484 gate_win32_closehandle(hfile);
2485 return ret;
2486 }
2487
2488
2489 gate_result_t gate_file_set_times(gate_string_t const* targetfile, gate_timestamp_t const* modified,
2490 gate_timestamp_t const* accessed, gate_timestamp_t const* created)
2491 {
2492 gate_result_t ret;
2493 TCHAR targetpath[GATE_MAX_FILEPATH_LENGTH];
2494 gate_size_t targetpathlen = gate_win32_string_2_winstr(targetfile, targetpath, sizeof(targetpath) / sizeof(targetpath[0]));
2495 HANDLE hfile = (HANDLE)INVALID_HANDLE_VALUE;
2496 FILETIME ftModified, ftAccessed, ftCreated;
2497 do
2498 {
2499 if (targetpathlen == 0)
2500 {
2501 ret = GATE_RESULT_INVALIDARG;
2502 break;
2503 }
2504
2505 if (created) gate_win32_convert_timestamp(*created, &ftCreated);
2506 if (accessed) gate_win32_convert_timestamp(*accessed, &ftAccessed);
2507 if (modified) gate_win32_convert_timestamp(*modified, &ftModified);
2508
2509 #if defined(GATE_SYS_WINSTORE) || defined(GATE_SYS_WIN16)
2510 ret = GATE_RESULT_NOTSUPPORTED;
2511 break;
2512 #else
2513 hfile = gate_win32_createfile(targetpath, FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING, 0, FILE_FLAG_BACKUP_SEMANTICS, NULL);
2514 if (hfile == INVALID_HANDLE_VALUE)
2515 {
2516 ret = GATE_RESULT_FAILED;
2517 break;
2518 }
2519
2520 if (!SetFileTime(hfile, (created ? &ftCreated : NULL), (accessed ? &ftAccessed : NULL), (modified ? &ftModified : NULL)))
2521 {
2522 ret = GATE_RESULT_FAILED;
2523 }
2524 else
2525 {
2526 ret = GATE_RESULT_OK;
2527 }
2528 #endif
2529 } while (0);
2530
2531 gate_win32_closehandle(hfile);
2532 return ret;
2533 }
2534
2535 #ifndef OWNER_SECURITY_INFORMATION
2536 #define OWNER_SECURITY_INFORMATION (0x00000001L)
2537 #endif
2538
2539 #ifndef GROUP_SECURITY_INFORMATION
2540 #define GROUP_SECURITY_INFORMATION (0x00000002L)
2541 #endif
2542
2543 gate_result_t gate_file_get_owner(gate_string_t const* targetpath,
2544 gate_uint32_t* owner_id, gate_string_t* owner_name)
2545 {
2546 #if defined(GATE_SYS_WINSTORE) || defined(GATE_SYS_WINCE) || defined(GATE_SYS_WIN16)
2547 GATE_UNUSED_ARG(targetpath);
2548 GATE_UNUSED_ARG(owner_id);
2549 GATE_UNUSED_ARG(owner_name);
2550 return GATE_RESULT_NOTSUPPORTED;
2551 #else
2552
2553 gate_result_t ret = GATE_RESULT_FAILED;
2554 HANDLE hfile = INVALID_HANDLE_VALUE;
2555 PSECURITY_DESCRIPTOR descriptor = NULL;
2556 DWORD sec_info = 0;
2557 PSID owner_sid = NULL;
2558 PSID group_sid = NULL;
2559 DWORD owner_rid = 0;
2560 DWORD result;
2561 TCHAR filepath[GATE_MAX_FILEPATH_LENGTH] = GATE_INIT_EMPTY;
2562 char owner_buffer[512] = GATE_INIT_EMPTY;
2563
2564 do
2565 {
2566 if (!gate_platform.AdvGetSecurityInfo)
2567 {
2568 ret = GATE_RESULT_NOTSUPPORTED;
2569 break;
2570 }
2571
2572 gate_win32_string_2_winstr(targetpath, filepath, sizeof(filepath) / sizeof(filepath[0]));
2573 hfile = gate_win32_createfile(filepath, READ_CONTROL, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING, 0, FILE_FLAG_BACKUP_SEMANTICS, NULL);
2574 if (hfile == INVALID_HANDLE_VALUE)
2575 {
2576 ret = gate_platform_print_last_error(NULL, 0);
2577 break;
2578 }
2579 sec_info = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION;
2580 result = gate_platform.AdvGetSecurityInfo(hfile, GATE_SE_FILE_OBJECT, sec_info, &owner_sid, &group_sid, NULL, NULL, &descriptor);
2581 if (0 != result)
2582 {
2583 ret = GATE_RESULT_FAILED;
2584 break;
2585 }
2586
2587 ret = GATE_RESULT_OK;
2588 if (owner_id)
2589 {
2590 if (gate_win32_sid_local_id(owner_sid, &owner_rid))
2591 {
2592 *owner_id = owner_rid;
2593 }
2594 else
2595 {
2596 *owner_id = 0;
2597 }
2598 }
2599 if (owner_name)
2600 {
2601 if (gate_win32_sid_resolve(owner_sid, owner_buffer, sizeof(owner_buffer)))
2602 {
2603 if (NULL == gate_string_create(owner_name, owner_buffer, gate_str_length(owner_buffer)))
2604 {
2605 ret = GATE_RESULT_OUTOFMEMORY;
2606 }
2607 }
2608 else
2609 {
2610 gate_string_create_empty(owner_name);
2611 }
2612 }
2613 } while (0);
2614
2615 if (descriptor != NULL)
2616 {
2617 LocalFree(descriptor);
2618 }
2619 gate_win32_closehandle(hfile);
2620 return ret;
2621 #endif
2622 }
2623
2624
2625
2626 #ifndef IO_REPARSE_TAG_SYMLINK
2627 #define IO_REPARSE_TAG_SYMLINK (0xA000000C)
2628 #endif
2629
2630 static void gate_win32_load_direntry(WIN32_FIND_DATA const* filedata, gate_file_entry_t* direntry,
2631 char const* filepath, gate_size_t filepathlen)
2632 {
2633 DWORD fileAttribs = filedata->dwFileAttributes;
2634 gate_string_t filepathstr;
2635
2636 #if !defined(GATE_SYS_WINCE) && !defined(GATE_SYS_WINSTORE) && !defined(GATE_SYS_WIN16)
2637 /* SymLink detection code */
2638
2639 BY_HANDLE_FILE_INFORMATION handleinfo;
2640 TCHAR tmppath[GATE_MAX_FILEPATH_LENGTH];
2641 HANDLE hfile;
2642
2643 direntry->props.attribs = 0;
2644
2645 if (GATE_FLAG_ENABLED(fileAttribs, FILE_ATTRIBUTE_REPARSE_POINT))
2646 {
2647 direntry->props.attribs |= GATE_FILEENTRY_ATTRIB_LINK;
2648 if (filedata->dwReserved0 == IO_REPARSE_TAG_SYMLINK)
2649 {
2650
2651 if (!GATE_FLAG_ENABLED(fileAttribs, FILE_ATTRIBUTE_DIRECTORY))
2652 {
2653 /* load data from real file */
2654 gate_win32_utf8_2_winstr(filepath, filepathlen, tmppath, sizeof(tmppath) / sizeof(tmppath[0]));
2655 hfile = gate_win32_createfile(tmppath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
2656 OPEN_EXISTING, 0, 0, NULL);
2657 if (hfile != INVALID_HANDLE_VALUE)
2658 {
2659 if (GetFileInformationByHandle(hfile, &handleinfo))
2660 {
2661 fileAttribs = handleinfo.dwFileAttributes;
2662 direntry->props.size = ((gate_uint64_t)handleinfo.nFileSizeHigh << 32) + (gate_uint64_t)(handleinfo.nFileSizeLow);
2663 direntry->props.time_created = gate_win32_to_timestamp(&handleinfo.ftCreationTime);
2664 direntry->props.time_accessed = gate_win32_to_timestamp(&handleinfo.ftLastAccessTime);
2665 direntry->props.time_modified = gate_win32_to_timestamp(&handleinfo.ftLastWriteTime);
2666 }
2667 gate_win32_closehandle(hfile);
2668 }
2669 }
2670 }
2671 }
2672 #else
2673 direntry->props.attribs = 0;
2674 #endif
2675
2676 direntry->props.size = ((gate_uint64_t)filedata->nFileSizeHigh << 32) + (gate_uint64_t)(filedata->nFileSizeLow);
2677
2678 direntry->props.time_created = gate_win32_to_timestamp(&filedata->ftCreationTime);
2679 direntry->props.time_accessed = gate_win32_to_timestamp(&filedata->ftLastAccessTime);
2680 direntry->props.time_modified = gate_win32_to_timestamp(&filedata->ftLastWriteTime);
2681
2682 if (GATE_FLAG_ENABLED(fileAttribs, FILE_ATTRIBUTE_DIRECTORY)) direntry->props.attribs |= GATE_FILEENTRY_ATTRIB_DIRECTORY;
2683 if (GATE_FLAG_ENABLED(fileAttribs, FILE_ATTRIBUTE_READONLY)) direntry->props.attribs |= GATE_FILEENTRY_ATTRIB_READONLY;
2684 if (GATE_FLAG_ENABLED(fileAttribs, FILE_ATTRIBUTE_HIDDEN)) direntry->props.attribs |= GATE_FILEENTRY_ATTRIB_HIDDEN;
2685 if (GATE_FLAG_ENABLED(fileAttribs, FILE_ATTRIBUTE_SYSTEM)) direntry->props.attribs |= GATE_FILEENTRY_ATTRIB_SYSTEM;
2686 if (GATE_FLAG_ENABLED(fileAttribs, FILE_ATTRIBUTE_ARCHIVE)) direntry->props.attribs |= GATE_FILEENTRY_ATTRIB_ARCHIVE;
2687
2688 /* windows special types: */
2689 if (GATE_FLAG_ENABLED(fileAttribs, FILE_ATTRIBUTE_TEMPORARY)) direntry->props.attribs |= GATE_FILEENTRY_ATTRIB_TEMP;
2690 if (GATE_FLAG_ENABLED(fileAttribs, FILE_ATTRIBUTE_COMPRESSED)) direntry->props.attribs |= GATE_FILEENTRY_ATTRIB_COMPRESSED;
2691 if (GATE_FLAG_ENABLED(fileAttribs, FILE_ATTRIBUTE_ENCRYPTED)) direntry->props.attribs |= GATE_FILEENTRY_ATTRIB_ENCRYPTED;
2692 #if defined(FILE_ATTRIBUTE_DEVICE)
2693 if (GATE_FLAG_ENABLED(fileAttribs, FILE_ATTRIBUTE_DEVICE)) direntry->props.attribs |= GATE_FILEENTRY_ATTRIB_DEVICE;
2694 #endif
2695
2696 if (0 == (fileAttribs & (FILE_ATTRIBUTE_DIRECTORY
2697 #if defined(FILE_ATTRIBUTE_DEVICE)
2698 | FILE_ATTRIBUTE_DEVICE
2699 #endif
2700 )))
2701 {
2702 /* neither a directory nor a device -> file */
2703 direntry->props.attribs |= GATE_FILEENTRY_ATTRIB_FILE;
2704 }
2705 gate_string_create_static_len(&filepathstr, filepath, filepathlen);
2706 if (gate_file_is_hidden_entry(&filepathstr))
2707 {
2708 direntry->props.attribs |= GATE_FILEENTRY_ATTRIB_HIDDEN;
2709 }
2710
2711 if (gate_str_ends_with_ic(filepath, filepathlen, ".exe", 4))
2712 {
2713 direntry->props.access |= (GATE_FILEENTRY_ACCESS_ALLEXECUTE | GATE_FILEENTRY_ACCESS_OWNEREXECUTE | GATE_FILEENTRY_ACCESS_GROUPEXECUTE);
2714 }
2715 }
2716
2717 gate_result_t gate_file_get_entry(gate_string_t const* srcpath, gate_file_entry_t* ptr_entry)
2718 {
2719 gate_result_t ret;
2720 TCHAR path[GATE_MAX_FILEPATH_LENGTH + 5];
2721 gate_size_t pathlen = gate_win32_string_2_winstr(srcpath, path, sizeof(path) / sizeof(path[0]));
2722 gate_size_t filenamelen;
2723 gate_size_t filepathlen;
2724
2725 HANDLE handle;
2726 WIN32_FIND_DATA filedata;
2727 do
2728 {
2729 gate_mem_clear(ptr_entry, sizeof(gate_file_entry_t));
2730 if (pathlen == 0)
2731 {
2732 ret = GATE_RESULT_INVALIDARG;
2733 break;
2734 }
2735
2736 if (gate_win32_winstr_ends_with(path, pathlen, GATE_WIN32_WINSTR("\\"), 1))
2737 {
2738 --pathlen;
2739 path[pathlen] = 0;
2740 }
2741
2742 filepathlen = gate_win32_winstr_2_utf8(path, pathlen, ptr_entry->path, sizeof(ptr_entry->path));
2743
2744 handle = gate_win32_findfirstfile(path, &filedata);
2745
2746 if (handle == (HANDLE)INVALID_HANDLE_VALUE)
2747 {
2748 gate_win32_print_lasterror(&ret, NULL, 0);
2749 break;
2750 }
2751 gate_win32_findclose(handle);
2752
2753 filenamelen = gate_win32_winstr_2_utf8(filedata.cFileName, gate_win32_winstr_length(filedata.cFileName),
2754 ptr_entry->name, sizeof(ptr_entry->name));
2755 if (filenamelen == 0)
2756 {
2757 ret = GATE_RESULT_FAILED;
2758 break;
2759 }
2760
2761
2762 gate_win32_load_direntry(&filedata, ptr_entry, ptr_entry->path, filepathlen);
2763
2764 ret = GATE_RESULT_OK;
2765 } while (0);
2766
2767 return ret;
2768 }
2769
2770 gate_result_t gate_file_root_list(gate_file_list_callback_t callback, void* userparam)
2771 {
2772 gate_result_t ret = GATE_RESULT_OK;
2773 gate_file_entry_t direntry;
2774
2775 #if !defined(GATE_SYS_WINCE)
2776 DWORD drives;
2777 DWORD ndx;
2778 char name[] = "A:";
2779 char path[] = "A:\\";
2780 #endif
2781
2782 #if defined(GATE_SYS_WINCE)
2783
2784 gate_mem_clear(&direntry, sizeof(direntry));
2785 direntry.props.attribs = GATE_FILEENTRY_ATTRIB_DIRECTORY;
2786
2787 gate_str_print_text(direntry.name, sizeof(direntry.name), "\\", 1);
2788 gate_str_print_text(direntry.path, sizeof(direntry.path), "\\", 1);
2789
2790 if (callback != NULL)
2791 {
2792 callback(&direntry, userparam);
2793 }
2794 #else
2795 drives = GetLogicalDrives();
2796
2797 for (ndx = 0; ndx < 26; ++ndx)
2798 {
2799 if ((drives & (1 << ndx)) != 0)
2800 {
2801 if (callback != NULL)
2802 {
2803 gate_mem_clear(&direntry, sizeof(direntry));
2804
2805 gate_str_print_text(direntry.name, sizeof(direntry.name), name, 2);
2806 gate_str_print_text(direntry.path, sizeof(direntry.path), path, 3);
2807
2808 direntry.props.attribs = GATE_FILEENTRY_ATTRIB_DIRECTORY | GATE_FILEENTRY_ATTRIB_VOLUME;
2809
2810 if (!callback(&direntry, userparam))
2811 {
2812 break;
2813 }
2814 }
2815 }
2816 ++name[0];
2817 ++path[0];
2818 }
2819 #endif
2820
2821 return ret;
2822 }
2823
2824 gate_result_t gate_file_dir_open(gate_string_t const* dirpath, gate_file_dirreader_t* dirhandle)
2825 {
2826 gate_result_t ret = GATE_RESULT_FAILED;
2827 TCHAR searchpath[GATE_MAX_FILEPATH_LENGTH + 5];
2828 gate_size_t searchpath_len;
2829 WIN32_FIND_DATA filedata;
2830 gate_size_t filename_len;
2831
2832 do
2833 {
2834 gate_mem_clear(dirhandle, sizeof(gate_file_dirreader_t));
2835
2836 dirhandle->bufferlen = gate_string_to_buffer(dirpath, dirhandle->buffer, sizeof(dirhandle->buffer));
2837 if (dirhandle->buffer[dirhandle->bufferlen - 1] != '\\')
2838 {
2839 dirhandle->buffer[dirhandle->bufferlen] = '\\';
2840 ++dirhandle->bufferlen;
2841 dirhandle->buffer[dirhandle->bufferlen] = '\0';
2842 }
2843
2844 searchpath_len = gate_win32_utf8_2_winstr(dirhandle->buffer, dirhandle->bufferlen, searchpath, sizeof(searchpath) / sizeof(searchpath[0]));
2845 searchpath[searchpath_len++] = (TCHAR)'*';
2846 searchpath[searchpath_len++] = (TCHAR)'.';
2847 searchpath[searchpath_len++] = (TCHAR)'*';
2848 searchpath[searchpath_len] = (TCHAR)'\0';
2849
2850 dirhandle->handle = (void*)gate_win32_findfirstfile(searchpath, &filedata);
2851 if ((HANDLE)dirhandle->handle == (HANDLE)INVALID_HANDLE_VALUE)
2852 {
2853 gate_win32_print_lasterror(&ret, NULL, 0);
2854 break;
2855 }
2856 filename_len = gate_win32_winstr_length(filedata.cFileName);
2857
2858 for (;;)
2859 {
2860 if ((0 != gate_win32_winstr_compare(filedata.cFileName, filename_len, _T("."), 1))
2861 && (0 != gate_win32_winstr_compare(filedata.cFileName, filename_len, _T(".."), 2)))
2862 {
2863 break;
2864 }
2865 if (gate_win32_findnext((HANDLE)dirhandle->handle, &filedata))
2866 {
2867 filename_len = gate_win32_winstr_length(filedata.cFileName);
2868 }
2869 else
2870 {
2871 gate_mem_clear(dirhandle->buffer, sizeof(dirhandle->buffer));
2872 dirhandle->bufferlen = 0;
2873 return GATE_RESULT_OK;
2874 }
2875 }
2876
2877 gate_win32_winstr_2_utf8(filedata.cFileName, gate_win32_winstr_length(filedata.cFileName),
2878 &dirhandle->buffer[dirhandle->bufferlen], sizeof(dirhandle->buffer) - dirhandle->bufferlen);
2879
2880 ret = GATE_RESULT_OK;
2881 } while (0);
2882
2883 return ret;
2884 }
2885 gate_size_t gate_file_dir_read(gate_file_dirreader_t* dirhandle, char* path, gate_size_t pathlen, gate_bool_t filename_only)
2886 {
2887 gate_size_t ret = 0;
2888 WIN32_FIND_DATA filedata;
2889
2890 if (filename_only)
2891 {
2892 /* return previously retrieved file name */
2893 ret = gate_str_print_text(path, pathlen,
2894 &dirhandle->buffer[dirhandle->bufferlen],
2895 gate_str_length(&dirhandle->buffer[dirhandle->bufferlen]));
2896 }
2897 else
2898 {
2899 /* return previously retrieved file path */
2900 ret = gate_str_print_text(path, pathlen,
2901 &dirhandle->buffer[0],
2902 gate_str_length(&dirhandle->buffer[0]));
2903 }
2904
2905 if (ret > 0)
2906 {
2907 if (gate_win32_findnext((HANDLE)dirhandle->handle, &filedata))
2908 {
2909 gate_win32_winstr_2_utf8(filedata.cFileName, gate_win32_winstr_length(filedata.cFileName),
2910 &dirhandle->buffer[dirhandle->bufferlen], sizeof(dirhandle->buffer) - dirhandle->bufferlen
2911 );
2912 }
2913 else
2914 {
2915 /* no more files can be retrieved -> set path buffer to zero*/
2916 gate_mem_clear(dirhandle->buffer, sizeof(dirhandle->buffer));
2917 dirhandle->bufferlen = 0;
2918 }
2919 /* find next */
2920 }
2921
2922 return ret;
2923 }
2924 gate_result_t gate_file_dir_close(gate_file_dirreader_t* dirhandle)
2925 {
2926 gate_result_t ret = GATE_RESULT_FAILED;
2927
2928 if (gate_win32_findclose((HANDLE)dirhandle->handle))
2929 {
2930 ret = GATE_RESULT_OK;
2931 }
2932 gate_mem_clear(dirhandle, sizeof(gate_file_dirreader_t));
2933
2934 return ret;
2935 }
2936
2937 #if !defined(GATE_SYS_WINCE) && !defined(GATE_SYS_WINSTORE) && !defined(GATE_SYS_WIN16)
2938 # define GATE_FILES_MPR_SUPPORTED 1
2939 #endif
2940
2941
2942 #if defined(GATE_FILES_MPR_SUPPORTED)
2943
2944 typedef struct win32_mpr_functions_class
2945 {
2946 DWORD(WINAPI* MprWNetOpenEnum)(DWORD dwScope, DWORD dwType, DWORD dwUsage, LPNETRESOURCE lpNetResource, LPHANDLE lphEnum);
2947 DWORD(WINAPI* MprWNetEnumResource)(HANDLE hEnum, LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize);
2948 DWORD(WINAPI* MprWNetCloseEnum)(HANDLE hEnum);
2949 } win32_mpr_functions_t;
2950
2951 static win32_mpr_functions_t* win32_mpr()
2952 {
2953 static win32_mpr_functions_t mpr;
2954 static HMODULE hmpr = NULL;
2955 static gate_atomic_int_t mpr_load_state = 0;
2956 gate_int32_t state = 1;
2957
2958 do
2959 {
2960 state = gate_atomic_int_xchg_if(&mpr_load_state, 0, 1);
2961 if (state >= 2)
2962 {
2963 /* functions are loaded */
2964 break;
2965 }
2966 else if (state == 0)
2967 {
2968 hmpr = gate_win32_load_library(_T("mpr"), 0);
2969
2970 if (hmpr != NULL)
2971 {
2972 gate_win32_get_proc_address(hmpr, GATE_WIN32_DUAL_NAME("WNetOpenEnum"), &mpr.MprWNetOpenEnum);
2973 gate_win32_get_proc_address(hmpr, GATE_WIN32_DUAL_NAME("WNetEnumResource"), &mpr.MprWNetEnumResource);
2974 gate_win32_get_proc_address(hmpr, "WNetCloseEnum", &mpr.MprWNetCloseEnum);
2975 }
2976 gate_atomic_int_set(&mpr_load_state, 2);
2977 break;
2978 }
2979 else if (state < 0)
2980 {
2981 /* error, invalid state */
2982 break;
2983 }
2984 /* another thread is loading functions, -> wait/retry*/
2985 Sleep(0);
2986 } while (state == 1);
2987
2988 return &mpr;
2989 }
2990
2991 static gate_result_t gate_file_list_server_shares(LPTSTR path, gate_file_list_callback_t callback, void* userparam)
2992 {
2993 gate_result_t ret = GATE_RESULT_FAILED;
2994 gate_file_entry_t direntry;
2995 DWORD result;
2996 DWORD count;
2997 DWORD size;
2998 NETRESOURCE netres;
2999 HANDLE handle = NULL;
3000 gate_size_t filenamelen;
3001 gate_size_t filepathlen;
3002 win32_mpr_functions_t* mpr = win32_mpr();
3003 union
3004 {
3005 NETRESOURCE net;
3006 char buffer[8192];
3007 } netbuffer;
3008
3009 do
3010 {
3011 /* enumerate shares of an smb file service host */
3012 gate_mem_clear(&netres, sizeof(netres));
3013 netres.dwScope = RESOURCE_GLOBALNET;
3014 netres.dwType = RESOURCETYPE_DISK;
3015 netres.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;
3016 netres.dwUsage = RESOURCEUSAGE_CONTAINER;
3017 netres.lpComment = NULL;
3018 netres.lpProvider = NULL;
3019 netres.lpLocalName = NULL;
3020 netres.lpRemoteName = path;
3021
3022 if (!mpr->MprWNetOpenEnum || !mpr->MprWNetEnumResource || !mpr->MprWNetCloseEnum)
3023 {
3024 ret = GATE_RESULT_NOTSUPPORTED;
3025 break;
3026 }
3027
3028 result = mpr->MprWNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, RESOURCEUSAGE_ALL, &netres, &handle);
3029 if (NO_ERROR != result)
3030 {
3031 gate_win32_setlasterror(result);
3032 ret = GATE_RESULT_FAILED;
3033 break;
3034 }
3035 count = 1;
3036 size = sizeof(netres);
3037 result = mpr->MprWNetEnumResource(handle, &count, &netbuffer, &size);
3038 while ((ERROR_MORE_DATA == result) || (NO_ERROR == result))
3039 {
3040 gate_mem_clear(&direntry, sizeof(direntry));
3041
3042 filenamelen = gate_win32_winstr_2_utf8(netbuffer.net.lpRemoteName, gate_win32_winstr_length(netbuffer.net.lpRemoteName),
3043 direntry.name, sizeof(direntry.name));
3044 filepathlen = gate_win32_winstr_2_utf8(path, gate_win32_winstr_length(path),
3045 direntry.path, sizeof(direntry.path));
3046 direntry.props.size = 0;
3047 direntry.props.attribs = GATE_FILEENTRY_ATTRIB_DIRECTORY;
3048 direntry.props.time_created = 0;
3049 direntry.props.time_modified = 0;
3050 direntry.props.time_accessed = 0;
3051
3052 if (callback != NULL)
3053 {
3054 if (false == callback(&direntry, userparam))
3055 {
3056 /* cancelled by user */
3057 break;
3058 }
3059 }
3060
3061 size = sizeof(netres);
3062 result = mpr->MprWNetEnumResource(handle, &count, &netbuffer, &size);
3063 }
3064 mpr->MprWNetCloseEnum(handle);
3065 } while (0);
3066
3067 return ret;
3068 }
3069 #endif /* defined(GATE_FILES_MPR_SUPPORTED) */
3070
3071
3072 gate_result_t gate_file_list(gate_string_t const* dirpath, gate_file_list_callback_t callback, void* userparam)
3073 {
3074 gate_result_t ret;
3075 TCHAR path[GATE_MAX_FILEPATH_LENGTH + 5];
3076 gate_size_t pathlen = gate_win32_string_2_winstr(dirpath, path, sizeof(path) / sizeof(path[0]));
3077 //char filename[GATE_MAX_FILENAME_LENGTH];
3078 gate_size_t filenamelen;
3079 char filepath[GATE_MAX_FILEPATH_LENGTH];
3080 gate_size_t filepathlen;
3081 gate_size_t filepathlen2;
3082 HANDLE hsearch = (HANDLE)NULL;
3083 WIN32_FIND_DATA filedata;
3084 gate_file_entry_t direntry;
3085
3086 do
3087 {
3088 if (pathlen == 0)
3089 {
3090 ret = GATE_RESULT_INVALIDARG;
3091 break;
3092 }
3093
3094 #if defined(GATE_FILES_MPR_SUPPORTED)
3095 if (!gate_file_is_server_share_path(path, false))
3096 {
3097 if (gate_file_is_server_path(path, true))
3098 {
3099 ret = gate_file_list_server_shares(path, callback, userparam);
3100 break;
3101 }
3102 }
3103 #endif /* defined(GATE_FILES_MPR_SUPPORTED) */
3104
3105 /* file search required '*.*' token at the end of the directory path */
3106 if (gate_win32_winstr_ends_with(path, pathlen, GATE_WIN32_WINSTR("\\"), 1))
3107 {
3108 gate_win32_winstr_print_text(&path[pathlen], sizeof(path) / sizeof(path[0]) - pathlen, GATE_WIN32_WINSTR("*.*"), 3);
3109 pathlen += 3;
3110
3111 }
3112 else if (!gate_win32_winstr_ends_with(path, pathlen, GATE_WIN32_WINSTR("\\*.*"), 4))
3113 {
3114 gate_win32_winstr_print_text(&path[pathlen], sizeof(path) / sizeof(path[0]) - pathlen, GATE_WIN32_WINSTR("\\*.*"), 4);
3115 pathlen += 4;
3116 }
3117
3118 filepathlen = gate_win32_winstr_2_utf8(path, pathlen - 3, filepath, sizeof(filepath));
3119
3120 hsearch = gate_win32_findfirstfile(path, &filedata);
3121 if ((HANDLE)INVALID_HANDLE_VALUE == hsearch)
3122 {
3123 #if defined(GATE_SYS_WINCE)
3124 /* empty directories return *.*-error in wince */
3125 path[pathlen - 3] = '\0';
3126 pathlen -= 3;
3127 hsearch = gate_win32_findfirstfile(path, &filedata);
3128 if (INVALID_HANDLE_VALUE != hsearch)
3129 {
3130 /* directory exists -> so it's empty */
3131 ret = GATE_RESULT_OK;
3132 break;
3133 }
3134 #endif
3135 gate_win32_print_lasterror(&ret, NULL, 0);
3136 break;
3137 }
3138 do
3139 {
3140 gate_mem_clear(&direntry, sizeof(direntry));
3141 filenamelen = gate_win32_winstr_2_utf8(filedata.cFileName, gate_win32_winstr_length(filedata.cFileName),
3142 direntry.name, sizeof(direntry.name));
3143 if (filenamelen == 0)
3144 {
3145 /* failed to convert filename -> skip */
3146 continue;
3147 }
3148 if (0 == gate_str_compare(direntry.name, filenamelen, "..", 2))
3149 {
3150 /* skip parent-reference */
3151 continue;
3152 }
3153 if (0 == gate_str_compare(direntry.name, filenamelen, ".", 1))
3154 {
3155 /* skip self-reference */
3156 continue;
3157 }
3158
3159 filepathlen2 = gate_str_print_text(&filepath[filepathlen], sizeof(filepath) - filepathlen, direntry.name, filenamelen);
3160
3161 GATE_DEBUG_ASSERT(filenamelen == filepathlen2);
3162
3163 gate_str_print_text(direntry.path, sizeof(direntry.path), filepath, filepathlen + filepathlen2);
3164
3165 gate_win32_load_direntry(&filedata, &direntry, filepath, filepathlen + filepathlen2);
3166
3167 if (callback != NULL)
3168 {
3169 if (false == callback(&direntry, userparam))
3170 {
3171 /* canceled by user */
3172 break;
3173 }
3174 }
3175
3176 } while (gate_win32_findnext(hsearch, &filedata));
3177 ret = GATE_RESULT_OK;
3178 } while (0);
3179 gate_win32_findclose(hsearch);
3180 return ret;
3181 }
3182
3183 #if defined(GATE_SYS_WIN16)
3184 static BOOL CreateDirectory(LPCSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
3185 {
3186 GATE_UNUSED_ARG(lpSecurityAttributes);
3187 if (0 == _mkdir(lpPathName))
3188 {
3189 return TRUE;
3190 }
3191 else
3192 {
3193 return FALSE;
3194 }
3195 }
3196 #endif
3197
3198 gate_result_t gate_file_dir_create(gate_string_t const* dirpath, gate_enumint_t flags)
3199 {
3200 gate_result_t ret;
3201 TCHAR path[GATE_MAX_FILEPATH_LENGTH];
3202 gate_size_t pathlen = gate_win32_string_2_winstr(dirpath, path, sizeof(path) / sizeof(path[0]));
3203 GATE_UNUSED_ARG(flags);
3204 if (pathlen == 0)
3205 {
3206 ret = GATE_RESULT_INVALIDARG;
3207 }
3208 else
3209 {
3210 if (path[pathlen - 1] == _T('\\'))
3211 {
3212 path[--pathlen] = 0;
3213 }
3214 if (CreateDirectory(path, NULL))
3215 {
3216 ret = GATE_RESULT_OK;
3217 }
3218 else
3219 {
3220 gate_win32_print_lasterror(&ret, NULL, 0);
3221 }
3222 }
3223 return ret;
3224 }
3225
3226 #if defined(GATE_SYS_WIN16)
3227 static BOOL RemoveDirectory(LPCSTR lpPathName)
3228 {
3229 if (0 == _rmdir(lpPathName))
3230 {
3231 return TRUE;
3232 }
3233 return FALSE;
3234 }
3235 #endif
3236
3237 gate_result_t gate_file_dir_delete(gate_string_t const* dirpath)
3238 {
3239 gate_result_t ret;
3240 DWORD dw_error;
3241 TCHAR path[GATE_MAX_FILEPATH_LENGTH];
3242 gate_size_t pathlen = gate_win32_string_2_winstr(dirpath, path, sizeof(path) / sizeof(path[0]) - 1);
3243 if (pathlen == 0)
3244 {
3245 ret = GATE_RESULT_INVALIDARG;
3246 }
3247 else
3248 {
3249 path[pathlen + 1] = 0; /* ensure double zero for shell-file-ops */
3250 if (RemoveDirectory(path))
3251 {
3252 ret = GATE_RESULT_OK;
3253 }
3254 else
3255 {
3256 dw_error = gate_win32_getlasterror();
3257 gate_win32_print_lasterror_code(dw_error, &ret, NULL, 0);
3258 /* try fallback */
3259 if (gate_win32_shfileop(GATE_WIN32_SHFILEOP_DELETE, path, NULL))
3260 {
3261 ret = GATE_RESULT_OK;
3262 }
3263 else
3264 {
3265 gate_win32_setlasterror(dw_error);
3266 }
3267 }
3268 }
3269 return ret;
3270 }
3271
3272 gate_result_t gate_file_dir_exists(gate_string_t const* dirpath)
3273 {
3274 WIN32_FIND_DATA data;
3275 DWORD attribs;
3276 HANDLE hfind;
3277 TCHAR path[GATE_MAX_FILEPATH_LENGTH];
3278 gate_size_t pathlen = gate_win32_utf8_2_winstr(dirpath->str, dirpath->length, path, sizeof(path) / sizeof(path[0]));
3279 if (path[pathlen - 1] == '\\')
3280 {
3281 --pathlen;
3282 path[pathlen] = 0;
3283 }
3284
3285 #if !defined(GATE_SYS_WIN16)
3286 if (gate_file_is_server_path(path, false))
3287 {
3288 return GATE_RESULT_OK;
3289 }
3290 if (gate_file_is_server_share_path(path, false))
3291 {
3292 return GATE_RESULT_OK;
3293 }
3294 #endif
3295
3296 attribs = GetFileAttributes(path);
3297 if (attribs != INVALID_FILE_ATTRIBUTES)
3298 {
3299 if (GATE_FLAG_ENABLED(attribs, FILE_ATTRIBUTE_DIRECTORY))
3300 {
3301 return GATE_RESULT_OK;
3302 }
3303 else
3304 {
3305 return GATE_RESULT_NOMATCH;
3306 }
3307 }
3308
3309 hfind = gate_win32_findfirstfile(path, &data);
3310 if (hfind != (HANDLE)INVALID_HANDLE_VALUE)
3311 {
3312 gate_win32_findclose(hfind);
3313 if (GATE_FLAG_ENABLED(data.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY))
3314 {
3315 return GATE_RESULT_OK;
3316 }
3317 else
3318 {
3319 return GATE_RESULT_NOMATCH;
3320 }
3321 }
3322 else
3323 {
3324 return GATE_RESULT_NOTAVAILABLE;
3325 }
3326 }
3327
3328
3329 #endif /* GATE_CORE_FILES_WINAPI_IMPL */
3330
3331
3332 #if defined(GATE_CORE_FILES_POSIX_IMPL)
3333
3334 #include "gate/platforms.h"
3335 #include <sys/stat.h>
3336 #include <sys/types.h>
3337 #include <stdio.h>
3338 #include <errno.h>
3339 #include <fcntl.h>
3340 #include <dirent.h>
3341 #include <utime.h>
3342 #include <stdlib.h>
3343
3344 char const gate_file_path_separator_char = '/';
3345 char const* const gate_file_path_separator = "/";
3346
3347
3348 317 gate_result_t gate_file_exists(gate_string_t const* filepath)
3349 {
3350 gate_result_t ret;
3351 char pathbuffer[GATE_MAX_FILEPATH_LENGTH];
3352 struct stat filestat;
3353 317 gate_string_to_buffer(filepath, pathbuffer, sizeof(pathbuffer));
3354
2/2
✓ Branch 1 taken 132 times.
✓ Branch 2 taken 185 times.
317 if (0 == stat(pathbuffer, &filestat))
3355 {
3356 132 ret = GATE_RESULT_OK;
3357 }
3358 else
3359 {
3360 185 gate_posix_errno(&ret);
3361 }
3362 317 return ret;
3363 }
3364 76 gate_result_t gate_file_dir_exists(gate_string_t const* dirpath)
3365 {
3366 gate_result_t ret;
3367 char pathbuffer[GATE_MAX_FILEPATH_LENGTH];
3368 struct stat filestat;
3369 76 gate_size_t len = gate_string_to_buffer(dirpath, pathbuffer, sizeof(pathbuffer));
3370
3/4
✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 61 times.
76 if ((len > 1) && (pathbuffer[len - 1] == '/'))
3371 {
3372 15 --len;
3373 15 pathbuffer[len] = 0;
3374 }
3375
3376
2/2
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 37 times.
76 if (0 == stat(pathbuffer, &filestat))
3377 {
3378
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 6 times.
39 if (S_ISDIR(filestat.st_mode))
3379 {
3380 33 ret = GATE_RESULT_OK;
3381 }
3382 else
3383 {
3384 6 ret = GATE_RESULT_INVALIDSTATE;
3385 }
3386 }
3387 else
3388 {
3389 37 gate_posix_errno(&ret);
3390 }
3391 76 return ret;
3392 }
3393
3394 3 gate_result_t gate_file_copy(gate_string_t const* srcfilepath, gate_string_t const* dstfilepath, gate_enumint_t flags)
3395 {
3396 gate_size_t ret;
3397
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (GATE_FLAG_ENABLED(flags, GATE_FILE_COPY_SIMPLE))
3398 {
3399 1 ret = gate_file_copy_internal(srcfilepath, dstfilepath, flags);
3400 }
3401 else
3402 {
3403 2 gate_file_t srcfile = GATE_FILE_INVALID;
3404 2 gate_file_t dstfile = GATE_FILE_INVALID;
3405 gate_size_t bufferused;
3406 gate_size_t pos;
3407 gate_size_t written;
3408 char buffer[GATE_MAX_COPYBUFFER_LENGTH];
3409 struct stat srcstat;
3410 struct utimbuf utm;
3411 2 gate_bool_t srcstatreceived = false;
3412
3413 do
3414 {
3415
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!GATE_FLAG_ENABLED(flags, GATE_FILE_COPY_OVERWRITE))
3416 {
3417
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (GATE_SUCCEEDED(gate_file_exists(dstfilepath)))
3418 {
3419 ret = GATE_RESULT_ALREADYEXISTS;
3420 break;
3421 }
3422 }
3423
3424 2 ret = gate_file_open(srcfilepath, GATE_STREAM_OPEN_READ, &srcfile);
3425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (GATE_FAILED(ret))
3426 {
3427 break;
3428 }
3429
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (0 == fstat((int)(gate_intptr_t)srcfile, &srcstat))
3430 {
3431 2 utm.actime = srcstat.st_atime;
3432 2 utm.modtime = srcstat.st_mtime;
3433 2 srcstatreceived = true;
3434 }
3435 2 ret = gate_file_open(dstfilepath, GATE_STREAM_OPEN_WRITE, &dstfile);
3436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (GATE_FAILED(ret))
3437 {
3438 break;
3439 }
3440 2 ret = gate_file_read(srcfile, buffer, sizeof(buffer), &bufferused);
3441
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 while (GATE_SUCCEEDED(ret))
3442 {
3443
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (bufferused == 0)
3444 {
3445 /* end of file */
3446 2 break;
3447 }
3448 2 pos = 0;
3449
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 while (pos < bufferused)
3450 {
3451 2 ret = gate_file_write(dstfile, &buffer[pos], bufferused - pos, &written);
3452
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (GATE_FAILED(ret))
3453 {
3454 break;
3455 }
3456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (written == 0)
3457 {
3458 ret = GATE_RESULT_INCORRECTSIZE;
3459 break;
3460 }
3461 2 pos += written;
3462 }
3463
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (GATE_SUCCEEDED(ret))
3464 {
3465 2 ret = gate_file_read(srcfile, buffer, sizeof(buffer), &bufferused);
3466 }
3467 }
3468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (GATE_FAILED(ret))
3469 {
3470 break;
3471 }
3472 } while (0);
3473
3474
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (srcfile != GATE_FILE_INVALID)
3475 {
3476 2 gate_file_close(srcfile);
3477 }
3478
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (dstfile != GATE_FILE_INVALID)
3479 {
3480 2 gate_file_close(dstfile);
3481 }
3482
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (GATE_SUCCEEDED(ret))
3483 {
3484
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (srcstatreceived)
3485 {
3486 2 gate_string_to_buffer(dstfilepath, buffer, sizeof(buffer));
3487 2 utime(buffer, &utm);
3488 }
3489 }
3490 }
3491 3 return ret;
3492 }
3493 1 gate_result_t gate_file_move(gate_string_t const* srcfilepath, gate_string_t const* dstfilepath)
3494 {
3495 gate_result_t ret;
3496 char srcpath[GATE_MAX_FILEPATH_LENGTH];
3497 char dstpath[GATE_MAX_FILEPATH_LENGTH];
3498 1 gate_string_to_buffer(srcfilepath, srcpath, sizeof(srcpath));
3499 1 gate_string_to_buffer(dstfilepath, dstpath, sizeof(dstpath));
3500
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (rename(srcpath, dstpath) == 0)
3501 {
3502 1 ret = GATE_RESULT_OK;
3503 }
3504 else
3505 {
3506 gate_posix_errno(&ret);
3507 }
3508 1 return ret;
3509 }
3510 14 gate_result_t gate_file_delete(gate_string_t const* filepath)
3511 {
3512 gate_result_t ret;
3513 char pathbuffer[GATE_MAX_FILEPATH_LENGTH];
3514 14 gate_string_to_buffer(filepath, pathbuffer, sizeof(pathbuffer));
3515
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 if (0 == unlink(pathbuffer))
3516 {
3517 14 ret = GATE_RESULT_OK;
3518 }
3519 else
3520 {
3521 gate_posix_errno(&ret);
3522 }
3523 14 return ret;
3524 }
3525 1 gate_result_t gate_file_real_path(gate_string_t const* relativepath, gate_string_t* absolutepath)
3526 {
3527 gate_result_t ret;
3528 char relpath[GATE_MAX_FILEPATH_LENGTH];
3529 char abspath[PATH_MAX + 1];
3530 1 gate_string_to_buffer(relativepath, relpath, sizeof(relpath));
3531
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (realpath(relpath, abspath) != NULL)
3532 {
3533
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (NULL == gate_string_create(absolutepath, abspath, gate_str_length(abspath)))
3534 {
3535 ret = GATE_RESULT_OUTOFMEMORY;
3536 }
3537 else
3538 {
3539 1 ret = GATE_RESULT_OK;
3540 }
3541 }
3542 else
3543 {
3544 gate_posix_errno(&ret);
3545 }
3546 1 return ret;
3547 }
3548 1 gate_result_t gate_file_create_link(gate_string_t const* targetpath, gate_string_t const* linkfile)
3549 {
3550 gate_result_t ret;
3551 char target[PATH_MAX];
3552 char link[GATE_MAX_FILEPATH_LENGTH];
3553 1 gate_string_to_buffer(targetpath, link, sizeof(link));
3554
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (NULL == realpath(link, target))
3555 {
3556 gate_posix_errno(&ret);
3557 }
3558 else
3559 {
3560 1 gate_string_to_buffer(linkfile, link, sizeof(link));
3561
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (symlink(target, link) == 0)
3562 {
3563 1 ret = GATE_RESULT_OK;
3564 }
3565 else
3566 {
3567 gate_posix_errno(&ret);
3568 }
3569 }
3570 1 return ret;
3571 }
3572 1 gate_result_t gate_file_read_link(gate_string_t const* filepath, gate_string_t* realpath)
3573 {
3574 gate_result_t ret;
3575 char linkpath[GATE_MAX_FILEPATH_LENGTH];
3576
3577 1 gate_string_to_buffer(filepath, linkpath, sizeof(linkpath));
3578 for (;;)
3579 1 {
3580 char destpath[GATE_MAX_FILEPATH_LENGTH];
3581 2 ssize_t rlresult = readlink(linkpath, destpath, sizeof(destpath) / sizeof(destpath[0]) - 1);
3582
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (rlresult <= 0)
3583 {
3584 1 int err = gate_posix_errno(&ret);
3585
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (err == EINVAL)
3586 {
3587 /* real path found (not another link), return it */
3588
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (NULL == gate_string_create(realpath, destpath, gate_str_length(destpath)))
3589 {
3590 ret = GATE_RESULT_OUTOFMEMORY;
3591 }
3592 else
3593 {
3594 1 ret = GATE_RESULT_OK;
3595 }
3596 }
3597 else
3598 {
3599 /* all other cases are real errors during resolution */
3600 }
3601 1 break;
3602 }
3603 else
3604 {
3605 /* a destination path could be resolved.
3606 make it a new source to check
3607 */
3608 1 destpath[rlresult] = 0;
3609 1 gate_str_print_text(linkpath, sizeof(linkpath), destpath, gate_str_length(destpath));
3610 }
3611 }
3612 1 return ret;
3613 }
3614 1 gate_result_t gate_file_create_hardlink(gate_string_t const* targetfile, gate_string_t const* linkfile)
3615 {
3616 gate_result_t ret;
3617 char target[GATE_MAX_FILEPATH_LENGTH];
3618 char linkpath[GATE_MAX_FILEPATH_LENGTH];
3619 1 gate_string_to_buffer(targetfile, target, sizeof(target));
3620 1 gate_string_to_buffer(linkfile, linkpath, sizeof(linkpath));
3621
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (link(target, linkpath) == 0)
3622 {
3623 1 ret = GATE_RESULT_OK;
3624 }
3625 else
3626 {
3627 gate_posix_errno(&ret);
3628 }
3629 1 return ret;
3630 }
3631
3632 65 static gate_bool_t gate_file_parent_stat(gate_string_t const* filepath, mode_t* ptrmode, uid_t* ptruid, gid_t* ptrgid)
3633 {
3634 65 gate_size_t pos = gate_str_char_pos_last(filepath->str, filepath->length, gate_file_path_separator_char);
3635
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 24 times.
65 if (pos != GATE_STR_NPOS)
3636 {
3637 char parent[GATE_MAX_FILEPATH_LENGTH];
3638 struct stat dirstat;
3639 41 gate_str_print_text(parent, sizeof(parent), filepath->str, pos);
3640
2/2
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 3 times.
41 if (0 == lstat(parent, &dirstat))
3641 {
3642 38 mode_t mode = dirstat.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
3643
1/2
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
38 if (ptrmode != NULL) *ptrmode = mode;
3644
1/2
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
38 if (ptruid != NULL) *ptruid = dirstat.st_uid;
3645
1/2
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
38 if (ptrgid != NULL) *ptrgid = dirstat.st_gid;
3646 38 return true;
3647 }
3648 }
3649 27 return false;
3650 }
3651
3652 226 gate_result_t gate_file_open(gate_string_t const* filepath, gate_enumint_t flags, gate_file_t* filehandle)
3653 {
3654 gate_result_t ret;
3655
3656 do
3657 {
3658 char path[GATE_MAX_FILEPATH_LENGTH];
3659 int openflags;
3660 int fd;
3661 mode_t mode;
3662 226 uid_t open_as_uid = getuid();
3663 226 uid_t open_as_gid = getgid();
3664
3665
2/4
✓ Branch 1 taken 226 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 226 times.
226 if (gate_string_is_empty(filepath) || (filehandle == NULL))
3666 {
3667 ret = GATE_RESULT_INVALIDARG;
3668 48 break;
3669 }
3670 226 gate_string_to_buffer(filepath, path, sizeof(path));
3671
3672
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 226 times.
226 if (GATE_FLAG_ENABLED(flags, GATE_STREAM_OPEN_APPENDREADWRITE)) { openflags = (O_CREAT | O_RDWR | O_APPEND); }
3673
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 209 times.
226 else if (GATE_FLAG_ENABLED(flags, GATE_STREAM_OPEN_APPENDWRITE)) { openflags = (O_CREAT | O_WRONLY | O_APPEND); }
3674
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 201 times.
209 else if (GATE_FLAG_ENABLED(flags, GATE_STREAM_OPEN_READWRITE)) { openflags = (O_CREAT | O_RDWR); }
3675
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 167 times.
201 else if (GATE_FLAG_ENABLED(flags, GATE_STREAM_OPEN_WRITE)) { openflags = (O_CREAT | O_WRONLY | O_TRUNC); }
3676
1/2
✓ Branch 0 taken 167 times.
✗ Branch 1 not taken.
167 else if (GATE_FLAG_ENABLED(flags, GATE_STREAM_OPEN_READ)) { openflags = (O_RDONLY); }
3677 else
3678 {
3679 ret = GATE_RESULT_INVALIDARG;
3680 break;
3681 }
3682
3683 #ifdef O_CLOEXEC
3684 226 openflags |= O_CLOEXEC;
3685 #endif
3686
2/2
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 167 times.
226 if (GATE_FLAG_ENABLED(openflags, O_CREAT))
3687 {
3688 /* if a new file is created we have a chance to influence its permissions
3689 */
3690
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (GATE_FLAG_ENABLED(flags, GATE_FILE_OPEN_CREATEOWNERRESTRICTED))
3691 {
3692 /* only the owner has read/write access */
3693 mode = S_IRUSR | S_IWUSR;
3694 if (GATE_FLAG_ENABLED(flags, GATE_FILE_OPEN_CREATEEXECUTABLE))
3695 {
3696 mode |= S_IXUSR;
3697 }
3698 }
3699
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 else if (GATE_FLAG_ENABLED(flags, GATE_FILE_OPEN_CREATEGROUPRESTRICTED))
3700 {
3701 /* owner and owner's primary group have read/write access */
3702 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
3703 if (GATE_FLAG_ENABLED(flags, GATE_FILE_OPEN_CREATEEXECUTABLE))
3704 {
3705 mode |= S_IXUSR | S_IXGRP;
3706 }
3707 }
3708
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 else if (GATE_FLAG_ENABLED(flags, GATE_FILE_OPEN_CREATEUNRESTRICTED))
3709 {
3710 /* everyone has read/write access */
3711 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
3712 if (GATE_FLAG_ENABLED(flags, GATE_FILE_OPEN_CREATEEXECUTABLE))
3713 {
3714 mode |= S_IXUSR | S_IXGRP;
3715 }
3716 }
3717 else
3718 {
3719 /* in case of no specification, we try to apply
3720 the windows convention, where permissions are
3721 inherited from the parent directory
3722 */
3723 59 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
3724
2/2
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 24 times.
59 if (gate_file_parent_stat(filepath, &mode, &open_as_uid, &open_as_gid))
3725 {
3726
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 if (open_as_uid == 0)
3727 {
3728 35 open_as_uid = getuid();
3729 }
3730
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 if (open_as_gid == 0)
3731 {
3732 35 open_as_gid = getgid();
3733 }
3734 /* remove directory-X-bits */
3735 35 mode &= ~(mode_t)(S_IXUSR | S_IXGRP | S_IXOTH);
3736 }
3737
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 58 times.
59 if (GATE_FLAG_ENABLED(flags, GATE_FILE_OPEN_CREATEEXECUTABLE))
3738 {
3739
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_FLAG_ENABLED(mode, S_IRUSR)) mode |= S_IXUSR;
3740
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_FLAG_ENABLED(mode, S_IRGRP)) mode |= S_IXGRP;
3741
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_FLAG_ENABLED(mode, S_IROTH)) mode |= S_IXOTH;
3742 }
3743 }
3744
3745 /* try to open exclusive and fail, if file existed */
3746 59 fd = open(path, openflags | O_EXCL, mode);
3747
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 23 times.
59 if (fd != -1)
3748 {
3749 int result;
3750 /* open() succeeded */
3751 36 *filehandle = (gate_file_t)(intptr_t)fd;
3752
3753 /* We cannot trust the given mode,
3754 due to umask and multithreading issues,
3755 so let's try to patch permissions.
3756 If it fails, we just go on as this step is optional
3757 */
3758 36 result = fchmod(fd, mode);
3759
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if(result != 0)
3760 {
3761 GATE_DEBUG_TRACE("fchmod() failed");
3762 }
3763
3764 /* In case of permission inheritance, we
3765 also need to change owner and group.
3766 Concept: If we are allowed to create a new file in the directory,
3767 then the directory's owner or group will allow the current process
3768 user to access its contents and we can safely change the ownership
3769 of our new created file.
3770 If this fails, we continue as this step is optional
3771 */
3772 36 result = fchown(fd, open_as_uid, open_as_gid);
3773
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if(result != 0)
3774 {
3775 GATE_DEBUG_TRACE("fchown() failed");
3776 }
3777
3778 36 ret = GATE_RESULT_OK;
3779 36 break;
3780 }
3781 /* in case of an error, the file may exist,
3782 so continue with the default opening-procedure
3783 */
3784 }
3785
3786 190 mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
3787 190 fd = open(path, openflags, mode);
3788
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 178 times.
190 if (fd == -1)
3789 {
3790 /* open() failed */
3791 12 gate_posix_errno(&ret);
3792 12 break;
3793 }
3794
3795 178 *filehandle = (gate_file_t)(intptr_t)fd;
3796 178 ret = GATE_RESULT_OK;
3797 } while (0);
3798
3799 226 return ret;
3800 }
3801 45595 gate_result_t gate_file_read(gate_file_t filehandle, char* buffer, gate_size_t bufferlength, gate_size_t* bufferused)
3802 {
3803 gate_result_t ret;
3804 45595 int fd = (int)(gate_intptr_t)filehandle;
3805 45595 ssize_t returned = read(fd, buffer, bufferlength);
3806
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 45595 times.
45595 if (returned < 0)
3807 {
3808 gate_posix_errno(&ret);
3809 }
3810 else
3811 {
3812
1/2
✓ Branch 0 taken 45595 times.
✗ Branch 1 not taken.
45595 if (bufferused != NULL)
3813 {
3814 45595 *bufferused = (gate_size_t)returned;
3815 }
3816 45595 ret = GATE_RESULT_OK;
3817 }
3818 45595 return ret;
3819 }
3820 6532 gate_result_t gate_file_write(gate_file_t filehandle, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
3821 {
3822 gate_result_t ret;
3823 6532 int fd = (int)(gate_intptr_t)filehandle;
3824 6532 ssize_t processed = write(fd, buffer, bufferlength);
3825
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6532 times.
6532 if (processed < 0)
3826 {
3827 gate_posix_errno(&ret);
3828 }
3829 else
3830 {
3831
1/2
✓ Branch 0 taken 6532 times.
✗ Branch 1 not taken.
6532 if (written != NULL)
3832 {
3833 6532 *written = (gate_size_t)processed;
3834 }
3835 6532 ret = GATE_RESULT_OK;
3836 }
3837 6532 return ret;
3838
3839 }
3840 14 gate_result_t gate_file_flush(gate_file_t filehandle)
3841 {
3842 gate_result_t ret;
3843 14 int fd = (int)(gate_intptr_t)filehandle;
3844
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 if (fsync(fd) == -1)
3845 {
3846 gate_posix_errno(&ret);
3847 }
3848 else
3849 {
3850 14 ret = GATE_RESULT_OK;
3851 }
3852 14 return ret;
3853 }
3854 216 gate_result_t gate_file_close(gate_file_t filehandle)
3855 {
3856 gate_result_t ret;
3857 216 int fd = (int)(gate_intptr_t)filehandle;
3858
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 214 times.
216 if (-1 == close(fd))
3859 {
3860 2 gate_posix_errno(&ret);
3861 }
3862 else
3863 {
3864 214 ret = GATE_RESULT_OK;
3865 }
3866 216 return ret;
3867 }
3868 24 gate_result_t gate_file_seek(gate_file_t filehandle, gate_int64_t position, gate_enumint_t origin, gate_int64_t* newposition)
3869 {
3870 gate_result_t ret;
3871 do
3872 {
3873 24 int fd = (int)(gate_intptr_t)filehandle;
3874 off_t offset;
3875 int whence;
3876
3877
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 14 times.
24 if (origin == GATE_FILE_SEEK_ORIGIN_BEGIN) { whence = SEEK_SET; }
3878
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 13 times.
14 else if (origin == GATE_FILE_SEEK_ORIGIN_CURPOS) { whence = SEEK_CUR; }
3879
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
13 else if (origin == GATE_FILE_SEEK_ORIGIN_END) { whence = SEEK_END; }
3880 else
3881 {
3882 ret = GATE_RESULT_INVALIDARG;
3883 break;
3884 }
3885 24 offset = lseek(fd, (off_t)position, whence);
3886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (offset == (off_t)-1)
3887 {
3888 gate_posix_errno(&ret);
3889 break;
3890 }
3891
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 14 times.
24 if (newposition != NULL)
3892 {
3893 10 *newposition = (gate_int64_t)offset;
3894 }
3895 24 ret = GATE_RESULT_OK;
3896 } while (0);
3897
3898 24 return ret;
3899 }
3900 2 gate_result_t gate_file_pos(gate_file_t filehandle, gate_int64_t* position)
3901 {
3902 gate_result_t ret;
3903 2 int fd = (int)(gate_intptr_t)filehandle;
3904 2 off_t offset = lseek(fd, 0, SEEK_CUR);
3905
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (offset == (off_t)-1)
3906 {
3907 gate_posix_errno(&ret);
3908 }
3909 else
3910 {
3911
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (position != NULL)
3912 {
3913 2 *position = (gate_int64_t)offset;
3914 }
3915 2 ret = GATE_RESULT_OK;
3916 }
3917 2 return ret;
3918 }
3919 4 gate_result_t gate_file_size(gate_file_t filehandle, gate_int64_t* size)
3920 {
3921 gate_result_t ret;
3922 4 int fd = (int)(gate_intptr_t)filehandle;
3923 struct stat filestat;
3924
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (fstat(fd, &filestat) == -1)
3925 {
3926 gate_posix_errno(&ret);
3927 }
3928 else
3929 {
3930
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (size != NULL)
3931 {
3932 4 *size = (gate_int64_t)filestat.st_size;
3933 }
3934 4 ret = GATE_RESULT_OK;
3935 }
3936 4 return ret;
3937 }
3938
3939 8 gate_result_t gate_file_truncate(gate_file_t filehandle)
3940 {
3941 gate_result_t ret;
3942 8 int fd = (int)(gate_intptr_t)filehandle;
3943 8 off_t offset = lseek(fd, 0, SEEK_CUR);
3944
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (offset == (off_t)-1)
3945 {
3946 gate_posix_errno(&ret);
3947 }
3948 else
3949 {
3950
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (0 != ftruncate(fd, offset))
3951 {
3952 gate_posix_errno(&ret);
3953 }
3954 else
3955 {
3956 8 ret = GATE_RESULT_OK;
3957 }
3958 }
3959 8 return ret;
3960 }
3961
3962
3963 16 gate_result_t gate_file_lock(gate_file_t filehandle, gate_bool_t wait)
3964 {
3965 16 gate_result_t ret = GATE_RESULT_FAILED;
3966 16 int fd = (int)(gate_intptr_t)filehandle;
3967
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 gate_posix_flock_operation op = wait ? gate_posix_flock_exclusive : gate_posix_flock_exclusive_test;
3968 16 int result = gate_posix_flock(fd, op);
3969
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 1 times.
16 if (result == 0)
3970 {
3971 15 ret = GATE_RESULT_OK;
3972 }
3973 16 return ret;
3974 }
3975 15 gate_result_t gate_file_unlock(gate_file_t filehandle)
3976 {
3977 15 gate_result_t ret = GATE_RESULT_FAILED;
3978 15 int fd = (int)(gate_intptr_t)filehandle;
3979 15 int result = gate_posix_flock(fd, gate_posix_flock_unlock);
3980
1/2
✓ Branch 0 taken 15 times.
✗ Branch 1 not taken.
15 if (result == 0)
3981 {
3982 15 ret = GATE_RESULT_OK;
3983 }
3984 15 return ret;
3985 }
3986
3987
3988
3989 168 static void gate_unix_mode_to_attributes(mode_t mode, gate_enumint_t* ptr_attribs, gate_enumint_t* ptr_accessbits)
3990 {
3991
1/2
✓ Branch 0 taken 168 times.
✗ Branch 1 not taken.
168 if (ptr_accessbits)
3992 {
3993 168 *ptr_accessbits = 0;
3994
1/2
✓ Branch 0 taken 168 times.
✗ Branch 1 not taken.
168 if (GATE_FLAG_ENABLED(mode, S_IRUSR)) *ptr_accessbits |= GATE_FILEENTRY_ACCESS_OWNERREAD;
3995
1/2
✓ Branch 0 taken 168 times.
✗ Branch 1 not taken.
168 if (GATE_FLAG_ENABLED(mode, S_IWUSR)) *ptr_accessbits |= GATE_FILEENTRY_ACCESS_OWNERWRITE;
3996
2/2
✓ Branch 0 taken 159 times.
✓ Branch 1 taken 9 times.
168 if (GATE_FLAG_ENABLED(mode, S_IXUSR)) *ptr_accessbits |= GATE_FILEENTRY_ACCESS_OWNEREXECUTE;
3997
2/2
✓ Branch 0 taken 161 times.
✓ Branch 1 taken 7 times.
168 if (GATE_FLAG_ENABLED(mode, S_IRGRP)) *ptr_accessbits |= GATE_FILEENTRY_ACCESS_GROUPREAD;
3998
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 48 times.
168 if (GATE_FLAG_ENABLED(mode, S_IWGRP)) *ptr_accessbits |= GATE_FILEENTRY_ACCESS_GROUPWRITE;
3999
2/2
✓ Branch 0 taken 158 times.
✓ Branch 1 taken 10 times.
168 if (GATE_FLAG_ENABLED(mode, S_IXGRP)) *ptr_accessbits |= GATE_FILEENTRY_ACCESS_GROUPEXECUTE;
4000
2/2
✓ Branch 0 taken 161 times.
✓ Branch 1 taken 7 times.
168 if (GATE_FLAG_ENABLED(mode, S_IROTH)) *ptr_accessbits |= GATE_FILEENTRY_ACCESS_ALLREAD;
4001
2/2
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 51 times.
168 if (GATE_FLAG_ENABLED(mode, S_IWOTH)) *ptr_accessbits |= GATE_FILEENTRY_ACCESS_ALLWRITE;
4002
2/2
✓ Branch 0 taken 158 times.
✓ Branch 1 taken 10 times.
168 if (GATE_FLAG_ENABLED(mode, S_IXOTH)) *ptr_accessbits |= GATE_FILEENTRY_ACCESS_ALLEXECUTE;
4003 }
4004
4005
2/2
✓ Branch 0 taken 154 times.
✓ Branch 1 taken 14 times.
168 if (ptr_attribs)
4006 {
4007 154 *ptr_attribs = 0;
4008 #if defined(S_IFLNK)
4009
2/2
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 37 times.
154 if (GATE_FLAG_ENABLED(mode, S_IFLNK)) *ptr_attribs |= GATE_FILEENTRY_ATTRIB_LINK;
4010 #endif
4011
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 153 times.
154 if (GATE_FLAG_ENABLED(mode, S_IFDIR)) *ptr_attribs |= GATE_FILEENTRY_ATTRIB_DIRECTORY;
4012
2/2
✓ Branch 0 taken 153 times.
✓ Branch 1 taken 1 times.
154 if (GATE_FLAG_ENABLED(mode, S_IFREG)) *ptr_attribs |= GATE_FILEENTRY_ATTRIB_FILE;
4013
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
154 if (GATE_FLAG_ENABLED(mode, S_IFBLK)) *ptr_attribs |= GATE_FILEENTRY_ATTRIB_DEVICE;
4014
2/2
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 37 times.
154 if (GATE_FLAG_ENABLED(mode, S_IFCHR)) *ptr_attribs |= GATE_FILEENTRY_ATTRIB_DEVICE;
4015
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
154 if (GATE_FLAG_ENABLED(mode, S_IFIFO)) *ptr_attribs |= GATE_FILEENTRY_ATTRIB_DEVICE;
4016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 154 times.
154 if (GATE_FLAG_ENABLED(mode, S_IFSOCK)) *ptr_attribs |= GATE_FILEENTRY_ATTRIB_DEVICE;
4017 }
4018 168 }
4019
4020 152 static gate_bool_t gate_fstat_to_direntry(char const* path, gate_file_entry_t* entry)
4021 {
4022 do
4023 {
4024 struct stat filestat;
4025 152 gate_string_t tmp = GATE_STRING_INIT_EMPTY;
4026
4027
1/2
✓ Branch 1 taken 152 times.
✗ Branch 2 not taken.
152 if (0 == lstat(path, &filestat))
4028 {
4029 152 entry->props.size = filestat.st_size;
4030 152 entry->props.time_created = 0;
4031 152 entry->props.time_modified = 0;
4032 152 entry->props.time_accessed = 0;
4033 152 gate_time_from_unix(filestat.st_ctime, &entry->props.time_created); /* this is not the creation time, but may be close to it */
4034 152 gate_time_from_unix(filestat.st_mtime, &entry->props.time_modified);
4035 152 gate_time_from_unix(filestat.st_atime, &entry->props.time_accessed);
4036
4037 152 gate_unix_mode_to_attributes(filestat.st_mode, &entry->props.attribs, &entry->props.access);
4038
2/2
✓ Branch 0 taken 117 times.
✓ Branch 1 taken 35 times.
152 if (GATE_FLAG_ENABLED(entry->props.attribs, GATE_FILEENTRY_ATTRIB_LINK))
4039 {
4040
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 117 times.
117 if (0 != stat(path, &filestat))
4041 {
4042 break;
4043 }
4044 }
4045 152 gate_string_create_static(&tmp, path);
4046
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 152 times.
152 if (gate_file_is_hidden_entry(&tmp))
4047 {
4048 entry->props.attribs |= GATE_FILEENTRY_ATTRIB_HIDDEN;
4049 }
4050
4051
4052 152 return true;
4053 }
4054 } while (0);
4055 return false;
4056 }
4057
4058 #if 0
4059 static gate_bool_t gate_readdir(DIR* dirp, struct dirent* entry)
4060 {
4061 struct dirent* returned_entry = NULL;
4062 int result = readdir_r(dirp, entry, &returned_entry);
4063 if (result == 0)
4064 {
4065 return entry != NULL;
4066 }
4067 return false;
4068 }
4069 #else
4070 231 static gate_bool_t gate_readdir(DIR* dirp, struct dirent* entry)
4071 {
4072 231 struct dirent* ptr_entry = readdir(dirp);
4073
2/2
✓ Branch 0 taken 220 times.
✓ Branch 1 taken 11 times.
231 if (ptr_entry)
4074 {
4075 220 gate_mem_copy(entry, ptr_entry, sizeof(struct dirent));
4076 220 return true;
4077 }
4078 11 return false;
4079 }
4080 #endif
4081
4082 12 gate_result_t gate_file_list(gate_string_t const* dirpath, gate_file_list_callback_t callback, void* userparam)
4083 {
4084 gate_result_t ret;
4085 12 DIR* dir = NULL;
4086
4087 do
4088 {
4089 char path[GATE_MAX_FILEPATH_LENGTH];
4090 char file[GATE_MAX_FILEPATH_LENGTH];
4091 gate_size_t namepos;
4092 12 struct dirent entry = GATE_INIT_EMPTY;
4093
4094
2/4
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
12 if (gate_string_is_empty(dirpath) || callback == NULL)
4095 {
4096 ret = GATE_RESULT_INVALIDARG;
4097 break;
4098 }
4099
4100 12 gate_string_to_buffer(dirpath, path, sizeof(path));
4101 12 namepos = gate_string_to_buffer(dirpath, file, sizeof(file));
4102
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 if (file[namepos - 1] != gate_file_path_separator_char)
4103 {
4104 9 file[namepos] = gate_file_path_separator_char;
4105 9 ++namepos;
4106 }
4107
4108 12 dir = opendir(path);
4109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (NULL == dir)
4110 {
4111 ret = GATE_RESULT_FAILED;
4112 break;
4113 }
4114
4115 12 ret = GATE_RESULT_OK;
4116
2/2
✓ Branch 1 taken 175 times.
✓ Branch 2 taken 6 times.
181 while (gate_readdir(dir, &entry))
4117 {
4118 gate_size_t namelen;
4119 gate_file_entry_t direntry;
4120
4121
4/4
✓ Branch 1 taken 163 times.
✓ Branch 2 taken 12 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 151 times.
175 if ((gate_str_comp(entry.d_name, "..") == 0) || (gate_str_comp(entry.d_name, ".") == 0))
4122 {
4123 24 continue;
4124 }
4125
4126 151 namelen = gate_str_print_text(&file[namepos], sizeof(file) - namepos, entry.d_name, gate_str_length(entry.d_name));
4127 151 gate_str_print_text(direntry.name, sizeof(direntry.name), entry.d_name, gate_str_length(entry.d_name));
4128 151 gate_str_print_text(direntry.path, sizeof(direntry.path), file, namepos + namelen);
4129 151 direntry.props.size = 0;
4130 151 direntry.props.attribs = 0;
4131 151 direntry.props.time_created = 0;
4132 151 direntry.props.time_modified = 0;
4133 151 direntry.props.time_accessed = 0;
4134 151 gate_fstat_to_direntry(direntry.path, &direntry);
4135
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 145 times.
151 if (!callback(&direntry, userparam))
4136 {
4137 6 break;
4138 }
4139 }
4140 } while (0);
4141
4142
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (dir != NULL)
4143 {
4144 12 closedir(dir);
4145 }
4146 12 return ret;
4147 }
4148
4149 12 gate_result_t gate_file_dir_open(gate_string_t const* dirpath, gate_file_dirreader_t* dirhandle)
4150 {
4151 12 gate_result_t ret = GATE_RESULT_FAILED;
4152 do
4153 {
4154 12 gate_mem_clear(dirhandle, sizeof(gate_file_dirreader_t));
4155 12 dirhandle->bufferlen = gate_str_print_text(dirhandle->buffer, sizeof(dirhandle->buffer),
4156 gate_string_ptr(dirpath, 0), gate_string_length(dirpath));
4157
4158 12 dirhandle->handle = opendir(dirhandle->buffer);
4159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (dirhandle->handle == NULL)
4160 {
4161 gate_posix_errno(&ret);
4162 }
4163 else
4164 {
4165 12 ret = GATE_RESULT_OK;
4166 }
4167
4168 } while (0);
4169
4170 12 return ret;
4171 }
4172 26 gate_size_t gate_file_dir_read(gate_file_dirreader_t* dirhandle, char* path, gate_size_t pathlen, gate_bool_t filename_only)
4173 {
4174 26 struct dirent entry = GATE_INIT_EMPTY;
4175 26 gate_size_t ret = 0;
4176
2/2
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 5 times.
50 while (gate_readdir((DIR*)dirhandle->handle, &entry))
4177 {
4178 45 gate_size_t name_len = gate_str_length(entry.d_name);
4179
4/4
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 12 times.
✓ Branch 4 taken 21 times.
✓ Branch 5 taken 12 times.
45 if ((gate_str_compare(entry.d_name, name_len, ".", 1) != 0) && (gate_str_compare(entry.d_name, name_len, "..", 2) != 0))
4180 {
4181
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 20 times.
21 if (filename_only)
4182 {
4183 1 ret = gate_str_print_text(path, pathlen, entry.d_name, name_len);
4184 }
4185 else
4186 {
4187 20 ret = gate_file_build_path(path, pathlen,
4188 20 dirhandle->buffer, dirhandle->bufferlen,
4189 entry.d_name, gate_str_length_max(entry.d_name, sizeof(entry.d_name)));
4190 }
4191
4192
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 if (ret > 0)
4193 {
4194 21 break;
4195 }
4196 }
4197 }
4198 26 return ret;
4199 }
4200 12 gate_result_t gate_file_dir_close(gate_file_dirreader_t* dirhandle)
4201 {
4202 12 gate_result_t ret = GATE_RESULT_OK;
4203 12 closedir((DIR*)dirhandle->handle);
4204 12 return ret;
4205 }
4206
4207 3 gate_result_t gate_file_root_list(gate_file_list_callback_t callback, void* userparam)
4208 {
4209 3 gate_result_t ret = GATE_RESULT_OK;
4210 gate_file_entry_t direntry;
4211 3 gate_mem_clear(&direntry, sizeof(direntry));
4212 3 gate_str_print_text(direntry.name, sizeof(direntry.name), "/", 1);
4213 3 gate_str_print_text(direntry.path, sizeof(direntry.path), "/", 1);
4214
4215 3 direntry.props.attribs = GATE_FILEENTRY_ATTRIB_DIRECTORY | GATE_FILEENTRY_ATTRIB_VOLUME;
4216
4217 3 callback(&direntry, userparam);
4218
4219 3 return ret;
4220 }
4221
4222 1 gate_result_t gate_file_get_entry(gate_string_t const* filepath, gate_file_entry_t* ptr_entry)
4223 {
4224 gate_result_t ret;
4225
4226 do
4227 {
4228 char path[GATE_MAX_FILEPATH_LENGTH];
4229 1 gate_size_t pathlength = gate_string_to_buffer(filepath, path, sizeof(path));
4230 gate_size_t pos;
4231
4232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pathlength == 0)
4233 {
4234 ret = GATE_RESULT_INVALIDARG;
4235 break;
4236 }
4237
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (path[pathlength - 1] == gate_file_path_separator_char)
4238 {
4239 path[--pathlength] = '\0';
4240 }
4241 1 pos = gate_str_char_pos_last(path, pathlength, gate_file_path_separator_char);
4242
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pos == GATE_STR_NPOS)
4243 {
4244 pos = 0;
4245 }
4246 else
4247 {
4248 1 ++pos;
4249 }
4250 1 gate_mem_clear(ptr_entry, sizeof(gate_file_entry_t));
4251
4252 1 gate_mem_copy(ptr_entry->path, path, pathlength);
4253 1 ptr_entry->path[pathlength] = 0;
4254 1 gate_str_print_text(ptr_entry->name, sizeof(ptr_entry->name), &ptr_entry->path[pos], pathlength - pos);
4255
4256
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!gate_fstat_to_direntry(path, ptr_entry))
4257 {
4258 ret = GATE_RESULT_FAILED;
4259 break;
4260 }
4261 1 ret = GATE_RESULT_OK;
4262 } while (0);
4263
4264 1 return ret;
4265 }
4266 6 gate_result_t gate_file_dir_create(gate_string_t const* dirpath, gate_enumint_t flags)
4267 {
4268 gate_result_t ret;
4269
4270 do
4271 {
4272 char path[GATE_MAX_FILEPATH_LENGTH];
4273 6 gate_size_t pathlen = gate_string_to_buffer(dirpath, path, sizeof(path));
4274 6 mode_t mode = 0;
4275 6 uid_t uid = 0;
4276 6 gid_t gid = 0;
4277 6 gate_bool_t parent_stat = false;
4278
4279
3/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
6 if ((pathlen != 0) && (path[pathlen - 1] == '/'))
4280 {
4281 3 path[--pathlen] = 0;
4282 }
4283
4284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (GATE_FLAG_ENABLED(flags, GATE_FILE_DIR_CREATE_OWNERRESTRICTED))
4285 {
4286 mode = (S_IRUSR | S_IWUSR | S_IXUSR);
4287 }
4288
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 else if (GATE_FLAG_ENABLED(flags, GATE_FILE_DIR_CREATE_GROUPRESTRICTED))
4289 {
4290 mode = (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP);
4291 }
4292
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 else if (GATE_FLAG_ENABLED(flags, GATE_FILE_DIR_CREATE_UNRESTRICTED))
4293 {
4294 mode = (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);
4295 }
4296 else
4297 {
4298 /* default */
4299 6 parent_stat = gate_file_parent_stat(dirpath, &mode, &uid, &gid);
4300
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (!parent_stat)
4301 {
4302 3 mode = 0;
4303 }
4304 6 mode |= (S_IRUSR | S_IWUSR | S_IXUSR);
4305 }
4306
4307
4308
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if (0 != mkdir(path, mode))
4309 {
4310 gate_posix_errno(&ret);
4311 break;
4312 }
4313
4314 6 ret = GATE_RESULT_OK;
4315
4316
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (parent_stat)
4317 {
4318 int result;
4319 3 result = chmod(path, mode);
4320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (result != 0)
4321 {
4322 GATE_DEBUG_TRACE("chmod() failed");
4323 }
4324 3 result = chown(path, uid, gid);
4325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (result != 0)
4326 {
4327 GATE_DEBUG_TRACE("chown() failed");
4328 }
4329 (void)result;
4330 }
4331 } while (0);
4332
4333 6 return ret;
4334 }
4335 4 gate_result_t gate_file_dir_delete(gate_string_t const* dirpath)
4336 {
4337 gate_result_t ret;
4338 char path[GATE_MAX_FILEPATH_LENGTH];
4339
4340 4 gate_string_to_buffer(dirpath, path, sizeof(path));
4341
4342
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if (0 != rmdir(path))
4343 {
4344 gate_posix_errno(&ret);
4345 }
4346 else
4347 {
4348 4 ret = GATE_RESULT_OK;
4349 }
4350 4 return ret;
4351 }
4352
4353 16 gate_result_t gate_file_get_attributes(gate_string_t const* targetfile, gate_enumint_t* attribs, gate_enumint_t* access_bits)
4354 {
4355 gate_result_t ret;
4356 char path[GATE_MAX_FILEPATH_LENGTH];
4357 struct stat filestat;
4358 16 gate_string_to_buffer(targetfile, path, sizeof(path));
4359
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
16 if (0 != lstat(path, &filestat))
4360 {
4361 ret = GATE_RESULT_FAILED;
4362 }
4363 else
4364 {
4365 16 ret = GATE_RESULT_OK;
4366 16 gate_unix_mode_to_attributes(filestat.st_mode, attribs, access_bits);
4367
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 14 times.
16 if (attribs)
4368 {
4369
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (gate_file_is_hidden_entry(targetfile))
4370 {
4371 *attribs |= GATE_FILEENTRY_ATTRIB_HIDDEN;
4372 }
4373 }
4374 }
4375 16 return ret;
4376 }
4377
4378 gate_result_t gate_file_get_size(gate_string_t const* targetfile, gate_int64_t* filesize)
4379 {
4380 gate_result_t ret;
4381 char path[GATE_MAX_FILEPATH_LENGTH];
4382 struct stat filestat;
4383 gate_string_to_buffer(targetfile, path, sizeof(path));
4384 if (0 != lstat(path, &filestat))
4385 {
4386 ret = GATE_RESULT_FAILED;
4387 }
4388 else
4389 {
4390 ret = GATE_RESULT_OK;
4391 if (filesize)
4392 {
4393 *filesize = (gate_int64_t)filestat.st_size;
4394 }
4395 }
4396 return ret;
4397 }
4398
4399 gate_result_t gate_file_get_owner(gate_string_t const* targetpath,
4400 gate_uint32_t* owner_id, gate_string_t* owner_name)
4401 {
4402 gate_result_t ret;
4403 char path[GATE_MAX_FILEPATH_LENGTH];
4404 struct stat filestat;
4405
4406 gate_string_to_buffer(targetpath, path, sizeof(path));
4407 if (0 != lstat(path, &filestat))
4408 {
4409 ret = GATE_RESULT_FAILED;
4410 }
4411 else
4412 {
4413 if (NULL != owner_id)
4414 {
4415 *owner_id = (gate_uint32_t)filestat.st_uid;
4416 }
4417 if (NULL != owner_name)
4418 {
4419 gate_posix_user_info_t user_info = GATE_INIT_EMPTY;
4420 ret = gate_posix_get_user_info(filestat.st_uid, &user_info);
4421 if (GATE_SUCCEEDED(ret))
4422 {
4423 gate_string_create(owner_name, user_info.name, gate_str_length(user_info.name));
4424 }
4425 else
4426 {
4427 gate_string_create_empty(owner_name);
4428 }
4429 }
4430 ret = GATE_RESULT_OK;
4431 }
4432 return ret;
4433 }
4434
4435
4436 #define GATE_FILE_MODE_SET(mode_var, mask, attribs, attrib, native_mode) \
4437 do { \
4438 if(GATE_FLAG_ENABLED(mask, attrib)) { \
4439 if(GATE_FLAG_ENABLED(attribs, attrib)) { \
4440 mode_var |= native_mode; \
4441 } \
4442 else { \
4443 mode_var &= ~native_mode; \
4444 } \
4445 } \
4446 } while(0)
4447
4448 gate_result_t gate_file_set_attributes(gate_string_t const* targetfile,
4449 gate_enumint_t attribs, gate_enumint_t attribs_mask,
4450 gate_enumint_t access_bits, gate_enumint_t access_mask)
4451 {
4452 gate_result_t ret;
4453 char path[GATE_MAX_FILEPATH_LENGTH];
4454 struct stat filestat;
4455
4456 gate_string_to_buffer(targetfile, path, sizeof(path));
4457 if (0 != lstat(path, &filestat))
4458 {
4459 ret = GATE_RESULT_FAILED;
4460 }
4461 else
4462 {
4463 mode_t mode = filestat.st_mode;
4464 if (access_mask != 0)
4465 {
4466 GATE_FILE_MODE_SET(mode, access_mask, access_bits, GATE_FILEENTRY_ACCESS_OWNERREAD, S_IRUSR);
4467 GATE_FILE_MODE_SET(mode, access_mask, access_bits, GATE_FILEENTRY_ACCESS_OWNERWRITE, S_IWUSR);
4468 GATE_FILE_MODE_SET(mode, access_mask, access_bits, GATE_FILEENTRY_ACCESS_OWNEREXECUTE, S_IXUSR);
4469 GATE_FILE_MODE_SET(mode, access_mask, access_bits, GATE_FILEENTRY_ACCESS_OWNERSETID, S_ISUID);
4470 GATE_FILE_MODE_SET(mode, access_mask, access_bits, GATE_FILEENTRY_ACCESS_GROUPREAD, S_IRGRP);
4471 GATE_FILE_MODE_SET(mode, access_mask, access_bits, GATE_FILEENTRY_ACCESS_GROUPWRITE, S_IWGRP);
4472 GATE_FILE_MODE_SET(mode, access_mask, access_bits, GATE_FILEENTRY_ACCESS_GROUPEXECUTE, S_IXGRP);
4473 GATE_FILE_MODE_SET(mode, access_mask, access_bits, GATE_FILEENTRY_ACCESS_GROUPSETID, S_ISGID);
4474 GATE_FILE_MODE_SET(mode, access_mask, access_bits, GATE_FILEENTRY_ACCESS_ALLREAD, S_IROTH);
4475 GATE_FILE_MODE_SET(mode, access_mask, access_bits, GATE_FILEENTRY_ACCESS_ALLWRITE, S_IWOTH);
4476 GATE_FILE_MODE_SET(mode, access_mask, access_bits, GATE_FILEENTRY_ACCESS_ALLEXECUTE, S_IXOTH);
4477 GATE_FILE_MODE_SET(mode, access_mask, access_bits, GATE_FILEENTRY_ACCESS_NODELETE, S_ISVTX);
4478 }
4479
4480 if (0 != chmod(path, mode))
4481 {
4482 ret = GATE_RESULT_FAILED;
4483 }
4484 else
4485 {
4486 ret = GATE_RESULT_OK;
4487 }
4488 }
4489 return ret;
4490 }
4491
4492 gate_result_t gate_file_get_times(gate_string_t const* targetfile, gate_timestamp_t* modified,
4493 gate_timestamp_t* accessed, gate_timestamp_t* created)
4494 {
4495 gate_result_t ret;
4496 char path[GATE_MAX_FILEPATH_LENGTH];
4497 struct stat filestat;
4498
4499 gate_string_to_buffer(targetfile, path, sizeof(path));
4500
4501 if (0 != lstat(path, &filestat))
4502 {
4503 ret = GATE_RESULT_FAILED;
4504 }
4505 else
4506 {
4507 ret = GATE_RESULT_OK;
4508 if (created) gate_time_from_unix(filestat.st_ctime, created);
4509 if (modified)gate_time_from_unix(filestat.st_mtime, modified);
4510 if (accessed)gate_time_from_unix(filestat.st_atime, accessed);
4511 }
4512 return ret;
4513 }
4514 gate_result_t gate_file_set_times(gate_string_t const* targetfile, gate_timestamp_t const* modified,
4515 gate_timestamp_t const* accessed, gate_timestamp_t const* created)
4516 {
4517 gate_result_t ret;
4518 char path[GATE_MAX_FILEPATH_LENGTH];
4519 struct utimbuf ft;
4520 gate_timestamp_t orig_modified = 0, orig_accessed = 0;
4521 gate_int64_t accesstime = 0;
4522 gate_int64_t modifiedtime = 0;
4523
4524 if (!modified || !accessed)
4525 {
4526 gate_file_get_times(targetfile, &orig_modified, &orig_accessed, NULL);
4527 if (!modified) modified = &orig_modified;
4528 if (!accessed) accessed = &orig_accessed;
4529 }
4530
4531 gate_time_to_unix(*modified, &modifiedtime);
4532 gate_time_to_unix(*accessed, &accesstime);
4533
4534 gate_string_to_buffer(targetfile, path, sizeof(path));
4535
4536 ft.actime = (time_t)accesstime;
4537 ft.modtime = (time_t)modifiedtime;
4538 if (0 != utime(path, &ft))
4539 {
4540 ret = GATE_RESULT_FAILED;
4541 }
4542 else
4543 {
4544 ret = GATE_RESULT_OK;
4545 }
4546 return ret;
4547 }
4548
4549 #endif /* GATE_CORE_FILES_POSIX_IMPL */
4550
4551
4552
4553 #if defined(GATE_CORE_FILES_DOS_IMPL)
4554
4555 #include "gate/platforms.h"
4556 #include <dos.h>
4557 #include <io.h>
4558 #include <direct.h>
4559
4560 char const gate_file_path_separator_char = '\\';
4561
4562 char const* const gate_file_path_separator = "\\";
4563
4564 gate_result_t gate_file_exists(gate_string_t const* filepath)
4565 {
4566 gate_result_t ret = GATE_RESULT_FAILED;
4567
4568 do
4569 {
4570 char path[GATE_MAX_FILEPATH_LENGTH];
4571 struct find_t f;
4572 unsigned result;
4573 gate_string_to_buffer(filepath, path, sizeof(path));
4574 result = _dos_findfirst(path, _A_NORMAL | _A_RDONLY | _A_HIDDEN | _A_SYSTEM, &f);
4575 if (0 != result)
4576 {
4577 ret = GATE_RESULT_NOTAVAILABLE;
4578 break;
4579 }
4580 ret = GATE_RESULT_OK;
4581 } while (0);
4582 return ret;
4583 }
4584 gate_result_t gate_file_copy(gate_string_t const* srcfilepath, gate_string_t const* dstfilepath, gate_enumint_t flags)
4585 {
4586 return gate_file_copy_internal(srcfilepath, dstfilepath, flags);
4587 }
4588 gate_result_t gate_file_move(gate_string_t const* srcfilepath, gate_string_t const* dstfilepath)
4589 {
4590 return gate_file_move_internal(srcfilepath, dstfilepath);
4591 }
4592 gate_result_t gate_file_delete(gate_string_t const* filepath)
4593 {
4594 union REGS regs;
4595 struct SREGS segregs;
4596 char path[GATE_MAX_FILEPATH_LENGTH];
4597 gate_string_to_buffer(filepath, path, sizeof(path));
4598
4599 segregs.ds = segregs.es = FP_SEG(&path[0]);
4600 regs.h.ah = 0x41;
4601 regs.w.bx = 0;
4602 regs.w.cx = 0;
4603 regs.w.dx = FP_OFF(&path[0]);
4604
4605 intdosx(&regs, &regs, &segregs);
4606 if (regs.w.cflag & INTR_CF)
4607 {
4608 return GATE_RESULT_FAILED;
4609 }
4610 return GATE_RESULT_OK;
4611
4612 /*
4613 if(0 == unlink(path))
4614 {
4615 return GATE_RESULT_OK;
4616 }
4617 return GATE_RESULT_FAILED;
4618 */
4619 }
4620 gate_result_t gate_file_real_path(gate_string_t const* relativepath, gate_string_t* absolutepath)
4621 {
4622 /* TODO */
4623 GATE_UNUSED_ARG(relativepath);
4624 GATE_UNUSED_ARG(absolutepath);
4625 return GATE_RESULT_NOTSUPPORTED;
4626 }
4627 gate_result_t gate_file_create_link(gate_string_t const* targetpath, gate_string_t const* linkfile)
4628 {
4629 GATE_UNUSED_ARG(targetpath);
4630 GATE_UNUSED_ARG(linkfile);
4631 return GATE_RESULT_NOTSUPPORTED;
4632 }
4633 gate_result_t gate_file_read_link(gate_string_t const* filepath, gate_string_t* realpath)
4634 {
4635 GATE_UNUSED_ARG(filepath);
4636 GATE_UNUSED_ARG(realpath);
4637 return GATE_RESULT_NOTSUPPORTED;
4638 }
4639 gate_result_t gate_file_create_hardlink(gate_string_t const* targetfile, gate_string_t const* linkfile)
4640 {
4641 GATE_UNUSED_ARG(targetfile);
4642 GATE_UNUSED_ARG(linkfile);
4643 return GATE_RESULT_NOTSUPPORTED;
4644 }
4645 gate_result_t gate_file_get_attributes(gate_string_t const* targetpath, gate_enumint_t* attribs, gate_enumint_t* access_bits)
4646 {
4647 gate_result_t ret = GATE_RESULT_FAILED;
4648
4649 do
4650 {
4651 struct find_t f;
4652 char path[GATE_MAX_FILEPATH_LENGTH];
4653 unsigned result;
4654
4655 gate_string_to_buffer(targetpath, path, sizeof(path));
4656
4657 result = _dos_findfirst(path, _A_NORMAL | _A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_SUBDIR | _A_ARCH, &f);
4658 if (0 != result)
4659 {
4660 ret = GATE_RESULT_NOTAVAILABLE;
4661 break;
4662 }
4663 if (attribs)
4664 {
4665 *attribs = 0;
4666 if (GATE_FLAG_ENABLED(f.attrib, _A_SUBDIR)) *attribs |= GATE_FILEENTRY_ATTRIB_DIRECTORY;
4667 else *attribs |= GATE_FILEENTRY_ATTRIB_FILE;
4668 if (GATE_FLAG_ENABLED(f.attrib, _A_RDONLY)) *attribs |= GATE_FILEENTRY_ATTRIB_READONLY;
4669 if (GATE_FLAG_ENABLED(f.attrib, _A_HIDDEN)) *attribs |= GATE_FILEENTRY_ATTRIB_HIDDEN;
4670 if (GATE_FLAG_ENABLED(f.attrib, _A_SYSTEM)) *attribs |= GATE_FILEENTRY_ATTRIB_SYSTEM;
4671 if (GATE_FLAG_ENABLED(f.attrib, _A_ARCH)) *attribs |= GATE_FILEENTRY_ATTRIB_ARCHIVE;
4672
4673 }
4674 if (access_bits)
4675 {
4676 gate_bool_t is_readonly = GATE_FLAG_ENABLED(f.attrib, _A_RDONLY);
4677 gate_bool_t is_executable = gate_string_ends_with_str_ic(targetpath, ".exe")
4678 || gate_string_ends_with_str_ic(targetpath, ".com")
4679 || gate_string_ends_with_str_ic(targetpath, ".bat");
4680
4681 /* all access granted */
4682 *access_bits = GATE_FILEENTRY_ACCESS_OWNERREAD | GATE_FILEENTRY_ACCESS_GROUPREAD | GATE_FILEENTRY_ACCESS_ALLREAD;
4683 if (!is_readonly)
4684 {
4685 *access_bits |= GATE_FILEENTRY_ACCESS_OWNERWRITE | GATE_FILEENTRY_ACCESS_GROUPWRITE | GATE_FILEENTRY_ACCESS_ALLWRITE;
4686 }
4687 if (is_executable)
4688 {
4689 *access_bits |= GATE_FILEENTRY_ACCESS_OWNEREXECUTE | GATE_FILEENTRY_ACCESS_GROUPEXECUTE | GATE_FILEENTRY_ACCESS_ALLEXECUTE;
4690 }
4691 }
4692
4693 ret = GATE_RESULT_OK;
4694 } while (0);
4695 return ret;
4696 }
4697 gate_result_t gate_file_set_attributes(gate_string_t const* targetpath,
4698 gate_enumint_t attribs, gate_enumint_t attribs_mask,
4699 gate_enumint_t access_bits, gate_enumint_t access_mask)
4700 {
4701 char path[GATE_MAX_FILEPATH_LENGTH];
4702
4703 GATE_UNUSED_ARG(access_bits);
4704 GATE_UNUSED_ARG(access_mask);
4705
4706 gate_string_to_buffer(targetpath, path, sizeof(path));
4707
4708 if (attribs_mask)
4709 {
4710 unsigned dosattribs = 0;
4711 unsigned result = _dos_getfileattr(path, &dosattribs);
4712 if (result != 0)
4713 {
4714 return GATE_RESULT_NOTAVAILABLE;
4715 }
4716
4717 if (GATE_FLAG_ENABLED(attribs_mask, GATE_FILEENTRY_ATTRIB_READONLY)) GATE_FLAG_SET(dosattribs, _A_RDONLY, GATE_FLAG_ENABLED(attribs, GATE_FILEENTRY_ATTRIB_READONLY));
4718 if (GATE_FLAG_ENABLED(attribs_mask, GATE_FILEENTRY_ATTRIB_HIDDEN)) GATE_FLAG_SET(dosattribs, _A_HIDDEN, GATE_FLAG_ENABLED(attribs, GATE_FILEENTRY_ATTRIB_HIDDEN));
4719 if (GATE_FLAG_ENABLED(attribs_mask, GATE_FILEENTRY_ATTRIB_SYSTEM)) GATE_FLAG_SET(dosattribs, _A_SYSTEM, GATE_FLAG_ENABLED(attribs, GATE_FILEENTRY_ATTRIB_SYSTEM));
4720 if (GATE_FLAG_ENABLED(attribs_mask, GATE_FILEENTRY_ATTRIB_ARCHIVE)) GATE_FLAG_SET(dosattribs, _A_ARCH, GATE_FLAG_ENABLED(attribs, GATE_FILEENTRY_ATTRIB_ARCHIVE));
4721
4722 result = _dos_setfileattr(path, dosattribs);
4723 if (result != 0)
4724 {
4725 return GATE_RESULT_FAILED;
4726 }
4727 }
4728
4729 return GATE_RESULT_OK;
4730 }
4731
4732 typedef struct {
4733 unsigned short twosecs : 5; /* seconds / 2 */
4734 unsigned short minutes : 6; /* minutes (0,59) */
4735 unsigned short hours : 5; /* hours (0,23) */
4736 } ftime_t;
4737
4738 typedef struct {
4739 unsigned short day : 5; /* day (1,31) */
4740 unsigned short month : 4; /* month (1,12) */
4741 unsigned short year : 7; /* 0 is 1980 */
4742 } fdate_t;
4743
4744 void gate_file_convert_time(unsigned short fdate, unsigned short ftime, gate_timestamp_t* ts)
4745 {
4746 fdate_t* ptr_date = (fdate_t*)&fdate;
4747 ftime_t* ptr_time = (ftime_t*)&ftime;
4748 gate_datetime_t dt;
4749 gate_time_t tm;
4750
4751 dt.date.year = 1980 + ptr_date->year;
4752 dt.date.month = ptr_date->month;
4753 dt.date.day = ptr_date->day;
4754 dt.time.hour = ptr_time->hours;
4755 dt.time.minute = ptr_time->minutes;
4756 dt.time.second = ptr_time->twosecs * 2;
4757 dt.time.microsecond = 0;
4758 gate_date_to_time(&dt, &tm);
4759 if (ts)
4760 {
4761 *ts = tm.timestamp;
4762 }
4763 }
4764
4765 gate_result_t gate_file_get_times(gate_string_t const* targetpath, gate_timestamp_t* modified, gate_timestamp_t* accessed, gate_timestamp_t* created)
4766 {
4767 gate_result_t ret = GATE_RESULT_FAILED;
4768
4769 do
4770 {
4771 struct find_t f;
4772 char path[GATE_MAX_FILEPATH_LENGTH];
4773 unsigned result;
4774
4775 gate_string_to_buffer(targetpath, path, sizeof(path));
4776
4777 result = _dos_findfirst(path, _A_NORMAL | _A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_SUBDIR | _A_ARCH, &f);
4778 if (0 != result)
4779 {
4780 ret = GATE_RESULT_NOTAVAILABLE;
4781 break;
4782 }
4783 if (modified)
4784 {
4785 gate_file_convert_time(f.wr_date, f.wr_time, modified);
4786 }
4787 if (accessed)
4788 {
4789 gate_file_convert_time(f.wr_date, f.wr_time, accessed);
4790 }
4791 if (created)
4792 {
4793 *created = 0;
4794 }
4795 ret = GATE_RESULT_OK;
4796 } while (0);
4797 return ret;
4798 }
4799 gate_result_t gate_file_set_times(gate_string_t const* targetpath, gate_timestamp_t const* modified, gate_timestamp_t const* accessed, gate_timestamp_t const* created)
4800 {
4801 GATE_UNUSED_ARG(targetpath);
4802 GATE_UNUSED_ARG(modified);
4803 GATE_UNUSED_ARG(accessed);
4804 GATE_UNUSED_ARG(created);
4805 /* TODO */
4806 return GATE_RESULT_NOTSUPPORTED;
4807 }
4808 gate_result_t gate_file_get_size(gate_string_t const* targetfile, gate_int64_t* filesize)
4809 {
4810 gate_result_t ret = GATE_RESULT_FAILED;
4811
4812 do
4813 {
4814 struct find_t f;
4815 char path[GATE_MAX_FILEPATH_LENGTH];
4816 unsigned result;
4817
4818 gate_string_to_buffer(targetfile, path, sizeof(path));
4819
4820 result = _dos_findfirst(path, _A_NORMAL | _A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH, &f);
4821 if (0 != result)
4822 {
4823 ret = GATE_RESULT_NOTAVAILABLE;
4824 break;
4825 }
4826 if (filesize)
4827 {
4828 *filesize = (gate_int64_t)f.size;
4829 }
4830 ret = GATE_RESULT_OK;
4831 } while (0);
4832 return ret;
4833 }
4834 gate_result_t gate_file_get_owner(gate_string_t const* targetfile,
4835 gate_uint32_t* owner_id, gate_string_t* owner_name)
4836 {
4837 GATE_UNUSED_ARG(targetfile);
4838 GATE_UNUSED_ARG(owner_id);
4839 GATE_UNUSED_ARG(owner_name);
4840 return GATE_RESULT_NOTSUPPORTED;
4841 }
4842
4843 gate_result_t gate_file_open(gate_string_t const* filepath, gate_enumint_t flags, gate_file_t* filehandle)
4844 {
4845 gate_result_t ret;
4846 int platform_flags;
4847 gate_bool_t seek_end = false;
4848 gate_platform_stream_t stream;
4849
4850 switch (flags)
4851 {
4852 case GATE_STREAM_OPEN_READ:
4853 platform_flags = GATE_PLATFORM_STREAM_OPEN_READ;
4854 break;
4855 case GATE_STREAM_OPEN_WRITE:
4856 platform_flags = GATE_PLATFORM_STREAM_OPEN_WRITE;
4857 break;
4858 case GATE_STREAM_OPEN_READWRITE:
4859 platform_flags = GATE_PLATFORM_STREAM_OPEN_READWRITE;
4860 break;
4861 case GATE_STREAM_OPEN_APPENDWRITE:
4862 case GATE_STREAM_OPEN_APPENDREADWRITE:
4863 platform_flags = GATE_PLATFORM_STREAM_OPEN_READWRITE;
4864 seek_end = true;
4865 break;
4866 default:
4867 return GATE_RESULT_INVALIDARG;
4868 }
4869
4870 do
4871 {
4872 char path[GATE_MAX_FILEPATH_LENGTH];
4873 gate_string_to_buffer(filepath, path, sizeof(path));
4874 ret = gate_platform_stream_open(path, platform_flags, 0, &stream);
4875 GATE_BREAK_IF_FAILED(ret);
4876
4877 *filehandle = (gate_file_t)stream;
4878 ret = GATE_RESULT_OK;
4879 } while (0);
4880 return ret;
4881 }
4882 gate_result_t gate_file_read(gate_file_t filehandle, char* buffer, gate_size_t bufferlength, gate_size_t* bufferused)
4883 {
4884 gate_platform_stream_t stream = (gate_platform_stream_t)filehandle;
4885 return gate_platform_stream_read(stream, buffer, bufferlength, bufferused);
4886 }
4887 gate_result_t gate_file_write(gate_file_t filehandle, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
4888 {
4889 gate_platform_stream_t stream = (gate_platform_stream_t)filehandle;
4890 return gate_platform_stream_write(stream, buffer, bufferlength, written);
4891 }
4892 gate_result_t gate_file_flush(gate_file_t filehandle)
4893 {
4894 int handle = (int)(gate_intptr_t)(gate_platform_stream_t)filehandle;
4895 unsigned result = _dos_commit(handle);
4896 if (result != 0)
4897 {
4898 return GATE_RESULT_FAILED;
4899 }
4900 else
4901 {
4902 return GATE_RESULT_OK;
4903 }
4904 }
4905 gate_result_t gate_file_close(gate_file_t filehandle)
4906 {
4907 gate_platform_stream_t stream = (gate_platform_stream_t)filehandle;
4908 return gate_platform_stream_close(&stream);
4909 }
4910 gate_result_t gate_file_seek(gate_file_t filehandle, gate_int64_t position, gate_enumint_t origin, gate_int64_t* newposition)
4911 {
4912 gate_platform_stream_t stream = (gate_platform_stream_t)filehandle;
4913 int native_origin = GATE_PLATFORM_STREAM_ORIGIN_BEGIN;
4914 switch (origin)
4915 {
4916 case GATE_FILE_SEEK_ORIGIN_BEGIN: native_origin = GATE_PLATFORM_STREAM_ORIGIN_BEGIN; break;
4917 case GATE_FILE_SEEK_ORIGIN_CURPOS: native_origin = GATE_PLATFORM_STREAM_ORIGIN_CURRENT; break;
4918 case GATE_FILE_SEEK_ORIGIN_END: native_origin = GATE_PLATFORM_STREAM_ORIGIN_END; break;
4919 default: return GATE_RESULT_INVALIDARG;
4920 }
4921 return gate_platform_stream_seek(stream, position, native_origin, newposition);
4922 }
4923 gate_result_t gate_file_pos(gate_file_t filehandle, gate_int64_t* position)
4924 {
4925 gate_platform_stream_t stream = (gate_platform_stream_t)filehandle;
4926 return gate_platform_stream_seek(stream, 0, GATE_PLATFORM_STREAM_ORIGIN_CURRENT, position);
4927 }
4928 gate_result_t gate_file_size(gate_file_t filehandle, gate_int64_t* size)
4929 {
4930 gate_result_t ret = GATE_RESULT_FAILED;
4931 gate_platform_stream_t stream = (gate_platform_stream_t)filehandle;
4932 gate_int64_t cur_pos = 0;
4933 do
4934 {
4935 ret = gate_platform_stream_seek(stream, 0, GATE_PLATFORM_STREAM_ORIGIN_CURRENT, &cur_pos);
4936 GATE_BREAK_IF_FAILED(ret);
4937
4938 ret = gate_platform_stream_seek(stream, 0, GATE_PLATFORM_STREAM_ORIGIN_END, size);
4939 gate_platform_stream_seek(stream, cur_pos, GATE_PLATFORM_STREAM_ORIGIN_BEGIN, NULL);
4940 } while (0);
4941 return ret;
4942 }
4943 gate_result_t gate_file_lock(gate_file_t filehandle, gate_bool_t wait)
4944 {
4945 GATE_UNUSED_ARG(filehandle);
4946 GATE_UNUSED_ARG(wait);
4947 return GATE_RESULT_NOTSUPPORTED;
4948 }
4949 gate_result_t gate_file_unlock(gate_file_t filehandle)
4950 {
4951 GATE_UNUSED_ARG(filehandle);
4952 return GATE_RESULT_NOTSUPPORTED;
4953 }
4954 gate_result_t gate_file_truncate(gate_file_t filehandle)
4955 {
4956 GATE_UNUSED_ARG(filehandle);
4957 return GATE_RESULT_NOTSUPPORTED;
4958 }
4959 gate_result_t gate_file_root_list(gate_file_list_callback_t callback, void* userparam)
4960 {
4961 gate_result_t ret = GATE_RESULT_OK;
4962 gate_size_t n;
4963 for (n = 0; n < 26; ++n)
4964 {
4965 gate_file_entry_t entry;
4966 gate_dos_gpregs_t regs = GATE_INIT_EMPTY;
4967 regs.a.h = 0x32;
4968 regs.d.x = (n + 1);
4969 gate_dos_intr(0x21, &regs, NULL);
4970 if (regs.a.l != 0)
4971 {
4972 continue;
4973 }
4974 gate_mem_clear(&entry, sizeof(entry));
4975 entry.path[0] = 'A' + n;
4976 entry.path[1] = ':';
4977 entry.path[2] = '\\';
4978 entry.path[3] = 0;
4979 entry.name[0] = 'A' + n;
4980 entry.name[1] = ':';
4981 entry.name[2] = 0;
4982 entry.props.attribs = GATE_FILEENTRY_ATTRIB_VOLUME;
4983 if (!callback(&entry, userparam))
4984 {
4985 break;
4986 }
4987 }
4988 return ret;
4989 }
4990
4991 static void dos_find_to_gate_file_entry(struct find_t* ptr_find, gate_file_entry_t* ptr_entry)
4992 {
4993 gate_size_t namelen = gate_str_length(ptr_find->name);
4994 gate_bool_t is_executable = gate_str_ends_with_ic(ptr_find->name, namelen, ".exe", 4)
4995 || gate_str_ends_with_ic(ptr_find->name, namelen, ".com", 4)
4996 || gate_str_ends_with_ic(ptr_find->name, namelen, ".bat", 4);
4997 gate_str_print_text(&ptr_entry->name[0], sizeof(ptr_entry->name), ptr_find->name, namelen);
4998 ptr_entry->props.size = ptr_find->size;
4999 ptr_entry->props.attribs = 0;
5000 ptr_entry->props.access = GATE_FILEENTRY_ACCESS_OWNERREAD | GATE_FILEENTRY_ACCESS_GROUPREAD | GATE_FILEENTRY_ACCESS_ALLREAD;
5001 GATE_FLAG_SET(ptr_entry->props.attribs, GATE_FILEENTRY_ATTRIB_DIRECTORY, (ptr_find->attrib & _A_SUBDIR));
5002 GATE_FLAG_SET(ptr_entry->props.attribs, GATE_FILEENTRY_ATTRIB_ARCHIVE, (ptr_find->attrib & _A_ARCH));
5003 GATE_FLAG_SET(ptr_entry->props.attribs, GATE_FILEENTRY_ATTRIB_HIDDEN, (ptr_find->attrib & _A_HIDDEN));
5004 GATE_FLAG_SET(ptr_entry->props.attribs, GATE_FILEENTRY_ATTRIB_READONLY, (ptr_find->attrib & _A_RDONLY));
5005 GATE_FLAG_SET(ptr_entry->props.attribs, GATE_FILEENTRY_ATTRIB_SYSTEM, (ptr_find->attrib & _A_SYSTEM));
5006 if (!GATE_FLAG_ENABLED(ptr_entry->props.attribs, GATE_FILEENTRY_ATTRIB_DIRECTORY))
5007 {
5008 ptr_entry->props.attribs |= GATE_FILEENTRY_ATTRIB_FILE;
5009 }
5010 if (!GATE_FLAG_ENABLED(ptr_entry->props.attribs, GATE_FILEENTRY_ATTRIB_READONLY))
5011 {
5012 ptr_entry->props.access |= GATE_FILEENTRY_ACCESS_OWNERWRITE | GATE_FILEENTRY_ACCESS_GROUPWRITE | GATE_FILEENTRY_ACCESS_ALLWRITE;
5013 }
5014 if (is_executable)
5015 {
5016 ptr_entry->props.access |= GATE_FILEENTRY_ACCESS_OWNEREXECUTE | GATE_FILEENTRY_ACCESS_GROUPEXECUTE | GATE_FILEENTRY_ACCESS_ALLEXECUTE;
5017 }
5018 gate_file_convert_time(ptr_find->wr_date, ptr_find->wr_time, &ptr_entry->props.time_modified);
5019 ptr_entry->props.time_accessed = ptr_entry->props.time_modified;
5020 ptr_entry->props.time_created = ptr_entry->props.time_modified;
5021 }
5022
5023 gate_result_t gate_file_list(gate_string_t const* dirpath, gate_file_list_callback_t callback, void* userparam)
5024 {
5025 gate_result_t ret = GATE_RESULT_OK;
5026 char path[GATE_MAX_FILEPATH_LENGTH];
5027 gate_size_t pathlen;
5028 gate_size_t namelen;
5029 struct find_t found_file;
5030 gate_file_entry_t file_entry;
5031 unsigned errorstatus;
5032
5033 pathlen = gate_string_to_buffer(dirpath, path, sizeof(path) - 5);
5034 if (pathlen != 0)
5035 {
5036 if (path[pathlen - 1] != '\\')
5037 {
5038 path[pathlen] = '\\';
5039 ++pathlen;
5040 }
5041 }
5042 path[pathlen + 0] = '*';
5043 path[pathlen + 1] = '.';
5044 path[pathlen + 2] = '*';
5045 path[pathlen + 3] = '\0';
5046
5047 errorstatus = _dos_findfirst(path, _A_SUBDIR | _A_ARCH | _A_HIDDEN | _A_NORMAL | _A_RDONLY | _A_SYSTEM, &found_file);
5048 if (errorstatus)
5049 {
5050 return GATE_RESULT_FAILED;
5051 }
5052 while (errorstatus == 0)
5053 {
5054 namelen = gate_str_length(found_file.name);
5055 if ((gate_str_compare(found_file.name, namelen, ".", 1) != 0)
5056 && (gate_str_compare(found_file.name, namelen, "..", 2) != 0)
5057 )
5058 {
5059 gate_str_print_text(&file_entry.path[0], sizeof(file_entry.path), path, pathlen);
5060 gate_str_print_text(&file_entry.path[pathlen], sizeof(file_entry.path) - pathlen, found_file.name, namelen);
5061
5062 dos_find_to_gate_file_entry(&found_file, &file_entry);
5063 if (callback)
5064 {
5065 if (!callback(&file_entry, userparam))
5066 {
5067 /* skip all other iterations */
5068 while (errorstatus == 0)
5069 {
5070 errorstatus = _dos_findnext(&found_file);
5071 }
5072 break;
5073 }
5074 }
5075 }
5076 errorstatus = _dos_findnext(&found_file);
5077 }
5078 return ret;
5079 }
5080 gate_result_t gate_file_get_entry(gate_string_t const* filepath, gate_file_entry_t* ptr_entry)
5081 {
5082 gate_result_t ret = GATE_RESULT_FAILED;
5083
5084 do
5085 {
5086 char path[GATE_MAX_FILEPATH_LENGTH];
5087 struct find_t found_file;
5088 gate_size_t pathlen;
5089 unsigned search_attribs = _A_NORMAL | _A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_SUBDIR | _A_ARCH;
5090 unsigned result;
5091
5092 gate_mem_clear(ptr_entry, sizeof(gate_file_entry_t));
5093 pathlen = gate_string_to_buffer(filepath, path, sizeof(path));
5094
5095 if (pathlen == 0)
5096 {
5097 ret = GATE_RESULT_INVALIDARG;
5098 break;
5099 }
5100
5101 if (pathlen == 3)
5102 {
5103 if (path[1] == ':' && path[2] == '\\')
5104 {
5105 /* path is a folder */
5106 path[3] = '*';
5107 path[4] = '.';
5108 path[5] = '*';
5109 path[6] = '\0';
5110 result = _dos_findfirst(path, _A_SUBDIR | _A_ARCH | _A_HIDDEN | _A_NORMAL | _A_VOLID | _A_RDONLY | _A_SYSTEM, &found_file);
5111 if (result == 0)
5112 {
5113 gate_string_to_buffer(filepath, ptr_entry->path, sizeof(ptr_entry->path));
5114 gate_string_to_buffer(filepath, ptr_entry->name, sizeof(ptr_entry->name));
5115 ptr_entry->props.attribs = GATE_FILEENTRY_ATTRIB_DIRECTORY | GATE_FILEENTRY_ATTRIB_VOLUME;
5116 ptr_entry->props.access = GATE_FILEENTRY_ACCESS_ALLREAD | GATE_FILEENTRY_ACCESS_ALLWRITE;
5117 ptr_entry->props.size = 0;
5118 ret = GATE_RESULT_OK;
5119 break;
5120 }
5121 }
5122 }
5123
5124 if (path[pathlen - 1] == '\\')
5125 {
5126 --pathlen;
5127 path[pathlen] = '\0';
5128 if (pathlen == 0)
5129 {
5130 ret = GATE_RESULT_INVALIDARG;
5131 break;
5132 }
5133 }
5134 gate_mem_clear(&found_file, sizeof(found_file));
5135
5136 result = _dos_findfirst(path, search_attribs, &found_file);
5137 if (0 != result)
5138 {
5139 ret = GATE_RESULT_NOTAVAILABLE;
5140 break;
5141 }
5142
5143 if (ptr_entry)
5144 {
5145 gate_string_to_buffer(filepath, ptr_entry->path, sizeof(ptr_entry->path));
5146 dos_find_to_gate_file_entry(&found_file, ptr_entry);
5147 }
5148 ret = GATE_RESULT_OK;
5149 } while (0);
5150
5151 return ret;
5152 }
5153 gate_result_t gate_file_dir_create(gate_string_t const* dirpath, gate_enumint_t flags)
5154 {
5155 char path[GATE_MAX_FILEPATH_LENGTH];
5156 GATE_UNUSED_ARG(flags);
5157 gate_string_to_buffer(dirpath, path, sizeof(path));
5158 if (0 != _mkdir(path))
5159 {
5160 return GATE_RESULT_FAILED;
5161 }
5162 return GATE_RESULT_OK;
5163 }
5164 gate_result_t gate_file_dir_delete(gate_string_t const* dirpath)
5165 {
5166 char path[GATE_MAX_FILEPATH_LENGTH];
5167 gate_string_to_buffer(dirpath, path, sizeof(path));
5168 if (0 != _rmdir(path))
5169 {
5170 return GATE_RESULT_FAILED;
5171 }
5172 return GATE_RESULT_OK;
5173 }
5174 gate_result_t gate_file_dir_exists(gate_string_t const* dirpath)
5175 {
5176 DIR* ptr_dir;
5177 char path[GATE_MAX_FILEPATH_LENGTH];
5178 gate_string_to_buffer(dirpath, path, sizeof(path));
5179 ptr_dir = opendir(path);
5180 if (ptr_dir == NULL)
5181 {
5182 return GATE_RESULT_NOTAVAILABLE;
5183 }
5184 closedir(ptr_dir);
5185 return GATE_RESULT_OK;
5186 }
5187 gate_result_t gate_file_dir_open(gate_string_t const* dirpath, gate_file_dirreader_t* dirhandle)
5188 {
5189 DIR* ptr_dir;
5190
5191 if (!dirpath || !dirhandle)
5192 {
5193 return GATE_RESULT_INVALIDARG;
5194 }
5195
5196 gate_mem_clear(dirhandle, sizeof(gate_file_dirreader_t));
5197
5198 dirhandle->bufferlen = gate_string_to_buffer(dirpath, dirhandle->buffer, sizeof(dirhandle->buffer) - 1);
5199 if (dirhandle->bufferlen == 0)
5200 {
5201 return GATE_RESULT_FAILED;
5202 }
5203 if (dirhandle->buffer[dirhandle->bufferlen - 1] != '\\')
5204 {
5205 dirhandle->buffer[dirhandle->bufferlen] = '\\';
5206 ++dirhandle->bufferlen;
5207 dirhandle->buffer[dirhandle->bufferlen] = 0;
5208 }
5209
5210 ptr_dir = opendir(dirhandle->buffer);
5211 if (ptr_dir == NULL)
5212 {
5213 return GATE_RESULT_NOTAVAILABLE;
5214 }
5215 dirhandle->handle = ptr_dir;
5216 return GATE_RESULT_OK;
5217 }
5218 gate_size_t gate_file_dir_read(gate_file_dirreader_t* dirhandle, char* path, gate_size_t pathlen, gate_bool_t filename_only)
5219 {
5220 gate_size_t ret = 0;
5221
5222 if (dirhandle && dirhandle->handle && path && pathlen)
5223 {
5224 DIR* ptr_dir = (DIR*)dirhandle->handle;
5225 struct dirent* ptr_dirent = readdir(ptr_dir);
5226 while (ptr_dirent)
5227 {
5228 if ((gate_str_comp(ptr_dirent->d_name, "..") == 0) || (gate_str_comp(ptr_dirent->d_name, ".") == 0))
5229 {
5230 ptr_dirent = readdir(ptr_dir);
5231 }
5232 else
5233 {
5234 if (filename_only)
5235 {
5236 ret = gate_str_print_text(path, pathlen, ptr_dirent->d_name, gate_str_length(ptr_dirent->d_name));
5237 }
5238 else
5239 {
5240 ret = gate_str_print_text(path, pathlen, dirhandle->buffer, dirhandle->bufferlen);
5241 path += ret;
5242 pathlen -= ret;
5243 ret += gate_str_print_text(path, pathlen, ptr_dirent->d_name, gate_str_length(ptr_dirent->d_name));
5244 }
5245 break;
5246 }
5247 }
5248 }
5249
5250 return ret;
5251 }
5252 gate_result_t gate_file_dir_close(gate_file_dirreader_t* dirhandle)
5253 {
5254 if (dirhandle && dirhandle->handle)
5255 {
5256 DIR* ptr_dir = (DIR*)dirhandle->handle;
5257 closedir(ptr_dir);
5258 dirhandle->handle = NULL;
5259 }
5260 return GATE_RESULT_OK;
5261 }
5262
5263 #endif /* GATE_CORE_FILES_DOS_IMPL */
5264
5265
5266
5267
5268 #if defined(GATE_CORE_FILES_EFI_IMPL)
5269
5270 #include "gate/platform/efi/efi_gate.h"
5271
5272 char const gate_file_path_separator_char = '\\';
5273
5274 char const* const gate_file_path_separator = "\\";
5275
5276 static void update_volumes(void** device_handles, gate_size_t device_handles_count)
5277 {
5278 gate_size_t ndx;
5279 int dummy = 0;
5280
5281 for (ndx = 0; ndx != device_handles_count; ++ndx)
5282 {
5283 gate_platform_efi_register_volume(device_handles[ndx], &dummy);
5284 }
5285 }
5286
5287 static gate_result_t update_all_volumes()
5288 {
5289 void* device_handles[256] = GATE_INIT_EMPTY;
5290 gate_size_t device_handles_count = sizeof(device_handles) / sizeof(device_handles[0]);
5291 gate_result_t ret;
5292 ret = gate_platform_efi_find_volume_device_handles(device_handles, &device_handles_count);
5293 if (GATE_SUCCEEDED(ret))
5294 {
5295 update_volumes(device_handles, device_handles_count);
5296 }
5297 return ret;
5298 }
5299
5300 static gate_result_t open_volume_root(gate_string_t const* dirpath, void** ptr_volume_root, gate_string_t* subpath)
5301 {
5302 gate_result_t ret;
5303 gate_string_t drive = GATE_STRING_INIT_EMPTY;
5304 do
5305 {
5306 static gate_bool_t is_initialized = false;
5307 if (!is_initialized)
5308 {
5309 is_initialized = true;
5310 update_all_volumes();
5311 }
5312
5313 if (gate_string_starts_with_str(dirpath, gate_file_path_separator))
5314 {
5315 /* open boot device */
5316 ret = gate_platform_efi_open_app_volume_root(ptr_volume_root);
5317 GATE_BREAK_IF_FAILED(ret);
5318 gate_string_substr(subpath, dirpath, 1, GATE_STR_NPOS);
5319 }
5320 else if (gate_string_starts_with_str(dirpath, "FS") || gate_string_starts_with_str(dirpath, "fs"))
5321 {
5322 /* check for UEFI shell paths FSx:\\ */
5323 wchar_t fspath[8];
5324 void* volume_handle = NULL;
5325
5326 gate_string_substr(&drive, dirpath, 0, 5);
5327 if (!gate_string_ends_with_str(&drive, ":\\"))
5328 {
5329 ret = GATE_RESULT_INVALIDARG;
5330 break;
5331 }
5332
5333 /* it is a shell path: */
5334 fspath[0] = 'f';
5335 fspath[1] = 's';
5336 fspath[2] = (wchar_t)dirpath->str[2];
5337 fspath[3] = ':';
5338 fspath[4] = 0;
5339
5340 ret = gate_platform_efi_shell_get_volume_from_path(fspath, &volume_handle);
5341 GATE_BREAK_IF_FAILED(ret);
5342
5343 ret = gate_platform_efi_resolve_volume(volume_handle, NULL);
5344 if (GATE_FAILED(ret))
5345 {
5346 ret = update_all_volumes();
5347 GATE_BREAK_IF_FAILED(ret);
5348 ret = gate_platform_efi_resolve_volume(volume_handle, NULL);
5349 GATE_BREAK_IF_FAILED(ret);
5350 }
5351
5352 ret = gate_platform_efi_open_volume_device(volume_handle, ptr_volume_root);
5353 GATE_BREAK_IF_FAILED(ret);
5354
5355 gate_string_substr(subpath, dirpath, 5, GATE_STR_NPOS);
5356 }
5357 else
5358 {
5359 /* check for GATE- or DOS- style drive letters: */
5360 char letter;
5361 int volume_id = 0;
5362 void* volume_handle = NULL;
5363
5364 gate_string_substr(&drive, dirpath, 0, 3);
5365 if (!gate_string_ends_with_str(&drive, ":\\"))
5366 {
5367 ret = GATE_RESULT_INVALIDARG;
5368 break;
5369 }
5370 letter = gate_string_char_at(&drive, 0);
5371 if ((letter >= 'A') && (letter <= 'Z'))
5372 {
5373 volume_id = letter - 'A' + 1;
5374 }
5375 else if ((letter >= 'a') && (letter <= 'z'))
5376 {
5377 volume_id = letter - 'a' + 1;
5378 }
5379 else
5380 {
5381 ret = GATE_RESULT_INVALIDARG;
5382 break;
5383 }
5384
5385 ret = gate_platform_efi_get_volume(volume_id, &volume_handle);
5386 if (GATE_FAILED(ret))
5387 {
5388 ret = update_all_volumes();
5389 GATE_BREAK_IF_FAILED(ret);
5390 ret = gate_platform_efi_get_volume(volume_id, &volume_handle);
5391 }
5392 if (GATE_FAILED(ret))
5393 {
5394 ret = GATE_RESULT_NOMATCH;
5395 break;
5396 }
5397
5398 ret = gate_platform_efi_open_volume_device(volume_handle, ptr_volume_root);
5399 GATE_BREAK_IF_FAILED(ret);
5400
5401 gate_string_substr(subpath, dirpath, 3, GATE_STR_NPOS);
5402 }
5403 /* code */
5404 } while (0);
5405
5406 gate_string_release(&drive);
5407
5408 return ret;
5409 }
5410
5411
5412 gate_result_t open_volume_file(gate_string_t const* filepath, gate_enumint_t efi_open_type, void** ptr_file_handle)
5413 {
5414 gate_result_t ret;
5415 void* volume_root = NULL;
5416 void* file_handle = NULL;
5417 gate_string_t subpath = GATE_STRING_INIT_EMPTY;
5418 do
5419 {
5420 ret = open_volume_root(filepath, &volume_root, &subpath);
5421 GATE_BREAK_IF_FAILED(ret);
5422
5423 if (gate_string_is_empty(&subpath))
5424 {
5425 /* open root path itself */
5426 if (ptr_file_handle)
5427 {
5428 *ptr_file_handle = volume_root;
5429 volume_root = NULL;
5430 }
5431 }
5432 else
5433 {
5434 wchar_t native_path[GATE_MAX_FILEPATH_LENGTH];
5435 gate_str_utf8_2_utf16(gate_string_ptr(&subpath, 0), gate_string_length(&subpath),
5436 native_path, sizeof(native_path) / sizeof(native_path[0]));
5437
5438 ret = gate_platform_efi_open_file(volume_root, native_path, GATE_PLATFORM_EFI_OPEN_READ, &file_handle);
5439 GATE_BREAK_IF_FAILED(ret);
5440
5441 if (ptr_file_handle)
5442 {
5443 *ptr_file_handle = file_handle;
5444 file_handle = NULL;
5445 }
5446 }
5447
5448 } while (0);
5449
5450 if (file_handle != NULL)
5451 {
5452 gate_platform_efi_close_file(file_handle);
5453 }
5454 if (volume_root != NULL)
5455 {
5456 gate_platform_efi_close_file(volume_root);
5457 }
5458 gate_string_release(&subpath);
5459
5460 return ret;
5461 }
5462
5463 gate_result_t gate_file_exists(gate_string_t const* filepath)
5464 {
5465 return open_volume_file(filepath, GATE_PLATFORM_EFI_OPEN_READ, NULL);
5466 }
5467 gate_result_t gate_file_copy(gate_string_t const* srcfilepath, gate_string_t const* dstfilepath, gate_enumint_t flags)
5468 {
5469 return gate_file_copy_internal(srcfilepath, dstfilepath, flags);
5470 }
5471 gate_result_t gate_file_move(gate_string_t const* srcfilepath, gate_string_t const* dstfilepath)
5472 {
5473 return gate_file_move_internal(srcfilepath, dstfilepath);
5474 }
5475 gate_result_t gate_file_delete(gate_string_t const* filepath)
5476 {
5477 void* file_handle = NULL;
5478 gate_result_t ret = open_volume_file(filepath, GATE_PLATFORM_EFI_OPEN_READ, &file_handle);
5479 if (GATE_SUCCEEDED(ret))
5480 {
5481 ret = gate_platform_efi_delete_file(file_handle);
5482 gate_platform_efi_close_file(file_handle);
5483 }
5484 return ret;
5485 }
5486 gate_result_t gate_file_real_path(gate_string_t const* relativepath, gate_string_t* absolutepath)
5487 {
5488 return GATE_RESULT_NOTSUPPORTED;
5489 }
5490 gate_result_t gate_file_create_link(gate_string_t const* targetpath, gate_string_t const* linkfile)
5491 {
5492 return GATE_RESULT_NOTSUPPORTED;
5493 }
5494 gate_result_t gate_file_read_link(gate_string_t const* filepath, gate_string_t* realpath)
5495 {
5496 return GATE_RESULT_NOTSUPPORTED;
5497 }
5498 gate_result_t gate_file_create_hardlink(gate_string_t const* targetfile, gate_string_t const* linkfile)
5499 {
5500 return GATE_RESULT_NOTSUPPORTED;
5501 }
5502 gate_result_t gate_file_get_attributes(gate_string_t const* targetpath, gate_enumint_t* attribs, gate_enumint_t* access_bits)
5503 {
5504 return GATE_RESULT_NOTSUPPORTED;
5505 }
5506 gate_result_t gate_file_set_attributes(gate_string_t const* targetpath,
5507 gate_enumint_t attribs, gate_enumint_t attribs_mask,
5508 gate_enumint_t access, gate_enumint_t access_mask)
5509 {
5510 return GATE_RESULT_NOTSUPPORTED;
5511 }
5512
5513 gate_result_t gate_file_get_times(gate_string_t const* targetpath, gate_timestamp_t* modified, gate_timestamp_t* accessed, gate_timestamp_t* created)
5514 {
5515 return GATE_RESULT_NOTSUPPORTED;
5516 }
5517 gate_result_t gate_file_set_times(gate_string_t const* targetpath, gate_timestamp_t const* modified, gate_timestamp_t const* accessed, gate_timestamp_t const* created)
5518 {
5519 return GATE_RESULT_NOTSUPPORTED;
5520 }
5521 gate_result_t gate_file_get_size(gate_string_t const* targetfile, gate_int64_t* filesize)
5522 {
5523 return GATE_RESULT_NOTSUPPORTED;
5524 }
5525 gate_result_t gate_file_get_owner(gate_string_t const* targetfile,
5526 gate_uint32_t* owner_id, gate_string_t* owner_name)
5527 {
5528 return GATE_RESULT_NOTSUPPORTED;
5529 }
5530
5531 gate_result_t gate_file_open(gate_string_t const* filepath, gate_enumint_t flags, gate_file_t* filehandle)
5532 {
5533 gate_result_t ret = GATE_RESULT_FAILED;
5534 int efi_open_flags = 0;
5535 void* efi_handle = NULL;
5536 gate_enumint_t attribs = 0;
5537
5538 do
5539 {
5540 if (GATE_FLAG_ENABLED(flags, GATE_STREAM_OPEN_READ))
5541 {
5542 efi_open_flags |= GATE_PLATFORM_EFI_OPEN_READ;
5543 }
5544 if (GATE_FLAG_ENABLED(flags, GATE_STREAM_OPEN_WRITE))
5545 {
5546 efi_open_flags |= GATE_PLATFORM_EFI_OPEN_WRITE;
5547 }
5548
5549 ret = open_volume_file(filepath, efi_open_flags, &efi_handle);
5550 GATE_BREAK_IF_FAILED(ret);
5551
5552 ret = gate_platform_efi_get_file_info(efi_handle,
5553 NULL, NULL, NULL,
5554 &attribs,
5555 NULL, NULL, NULL);
5556
5557 GATE_BREAK_IF_FAILED(ret);
5558
5559 if (GATE_FLAG_ENABLED(attribs, GATE_PLATFORM_EFI_FILEATTR_DIRECTORY))
5560 {
5561 /* directories cannot be opened as a file! */
5562 ret = GATE_RESULT_INVALIDSTATE;
5563 break;
5564 }
5565
5566 /* success case */
5567 ret = GATE_RESULT_OK;
5568 if (filehandle)
5569 {
5570 *filehandle = efi_handle;
5571 efi_handle = NULL;
5572 }
5573 } while (0);
5574
5575 if (efi_handle != NULL)
5576 {
5577 gate_platform_efi_close_file(efi_handle);
5578 }
5579
5580 return ret;
5581 }
5582 gate_result_t gate_file_read(gate_file_t filehandle, char* buffer, gate_size_t bufferlength, gate_size_t* bufferused)
5583 {
5584 gate_result_t ret = GATE_RESULT_FAILED;
5585 do
5586 {
5587 if (!filehandle)
5588 {
5589 ret = GATE_RESULT_INVALIDARG;
5590 break;
5591 }
5592 if ((bufferlength != 0) && (buffer == NULL))
5593 {
5594 ret = GATE_RESULT_INVALIDARG;
5595 break;
5596 }
5597 ret = gate_platform_efi_read_file(filehandle, (char*)buffer, bufferlength, bufferused);
5598 } while (0);
5599 return ret;
5600 }
5601 gate_result_t gate_file_write(gate_file_t filehandle, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
5602 {
5603 gate_result_t ret = GATE_RESULT_FAILED;
5604 do
5605 {
5606 if (!filehandle)
5607 {
5608 ret = GATE_RESULT_INVALIDARG;
5609 break;
5610 }
5611 if ((bufferlength != 0) && (buffer == NULL))
5612 {
5613 ret = GATE_RESULT_INVALIDARG;
5614 break;
5615 }
5616 ret = gate_platform_efi_read_file(filehandle, (char*)buffer, bufferlength, written);
5617 } while (0);
5618 return ret;
5619 }
5620 gate_result_t gate_file_flush(gate_file_t filehandle)
5621 {
5622 return gate_platform_efi_flush_file(filehandle);
5623 }
5624 gate_result_t gate_file_close(gate_file_t filehandle)
5625 {
5626 if (filehandle)
5627 {
5628 gate_platform_efi_close_file(filehandle);
5629 return GATE_RESULT_OK;
5630 }
5631 else
5632 {
5633 return GATE_RESULT_INVALIDARG;
5634 }
5635 }
5636 gate_result_t gate_file_seek(gate_file_t filehandle, gate_int64_t position, gate_enumint_t origin, gate_int64_t* newposition)
5637 {
5638 gate_result_t result = GATE_RESULT_OK;
5639 gate_int64_t target_pos = 0;
5640
5641 switch (origin)
5642 {
5643 case GATE_FILE_SEEK_ORIGIN_BEGIN:
5644 {
5645 target_pos = position;
5646 break;
5647 }
5648 case GATE_FILE_SEEK_ORIGIN_CURPOS:
5649 {
5650 result = gate_platform_efi_get_file_position(filehandle, &target_pos);
5651 target_pos += position;
5652 break;
5653 }
5654 case GATE_FILE_SEEK_ORIGIN_END:
5655 {
5656 result = gate_file_size(filehandle, &target_pos);
5657 target_pos += position;
5658 break;
5659 }
5660 default:
5661 {
5662 result = GATE_RESULT_INVALIDARG;
5663 break;
5664 }
5665 }
5666
5667 if (GATE_SUCCEEDED(result))
5668 {
5669 result = gate_platform_efi_set_file_position(filehandle, target_pos);
5670 if (newposition)
5671 {
5672 result = gate_platform_efi_get_file_position(filehandle, newposition);
5673 }
5674 }
5675 return result;
5676 }
5677 gate_result_t gate_file_pos(gate_file_t filehandle, gate_int64_t* position)
5678 {
5679 return gate_platform_efi_get_file_position(filehandle, position);
5680 }
5681 gate_result_t gate_file_size(gate_file_t filehandle, gate_int64_t* size)
5682 {
5683 gate_uint64_t sz = 0;
5684 gate_uint64_t f_sz = 0;
5685 gate_result_t ret = gate_platform_efi_get_file_info(filehandle, &sz, &f_sz, NULL, NULL, NULL, NULL, NULL);
5686 if (size) *size = f_sz;
5687 return ret;
5688 }
5689
5690 gate_result_t gate_file_truncate(gate_file_t filehandle)
5691 {
5692 gate_result_t ret = GATE_RESULT_NOTSUPPORTED;
5693 return ret;
5694 }
5695
5696
5697 gate_result_t gate_file_lock(gate_file_t filehandle, gate_bool_t wait)
5698 {
5699 return GATE_RESULT_NOTSUPPORTED;
5700 }
5701 gate_result_t gate_file_unlock(gate_file_t filehandle)
5702 {
5703 return GATE_RESULT_NOTSUPPORTED;
5704 }
5705
5706 gate_result_t gate_file_root_list(gate_file_list_callback_t callback, void* userparam)
5707 {
5708 gate_result_t ret;
5709 gate_size_t ndx;
5710 int volume_ids[26];
5711 gate_size_t volumes_count;
5712 gate_file_entry_t file_entry;
5713
5714 do
5715 {
5716 ret = update_all_volumes();
5717 GATE_BREAK_IF_FAILED(ret);
5718
5719 if (!callback)
5720 {
5721 break;
5722 }
5723
5724 ret = GATE_RESULT_OK;
5725 volumes_count = gate_platform_efi_list_volumes(volume_ids, sizeof(volume_ids) / sizeof(volume_ids[0]));
5726 for (ndx = 0; ndx != volumes_count; ++ndx)
5727 {
5728 int vol_id = volume_ids[ndx];
5729 gate_mem_clear(&file_entry, sizeof(file_entry));
5730 file_entry.path[0] = (char)('@' + vol_id);
5731 file_entry.path[1] = ':';
5732 file_entry.path[2] = '\\';
5733 file_entry.path[3] = 0;
5734
5735 file_entry.name[0] = (char)('@' + vol_id);
5736 file_entry.name[1] = ':';
5737 file_entry.name[2] = 0;
5738
5739 file_entry.props.attribs = GATE_FILEENTRY_ATTRIB_DIRECTORY | GATE_FILEENTRY_ATTRIB_VOLUME;
5740 if (!callback(&file_entry, userparam))
5741 {
5742 break;
5743 }
5744 }
5745 } while (0);
5746 return ret;
5747 }
5748
5749 gate_result_t gate_file_list(gate_string_t const* dirpath, gate_file_list_callback_t callback, void* userparam)
5750 {
5751 gate_result_t ret = GATE_RESULT_FAILED;
5752 void* file_handle = NULL;
5753
5754 do
5755 {
5756 gate_file_entry_t entry;
5757 gate_size_t parent_length;
5758
5759 ret = open_volume_file(dirpath, GATE_PLATFORM_EFI_OPEN_READ, &file_handle);
5760 GATE_BREAK_IF_FAILED(ret);
5761
5762 gate_mem_clear(&entry, sizeof(entry));
5763
5764 parent_length = gate_str_print_text(entry.path, sizeof(entry.path) - 1, gate_string_ptr(dirpath, 0), gate_string_length(dirpath));
5765 if (parent_length == 0)
5766 {
5767 ret = GATE_RESULT_INVALIDDATA;
5768 break;
5769 }
5770 if (entry.path[parent_length - 1] != gate_file_path_separator_char)
5771 {
5772 entry.path[parent_length] = gate_file_path_separator_char;
5773 ++parent_length;
5774 }
5775
5776 while (GATE_SUCCEEDED(ret))
5777 {
5778 wchar_t filename[256];
5779 gate_size_t filename_len = sizeof(filename) / sizeof(filename[0]);
5780 gate_size_t filename_used;
5781 gate_uint64_t filesize = 0;
5782 gate_uint32_t attribs = 0;
5783 gate_int64_t times[3];
5784 gate_bool_t is_readonly;
5785 gate_bool_t is_executable;
5786
5787 ret = gate_platform_efi_read_dir(file_handle,
5788 filename, &filename_len,
5789 NULL, &filesize, NULL,
5790 &attribs,
5791 &times[0],
5792 &times[1],
5793 &times[2]
5794 );
5795 if (ret == GATE_RESULT_ENDOFSTREAM)
5796 {
5797 ret = GATE_RESULT_OK;
5798 break;
5799 }
5800 GATE_BREAK_IF_FAILED(ret);
5801
5802 /* print filename */
5803 filename_used = gate_str_utf16_2_utf8(filename, filename_len, &entry.name[0], sizeof(entry.name));
5804 /* print filename after parent path */
5805 gate_str_print_text(&entry.path[parent_length], sizeof(entry.path) - parent_length, entry.name, filename_used);
5806
5807 entry.props.size = filesize;
5808 entry.props.attribs = 0;
5809 GATE_FLAG_SET(entry.props.attribs, GATE_FILEENTRY_ATTRIB_READONLY, GATE_FLAG_ENABLED(attribs, GATE_PLATFORM_EFI_FILEATTR_READONLY));
5810 GATE_FLAG_SET(entry.props.attribs, GATE_FILEENTRY_ATTRIB_HIDDEN, GATE_FLAG_ENABLED(attribs, GATE_PLATFORM_EFI_FILEATTR_HIDDEN));
5811 GATE_FLAG_SET(entry.props.attribs, GATE_FILEENTRY_ATTRIB_SYSTEM, GATE_FLAG_ENABLED(attribs, GATE_PLATFORM_EFI_FILEATTR_SYSTEM));
5812 GATE_FLAG_SET(entry.props.attribs, GATE_FILEENTRY_ATTRIB_ARCHIVE, GATE_FLAG_ENABLED(attribs, GATE_PLATFORM_EFI_FILEATTR_ARCHIVE));
5813 GATE_FLAG_SET(entry.props.attribs, GATE_FILEENTRY_ATTRIB_DIRECTORY, GATE_FLAG_ENABLED(attribs, GATE_PLATFORM_EFI_FILEATTR_DIRECTORY));
5814
5815 is_readonly = GATE_FLAG_ENABLED(attribs, GATE_PLATFORM_EFI_FILEATTR_READONLY);
5816 is_executable = gate_str_ends_with_ic(entry.name, filename_used, ".efi", 4);
5817
5818 entry.props.access = GATE_FILEENTRY_ACCESS_OWNERREAD
5819 | GATE_FILEENTRY_ACCESS_GROUPREAD
5820 | GATE_FILEENTRY_ACCESS_ALLREAD
5821 ;
5822
5823 if (!is_readonly)
5824 {
5825 entry.props.access |= GATE_FILEENTRY_ACCESS_OWNERWRITE
5826 | GATE_FILEENTRY_ACCESS_GROUPWRITE
5827 | GATE_FILEENTRY_ACCESS_ALLWRITE
5828 ;
5829 }
5830
5831 if (is_executable)
5832 {
5833 entry.props.access |= GATE_FILEENTRY_ACCESS_OWNEREXECUTE
5834 | GATE_FILEENTRY_ACCESS_GROUPEXECUTE
5835 | GATE_FILEENTRY_ACCESS_ALLEXECUTE
5836 ;
5837 }
5838
5839 gate_time_from_unix(times[0] / 1000, &entry.props.time_created);
5840 gate_time_from_unix(times[1] / 1000, &entry.props.time_accessed);
5841 gate_time_from_unix(times[2] / 1000, &entry.props.time_modified);
5842
5843 if (callback)
5844 {
5845 const gate_bool_t continue_iteration = callback(&entry, userparam);
5846 if (!continue_iteration)
5847 {
5848 break;
5849 }
5850 }
5851 }
5852 } while (0);
5853
5854 if (file_handle != NULL)
5855 {
5856 gate_platform_efi_close_file(file_handle);
5857 }
5858
5859 return ret;
5860
5861 return GATE_RESULT_NOTSUPPORTED;
5862 }
5863 gate_result_t gate_file_get_entry(gate_string_t const* filepath, gate_file_entry_t* ptrtonewentry)
5864 {
5865 return GATE_RESULT_NOTSUPPORTED;
5866 }
5867 gate_result_t gate_file_dir_create(gate_string_t const* dirpath, gate_enumint_t flags)
5868 {
5869 return GATE_RESULT_NOTSUPPORTED;
5870 }
5871 gate_result_t gate_file_dir_delete(gate_string_t const* dirpath)
5872 {
5873 return GATE_RESULT_NOTSUPPORTED;
5874 }
5875 gate_result_t gate_file_dir_exists(gate_string_t const* dirpath)
5876 {
5877 return GATE_RESULT_NOTSUPPORTED;
5878 }
5879 gate_result_t gate_file_dir_open(gate_string_t const* dirpath, gate_file_dirreader_t* dirhandle)
5880 {
5881 return GATE_RESULT_NOTSUPPORTED;
5882 }
5883 gate_size_t gate_file_dir_read(gate_file_dirreader_t* dirhandle, char* path, gate_size_t pathlen, gate_bool_t filename_only)
5884 {
5885 return GATE_RESULT_NOTSUPPORTED;
5886 }
5887 gate_result_t gate_file_dir_close(gate_file_dirreader_t* dirhandle)
5888 {
5889 return GATE_RESULT_NOTSUPPORTED;
5890 }
5891
5892 #endif /* GATE_CORE_FILES_EFI_IMPL */
5893
5894
5895 #if defined(GATE_CORE_FILES_WASM_IMPL)
5896
5897 #include <emscripten.h>
5898 #include "gate/strings.h"
5899 #include "gate/platform/wasm/wasm_gate.h"
5900
5901
5902 char const gate_file_path_separator_char = '/';
5903
5904 char const* const gate_file_path_separator = "/";
5905
5906 gate_result_t gate_file_exists(gate_string_t const* filepath)
5907 {
5908 return GATE_RESULT_NOTSUPPORTED;
5909 }
5910 gate_result_t gate_file_copy(gate_string_t const* srcfilepath, gate_string_t const* dstfilepath, gate_enumint_t flags)
5911 {
5912 return gate_file_copy_internal(srcfilepath, dstfilepath, flags);
5913 }
5914 gate_result_t gate_file_move(gate_string_t const* srcfilepath, gate_string_t const* dstfilepath)
5915 {
5916 return gate_file_move_internal(srcfilepath, dstfilepath);
5917 }
5918 gate_result_t gate_file_delete(gate_string_t const* filepath)
5919 {
5920 return GATE_RESULT_NOTSUPPORTED;
5921 }
5922 gate_result_t gate_file_real_path(gate_string_t const* relativepath, gate_string_t* absolutepath)
5923 {
5924 return GATE_RESULT_NOTSUPPORTED;
5925 }
5926 gate_result_t gate_file_create_link(gate_string_t const* targetpath, gate_string_t const* linkfile)
5927 {
5928 return GATE_RESULT_NOTSUPPORTED;
5929 }
5930 gate_result_t gate_file_read_link(gate_string_t const* filepath, gate_string_t* realpath)
5931 {
5932 return GATE_RESULT_NOTSUPPORTED;
5933 }
5934 gate_result_t gate_file_create_hardlink(gate_string_t const* targetfile, gate_string_t const* linkfile)
5935 {
5936 return GATE_RESULT_NOTSUPPORTED;
5937 }
5938 gate_result_t gate_file_get_attributes(gate_string_t const* targetpath, gate_enumint_t* attribs, gate_enumint_t* access_bits)
5939 {
5940 return GATE_RESULT_NOTSUPPORTED;
5941
5942 }
5943 gate_result_t gate_file_set_attributes(gate_string_t const* targetpath,
5944 gate_enumint_t attribs, gate_enumint_t attribs_mask,
5945 gate_enumint_t access_bits, gate_enumint_t access_mask)
5946 {
5947 return GATE_RESULT_NOTSUPPORTED;
5948 }
5949 gate_result_t gate_file_get_times(gate_string_t const* targetpath, gate_timestamp_t* modified, gate_timestamp_t* accessed, gate_timestamp_t* created)
5950 {
5951 return GATE_RESULT_NOTSUPPORTED;
5952 }
5953 gate_result_t gate_file_set_times(gate_string_t const* targetpath, gate_timestamp_t const* modified, gate_timestamp_t const* accessed, gate_timestamp_t const* created)
5954 {
5955 return GATE_RESULT_NOTSUPPORTED;
5956 }
5957 gate_result_t gate_file_get_size(gate_string_t const* targetfile, gate_int64_t* filesize)
5958 {
5959 return GATE_RESULT_NOTSUPPORTED;
5960 }
5961 gate_result_t gate_file_get_owner(gate_string_t const* targetfile,
5962 gate_uint32_t* owner_id, gate_string_t* owner_name)
5963 {
5964 return GATE_RESULT_NOTSUPPORTED;
5965 }
5966
5967 gate_result_t gate_file_open(gate_string_t const* filepath, gate_enumint_t flags, gate_file_t* filehandle)
5968 {
5969 gate_result_t ret;
5970 gate_cstrbuffer_t buffer = GATE_INIT_EMPTY;
5971
5972 gate_cstrbuffer_create_string(&buffer, filepath, false);
5973 do
5974 {
5975 int fd = gate_wasm_open(gate_cstrbuffer_get(&buffer), flags);
5976 if (fd < 0)
5977 {
5978 ret = GATE_RESULT_FAILED;
5979 break;
5980 }
5981 *filehandle = (gate_file_t)fd;
5982 ret = GATE_RESULT_OK;
5983 } while (0);
5984
5985 gate_cstrbuffer_destroy(&buffer);
5986 return ret;
5987 }
5988 gate_result_t gate_file_read(gate_file_t filehandle, char* buffer, gate_size_t bufferlength, gate_size_t* bufferused)
5989 {
5990 int fd = (int)filehandle;
5991 gate_intptr_t result = gate_wasm_read(fd, buffer, bufferlength);
5992 if (result < 0)
5993 {
5994 return GATE_RESULT_FAILED;
5995 }
5996 else
5997 {
5998 if (bufferused)
5999 {
6000 *bufferused = (gate_size_t)result;
6001 }
6002 return GATE_RESULT_OK;
6003 }
6004 }
6005 gate_result_t gate_file_write(gate_file_t filehandle, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
6006 {
6007 int fd = (int)filehandle;
6008 gate_intptr_t result = gate_wasm_write(fd, buffer, bufferlength);
6009 if (result < 0)
6010 {
6011 return GATE_RESULT_FAILED;
6012 }
6013 else
6014 {
6015 if (written)
6016 {
6017 *written = (gate_size_t)result;
6018 }
6019 return GATE_RESULT_OK;
6020 }
6021 }
6022 gate_result_t gate_file_flush(gate_file_t filehandle)
6023 {
6024 return GATE_RESULT_NOTSUPPORTED;
6025 }
6026 gate_result_t gate_file_close(gate_file_t filehandle)
6027 {
6028 int fd = (int)filehandle;
6029 return gate_wasm_close(fd);
6030 }
6031 gate_result_t gate_file_seek(gate_file_t filehandle, gate_int64_t position, gate_enumint_t origin, gate_int64_t* newposition)
6032 {
6033 int fd = (int)filehandle;
6034 return gate_wasm_seek(fd, position, origin, newposition);
6035 }
6036 gate_result_t gate_file_pos(gate_file_t filehandle, gate_int64_t* position)
6037 {
6038 return GATE_RESULT_NOTSUPPORTED;
6039 }
6040 gate_result_t gate_file_size(gate_file_t filehandle, gate_int64_t* size)
6041 {
6042 return GATE_RESULT_NOTSUPPORTED;
6043 }
6044 gate_result_t gate_file_lock(gate_file_t filehandle, gate_bool_t wait)
6045 {
6046 return GATE_RESULT_NOTSUPPORTED;
6047 }
6048 gate_result_t gate_file_unlock(gate_file_t filehandle)
6049 {
6050 return GATE_RESULT_NOTSUPPORTED;
6051 }
6052 gate_result_t gate_file_root_list(gate_file_list_callback_t callback, void* userparam)
6053 {
6054 return GATE_RESULT_NOTSUPPORTED;
6055 }
6056 gate_result_t gate_file_list(gate_string_t const* dirpath, gate_file_list_callback_t callback, void* userparam)
6057 {
6058 gate_result_t ret;
6059 gate_cstrbuffer8_t buffer;
6060
6061 do
6062 {
6063 gate_string_t filenames[1024];
6064 gate_size_t used, n;
6065 gate_file_entry_t entry;
6066 char const* path_ptr;
6067 gate_size_t path_len;
6068
6069 if (NULL == gate_cstrbuffer_create_string(&buffer, dirpath, false))
6070 {
6071 ret = GATE_RESULT_OUTOFMEMORY;
6072 break;
6073 }
6074
6075 path_ptr = gate_cstrbuffer_get(&buffer);
6076 path_len = gate_cstrbuffer_length(&buffer);
6077
6078 used = gate_wasm_fs_readdir(path_ptr, filenames, sizeof(filenames) / sizeof(filenames[0]));
6079
6080 gate_mem_clear(&entry, sizeof(entry));
6081
6082 path_len = gate_str_print_text(entry.path, sizeof(entry.path) - 2, path_ptr, path_len);
6083 if (entry.path[path_len - 1] != gate_file_path_separator_char)
6084 {
6085 entry.path[path_len] = gate_file_path_separator_char;
6086 ++path_len;
6087 }
6088
6089 for (n = 0; n != used; ++n)
6090 {
6091 char const* name = gate_string_ptr(&filenames[n], 0);
6092 gate_size_t namelen = gate_string_length(&filenames[n]);
6093 gate_str_print_text(entry.name, sizeof(entry.name), name, namelen);
6094 gate_str_print_text(&entry.path[path_len], sizeof(entry.path) - path_len, name, namelen);
6095 entry.props.attribs = GATE_FILEENTRY_ATTRIB_FILE;
6096 entry.props.size = 1;
6097 if (!callback(&entry, userparam))
6098 {
6099 break;
6100 }
6101 }
6102 ret = GATE_RESULT_OK;
6103 for (n = 0; n != used; ++n)
6104 {
6105 gate_string_release(&filenames[n]);
6106 }
6107 } while (0);
6108 return ret;
6109 }
6110 gate_result_t gate_file_get_entry(gate_string_t const* filepath, gate_file_entry_t* ptrtonewentry)
6111 {
6112 return GATE_RESULT_NOTSUPPORTED;
6113 }
6114 gate_result_t gate_file_dir_create(gate_string_t const* dirpath, gate_enumint_t flags)
6115 {
6116 return GATE_RESULT_NOTSUPPORTED;
6117 }
6118 gate_result_t gate_file_dir_delete(gate_string_t const* dirpath)
6119 {
6120 return GATE_RESULT_NOTSUPPORTED;
6121 }
6122 gate_result_t gate_file_dir_exists(gate_string_t const* dirpath)
6123 {
6124 return GATE_RESULT_NOTSUPPORTED;
6125 }
6126 gate_result_t gate_file_dir_open(gate_string_t const* dirpath, gate_file_dirreader_t* dirhandle)
6127 {
6128 return GATE_RESULT_NOTSUPPORTED;
6129 }
6130 gate_size_t gate_file_dir_read(gate_file_dirreader_t* dirhandle, char* path, gate_size_t pathlen, gate_bool_t filename_only)
6131 {
6132 return GATE_RESULT_NOTSUPPORTED;
6133 }
6134 gate_result_t gate_file_dir_close(gate_file_dirreader_t* dirhandle)
6135 {
6136 return GATE_RESULT_NOTSUPPORTED;
6137 }
6138 gate_result_t gate_file_truncate(gate_file_t filehandle)
6139 {
6140 return GATE_RESULT_NOTSUPPORTED;
6141 }
6142
6143
6144 #endif /* GATE_CORE_FILES_WASM_IMPL */
6145
6146
6147
6148
6149 #if defined(GATE_CORE_FILES_NO_IMPL)
6150
6151 char const gate_file_path_separator_char = '/';
6152
6153 char const* const gate_file_path_separator = "/";
6154
6155 gate_result_t gate_file_exists(gate_string_t const* filepath)
6156 {
6157 return GATE_RESULT_NOTSUPPORTED;
6158 }
6159 gate_result_t gate_file_copy(gate_string_t const* srcfilepath, gate_string_t const* dstfilepath, gate_enumint_t flags)
6160 {
6161 return GATE_RESULT_NOTSUPPORTED;
6162 }
6163 gate_result_t gate_file_move(gate_string_t const* srcfilepath, gate_string_t const* dstfilepath)
6164 {
6165 return GATE_RESULT_NOTSUPPORTED;
6166 }
6167 gate_result_t gate_file_delete(gate_string_t const* filepath)
6168 {
6169 return GATE_RESULT_NOTSUPPORTED;
6170 }
6171 gate_result_t gate_file_real_path(gate_string_t const* relativepath, gate_string_t* absolutepath)
6172 {
6173 return GATE_RESULT_NOTSUPPORTED;
6174 }
6175 gate_result_t gate_file_create_link(gate_string_t const* targetpath, gate_string_t const* linkfile)
6176 {
6177 return GATE_RESULT_NOTSUPPORTED;
6178 }
6179 gate_result_t gate_file_read_link(gate_string_t const* filepath, gate_string_t* realpath)
6180 {
6181 return GATE_RESULT_NOTSUPPORTED;
6182 }
6183 gate_result_t gate_file_create_hardlink(gate_string_t const* targetfile, gate_string_t const* linkfile)
6184 {
6185 return GATE_RESULT_NOTSUPPORTED;
6186 }
6187 gate_result_t gate_file_get_attributes(gate_string_t const* targetpath, gate_enumint_t* attribs, gate_enumint_t* access_bits)
6188 {
6189 return GATE_RESULT_NOTSUPPORTED;
6190
6191 }
6192 gate_result_t gate_file_set_attributes(gate_string_t const* targetpath,
6193 gate_enumint_t attribs, gate_enumint_t attribs_mask,
6194 gate_enumint_t access_bits, gate_enumint_t access_mask)
6195 {
6196 return GATE_RESULT_NOTSUPPORTED;
6197 }
6198 gate_result_t gate_file_get_times(gate_string_t const* targetpath, gate_timestamp_t* modified, gate_timestamp_t* accessed, gate_timestamp_t* created)
6199 {
6200 return GATE_RESULT_NOTSUPPORTED;
6201 }
6202 gate_result_t gate_file_set_times(gate_string_t const* targetpath, gate_timestamp_t const* modified, gate_timestamp_t const* accessed, gate_timestamp_t const* created)
6203 {
6204 return GATE_RESULT_NOTSUPPORTED;
6205 }
6206 gate_result_t gate_file_get_size(gate_string_t const* targetfile, gate_int64_t* filesize)
6207 {
6208 return GATE_RESULT_NOTSUPPORTED;
6209 }
6210 gate_result_t gate_file_get_owner(gate_string_t const* targetfile,
6211 gate_uint32_t* owner_id, gate_string_t* owner_name)
6212 {
6213 return GATE_RESULT_NOTSUPPORTED;
6214 }
6215
6216 gate_result_t gate_file_open(gate_string_t const* filepath, gate_enumint_t flags, gate_file_t* filehandle)
6217 {
6218 return GATE_RESULT_NOTSUPPORTED;
6219 }
6220 gate_result_t gate_file_read(gate_file_t filehandle, char* buffer, gate_size_t bufferlength, gate_size_t* bufferused)
6221 {
6222 return GATE_RESULT_NOTSUPPORTED;
6223 }
6224 gate_result_t gate_file_write(gate_file_t filehandle, char const* buffer, gate_size_t bufferlength, gate_size_t* written)
6225 {
6226 return GATE_RESULT_NOTSUPPORTED;
6227 }
6228 gate_result_t gate_file_flush(gate_file_t filehandle)
6229 {
6230 return GATE_RESULT_NOTSUPPORTED;
6231 }
6232 gate_result_t gate_file_close(gate_file_t filehandle)
6233 {
6234 return GATE_RESULT_NOTSUPPORTED;
6235 }
6236 gate_result_t gate_file_seek(gate_file_t filehandle, gate_int64_t position, gate_enumint_t origin, gate_int64_t* newposition)
6237 {
6238 return GATE_RESULT_NOTSUPPORTED;
6239 }
6240 gate_result_t gate_file_pos(gate_file_t filehandle, gate_int64_t* position)
6241 {
6242 return GATE_RESULT_NOTSUPPORTED;
6243 }
6244 gate_result_t gate_file_size(gate_file_t filehandle, gate_int64_t* size)
6245 {
6246 return GATE_RESULT_NOTSUPPORTED;
6247 }
6248 gate_result_t gate_file_lock(gate_file_t filehandle, gate_bool_t wait)
6249 {
6250 return GATE_RESULT_NOTSUPPORTED;
6251 }
6252 gate_result_t gate_file_unlock(gate_file_t filehandle)
6253 {
6254 return GATE_RESULT_NOTSUPPORTED;
6255 }
6256 gate_result_t gate_file_root_list(gate_file_list_callback_t callback, void* userparam)
6257 {
6258 return GATE_RESULT_NOTSUPPORTED;
6259 }
6260 gate_result_t gate_file_list(gate_string_t const* dirpath, gate_file_list_callback_t callback, void* userparam)
6261 {
6262 return GATE_RESULT_NOTSUPPORTED;
6263 }
6264 gate_result_t gate_file_get_entry(gate_string_t const* filepath, gate_file_entry_t* ptrtonewentry)
6265 {
6266 return GATE_RESULT_NOTSUPPORTED;
6267 }
6268 gate_result_t gate_file_dir_create(gate_string_t const* dirpath, gate_enumint_t flags)
6269 {
6270 return GATE_RESULT_NOTSUPPORTED;
6271 }
6272 gate_result_t gate_file_dir_delete(gate_string_t const* dirpath)
6273 {
6274 return GATE_RESULT_NOTSUPPORTED;
6275 }
6276 gate_result_t gate_file_dir_exists(gate_string_t const* dirpath)
6277 {
6278 return GATE_RESULT_NOTSUPPORTED;
6279 }
6280 gate_result_t gate_file_dir_open(gate_string_t const* dirpath, gate_file_dirreader_t* dirhandle)
6281 {
6282 return GATE_RESULT_NOTSUPPORTED;
6283 }
6284 gate_size_t gate_file_dir_read(gate_file_dirreader_t* dirhandle, char* path, gate_size_t pathlen, gate_bool_t filename_only)
6285 {
6286 return GATE_RESULT_NOTSUPPORTED;
6287 }
6288 gate_result_t gate_file_dir_close(gate_file_dirreader_t* dirhandle)
6289 {
6290 return GATE_RESULT_NOTSUPPORTED;
6291 }
6292 gate_result_t gate_file_truncate(gate_file_t filehandle)
6293 {
6294 return GATE_RESULT_NOTSUPPORTED;
6295 }
6296
6297 #endif /* GATE_CORE_FILES_NO_IMPL */
6298
6299