GCC Code Coverage Report


Directory: src/gate/
File: src/gate/files.c
Date: 2026-02-03 22:06:38
Exec Total Coverage
Lines: 672 883 76.1%
Functions: 55 62 88.7%
Branches: 309 600 51.5%

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