1
2 /********************************************************************/
3 /* */
4 /* cmd_rtl.c Directory, file and other system functions. */
5 /* Copyright (C) 1989 - 2016, 2018 - 2021 Thomas Mertes */
6 /* */
7 /* This file is part of the Seed7 Runtime Library. */
8 /* */
9 /* The Seed7 Runtime Library is free software; you can */
10 /* redistribute it and/or modify it under the terms of the GNU */
11 /* Lesser General Public License as published by the Free Software */
12 /* Foundation; either version 2.1 of the License, or (at your */
13 /* option) any later version. */
14 /* */
15 /* The Seed7 Runtime Library is distributed in the hope that it */
16 /* will be useful, but WITHOUT ANY WARRANTY; without even the */
17 /* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR */
18 /* PURPOSE. See the GNU Lesser General Public License for more */
19 /* details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General */
22 /* Public License along with this program; if not, write to the */
23 /* Free Software Foundation, Inc., 51 Franklin Street, */
24 /* Fifth Floor, Boston, MA 02110-1301, USA. */
25 /* */
26 /* Module: Seed7 Runtime Library */
27 /* File: seed7/src/cmd_rtl.c */
28 /* Changes: 1994, 2006, 2009, 2018 - 2021 Thomas Mertes */
29 /* Content: Directory, file and other system functions. */
30 /* */
31 /********************************************************************/
32
33 #define LOG_FUNCTIONS 0
34 #define VERBOSE_EXCEPTIONS 0
35
36 #include "version.h"
37
38 #include "stdlib.h"
39 #include "stdio.h"
40 #include "string.h"
41 #include "limits.h"
42 #include "time.h"
43 #include "sys/types.h"
44 #include "sys/stat.h"
45 #ifdef INCLUDE_SYS_UTIME
46 #include "sys/utime.h"
47 #else
48 #include "utime.h"
49 #endif
50 #ifdef OS_STRI_WCHAR
51 #include "wchar.h"
52 #ifdef OS_WIDE_DIR_INCLUDE_DIR_H
53 #include "dir.h"
54 #endif
55 #ifdef OS_CHMOD_INCLUDE_IO_H
56 #include "io.h"
57 #endif
58 #endif
59 #ifdef DEFINE_SYSTEM_FUNCTION
60 #include "emscripten.h"
61 #endif
62 #include "errno.h"
63
64 #if UNISTD_H_PRESENT
65 #include "unistd.h"
66 #endif
67
68 #if HAS_MMAP
69 #include "sys/mman.h"
70 #endif
71
72 #include "common.h"
73 #include "data_rtl.h"
74 #include "os_decls.h"
75 #include "heaputl.h"
76 #include "striutl.h"
77 #include "level.h"
78 #include "str_rtl.h"
79 #include "chr_rtl.h"
80 #include "int_rtl.h"
81 #include "fil_rtl.h"
82 #include "dir_drv.h"
83 #include "dir_rtl.h"
84 #include "set_rtl.h"
85 #include "tim_rtl.h"
86 #include "arr_rtl.h"
87 #include "tim_drv.h"
88 #include "big_drv.h"
89 #include "cmd_drv.h"
90 #include "stat_drv.h"
91 #include "rtl_err.h"
92
93 #undef EXTERN
94 #define EXTERN
95 #include "cmd_rtl.h"
96
97
98 #define MAX_CSTRI_BUFFER_LEN 40
99
100 #ifndef CALL_C_COMPILER_FROM_SHELL
101 #define CALL_C_COMPILER_FROM_SHELL 0
102 #endif
103 #ifndef CPLUSPLUS_COMPILER
104 #define CPLUSPLUS_COMPILER C_COMPILER
105 #endif
106 #ifndef EXECUTABLE_FILE_EXTENSION
107 #define EXECUTABLE_FILE_EXTENSION ""
108 #endif
109 #ifndef CC_OPT_LINK_TIME_OPTIMIZATION
110 #define CC_OPT_LINK_TIME_OPTIMIZATION ""
111 #endif
112 #ifndef LINKER_OPT_LTO_MANDATORY
113 #define LINKER_OPT_LTO_MANDATORY 0
114 #endif
115 #ifndef CC_OPT_TRAP_OVERFLOW
116 #define CC_OPT_TRAP_OVERFLOW ""
117 #endif
118 #ifndef CC_OPT_VERSION_INFO
119 #define CC_OPT_VERSION_INFO ""
120 #endif
121 #ifndef CC_ENVIRONMENT_INI
122 #define CC_ENVIRONMENT_INI ""
123 #endif
124 #ifndef CC_FLAGS
125 #define CC_FLAGS ""
126 #endif
127 #ifndef LINKER_OPT_DEBUG_INFO
128 #define LINKER_OPT_DEBUG_INFO ""
129 #endif
130 #ifndef LINKER_OPT_NO_DEBUG_INFO
131 #define LINKER_OPT_NO_DEBUG_INFO ""
132 #endif
133 #ifndef LINKER_OPT_OUTPUT_FILE
134 #define LINKER_OPT_OUTPUT_FILE ""
135 #endif
136 #ifndef LINKER_OPT_SPECIAL_LIB
137 #define LINKER_OPT_SPECIAL_LIB ""
138 #endif
139 #ifndef LINKER_FLAGS
140 #define LINKER_FLAGS ""
141 #endif
142 #ifndef LINKED_PROGRAM_EXTENSION
143 #ifdef EXECUTABLE_FILE_EXTENSION
144 #define LINKED_PROGRAM_EXTENSION EXECUTABLE_FILE_EXTENSION
145 #else
146 #define LINKED_PROGRAM_EXTENSION ""
147 #endif
148 #endif
149 #ifndef SPECIAL_LIB
150 #define SPECIAL_LIB ""
151 #endif
152 #ifndef SYSTEM_LIBS
153 #define SYSTEM_LIBS ""
154 #endif
155 #ifndef SYSTEM_MATH_LIBS
156 #define SYSTEM_MATH_LIBS ""
157 #endif
158 #ifndef PIXEL_RED_MASK
159 #define PIXEL_RED_MASK "0"
160 #endif
161 #ifndef PIXEL_GREEN_MASK
162 #define PIXEL_GREEN_MASK "0"
163 #endif
164 #ifndef PIXEL_BLUE_MASK
165 #define PIXEL_BLUE_MASK "0"
166 #endif
167 #ifndef RGB_TO_PIXEL_FLAG_NAME
168 #define RGB_TO_PIXEL_FLAG_NAME ""
169 #endif
170
171
172 #if HAS_BUILTIN_OVERFLOW_OPERATIONS
173 #if INTTYPE_SIZE == INT_SIZE
174 #define BUILTIN_ADD_OVERFLOW "__builtin_sadd_overflow"
175 #define BUILTIN_SUB_OVERFLOW "__builtin_ssub_overflow"
176 #define BUILTIN_MULT_OVERFLOW "__builtin_smul_overflow"
177 #elif INTTYPE_SIZE == LONG_SIZE
178 #define BUILTIN_ADD_OVERFLOW "__builtin_saddl_overflow"
179 #define BUILTIN_SUB_OVERFLOW "__builtin_ssubl_overflow"
180 #define BUILTIN_MULT_OVERFLOW "__builtin_smull_overflow"
181 #elif defined(LONG_LONG_SIZE) && INTTYPE_SIZE == LONG_LONG_SIZE
182 #define BUILTIN_ADD_OVERFLOW "__builtin_saddll_overflow"
183 #define BUILTIN_SUB_OVERFLOW "__builtin_ssubll_overflow"
184 #define BUILTIN_MULT_OVERFLOW "__builtin_smulll_overflow"
185 #endif
186 #else
187 #define BUILTIN_ADD_OVERFLOW ""
188 #define BUILTIN_SUB_OVERFLOW ""
189 #define BUILTIN_MULT_OVERFLOW ""
190 #endif
191
192
193 #ifndef INT64TYPE
194 #define INT64TYPE_STRI ""
195 #define UINT64TYPE_STRI ""
196 #undef INT32TYPE_LITERAL_SUFFIX
197 #define INT32TYPE_LITERAL_SUFFIX ""
198 #define INT64TYPE_LITERAL_SUFFIX ""
199 #endif
200
201 #ifndef INT128TYPE
202 #define INT128TYPE_STRI ""
203 #define UINT128TYPE_STRI ""
204 #endif
205
206 #ifndef PATH_MAX
207 #define PATH_MAX 2048
208 #endif
209
210 #define CLASSIC_WINDOWS_MAX_PATH 260
211
212 #define SIZE_NORMAL_BUFFER 32768
213 #define SIZE_RESERVE_BUFFER 2048
214
215 #define PRESERVE_NOTHING 0x00
216 #define PRESERVE_MODE 0x01
217 #define PRESERVE_OWNERSHIP 0x02
218 #define PRESERVE_TIMESTAMPS 0x04
219 #define PRESERVE_SYMLINKS 0x08
220 #define PRESERVE_ALL 0xFF
221
222 #define USR_BITS_NORMAL (S_IRUSR == 0400 && S_IWUSR == 0200 && S_IXUSR == 0100)
223 #define GRP_BITS_NORMAL (S_IRGRP == 0040 && S_IWGRP == 0020 && S_IXGRP == 0010)
224 #define OTH_BITS_NORMAL (S_IROTH == 0004 && S_IWOTH == 0002 && S_IXOTH == 0001)
225 #define MODE_BITS_NORMAL (USR_BITS_NORMAL && GRP_BITS_NORMAL && OTH_BITS_NORMAL)
226
227 #define INITAL_ARRAY_SIZE 256
228 #define ARRAY_SIZE_DELTA 256
229
230 #define CONFIG_VALUE_BUFFER_SIZE 4096
231
232 #if DECLARE_OS_ENVIRON
233 extern os_striType *os_environ;
234 #endif
235
236 static const os_charType path_variable[] = {'P', 'A', 'T', 'H', 0};
237
238
239 #define driveLetterPathWrong(standardPath) \
240 (standardPath->size >= 2 && \
241 (standardPath->mem[standardPath->size - 1] == '/' || \
242 (standardPath->mem[1] == ':' && \
243 ((standardPath->mem[0] >= 'a' && standardPath->mem[0] <= 'z') || \
244 (standardPath->mem[0] >= 'A' && standardPath->mem[0] <= 'Z')))))
245
246 #define standardPathWrong(standardPath) \
247 (standardPath->size >= 2 && \
248 standardPath->mem[standardPath->size - 1] == '/')
249
250
251 #ifdef DETERMINE_OS_PROPERTIES_AT_RUNTIME
252
253 char *nullDevice;
254 unsigned char shellPathDelimiter;
255 boolType shellUsesDriveLetters;
256 #ifdef EMULATE_ENVIRONMENT
257 int (*environmentStrncmp) (const char *s1, const char *s2, size_t n);
258 #endif
259 #define NULL_DEVICE_FOR_SCRIPTS nullDevice
260 #define SHELL_PATH_DELIMITER shellPathDelimiter
261 #define if_pathDelimiterNotSlash(thenPart) if (shellPathDelimiter != '/') thenPart
262 #define pathIsWrong(standardPath) (shellUsesDriveLetters && driveLetterPathWrong(standardPath)) || \
263 (!shellUsesDriveLetters && standardPathWrong(standardPath))
264 #define if_mapAbsoluteShellPathToDriveLetters(cond, thenPart, elsePart) \
265 if (shellUsesDriveLetters && (cond)) thenPart else elsePart
266
267 #else
268
269 #define NULL_DEVICE_FOR_SCRIPTS NULL_DEVICE
270 #define SHELL_PATH_DELIMITER PATH_DELIMITER
271
272 #if PATH_DELIMITER != '/'
273 #define if_pathDelimiterNotSlash(thenPart) thenPart
274 #else
275 #define if_pathDelimiterNotSlash(thenPart)
276 #endif
277
278 #if MAP_ABSOLUTE_PATH_TO_DRIVE_LETTERS
279 #define pathIsWrong(standardPath) driveLetterPathWrong(standardPath)
280 #define if_mapAbsoluteShellPathToDriveLetters(cond, thenPart, elsePart) if (cond) thenPart else elsePart
281 #else
282 #define pathIsWrong(standardPath) standardPathWrong(standardPath)
283 #define if_mapAbsoluteShellPathToDriveLetters(cond, thenPart, elsePart) elsePart
284 #endif
285
286 #endif
287
288
289
290 #ifdef USE_CDECL
cmp_mem(char * strg1,char * strg2)291 static int _cdecl cmp_mem (char *strg1, char *strg2)
292 #else
293 static int cmp_mem (void const *strg1, void const *strg2)
294 #endif
295
296 { /* cmp_mem */
297 return (int) strCompare(
298 ((const_rtlObjectType *) strg1)->value.striValue,
299 ((const_rtlObjectType *) strg2)->value.striValue);
300 } /* cmp_mem */
301
302
303
304 static void remove_any_file (const const_os_striType file_name, errInfoType *);
305 static void copy_any_file (const const_os_striType from_name,
306 const const_os_striType to_name, int, errInfoType *err_info);
307
308
309
remove_dir(const const_os_striType dir_name,errInfoType * err_info)310 static void remove_dir (const const_os_striType dir_name, errInfoType *err_info)
311
312 {
313 os_DIR *directory;
314 os_dirent_struct *current_entry;
315 size_t dir_name_size;
316 size_t dir_path_capacity = 0;
317 os_striType dir_path = NULL;
318 size_t new_size;
319 os_striType resized_path;
320 boolType init_path = TRUE;
321
322 /* remove_dir */
323 logFunction(printf("remove_dir(\"" FMT_S_OS "\")\n", dir_name););
324 if ((directory = os_opendir(dir_name)) == NULL) {
325 logError(printf("remove_dir: os_opendir(\"" FMT_S_OS "\") failed:\n"
326 "errno=%d\nerror: %s\n",
327 dir_name, errno, strerror(errno)););
328 *err_info = FILE_ERROR;
329 } else {
330 do {
331 current_entry = os_readdir(directory);
332 /* printf("$" FMT_U_MEM "$\n", (memSizeType) current_entry);
333 fflush(stdout); */
334 } while (current_entry != NULL && current_entry->d_name[0] == '.' &&
335 (current_entry->d_name[1] == '\0' ||
336 (current_entry->d_name[1] == '.' &&
337 current_entry->d_name[2] == '\0')));
338 dir_name_size = os_stri_strlen(dir_name);
339 while (*err_info == OKAY_NO_ERROR && current_entry != NULL) {
340 /* printf("!" FMT_S_OS "!\n", current_entry->d_name);
341 fflush(stdout); */
342 new_size = dir_name_size + 1 + os_stri_strlen(current_entry->d_name);
343 if (new_size > dir_path_capacity) {
344 resized_path = REALLOC_OS_STRI(dir_path, new_size);
345 if (resized_path != NULL) {
346 dir_path = resized_path;
347 dir_path_capacity = new_size;
348 } else if (dir_path != NULL) {
349 FREE_OS_STRI(dir_path);
350 dir_path = NULL;
351 } /* if */
352 } /* if */
353 if (dir_path != NULL) {
354 if (init_path) {
355 os_stri_strcpy(dir_path, dir_name);
356 os_stri_strcpy(&dir_path[dir_name_size], pathDelimiter);
357 init_path = FALSE;
358 } /* if */
359 os_stri_strcpy(&dir_path[dir_name_size + 1], current_entry->d_name);
360 remove_any_file(dir_path, err_info);
361 } else {
362 *err_info = MEMORY_ERROR;
363 } /* if */
364 do {
365 current_entry = os_readdir(directory);
366 /* printf("$" FMT_U_MEM "$\n", (memSizeType) current_entry);
367 fflush(stdout); */
368 } while (current_entry != NULL && current_entry->d_name[0] == '.' &&
369 (current_entry->d_name[1] == '\0' ||
370 (current_entry->d_name[1] == '.' &&
371 current_entry->d_name[2] == '\0')));
372 } /* while */
373 if (dir_path != NULL) {
374 FREE_OS_STRI(dir_path);
375 } /* if */
376 os_closedir(directory);
377 if (*err_info == OKAY_NO_ERROR) {
378 /* printf("before remove directory <" FMT_S_OS ">\n", dir_name); */
379 if (os_rmdir(dir_name) != 0) {
380 logError(printf("remove_dir: os_rmdir(\"" FMT_S_OS "\") failed:\n"
381 "errno=%d\nerror: %s\n",
382 dir_name, errno, strerror(errno)););
383 *err_info = FILE_ERROR;
384 } /* if */
385 } /* if */
386 } /* if */
387 logFunction(printf("remove_dir(\"" FMT_S_OS "\", %d) -->\n", dir_name, *err_info););
388 } /* remove_dir */
389
390
391
remove_any_file(const const_os_striType file_name,errInfoType * err_info)392 static void remove_any_file (const const_os_striType file_name, errInfoType *err_info)
393
394 {
395 os_stat_struct file_stat;
396
397 /* remove_any_file */
398 logFunction(printf("remove_any_file(\"" FMT_S_OS "\")\n", file_name););
399 if (os_lstat(file_name, &file_stat) != 0) {
400 logError(printf("remove_any_file: os_lstat(" FMT_S_OS ", *) failed:\n"
401 "errno=%d\nerror: %s\n",
402 file_name, errno, strerror(errno)););
403 *err_info = FILE_ERROR;
404 } else {
405 if (S_ISDIR(file_stat.st_mode)) {
406 remove_dir(file_name, err_info);
407 } else {
408 if (os_remove(file_name) != 0) {
409 logError(printf("remove_any_file: os_remove(\"" FMT_S_OS "\") failed:\n"
410 "errno=%d\nerror: %s\n",
411 file_name, errno, strerror(errno)););
412 *err_info = FILE_ERROR;
413 } /* if */
414 } /* if */
415 } /* if */
416 logFunction(printf("remove_any_file(\"" FMT_S_OS "\", %d) -->\n",
417 file_name, *err_info););
418 } /* remove_any_file */
419
420
421
copy_file(const const_os_striType from_name,const const_os_striType to_name,errInfoType * err_info)422 static void copy_file (const const_os_striType from_name,
423 const const_os_striType to_name, errInfoType *err_info)
424
425 {
426 FILE *from_file;
427 FILE *to_file;
428 #if HAS_MMAP
429 int file_no;
430 os_fstat_struct file_stat;
431 memSizeType file_length;
432 ustriType file_content;
433 boolType classic_copy = TRUE;
434 #endif
435 char *normal_buffer;
436 char *buffer;
437 size_t buffer_size;
438 char reserve_buffer[SIZE_RESERVE_BUFFER];
439 size_t bytes_read;
440
441 /* copy_file */
442 logFunction(printf("copy_file(\"" FMT_S_OS "\", \"" FMT_S_OS "\")\n",
443 from_name, to_name););
444 if ((from_file = os_fopen(from_name, os_mode_rb)) != NULL) {
445 if ((to_file = os_fopen(to_name, os_mode_wb)) != NULL) {
446 #if HAS_MMAP
447 file_no = fileno(from_file);
448 if (file_no != -1 && os_fstat(file_no, &file_stat) == 0) {
449 if (file_stat.st_size >= 0 &&
450 (unsigned_os_off_t) file_stat.st_size < MAX_MEMSIZETYPE) {
451 file_length = (memSizeType) file_stat.st_size;
452 if ((file_content = (ustriType) mmap(NULL, file_length,
453 PROT_READ, MAP_PRIVATE, file_no, 0)) != (ustriType) -1) {
454 if (fwrite(file_content, 1, file_length, to_file) != file_length) {
455 logError(printf("copy_file(\"" FMT_S_OS "\", \"" FMT_S_OS "\"): "
456 "fwrite(*, 1, " FMT_U_MEM ", %d) failed:\n"
457 "errno=%d\nerror: %s\n",
458 from_name, to_name, file_length, safe_fileno(to_file),
459 errno, strerror(errno)););
460 *err_info = FILE_ERROR;
461 } /* if */
462 munmap(file_content, file_length);
463 classic_copy = FALSE;
464 } /* if */
465 } /* if */
466 } /* if */
467 if (classic_copy) {
468 #endif
469 if (ALLOC_BYTES(normal_buffer, SIZE_NORMAL_BUFFER)) {
470 buffer = normal_buffer;
471 buffer_size = SIZE_NORMAL_BUFFER;
472 } else {
473 buffer = reserve_buffer;
474 buffer_size = SIZE_RESERVE_BUFFER;
475 } /* if */
476 while (*err_info == OKAY_NO_ERROR && (bytes_read =
477 fread(buffer, 1, buffer_size, from_file)) != 0) {
478 if (fwrite(buffer, 1, bytes_read, to_file) != bytes_read) {
479 logError(printf("copy_file(\"" FMT_S_OS "\", \"" FMT_S_OS "\"): "
480 "fwrite(*, 1, " FMT_U_MEM ", %d) failed:\n"
481 "errno=%d\nerror: %s\n",
482 from_name, to_name, (memSizeType) bytes_read,
483 safe_fileno(to_file), errno, strerror(errno)););
484 *err_info = FILE_ERROR;
485 } /* if */
486 } /* while */
487 if (normal_buffer != NULL) {
488 FREE_BYTES(normal_buffer, SIZE_NORMAL_BUFFER);
489 } /* if */
490 #if HAS_MMAP
491 } /* if */
492 #endif
493 if (fclose(from_file) != 0) {
494 logError(printf("copy_file(\"" FMT_S_OS "\", \"" FMT_S_OS "\"): "
495 "fclose(%d) failed:\n"
496 "errno=%d\nerror: %s\n",
497 from_name, to_name, safe_fileno(from_file),
498 errno, strerror(errno)););
499 *err_info = FILE_ERROR;
500 } /* if */
501 if (fclose(to_file) != 0) {
502 logError(printf("copy_file(\"" FMT_S_OS "\", \"" FMT_S_OS "\"): "
503 "fclose(%d) failed:\n"
504 "errno=%d\nerror: %s\n",
505 from_name, to_name, safe_fileno(to_file),
506 errno, strerror(errno)););
507 *err_info = FILE_ERROR;
508 } /* if */
509 if (unlikely(*err_info != OKAY_NO_ERROR)) {
510 os_remove(to_name);
511 } /* if */
512 } else {
513 logError(printf("copy_file: os_fopen(\"" FMT_S_OS "\", \"" FMT_S_OS "\") failed:\n"
514 "errno=%d\nerror: %s\n",
515 to_name, os_mode_wb, errno, strerror(errno)););
516 fclose(from_file);
517 *err_info = FILE_ERROR;
518 } /* if */
519 } else {
520 logError(printf("copy_file: os_fopen(\"" FMT_S_OS "\", \"" FMT_S_OS "\") failed:\n"
521 "errno=%d\nerror: %s\n",
522 from_name, os_mode_rb, errno, strerror(errno)););
523 *err_info = FILE_ERROR;
524 } /* if */
525 logFunction(printf("copy_file(\"" FMT_S_OS "\", \"" FMT_S_OS "\", %d) -->\n",
526 from_name, to_name, *err_info););
527 } /* copy_file */
528
529
530
copy_dir(const const_os_striType from_name,const const_os_striType to_name,int flags,errInfoType * err_info)531 static void copy_dir (const const_os_striType from_name,
532 const const_os_striType to_name, int flags, errInfoType *err_info)
533
534 {
535 os_DIR *directory;
536 os_dirent_struct *current_entry;
537 size_t from_name_size;
538 size_t to_name_size;
539 size_t d_name_size;
540 size_t from_path_capacity = 0;
541 os_striType from_path = NULL;
542 size_t to_path_capacity = 0;
543 os_striType to_path = NULL;
544 size_t new_size;
545 os_striType resized_path;
546 boolType init_path = TRUE;
547
548 /* copy_dir */
549 logFunction(printf("copy_dir(\"" FMT_S_OS "\", \"" FMT_S_OS "\")\n",
550 from_name, to_name););
551 if ((directory = os_opendir(from_name)) == NULL) {
552 logError(printf("copy_dir: os_opendir(\"" FMT_S_OS "\") failed:\n"
553 "errno=%d\nerror: %s\n",
554 from_name, errno, strerror(errno)););
555 *err_info = FILE_ERROR;
556 } else {
557 if (os_mkdir(to_name, (S_IRWXU | S_IRWXG | S_IRWXO)) != 0) {
558 logError(printf("copy_dir: os_mkdir(\"" FMT_S_OS "\", rwxrwxrwx) failed:\n"
559 "errno=%d\nerror: %s\n",
560 to_name, errno, strerror(errno)););
561 *err_info = FILE_ERROR;
562 } else {
563 do {
564 current_entry = os_readdir(directory);
565 /* printf("$" FMT_U_MEM "$\n", (memSizeType) current_entry);
566 fflush(stdout); */
567 } while (current_entry != NULL && current_entry->d_name[0] == '.' &&
568 (current_entry->d_name[1] == '\0' ||
569 (current_entry->d_name[1] == '.' &&
570 current_entry->d_name[2] == '\0')));
571 from_name_size = os_stri_strlen(from_name);
572 to_name_size = os_stri_strlen(to_name);
573 while (*err_info == OKAY_NO_ERROR && current_entry != NULL) {
574 /* printf("!" FMT_S_OS "!\n", current_entry->d_name);
575 fflush(stdout); */
576 d_name_size = os_stri_strlen(current_entry->d_name);
577 new_size = from_name_size + 1 + d_name_size;
578 if (new_size > from_path_capacity) {
579 resized_path = REALLOC_OS_STRI(from_path, new_size);
580 if (resized_path != NULL) {
581 from_path = resized_path;
582 from_path_capacity = new_size;
583 } else if (from_path != NULL) {
584 FREE_OS_STRI(from_path);
585 from_path = NULL;
586 } /* if */
587 } /* if */
588 new_size = to_name_size + 1 + d_name_size;
589 if (new_size > to_path_capacity) {
590 resized_path = REALLOC_OS_STRI(to_path, new_size);
591 if (resized_path != NULL) {
592 to_path = resized_path;
593 to_path_capacity = new_size;
594 } else if (to_path != NULL) {
595 FREE_OS_STRI(to_path);
596 to_path = NULL;
597 } /* if */
598 } /* if */
599 if (from_path != NULL && to_path != NULL) {
600 if (init_path) {
601 os_stri_strcpy(from_path, from_name);
602 os_stri_strcpy(&from_path[from_name_size], pathDelimiter);
603 os_stri_strcpy(to_path, to_name);
604 os_stri_strcpy(&to_path[to_name_size], pathDelimiter);
605 init_path = FALSE;
606 } /* if */
607 os_stri_strcpy(&from_path[from_name_size + 1], current_entry->d_name);
608 os_stri_strcpy(&to_path[to_name_size + 1], current_entry->d_name);
609 copy_any_file(from_path, to_path, flags, err_info);
610 } else {
611 *err_info = MEMORY_ERROR;
612 } /* if */
613 do {
614 current_entry = os_readdir(directory);
615 /* printf("$" FMT_U_MEM "$\n", (memSizeType) current_entry);
616 fflush(stdout); */
617 } while (current_entry != NULL && current_entry->d_name[0] == '.' &&
618 (current_entry->d_name[1] == '\0' ||
619 (current_entry->d_name[1] == '.' &&
620 current_entry->d_name[2] == '\0')));
621 } /* while */
622 if (unlikely(*err_info != OKAY_NO_ERROR)) {
623 remove_dir(to_name, err_info);
624 } /* if */
625 if (from_path != NULL) {
626 FREE_OS_STRI(from_path);
627 } /* if */
628 if (to_path != NULL) {
629 FREE_OS_STRI(to_path);
630 } /* if */
631 } /* if */
632 os_closedir(directory);
633 } /* if */
634 logFunction(printf("copy_dir(\"" FMT_S_OS "\", \"" FMT_S_OS "\", %d) -->\n",
635 from_name, to_name, *err_info););
636 } /* copy_dir */
637
638
639
copy_any_file(const const_os_striType from_name,const const_os_striType to_name,int flags,errInfoType * err_info)640 static void copy_any_file (const const_os_striType from_name,
641 const const_os_striType to_name, int flags, errInfoType *err_info)
642
643 {
644 os_stat_struct from_stat;
645 int from_stat_result;
646 #if HAS_SYMBOLIC_LINKS
647 os_striType link_destination;
648 ssize_t readlink_result;
649 #endif
650 os_utimbuf_struct to_utime;
651
652 /* copy_any_file */
653 logFunction(printf("copy_any_file(\"" FMT_S_OS "\", \"" FMT_S_OS "\")\n",
654 from_name, to_name););
655 if (flags & PRESERVE_SYMLINKS) {
656 from_stat_result = os_lstat(from_name, &from_stat);
657 } else {
658 from_stat_result = os_stat(from_name, &from_stat);
659 } /* if */
660 if (from_stat_result != 0) {
661 /* Source file does not exist */
662 logError(printf("copy_any_file: os_%sstat(\"" FMT_S_OS "\", *) failed:\n"
663 "errno=%d\nerror: %s\n",
664 flags & PRESERVE_SYMLINKS ? "l" : "",
665 from_name, errno, strerror(errno)););
666 *err_info = FILE_ERROR;
667 } else {
668 if (S_ISLNK(from_stat.st_mode)) {
669 #if HAS_SYMBOLIC_LINKS
670 /* printf("link size=%lu\n", from_stat.st_size); */
671 if (unlikely(from_stat.st_size < 0 ||
672 (unsigned_os_off_t) from_stat.st_size > MAX_OS_STRI_LEN)) {
673 *err_info = RANGE_ERROR;
674 } else {
675 if (unlikely(!os_stri_alloc(link_destination,
676 (memSizeType) from_stat.st_size))) {
677 *err_info = MEMORY_ERROR;
678 } else {
679 readlink_result = readlink(from_name, link_destination,
680 (size_t) from_stat.st_size);
681 if (unlikely(readlink_result != -1)) {
682 link_destination[readlink_result] = '\0';
683 /* printf("readlink_result=%lu\n", readlink_result);
684 printf("link=" FMT_S_OS "\n", link_destination); */
685 if (symlink(link_destination, to_name) != 0) {
686 *err_info = FILE_ERROR;
687 } /* if */
688 } else {
689 *err_info = FILE_ERROR;
690 } /* if */
691 os_stri_free(link_destination);
692 } /* if */
693 } /* if */
694 #else
695 *err_info = FILE_ERROR;
696 #endif
697 } else if (S_ISREG(from_stat.st_mode)) {
698 copy_file(from_name, to_name, err_info);
699 } else if (S_ISDIR(from_stat.st_mode)) {
700 copy_dir(from_name, to_name, flags, err_info);
701 } else if (S_ISFIFO(from_stat.st_mode)) {
702 #if HAS_FIFO_FILES
703 if (mkfifo(to_name, (S_IRWXU | S_IRWXG | S_IRWXO)) != 0) {
704 *err_info = FILE_ERROR;
705 } /* if */
706 #else
707 *err_info = FILE_ERROR;
708 #endif
709 } else {
710 *err_info = FILE_ERROR;
711 } /* if */
712 if (*err_info == OKAY_NO_ERROR && !S_ISLNK(from_stat.st_mode)) {
713 if (flags & PRESERVE_TIMESTAMPS) {
714 to_utime.actime = from_stat.st_atime;
715 to_utime.modtime = from_stat.st_mtime;
716 /* printf("copy_any_file: st_atime=%ld\n", from_stat.st_atime); */
717 /* printf("copy_any_file: st_mtime=%ld\n", from_stat.st_mtime); */
718 os_utime(to_name, &to_utime);
719 } /* if */
720 if (flags & PRESERVE_MODE) {
721 os_chmod(to_name, from_stat.st_mode);
722 } /* if */
723 if (flags & PRESERVE_OWNERSHIP) {
724 os_chown(to_name, from_stat.st_uid, from_stat.st_gid);
725 } /* if */
726 } /* if */
727 } /* if */
728 logFunction(printf("copy_any_file(\"" FMT_S_OS "\", \"" FMT_S_OS "\", %d) -->\n",
729 from_name, to_name, *err_info););
730 } /* copy_any_file */
731
732
733
move_with_copy(const const_os_striType from_name,const const_os_striType to_name,errInfoType * err_info)734 static void move_with_copy (const const_os_striType from_name,
735 const const_os_striType to_name, errInfoType *err_info)
736
737 {
738 os_striType temp_name;
739
740 /* move_with_copy */
741 logFunction(printf("move_with_copy(\"" FMT_S_OS "\", \"" FMT_S_OS "\")\n",
742 from_name, to_name););
743 temp_name = temp_name_in_dir(from_name);
744 if (unlikely(temp_name == NULL)) {
745 *err_info = MEMORY_ERROR;
746 } else {
747 if (os_rename(from_name, temp_name) != 0) {
748 logError(printf("move_with_copy: "
749 "os_rename(\"" FMT_S_OS "\", \"" FMT_S_OS "\") failed:\n"
750 "errno=%d\nerror: %s\n",
751 from_name, temp_name, errno, strerror(errno)););
752 *err_info = FILE_ERROR;
753 } else {
754 copy_any_file(temp_name, to_name, PRESERVE_ALL, err_info);
755 if (*err_info == OKAY_NO_ERROR) {
756 remove_any_file(temp_name, err_info);
757 } else {
758 /* Rename back to the original name. */
759 if (os_rename(temp_name, from_name) != 0) {
760 logError(printf("move_with_copy: "
761 "os_rename(\"" FMT_S_OS "\", \"" FMT_S_OS "\") failed:\n"
762 "errno=%d\nerror: %s\n",
763 temp_name, from_name, errno, strerror(errno)););
764 } /* if */
765 } /* if */
766 } /* if */
767 os_stri_free(temp_name);
768 } /* if */
769 logFunction(printf("move_with_copy(\"" FMT_S_OS "\", \"" FMT_S_OS "\", %d) -->\n",
770 from_name, to_name, *err_info););
771 } /* move_with_copy */
772
773
774
775 #ifdef USE_EACCES_INSTEAD_OF_EXDEV
devices_differ(const const_os_striType from_name,const const_os_striType to_name)776 static boolType devices_differ (const const_os_striType from_name,
777 const const_os_striType to_name)
778
779 {
780 os_stat_struct from_stat;
781 os_stat_struct dir_stat;
782 memSizeType to_name_length;
783 memSizeType pos;
784 memSizeType dir_name_length;
785 os_striType dir_name;
786 boolType differs = TRUE;
787
788 /* devices_differ */
789 if (os_stat(from_name, &from_stat) == 0) {
790 to_name_length = os_stri_strlen(to_name);
791 pos = to_name_length;
792 while (pos > 0 && to_name[pos - 1] != '/' && to_name[pos - 1] != '\\') {
793 pos--;
794 } /* while */
795 if (pos > 0) {
796 dir_name_length = pos;
797 if (likely(os_stri_alloc(dir_name, dir_name_length))) {
798 memcpy(dir_name, to_name, dir_name_length * sizeof(os_charType));
799 dir_name[dir_name_length] = '\0';
800 /* printf("dir_name: " FMT_S_OS "\n", dir_name); */
801 if (os_stat(dir_name, &dir_stat) == 0) {
802 /* printf("from device: %ld, to device: %ld\n",
803 from_stat.st_dev, dir_stat.st_dev); */
804 differs = from_stat.st_dev != dir_stat.st_dev;
805 } /* if */
806 os_stri_free(dir_name);
807 } /* if */
808 } /* if */
809 } /* if */
810 logFunction(printf("devices_differ(" FMT_S_OS ", " FMT_S_OS ") --> %d\n",
811 from_name, to_name, differs););
812 return differs;
813 } /* devices_differ */
814 #endif
815
816
817
move_any_file(const const_os_striType from_name,const const_os_striType to_name,errInfoType * err_info)818 static void move_any_file (const const_os_striType from_name,
819 const const_os_striType to_name, errInfoType *err_info)
820
821 {
822 os_stat_struct to_stat;
823
824 /* move_any_file */
825 logFunction(printf("move_any_file(\"" FMT_S_OS "\", \"" FMT_S_OS "\")\n",
826 from_name, to_name););
827 if (os_stat(to_name, &to_stat) == 0) {
828 logError(printf("move_any_file: "
829 "Destination " FMT_S_OS " exists already.\n",
830 to_name););
831 *err_info = FILE_ERROR;
832 } else {
833 if (os_rename(from_name, to_name) != 0) {
834 switch (errno) {
835 #ifdef EXDEV
836 case EXDEV:
837 /* printf("move_any_file: "
838 "os_rename(\"" FMT_S_OS "\", \"" FMT_S_OS "\") triggers EXDEV\n",
839 from_name, to_name); */
840 move_with_copy(from_name, to_name, err_info);
841 break;
842 #endif
843 #ifdef USE_EACCES_INSTEAD_OF_EXDEV
844 case EACCES:
845 /* printf("move_any_file: "
846 "os_rename(\"" FMT_S_OS "\", \"" FMT_S_OS "\") triggers EACCES\n",
847 from_name, to_name); */
848 if (devices_differ(from_name, to_name)) {
849 move_with_copy(from_name, to_name, err_info);
850 } else {
851 logError(printf("move_any_file: "
852 "os_rename(\"" FMT_S_OS "\", \"" FMT_S_OS "\") failed:\n"
853 "errno=%d\nerror: %s\n",
854 from_name, to_name, EACCES, strerror(EACCES)););
855 } /* if */
856 break;
857 #endif
858 default:
859 logError(printf("move_any_file: "
860 "os_rename(\"" FMT_S_OS "\", \"" FMT_S_OS "\") failed:\n"
861 "errno=%d\nerror: %s\n",
862 from_name, to_name, errno, strerror(errno)););
863 *err_info = FILE_ERROR;
864 break;
865 } /* switch */
866 } /* if */
867 } /* if */
868 logFunction(printf("move_any_file(\"" FMT_S_OS "\", \"" FMT_S_OS "\", %d) -->\n",
869 from_name, to_name, *err_info););
870 } /* move_any_file */
871
872
873
addStriToRtlArray(const striType stri,rtlArrayType work_array,intType used_max_position)874 static rtlArrayType addStriToRtlArray (const striType stri,
875 rtlArrayType work_array, intType used_max_position)
876
877 {
878 rtlArrayType resized_work_array;
879
880 /* addStriToRtlArray */
881 logFunction(printf("addStriToRtlArray(\"%s\", *, " FMT_D ")\n",
882 striAsUnquotedCStri(stri), used_max_position););
883 if (used_max_position >= work_array->max_position) {
884 if (unlikely(work_array->max_position > (intType) (MAX_RTL_ARR_INDEX - ARRAY_SIZE_DELTA) ||
885 (resized_work_array = REALLOC_RTL_ARRAY(work_array,
886 (uintType) work_array->max_position,
887 (uintType) work_array->max_position + ARRAY_SIZE_DELTA)) == NULL)) {
888 FREE_STRI(stri, stri->size);
889 freeRtlStriArray(work_array, used_max_position);
890 work_array = NULL;
891 } else {
892 work_array = resized_work_array;
893 COUNT3_RTL_ARRAY((uintType) work_array->max_position,
894 (uintType) work_array->max_position + ARRAY_SIZE_DELTA);
895 work_array->max_position += ARRAY_SIZE_DELTA;
896 work_array->arr[used_max_position].value.striValue = stri;
897 } /* if */
898 } else {
899 work_array->arr[used_max_position].value.striValue = stri;
900 } /* if */
901 return work_array;
902 } /* addStriToRtlArray */
903
904
905
completeRtlStriArray(rtlArrayType work_array,intType used_max_position)906 static rtlArrayType completeRtlStriArray (rtlArrayType work_array,
907 intType used_max_position)
908
909 {
910 rtlArrayType resized_work_array;
911
912 /* completeRtlStriArray */
913 if (likely(work_array != NULL)) {
914 resized_work_array = REALLOC_RTL_ARRAY(work_array,
915 (uintType) work_array->max_position, (uintType) used_max_position);
916 if (unlikely(resized_work_array == NULL)) {
917 freeRtlStriArray(work_array, used_max_position);
918 work_array = NULL;
919 } else {
920 work_array = resized_work_array;
921 COUNT3_RTL_ARRAY((uintType) work_array->max_position,
922 (uintType) used_max_position);
923 work_array->max_position = used_max_position;
924 } /* if */
925 } /* if */
926 return work_array;
927 } /* completeRtlStriArray */
928
929
930
read_dir(const const_striType dir_name,errInfoType * err_info)931 static rtlArrayType read_dir (const const_striType dir_name, errInfoType *err_info)
932
933 {
934 intType used_max_position;
935 dirType directory;
936 striType nameStri;
937 rtlArrayType dir_array;
938
939 /* read_dir */
940 logFunction(printf("read_dir(\"%s\", *)\n",
941 striAsUnquotedCStri(dir_name)););
942 if (unlikely((directory = dirOpen(dir_name)) == NULL)) {
943 logError(printf("read_dir: dirOpen(\"%s\") failed.\n",
944 striAsUnquotedCStri(dir_name)););
945 dir_array = NULL;
946 *err_info = FILE_ERROR;
947 } else {
948 if (likely(ALLOC_RTL_ARRAY(dir_array, INITAL_ARRAY_SIZE))) {
949 dir_array->min_position = 1;
950 dir_array->max_position = INITAL_ARRAY_SIZE;
951 used_max_position = 0;
952 nameStri = dirRead(directory);
953 if (nameStri != NULL) {
954 do {
955 dir_array = addStriToRtlArray(nameStri, dir_array,
956 used_max_position);
957 used_max_position++;
958 nameStri = dirRead(directory);
959 } while (nameStri != NULL && dir_array != NULL);
960 } /* if */
961 if (unlikely(nameStri != NULL)) {
962 FREE_STRI(nameStri, nameStri->size);
963 } /* if */
964 dir_array = completeRtlStriArray(dir_array, used_max_position);
965 if (unlikely(dir_array == NULL)) {
966 *err_info = MEMORY_ERROR;
967 } /* if */
968 } else {
969 *err_info = MEMORY_ERROR;
970 } /* if */
971 dirClose(directory);
972 } /* if */
973 return dir_array;
974 } /* read_dir */
975
976
977
978 #ifdef os_setenv
setEnvironmentVariable(const const_striType name,const const_striType value,errInfoType * err_info)979 static void setEnvironmentVariable (const const_striType name, const const_striType value,
980 errInfoType *err_info)
981
982 {
983 os_striType env_name;
984 os_striType env_value;
985 int setenv_result;
986 int saved_errno;
987
988 /* setEnvironmentVariable */
989 logFunction(printf("setEnvironmentVariable(\"%s\", ",
990 striAsUnquotedCStri(name));
991 printf("\"%s\", *)\n",
992 striAsUnquotedCStri(value)););
993 env_name = stri_to_os_stri(name, err_info);
994 if (likely(env_name != NULL)) {
995 env_value = stri_to_os_stri(value, err_info);
996 if (likely(env_value != NULL)) {
997 setenv_result = os_setenv(env_name, env_value, 1);
998 saved_errno = errno;
999 os_stri_free(env_value);
1000 if (unlikely(setenv_result != 0)) {
1001 logError(printf("setEnvironmentVariable: "
1002 "os_setenv(\"" FMT_S_OS "\", \"" FMT_S_OS "\") failed:\n"
1003 "errno=%d\nerror: %s\n",
1004 env_name, env_value, saved_errno, strerror(saved_errno)););
1005 if (saved_errno == ENOMEM) {
1006 *err_info = MEMORY_ERROR;
1007 } else {
1008 *err_info = RANGE_ERROR;
1009 } /* if */
1010 } /* if */
1011 } /* if */
1012 /* printf("getenv7(\"%s\"): \"%s\"\n", env_name, os_getenv(env_name)); */
1013 os_stri_free(env_name);
1014 } /* if */
1015 logFunction(printf("setEnvironmentVariable -->\n"););
1016 } /* setEnvironmentVariable */
1017
1018 #else
1019
1020
1021
setEnvironmentVariable(const const_striType name,const const_striType value,errInfoType * err_info)1022 static void setEnvironmentVariable (const const_striType name, const const_striType value,
1023 errInfoType *err_info)
1024
1025 {
1026 memSizeType stri_size;
1027 striType stri;
1028 os_striType env_stri;
1029 int putenv_result;
1030
1031 /* setEnvironmentVariable */
1032 logFunction(printf("setEnvironmentVariable(\"%s\", ",
1033 striAsUnquotedCStri(name));
1034 printf("\"%s\", *)\n",
1035 striAsUnquotedCStri(value)););
1036 if (strChPos(name, (charType) '=') != 0) {
1037 logError(printf("setEnvironmentVariable(\"%s\", ",
1038 striAsUnquotedCStri(name));
1039 printf("\"%s\", *): "
1040 "Name contains '=' (putenv() works with \"name=value\").\n",
1041 striAsUnquotedCStri(value)););
1042 *err_info = RANGE_ERROR;
1043 } else if (unlikely(name->size > MAX_STRI_LEN - value->size - 1)) {
1044 /* Number of bytes does not fit into memSizeType. */
1045 *err_info = MEMORY_ERROR;
1046 } else {
1047 stri_size = name->size + value->size + 1;
1048 if (unlikely(!ALLOC_STRI_SIZE_OK(stri, stri_size))) {
1049 *err_info = MEMORY_ERROR;
1050 } else {
1051 stri->size = stri_size;
1052 memcpy(stri->mem, name->mem,
1053 name->size * sizeof(strElemType));
1054 stri->mem[name->size] = (strElemType) '=';
1055 memcpy(&stri->mem[name->size + 1], value->mem,
1056 value->size * sizeof(strElemType));
1057 env_stri = stri_to_os_stri(stri, err_info);
1058 FREE_STRI(stri, stri->size);
1059 if (likely(env_stri != NULL)) {
1060 putenv_result = os_putenv(env_stri);
1061 if (unlikely(putenv_result != 0)) {
1062 logError(printf("setEnvironmentVariable: os_putenv(\"" FMT_S_OS "\") failed:\n"
1063 "errno=%d\nerror: %s\n",
1064 env_stri, errno, strerror(errno)););
1065 *err_info = RANGE_ERROR;
1066 } /* if */
1067 #if DELETE_PUTENV_ARGUMENT
1068 os_stri_free(env_stri);
1069 #endif
1070 } /* if */
1071 } /* if */
1072 } /* if */
1073 logFunction(printf("setEnvironmentVariable -->\n"););
1074 } /* setEnvironmentVariable */
1075
1076 #endif
1077
1078
1079
1080 #if SEARCH_PATH_DELIMITER != 0
1081 #define getSearchPathDelimiter(path) SEARCH_PATH_DELIMITER
1082 #else
1083
1084
1085
getSearchPathDelimiter(os_striType path)1086 static os_charType getSearchPathDelimiter (os_striType path)
1087
1088 {
1089 static os_charType searchPathDelimiter = 0;
1090 boolType colonFound = FALSE;
1091
1092 /* getSearchPathDelimiter */
1093 if (searchPathDelimiter == 0) {
1094 if (SEARCH_PATH_DELIMITER != 0) {
1095 searchPathDelimiter = SEARCH_PATH_DELIMITER;
1096 } else if (path != NULL) {
1097 /* Try to guess the search path delimiter. */
1098 if (((path[0] >= 'a' && path[0] <= 'z') ||
1099 (path[0] >= 'A' && path[0] <= 'Z')) && path[1] == ':') {
1100 searchPathDelimiter = ';';
1101 } else {
1102 while (*path != '\0' && searchPathDelimiter == 0) {
1103 if (*path == ';' &&
1104 ((path[1] >= 'a' && path[1] <= 'z') ||
1105 (path[1] >= 'A' && path[1] <= 'Z')) && path[2] == ':') {
1106 searchPathDelimiter = ';';
1107 } else if (*path == ':') {
1108 colonFound = TRUE;
1109 } /* if */
1110 path++;
1111 } /* while */
1112 if (searchPathDelimiter == 0 && colonFound) {
1113 searchPathDelimiter = ':';
1114 } /* if */
1115 } /* if */
1116 } /* if */
1117 } /* if */
1118 return searchPathDelimiter;
1119 } /* getSearchPathDelimiter */
1120
1121 #endif
1122
1123
1124
getSearchPath(errInfoType * err_info)1125 static rtlArrayType getSearchPath (errInfoType *err_info)
1126
1127 {
1128 os_striType search_path_value;
1129 os_charType searchPathDelimiter;
1130 memSizeType path_length;
1131 os_striType path_copy;
1132 os_striType path_start;
1133 os_striType path_end;
1134 striType pathStri;
1135 intType used_max_position;
1136 rtlArrayType path_array;
1137
1138 /* getSearchPath */
1139 logFunction(printf("getSearchPath(*)\n"););
1140 search_path_value = os_getenv(path_variable);
1141 searchPathDelimiter = getSearchPathDelimiter(search_path_value);
1142 if (unlikely(searchPathDelimiter == 0)) {
1143 logError(printf("getSearchPath(*): "
1144 "Unable to determine the search path delimiter."););
1145 path_array = NULL;
1146 *err_info = FILE_ERROR;
1147 } else if (unlikely(!ALLOC_RTL_ARRAY(path_array, INITAL_ARRAY_SIZE))) {
1148 *err_info = MEMORY_ERROR;
1149 } else {
1150 path_array->min_position = 1;
1151 path_array->max_position = INITAL_ARRAY_SIZE;
1152 used_max_position = 0;
1153 if (search_path_value != NULL) {
1154 /* printf("path: " FMT_S_OS "\n", search_path_value); */
1155 path_length = os_stri_strlen(search_path_value);
1156 if (unlikely(!os_stri_alloc(path_copy, path_length))) {
1157 *err_info = MEMORY_ERROR;
1158 } else {
1159 os_stri_strcpy(path_copy, search_path_value);
1160 path_start = path_copy;
1161 do {
1162 path_end = os_stri_strchr(path_start, searchPathDelimiter);
1163 if (path_end != NULL) {
1164 *path_end = '\0';
1165 } /* if */
1166 pathStri = cp_from_os_path(path_start, err_info);
1167 if (likely(pathStri != NULL)) {
1168 path_array = addStriToRtlArray(pathStri, path_array,
1169 used_max_position);
1170 used_max_position++;
1171 } /* if */
1172 if (path_end == NULL) {
1173 path_start = NULL;
1174 } else {
1175 path_start = path_end + 1;
1176 } /* if */
1177 } while (path_start != NULL && path_array != NULL);
1178 os_stri_free(path_copy);
1179 } /* if */
1180 } /* if */
1181 path_array = completeRtlStriArray(path_array, used_max_position);
1182 if (unlikely(path_array == NULL)) {
1183 *err_info = MEMORY_ERROR;
1184 } /* if */
1185 } /* if */
1186 if (search_path_value != NULL) {
1187 os_getenv_string_free(search_path_value);
1188 } /* if */
1189 logFunction(printf("getSearchPath --> " FMT_U_MEM
1190 " (size=" FMT_U_MEM ", err_info=%d)\n",
1191 (memSizeType) path_array,
1192 path_array != NULL ? arraySize(path_array) : 0,
1193 *err_info););
1194 return path_array;
1195 } /* getSearchPath */
1196
1197
1198
setSearchPath(rtlArrayType searchPath,errInfoType * err_info)1199 static void setSearchPath (rtlArrayType searchPath, errInfoType *err_info)
1200
1201 {
1202 os_charType searchPathDelimiter;
1203 memSizeType numElements;
1204 memSizeType idx;
1205 memSizeType length = 0;
1206 memSizeType pos;
1207 striType pathElement;
1208 striType pathStri;
1209 striType pathVariableName;
1210
1211 /* setSearchPath */
1212 logFunction(printf("setSearchPath(" FMT_U_MEM " (size = " FMT_U_MEM "), *)\n",
1213 (memSizeType) searchPath,
1214 searchPath != NULL ? arraySize(searchPath) : 0););
1215 searchPathDelimiter = getSearchPathDelimiter(NULL);
1216 if (searchPathDelimiter == 0) {
1217 searchPathDelimiter = getSearchPathDelimiter(os_getenv(path_variable));
1218 } /* if */
1219 if (unlikely(searchPathDelimiter == 0)) {
1220 logError(printf("setSearchPath(*): "
1221 "Unable to determine the search path delimiter."););
1222 *err_info = FILE_ERROR;
1223 } else {
1224 numElements = arraySize(searchPath);
1225 if (numElements != 0) {
1226 for (idx = 0; idx < numElements; idx++) {
1227 length += searchPath->arr[idx].value.striValue->size;
1228 } /* for */
1229 length += numElements - 1;
1230 } /* if */
1231 if (!ALLOC_STRI_SIZE_OK(pathStri, length)) {
1232 *err_info = MEMORY_ERROR;
1233 } else {
1234 pathStri->size = length;
1235 if (numElements != 0) {
1236 pathElement = searchPath->arr[0].value.striValue;
1237 memcpy(pathStri->mem, pathElement->mem, pathElement->size * sizeof(strElemType));
1238 pos = pathElement->size;
1239 for (idx = 1; idx < numElements; idx++) {
1240 pathStri->mem[pos] = (charType) searchPathDelimiter;
1241 pos++;
1242 pathElement = searchPath->arr[idx].value.striValue;
1243 memcpy(&pathStri->mem[pos], pathElement->mem,
1244 pathElement->size * sizeof(strElemType));
1245 pos += pathElement->size;
1246 } /* for */
1247 } /* if */
1248 pathVariableName = CSTRI_LITERAL_TO_STRI("PATH");
1249 if (pathVariableName == NULL) {
1250 *err_info = MEMORY_ERROR;
1251 } else {
1252 setEnvironmentVariable(pathVariableName, pathStri, err_info);
1253 FREE_STRI(pathVariableName, pathVariableName->size);
1254 } /* if */
1255 FREE_STRI(pathStri, pathStri->size);
1256 } /* if */
1257 } /* if */
1258 logFunction(printf("setSearchPath --> (err_info=%d)\n",
1259 *err_info););
1260 } /* setSearchPath */
1261
1262
1263
getFileTypeSL(const const_striType filePath,errInfoType * err_info)1264 static intType getFileTypeSL (const const_striType filePath, errInfoType *err_info)
1265
1266 {
1267 os_striType os_path;
1268 os_stat_struct stat_buf;
1269 int stat_result;
1270 int path_info = PATH_IS_NORMAL;
1271 int saved_errno;
1272 intType type_of_file;
1273
1274 /* getFileTypeSL */
1275 logFunction(printf("getFileTypeSL(\"%s\")\n",
1276 striAsUnquotedCStri(filePath)););
1277 os_path = cp_to_os_path(filePath, &path_info, err_info);
1278 if (unlikely(os_path == NULL)) {
1279 #if MAP_ABSOLUTE_PATH_TO_DRIVE_LETTERS
1280 if (path_info == PATH_IS_EMULATED_ROOT) {
1281 type_of_file = FILE_DIR;
1282 } else if (path_info == PATH_NOT_MAPPED) {
1283 type_of_file = FILE_ABSENT;
1284 } else
1285 #endif
1286 {
1287 logError(printf("getFileTypeSL: cp_to_os_path(\"%s\", *, *) failed:\n"
1288 "path_info=%d, err_info=%d\n",
1289 striAsUnquotedCStri(filePath), path_info, *err_info););
1290 type_of_file = FILE_ABSENT;
1291 }
1292 } else {
1293 stat_result = os_lstat(os_path, &stat_buf);
1294 saved_errno = errno;
1295 /* printf("lstat(\"" FMT_S_OS "\") returns: %d, errno=%d\n",
1296 os_path, stat_result, saved_errno); */
1297 if (stat_result == 0) {
1298 if (S_ISREG(stat_buf.st_mode)) {
1299 type_of_file = FILE_REGULAR;
1300 } else if (S_ISDIR(stat_buf.st_mode)) {
1301 type_of_file = FILE_DIR;
1302 } else if (S_ISCHR(stat_buf.st_mode)) {
1303 type_of_file = FILE_CHAR;
1304 } else if (S_ISBLK(stat_buf.st_mode)) {
1305 type_of_file = FILE_BLOCK;
1306 } else if (S_ISFIFO(stat_buf.st_mode)) {
1307 type_of_file = FILE_FIFO;
1308 } else if (S_ISLNK(stat_buf.st_mode)) {
1309 type_of_file = FILE_SYMLINK;
1310 } else if (S_ISSOCK(stat_buf.st_mode)) {
1311 type_of_file = FILE_SOCKET;
1312 } else {
1313 type_of_file = FILE_UNKNOWN;
1314 } /* if */
1315 } else {
1316 type_of_file = FILE_ABSENT;
1317 if (unlikely(filePath->size != 0 && saved_errno != ENOENT &&
1318 saved_errno != ENOTDIR && saved_errno != ENAMETOOLONG &&
1319 saved_errno != EACCES)) {
1320 logError(printf("getFileTypeSL: os_lstat(\"" FMT_S_OS "\") failed:\n"
1321 "errno=%d\nerror: %s\n",
1322 os_path, saved_errno, strerror(saved_errno)););
1323 /* printf("filePath->size=%lu\n", filePath->size); */
1324 /* printf("strlen(os_path)=%d\n", os_stri_strlen(os_path)); */
1325 *err_info = FILE_ERROR;
1326 } /* if */
1327 } /* if */
1328 os_stri_free(os_path);
1329 } /* if */
1330 logFunction(printf("getFileTypeSL(\"%s\") --> " FMT_D " (err_info=%d)\n",
1331 striAsUnquotedCStri(filePath),
1332 type_of_file, *err_info););
1333 return type_of_file;
1334 } /* getFileTypeSL */
1335
1336
1337
1338 #if HAS_READLINK
1339 /**
1340 * Reads the destination of a symbolic link.
1341 * @param err_info Unchanged if the function succeeds, and
1342 * MEMORY_ERROR if a memory allocation failed, and
1343 * RANGE_ERROR if the conversion to the system path failed, and
1344 * FILE_ERROR if the file does not exist or is not a symbolic link.
1345 * @return The destination referred by the symbolic link, or
1346 * NULL if an error occurred.
1347 */
doReadLink(const const_striType filePath,errInfoType * err_info)1348 striType doReadLink (const const_striType filePath, errInfoType *err_info)
1349
1350 {
1351 os_striType os_filePath;
1352 os_stat_struct link_stat;
1353 memSizeType link_size;
1354 os_striType link_destination;
1355 os_charType buffer[PATH_MAX];
1356 ssize_t readlink_result;
1357 int path_info;
1358 striType destination = NULL;
1359
1360 /* doReadLink */
1361 logFunction(printf("doReadLink(\"%s\", %d)\n",
1362 striAsUnquotedCStri(filePath), *err_info););
1363 os_filePath = cp_to_os_path(filePath, &path_info, err_info);
1364 if (unlikely(os_filePath == NULL)) {
1365 logError(printf("cmdReadLink: cp_to_os_path(\"%s\", *, *) failed:\n"
1366 "path_info=%d, err_info=%d\n",
1367 striAsUnquotedCStri(filePath), path_info, *err_info););
1368 } else {
1369 if (unlikely(os_lstat(os_filePath, &link_stat) != 0)) {
1370 logError(printf("cmdReadLink: os_lstat(" FMT_S_OS ", *) failed:\n"
1371 "errno=%d\nerror: %s\n",
1372 os_filePath, errno, strerror(errno)););
1373 *err_info = FILE_ERROR;
1374 } else if (unlikely(!S_ISLNK(link_stat.st_mode))) {
1375 logError(printf("cmdReadLink: "
1376 "The file " FMT_S_OS " is not a symbolic link.\n",
1377 os_filePath););
1378 *err_info = FILE_ERROR;
1379 } else if (unlikely(link_stat.st_size < 0 ||
1380 (unsigned_os_off_t) link_stat.st_size > MAX_OS_STRI_LEN)) {
1381 *err_info = FILE_ERROR;
1382 } else {
1383 link_size = (memSizeType) link_stat.st_size;
1384 /* printf("link size=" FMT_U_MEM "\n", link_size); */
1385 if (link_size < sizeof(buffer)) {
1386 link_size = (memSizeType) sizeof(buffer) - NULL_TERMINATION_LEN;
1387 link_destination = buffer;
1388 } else if (unlikely(!os_stri_alloc(link_destination, link_size))) {
1389 *err_info = MEMORY_ERROR;
1390 } /* if */
1391 if (likely(link_destination != NULL)) {
1392 readlink_result = readlink(os_filePath, link_destination,
1393 (size_t) (link_size + NULL_TERMINATION_LEN));
1394 if (unlikely(readlink_result == -1)) {
1395 logError(printf("cmdReadLink: "
1396 "readlink(\"" FMT_S_OS "\", *, " FMT_U_MEM ") failed:\n"
1397 "errno=%d\nerror: %s\n",
1398 os_filePath, link_size + NULL_TERMINATION_LEN,
1399 errno, strerror(errno)););
1400 *err_info = FILE_ERROR;
1401 } else if (unlikely(readlink_result > link_size)) {
1402 logError(printf("cmdReadLink: "
1403 "readlink(\"" FMT_S_OS "\", *, " FMT_U_MEM ") failed:\n"
1404 "Link destination possibly truncated.\n",
1405 os_filePath, link_size + NULL_TERMINATION_LEN););
1406 *err_info = FILE_ERROR;
1407 } else {
1408 link_destination[readlink_result] = '\0';
1409 destination = cp_from_os_path(link_destination, err_info);
1410 if (unlikely(destination == NULL)) {
1411 logError(printf("cmdReadLink: "
1412 "cp_from_os_path(\"" FMT_S_OS "\", *) failed:\n"
1413 "err_info=%d\n",
1414 link_destination, *err_info););
1415 } /* if */
1416 } /* if */
1417 if (link_destination != buffer) {
1418 os_stri_free(link_destination);
1419 } /* if */
1420 } /* if */
1421 } /* if */
1422 os_stri_free(os_filePath);
1423 } /* if */
1424 logFunction(printf("doReadLink(\"%s\", %d) --> ",
1425 striAsUnquotedCStri(filePath), *err_info);
1426 printf("\"%s\"\n", striAsUnquotedCStri(destination)););
1427 return destination;
1428 } /* doReadLink */
1429 #endif
1430
1431
1432
1433 #if HAS_SYMBOLIC_LINKS
followLink(striType startPath,errInfoType * err_info)1434 striType followLink (striType startPath, errInfoType *err_info)
1435
1436 {
1437 striType helpPath;
1438 int number_of_links_followed = 5;
1439 striType path;
1440
1441 /* followLink */
1442 logFunction(printf("followLink(\"%s\")\n", striAsUnquotedCStri(startPath)););
1443 if (getFileTypeSL(startPath, err_info) == FILE_SYMLINK) {
1444 path = doReadLink(startPath, err_info);
1445 while (path != NULL &&
1446 getFileTypeSL(path, err_info) == FILE_SYMLINK &&
1447 number_of_links_followed != 0) {
1448 helpPath = path;
1449 path = doReadLink(helpPath, err_info);
1450 FREE_STRI(helpPath, helpPath->size);
1451 number_of_links_followed--;
1452 } /* while */
1453 if (path == NULL || number_of_links_followed != 0) {
1454 FREE_STRI(startPath, startPath->size);
1455 } else {
1456 FREE_STRI(path, path->size);
1457 path = startPath;
1458 } /* if */
1459 } else {
1460 path = startPath;
1461 } /* if */
1462 logFunction(printf("followLink --> \"%s\" (err_info=%d)\n",
1463 striAsUnquotedCStri(path), *err_info););
1464 return path;
1465 } /* followLink */
1466 #endif
1467
1468
1469
1470 /**
1471 * Return the absolute path of the current working directory.
1472 * If the size of the provided 'buffer' is not sufficient a buffer
1473 * with sufficient size is allocated. The allocated buffer must be
1474 * freed afterwards with FREE_OS_STRI().
1475 * @param buffer Buffer to be used if its size is sufficient.
1476 * @param buffer_size Size of 'buffer'.
1477 * @param err_info Unchanged if the function succeeds, and
1478 * MEMORY_ERROR if a memory allocation failed, and
1479 * FILE_ERROR if the operating system function failed.
1480 * @return the 'buffer' or an allocated buffer with a null terminated
1481 * operating system string.
1482 */
getOsCwd(const os_striType buffer,memSizeType buffer_size,errInfoType * err_info)1483 static os_striType getOsCwd (const os_striType buffer, memSizeType buffer_size,
1484 errInfoType *err_info)
1485
1486 {
1487 os_striType large_buffer = NULL;
1488 os_striType os_cwd;
1489
1490 /* getOsCwd */
1491 logFunction(printf("getOsCwd(*, " FMT_U_MEM ", *)", buffer_size);
1492 fflush(stdout););
1493 if (unlikely((os_cwd = os_getcwd(buffer, buffer_size)) == NULL)) {
1494 if (errno == ERANGE || errno == ENAMETOOLONG) {
1495 do {
1496 buffer_size *= 2;
1497 FREE_OS_STRI(large_buffer);
1498 #ifdef OS_GETCWD_MAX_BUFFER_SIZE
1499 if (unlikely(buffer_size > OS_GETCWD_MAX_BUFFER_SIZE)) {
1500 large_buffer = NULL;
1501 *err_info = MEMORY_ERROR;
1502 } else
1503 #endif
1504 if (unlikely(!ALLOC_OS_STRI(large_buffer, buffer_size))) {
1505 *err_info = MEMORY_ERROR;
1506 } else {
1507 /* printf("getOsCwd: os_getcwd(*, " FMT_U_MEM ")\n", buffer_size); */
1508 if (unlikely((os_cwd = os_getcwd(large_buffer, buffer_size)) == NULL)) {
1509 if (errno != ERANGE && errno != ENAMETOOLONG) {
1510 logError(printf("getOsCwd: os_getcwd(*, " FMT_U_MEM ") failed:\n"
1511 "errno=%d\nerror: %s\n",
1512 buffer_size, errno, strerror(errno)););
1513 FREE_OS_STRI(large_buffer);
1514 large_buffer = NULL;
1515 *err_info = FILE_ERROR;
1516 } /* if */
1517 } /* if */
1518 } /* if */
1519 } while (os_cwd == NULL && large_buffer != NULL);
1520 } else {
1521 logError(printf("getOsCwd: os_getcwd(*, " FMT_U_MEM ") failed:\n"
1522 "errno=%d\nerror: %s\n",
1523 buffer_size, errno, strerror(errno)););
1524 *err_info = FILE_ERROR;
1525 } /* if */
1526 } /* if */
1527 #ifdef OS_GETCWD_RETURNS_SLASH
1528 {
1529 os_charType *ch;
1530
1531 for (ch = os_cwd; *ch != 0; ch++) {
1532 if (*ch == '/') {
1533 *ch = PATH_DELIMITER;
1534 } /* if */
1535 } /* for */
1536 }
1537 #endif
1538 logFunctionResult(printf("\"" FMT_S_OS "\"\n", os_cwd););
1539 return os_cwd;
1540 } /* getOsCwd */
1541
1542
1543
1544 #if defined USE_EXTENDED_LENGTH_PATH && USE_EXTENDED_LENGTH_PATH
adjustCwdForShell(errInfoType * err_info)1545 void adjustCwdForShell (errInfoType *err_info)
1546
1547 {
1548 struct striStruct stri1_buffer;
1549 striType dotStri;
1550 os_striType os_cwd;
1551 int path_info = PATH_IS_NORMAL;
1552 int chdir_result;
1553
1554 /* adjustCwdForShell */
1555 logFunction(printf("adjustCwdForShell(%d)\n", *err_info););
1556 dotStri = chrStrMacro('.', stri1_buffer);
1557 os_cwd = cp_to_os_path(dotStri, &path_info, err_info);
1558 if (unlikely(os_cwd == NULL)) {
1559 if (likely(path_info == PATH_IS_EMULATED_ROOT)) {
1560 logError(printf("adjustCwdForShell: Current directory is emulated root.\n"););
1561 } else {
1562 logError(printf("adjustCwdForShell: Cannot get current_emulated_cwd.\n"););
1563 } /* if */
1564 } else {
1565 logMessage(printf("adjustCwdForShell: os_chdir(\"" FMT_S_OS "\")\n",
1566 &os_cwd[PREFIX_LEN]););
1567 chdir_result = os_chdir(&os_cwd[PREFIX_LEN]);
1568 if (unlikely(chdir_result != 0)) {
1569 logError(printf("adjustCwdForShell: os_chdir(\"" FMT_S_OS "\") failed:\n"
1570 "errno=%d\nerror: %s\n",
1571 &os_cwd[PREFIX_LEN], errno, strerror(errno)););
1572 *err_info = FILE_ERROR;
1573 } /* if */
1574 os_stri_free(os_cwd);
1575 } /* if */
1576 logFunction(printf("adjustCwdForShell(%d) -->\n", *err_info););
1577 } /* adjustCwdForShell */
1578 #endif
1579
1580
1581
1582 #if EMULATE_ROOT_CWD
initEmulatedCwd(errInfoType * err_info)1583 void initEmulatedCwd (errInfoType *err_info)
1584
1585 {
1586 os_charType buffer[PATH_MAX];
1587 os_striType os_cwd;
1588
1589 /* initEmulatedCwd */
1590 logFunction(printf("initEmulatedCwd(*)\n"););
1591 if ((os_cwd = getOsCwd(buffer, PATH_MAX, err_info)) != NULL) {
1592 setEmulatedCwd(os_cwd, err_info);
1593 if (os_cwd != buffer) {
1594 FREE_OS_STRI(os_cwd);
1595 } /* if */
1596 } /* if */
1597 logFunction(printf("initEmulatedCwd(%d) -->\n", *err_info););
1598 } /* initEmulatedCwd */
1599 #endif
1600
1601
1602
1603 #if defined USE_EXTENDED_LENGTH_PATH && USE_EXTENDED_LENGTH_PATH
1604 /**
1605 * Determine the current working directory of the calling process.
1606 * @param err_info Unchanged if the function succeeds, and
1607 * MEMORY_ERROR if a memory allocation failed, and
1608 * FILE_ERROR if the system function returns an error.
1609 * @return The absolute path of the current working directory, or
1610 * NULL if an error occurred.
1611 */
doGetCwd(errInfoType * err_info)1612 striType doGetCwd (errInfoType *err_info)
1613
1614 {
1615 struct striStruct stri1_buffer;
1616 striType dotStri;
1617 os_striType os_cwd;
1618 int path_info = PATH_IS_NORMAL;
1619 striType cwd;
1620
1621 /* doGetCwd */
1622 logFunction(printf("doGetCwd\n"););
1623 dotStri = chrStrMacro('.', stri1_buffer);
1624 os_cwd = cp_to_os_path(dotStri, &path_info, err_info);
1625 if (unlikely(os_cwd == NULL)) {
1626 #if EMULATE_ROOT_CWD
1627 if (likely(path_info == PATH_IS_EMULATED_ROOT)) {
1628 cwd = cp_from_os_path(current_emulated_cwd, err_info);
1629 if (unlikely(cwd == NULL)) {
1630 logError(printf("doGetCwd: "
1631 "cp_from_os_path(\"" FMT_S_OS "\", *) failed:\n"
1632 "err_info=%d\n",
1633 current_emulated_cwd, *err_info););
1634 } /* if */
1635 } else
1636 #endif
1637 {
1638 logError(printf("doGetCwd: Cannot get current_emulated_cwd.\n"););
1639 cwd = NULL;
1640 }
1641 } else {
1642 cwd = cp_from_os_path(os_cwd, err_info);
1643 if (unlikely(cwd == NULL)) {
1644 logError(printf("doGetCwd: "
1645 "cp_from_os_path(\"" FMT_S_OS "\", *) failed:\n"
1646 "err_info=%d\n",
1647 os_cwd, *err_info););
1648 } /* if */
1649 os_stri_free(os_cwd);
1650 } /* if */
1651 logFunction(printf("doGetCwd --> \"%s\" (err_info=%d)\n",
1652 striAsUnquotedCStri(cwd), *err_info););
1653 return cwd;
1654 } /* doGetCwd */
1655
1656 #else
1657
1658
1659
1660 /**
1661 * Determine the current working directory of the calling process.
1662 * @param err_info Unchanged if the function succeeds, and
1663 * MEMORY_ERROR if a memory allocation failed, and
1664 * FILE_ERROR if the system function returns an error.
1665 * @return The absolute path of the current working directory, or
1666 * NULL if an error occurred.
1667 */
doGetCwd(errInfoType * err_info)1668 striType doGetCwd (errInfoType *err_info)
1669
1670 {
1671 os_charType buffer[PATH_MAX];
1672 os_striType os_cwd;
1673 striType cwd;
1674
1675 /* doGetCwd */
1676 logFunction(printf("doGetCwd\n"););
1677 #if EMULATE_ROOT_CWD
1678 if (IS_EMULATED_ROOT(current_emulated_cwd)) {
1679 cwd = cp_from_os_path(current_emulated_cwd, err_info);
1680 if (unlikely(cwd == NULL)) {
1681 logError(printf("doGetCwd: "
1682 "cp_from_os_path(\"" FMT_S_OS "\", *) failed:\n"
1683 "err_info=%d\n",
1684 current_emulated_cwd, *err_info););
1685 } /* if */
1686 } else
1687 #endif
1688 {
1689 if (unlikely((os_cwd = getOsCwd(buffer, PATH_MAX, err_info)) == NULL)) {
1690 cwd = NULL;
1691 } else {
1692 cwd = cp_from_os_path(os_cwd, err_info);
1693 if (unlikely(cwd == NULL)) {
1694 logError(printf("doGetCwd: "
1695 "cp_from_os_path(\"" FMT_S_OS "\", *) failed:\n"
1696 "err_info=%d\n",
1697 os_cwd, *err_info););
1698 } /* if */
1699 if (os_cwd != buffer) {
1700 FREE_OS_STRI(os_cwd);
1701 } /* if */
1702 } /* if */
1703 }
1704 logFunction(printf("doGetCwd --> \"%s\" (err_info=%d)\n",
1705 striAsUnquotedCStri(cwd), *err_info););
1706 return cwd;
1707 } /* doGetCwd */
1708
1709 #endif
1710
1711
1712
1713 /**
1714 * Get the absolute file path in the standard path representation.
1715 * @return the absolute file path in the standard path
1716 * representation, or NULL if the memory allocation failed.
1717 */
getAbsolutePath(const const_striType aPath)1718 striType getAbsolutePath (const const_striType aPath)
1719
1720 {
1721 striType cwd;
1722 errInfoType err_info = OKAY_NO_ERROR;
1723 striType absolutePath;
1724
1725 /* getAbsolutePath */
1726 logFunction(printf("getAbsolutePath(\"%s\")\n",
1727 striAsUnquotedCStri(aPath)););
1728 if (aPath->size >= 1 &&
1729 aPath->mem[0] == (charType) '/') {
1730 absolutePath = straightenAbsolutePath(aPath);
1731 } else {
1732 cwd = doGetCwd(&err_info);
1733 if (unlikely(cwd == NULL)) {
1734 absolutePath = NULL;
1735 } else {
1736 absolutePath = concatPath(cwd, aPath);
1737 FREE_STRI(cwd, cwd->size);
1738 } /* if */
1739 } /* if */
1740 logFunction(printf("getAbsolutePath --> \"%s\"\n",
1741 striAsUnquotedCStri(absolutePath)););
1742 return absolutePath;
1743 } /* getAbsolutePath */
1744
1745
1746
1747 #ifdef DEFINE_SYSTEM_FUNCTION
systemForNodeJs(const char * command)1748 static int systemForNodeJs (const char *command)
1749
1750 {
1751 int result;
1752
1753 /* systemForNodeJs */
1754 logFunction(printf("systemForNodeJs(\"%s\")\n", command););
1755 result = EM_ASM_INT({
1756 let cmd = Module.UTF8ToString($0);
1757 // console.log('I received: ' + cmd);
1758 if (typeof require === 'function') {
1759 var child_process;
1760 try {
1761 child_process = require('child_process');
1762 } catch (e) {
1763 child_process = null;
1764 }
1765 if (child_process !== null) {
1766 let bslash = String.fromCharCode(92);
1767 let currDir = process.cwd().replace(new RegExp(bslash + bslash, 'g'), '/');
1768 let newDir = FS.cwd();
1769 // console.log('emcc cwd: ' + newDir);
1770 // console.log('node cwd: ' + currDir);
1771 if (currDir.charAt(1) === ':' && currDir.charAt(2) === '/') {
1772 if (newDir !== '/') {
1773 if (newDir.charAt(0) === '/' && newDir.charAt(1).match(/[a-z]/i) && newDir.charAt(2) === '/') {
1774 newDir = newDir.charAt(1) + ':' + newDir.substring(2);
1775 }
1776 }
1777 }
1778 try {
1779 process.chdir(newDir);
1780 } catch (e) {
1781 // console.log('chdir: ' + e);
1782 }
1783 try {
1784 child_process.execSync(cmd);
1785 return 0;
1786 } catch (e) {
1787 return -1;
1788 }
1789 }
1790 }
1791 return -1;
1792 }, command);
1793 return result;
1794 } /* systemForNodeJs */
1795
1796 #ifdef os_system
1797 #undef os_system
1798 #endif
1799 #define os_system(cmd) systemForNodeJs(cmd)
1800 #endif
1801
1802
1803
1804 /**
1805 * Determine the size of a file.
1806 * The file size is measured in bytes.
1807 * For directories, fifos and sockets a size of 0 is returned.
1808 * @return the size of the file.
1809 * @exception MEMORY_ERROR Not enough memory to convert 'filePath'
1810 * to the system path type.
1811 * @exception RANGE_ERROR 'filePath' does not use the standard path
1812 * representation or it cannot be converted to the system
1813 * path type.
1814 * @exception FILE_ERROR It was not possible to determine the file size.
1815 */
cmdBigFileSize(const const_striType filePath)1816 bigIntType cmdBigFileSize (const const_striType filePath)
1817
1818 {
1819 os_striType os_path;
1820 os_stat_struct stat_buf;
1821 int stat_result;
1822 cFileType aFile;
1823 int path_info = PATH_IS_NORMAL;
1824 errInfoType err_info = OKAY_NO_ERROR;
1825 bigIntType size_of_file;
1826
1827 /* cmdBigFileSize */
1828 logFunction(printf("cmdBigFileSize(\"%s\")", striAsUnquotedCStri(filePath));
1829 fflush(stdout););
1830 os_path = cp_to_os_path(filePath, &path_info, &err_info);
1831 if (unlikely(os_path == NULL)) {
1832 #if MAP_ABSOLUTE_PATH_TO_DRIVE_LETTERS
1833 if (likely(path_info == PATH_IS_EMULATED_ROOT)) {
1834 size_of_file = bigIConv(0);
1835 } else
1836 #endif
1837 {
1838 logError(printf("cmdBigFileSize: cp_to_os_path(\"%s\", *, *) failed:\n"
1839 "path_info=%d, err_info=%d\n",
1840 striAsUnquotedCStri(filePath), path_info, err_info););
1841 raise_error(err_info);
1842 size_of_file = NULL;
1843 }
1844 } else {
1845 stat_result = os_stat(os_path, &stat_buf);
1846 if (stat_result == 0 && S_ISREG(stat_buf.st_mode)) {
1847 #if OS_OFF_T_SIZE == 32
1848 size_of_file = bigFromUInt32((uint32Type) stat_buf.st_size);
1849 #elif OS_OFF_T_SIZE == 64
1850 size_of_file = bigFromUInt64((uint64Type) stat_buf.st_size);
1851 #else
1852 #error "sizeof(os_off_t) is neither 4 nor 8."
1853 #endif
1854 } else if (stat_result == 0 && (S_ISDIR(stat_buf.st_mode) ||
1855 S_ISFIFO(stat_buf.st_mode) ||
1856 S_ISSOCK(stat_buf.st_mode))) {
1857 size_of_file = bigIConv(0);
1858 } else {
1859 aFile = os_fopen(os_path, os_mode_rb);
1860 if (aFile == NULL) {
1861 logError(printf("cmdBigFileSize: "
1862 "os_fopen(\"" FMT_S_OS "\", \"" FMT_S_OS "\") failed:\n"
1863 "errno=%d\nerror: %s\n",
1864 os_path, os_mode_rb, errno, strerror(errno)););
1865 /* if (stat_result == 0) {
1866 printf("stat_buf.st_blksize=%lu\n", stat_buf.st_blksize);
1867 printf("stat_buf.st_blocks=%llu\n", stat_buf.st_blocks);
1868 printf("stat_buf.st_size=%llu\n", stat_buf.st_size);
1869 } */
1870 err_info = FILE_ERROR;
1871 size_of_file = NULL;
1872 } else {
1873 size_of_file = getBigFileLengthUsingSeek(aFile);
1874 fclose(aFile);
1875 } /* if */
1876 } /* if */
1877 os_stri_free(os_path);
1878 if (unlikely(err_info != OKAY_NO_ERROR)) {
1879 raise_error(err_info);
1880 } /* if */
1881 } /* if */
1882 return size_of_file;
1883 } /* cmdBigFileSize */
1884
1885
1886
1887 /**
1888 * Changes the current working directory of the calling process.
1889 * @exception MEMORY_ERROR Not enough memory to convert 'dirPath' to
1890 * the system path type.
1891 * @exception RANGE_ERROR 'dirPath' does not use the standard path
1892 * representation or it cannot be converted to the system
1893 * path type.
1894 * @exception FILE_ERROR A system function returns an error.
1895 */
cmdChdir(const const_striType dirPath)1896 void cmdChdir (const const_striType dirPath)
1897
1898 {
1899 os_striType os_path;
1900 int path_info = PATH_IS_NORMAL;
1901 errInfoType err_info = OKAY_NO_ERROR;
1902 int chdir_result;
1903
1904 /* cmdChdir */
1905 logFunction(printf("cmdChdir(\"%s\")\n", striAsUnquotedCStri(dirPath)););
1906 os_path = cp_to_os_path(dirPath, &path_info, &err_info);
1907 if (unlikely(os_path == NULL)) {
1908 #if MAP_ABSOLUTE_PATH_TO_DRIVE_LETTERS
1909 if (likely(path_info == PATH_IS_EMULATED_ROOT)) {
1910 setEmulatedCwdToRoot();
1911 } else {
1912 logError(printf("cmdChdir: cp_to_os_path(\"%s\", *, *) failed:\n"
1913 "path_info=%d, err_info=%d\n",
1914 striAsUnquotedCStri(dirPath), path_info, err_info););
1915 raise_error(err_info);
1916 } /* if */
1917 } else {
1918 #if defined USE_EXTENDED_LENGTH_PATH && USE_EXTENDED_LENGTH_PATH
1919 /* The extended length path is only used, if it */
1920 /* is absolutely necessary. Many subprocesses */
1921 /* cannot handle a current working directory */
1922 /* with an extended length path. */
1923 if (os_stri_strlen(&os_path[PREFIX_LEN]) < CLASSIC_WINDOWS_MAX_PATH) {
1924 logMessage(printf("cmdChdir: os_chdir(\"" FMT_S_OS "\")\n",
1925 &os_path[PREFIX_LEN]););
1926 chdir_result = os_chdir(&os_path[PREFIX_LEN]);
1927 } else {
1928 logMessage(printf("cmdChdir: os_chdir(\"" FMT_S_OS "\")\n",
1929 os_path););
1930 chdir_result = os_chdir(os_path);
1931 } /* if */
1932 if (unlikely(chdir_result != 0)) {
1933 logMessage(printf("cmdChdir: os_chdir(\"" FMT_S_OS "\") failed:\n"
1934 "errno=%d\nerror: %s\n",
1935 os_path, errno, strerror(errno)););
1936 setEmulatedCwd(os_path, &err_info);
1937 #else
1938 logMessage(printf("cmdChdir: os_chdir(\"" FMT_S_OS "\")\n",
1939 os_path););
1940 chdir_result = os_chdir(os_path);
1941 if (unlikely(chdir_result != 0)) {
1942 logError(printf("cmdChdir: os_chdir(\"" FMT_S_OS "\") failed:\n"
1943 "errno=%d\nerror: %s\n",
1944 os_path, errno, strerror(errno)););
1945 err_info = FILE_ERROR;
1946 #endif
1947 } else {
1948 setEmulatedCwd(os_path, &err_info);
1949 } /* if */
1950 #else
1951 logError(printf("cmdChdir: cp_to_os_path(\"%s\", *, *) failed:\n"
1952 "path_info=%d, err_info=%d\n",
1953 striAsUnquotedCStri(dirPath), path_info, err_info););
1954 raise_error(err_info);
1955 } else {
1956 logMessage(printf("cmdChdir: os_chdir(\"" FMT_S_OS "\")\n",
1957 os_path););
1958 chdir_result = os_chdir(os_path);
1959 if (unlikely(chdir_result != 0)) {
1960 logError(printf("cmdChdir: os_chdir(\"" FMT_S_OS "\") failed:\n"
1961 "errno=%d\nerror: %s\n",
1962 os_path, errno, strerror(errno)););
1963 err_info = FILE_ERROR;
1964 } /* if */
1965 #endif
1966 os_stri_free(os_path);
1967 if (unlikely(err_info != OKAY_NO_ERROR)) {
1968 raise_error(err_info);
1969 } /* if */
1970 } /* if */
1971 logFunction(printf("cmdChdir(\"%s\") -->\n",
1972 striAsUnquotedCStri(dirPath)););
1973 } /* cmdChdir */
1974
1975
1976
1977 /**
1978 * Clone a file or directory tree.
1979 * Permissions/mode, ownership and timestamps of the original are
1980 * preserved. Symlinks are not followed. Instead the symlink is
1981 * copied. Note that 'cloneFile' does not preserve hard links (they
1982 * are resolved to distinct files).
1983 * @exception MEMORY_ERROR Not enough memory to convert
1984 * 'sourcePath' or 'destPath' to the system path type.
1985 * @exception RANGE_ERROR 'sourcePath' or 'destPath' does not use
1986 * the standard path representation or one of them cannot be
1987 * converted to the system path type.
1988 * @exception FILE_ERROR Source file does not exist, destination file
1989 * already exists or a system function returns an error.
1990 */
1991 void cmdCloneFile (const const_striType sourcePath, const const_striType destPath)
1992
1993 {
1994 os_striType os_sourcePath;
1995 os_striType os_destPath;
1996 os_stat_struct to_stat;
1997 int path_info;
1998 errInfoType err_info = OKAY_NO_ERROR;
1999
2000 /* cmdCloneFile */
2001 logFunction(printf("cmdCloneFile(\"%s\", ", striAsUnquotedCStri(sourcePath));
2002 printf("\"%s\")\n", striAsUnquotedCStri(destPath)););
2003 os_sourcePath = cp_to_os_path(sourcePath, &path_info, &err_info);
2004 if (unlikely(os_sourcePath == NULL)) {
2005 logError(printf("cmdCloneFile: cp_to_os_path(\"%s\", *, *) failed:\n"
2006 "path_info=%d, err_info=%d\n",
2007 striAsUnquotedCStri(sourcePath), path_info, err_info););
2008 } else {
2009 os_destPath = cp_to_os_path(destPath, &path_info, &err_info);
2010 if (unlikely(os_destPath == NULL)) {
2011 logError(printf("cmdCloneFile: cp_to_os_path(\"%s\", *, *) failed:\n"
2012 "path_info=%d, err_info=%d\n",
2013 striAsUnquotedCStri(destPath), path_info, err_info););
2014 } else {
2015 if (os_stat(os_destPath, &to_stat) == 0) {
2016 logError(printf("cmdCloneFile: "
2017 "Destination " FMT_S_OS " exists already.\n",
2018 os_destPath););
2019 err_info = FILE_ERROR;
2020 } else {
2021 copy_any_file(os_sourcePath, os_destPath, PRESERVE_ALL, &err_info);
2022 } /* if */
2023 os_stri_free(os_destPath);
2024 } /* if */
2025 os_stri_free(os_sourcePath);
2026 } /* if */
2027 if (unlikely(err_info != OKAY_NO_ERROR)) {
2028 raise_error(err_info);
2029 } /* if */
2030 } /* cmdCloneFile */
2031
2032
2033
2034 /**
2035 * Get a built-in C compiler/runtime configuration value.
2036 * The makefile (used to compile Seed7) and the program chkccomp.c
2037 * write the configuration values to version.h. The configuration
2038 * values are hard-coded in the Seed7 runtime library.
2039 * @param name Name of the configuration value to be retrieved.
2040 * @return the requested configuration value, and
2041 * "" if a value with the name does not exist.
2042 * @exception MEMORY_ERROR Not enough memory to convert the
2043 * configuration value to a string.
2044 */
2045 striType cmdConfigValue (const const_striType name)
2046
2047 {
2048 char opt_name[MAX_CSTRI_BUFFER_LEN + NULL_TERMINATION_LEN];
2049 const_cstriType opt;
2050 char buffer[CONFIG_VALUE_BUFFER_SIZE];
2051 striType configValue = NULL;
2052
2053 /* cmdConfigValue */
2054 if (unlikely(name->size > MAX_CSTRI_BUFFER_LEN)) {
2055 opt = "";
2056 } else if (unlikely(conv_to_cstri(opt_name, name) == NULL)) {
2057 opt = "";
2058 } else if (strcmp(opt_name, "OBJECT_FILE_EXTENSION") == 0) {
2059 opt = OBJECT_FILE_EXTENSION;
2060 } else if (strcmp(opt_name, "LIBRARY_FILE_EXTENSION") == 0) {
2061 opt = LIBRARY_FILE_EXTENSION;
2062 } else if (strcmp(opt_name, "EXECUTABLE_FILE_EXTENSION") == 0) {
2063 opt = EXECUTABLE_FILE_EXTENSION;
2064 } else if (strcmp(opt_name, "LINKED_PROGRAM_EXTENSION") == 0) {
2065 opt = LINKED_PROGRAM_EXTENSION;
2066 } else if (strcmp(opt_name, "C_COMPILER") == 0) {
2067 opt = C_COMPILER;
2068 } else if (strcmp(opt_name, "CPLUSPLUS_COMPILER") == 0) {
2069 opt = CPLUSPLUS_COMPILER;
2070 } else if (strcmp(opt_name, "CALL_C_COMPILER_FROM_SHELL") == 0) {
2071 opt = CALL_C_COMPILER_FROM_SHELL ? "TRUE" : "FALSE";
2072 } else if (strcmp(opt_name, "C_COMPILER_VERSION") == 0) {
2073 opt = C_COMPILER_VERSION;
2074 } else if (strcmp(opt_name, "CC_OPT_DEBUG_INFO") == 0) {
2075 opt = CC_OPT_DEBUG_INFO;
2076 } else if (strcmp(opt_name, "CC_OPT_LINK_TIME_OPTIMIZATION") == 0) {
2077 opt = CC_OPT_LINK_TIME_OPTIMIZATION;
2078 } else if (strcmp(opt_name, "LINKER_OPT_LTO_MANDATORY") == 0) {
2079 opt = LINKER_OPT_LTO_MANDATORY ? "TRUE" : "FALSE";
2080 } else if (strcmp(opt_name, "CC_OPT_NO_WARNINGS") == 0) {
2081 opt = CC_OPT_NO_WARNINGS;
2082 } else if (strcmp(opt_name, "CC_OPT_OPTIMIZE_1") == 0) {
2083 opt = CC_OPT_OPTIMIZE_1;
2084 } else if (strcmp(opt_name, "CC_OPT_OPTIMIZE_2") == 0) {
2085 opt = CC_OPT_OPTIMIZE_2;
2086 } else if (strcmp(opt_name, "CC_OPT_OPTIMIZE_3") == 0) {
2087 opt = CC_OPT_OPTIMIZE_3;
2088 } else if (strcmp(opt_name, "CC_OPT_TRAP_OVERFLOW") == 0) {
2089 opt = CC_OPT_TRAP_OVERFLOW;
2090 } else if (strcmp(opt_name, "CC_OPT_VERSION_INFO") == 0) {
2091 opt = CC_OPT_VERSION_INFO;
2092 } else if (strcmp(opt_name, "CC_ENVIRONMENT_INI") == 0) {
2093 opt = CC_ENVIRONMENT_INI;
2094 } else if (strcmp(opt_name, "CC_FLAGS") == 0) {
2095 opt = CC_FLAGS;
2096 } else if (strcmp(opt_name, "CC_ERROR_FILEDES") == 0) {
2097 opt = STRINGIFY(CC_ERROR_FILEDES);
2098 } else if (strcmp(opt_name, "CC_VERSION_INFO_FILEDES") == 0) {
2099 opt = STRINGIFY(CC_VERSION_INFO_FILEDES);
2100 } else if (strcmp(opt_name, "LINKER_OPT_DEBUG_INFO") == 0) {
2101 opt = LINKER_OPT_DEBUG_INFO;
2102 } else if (strcmp(opt_name, "LINKER_OPT_NO_DEBUG_INFO") == 0) {
2103 opt = LINKER_OPT_NO_DEBUG_INFO;
2104 } else if (strcmp(opt_name, "LINKER_OPT_OUTPUT_FILE") == 0) {
2105 opt = LINKER_OPT_OUTPUT_FILE;
2106 } else if (strcmp(opt_name, "LINKER_OPT_SPECIAL_LIB") == 0) {
2107 opt = LINKER_OPT_SPECIAL_LIB;
2108 } else if (strcmp(opt_name, "LINKER_FLAGS") == 0) {
2109 opt = LINKER_FLAGS;
2110 } else if (strcmp(opt_name, "SYSTEM_LIBS") == 0) {
2111 opt = SYSTEM_LIBS;
2112 } else if (strcmp(opt_name, "SYSTEM_BIGINT_LIBS") == 0) {
2113 opt = SYSTEM_BIGINT_LIBS;
2114 } else if (strcmp(opt_name, "SYSTEM_DATABASE_LIBS") == 0) {
2115 opt = SYSTEM_DATABASE_LIBS;
2116 } else if (strcmp(opt_name, "SYSTEM_DRAW_LIBS") == 0) {
2117 opt = SYSTEM_DRAW_LIBS;
2118 } else if (strcmp(opt_name, "SYSTEM_MATH_LIBS") == 0) {
2119 opt = SYSTEM_MATH_LIBS;
2120 } else if (strcmp(opt_name, "SEED7_LIB") == 0) {
2121 opt = SEED7_LIB;
2122 } else if (strcmp(opt_name, "DRAW_LIB") == 0) {
2123 opt = DRAW_LIB;
2124 } else if (strcmp(opt_name, "CONSOLE_LIB") == 0) {
2125 opt = CONSOLE_LIB;
2126 } else if (strcmp(opt_name, "DATABASE_LIB") == 0) {
2127 opt = DATABASE_LIB;
2128 } else if (strcmp(opt_name, "COMP_DATA_LIB") == 0) {
2129 opt = COMP_DATA_LIB;
2130 } else if (strcmp(opt_name, "COMPILER_LIB") == 0) {
2131 opt = COMPILER_LIB;
2132 } else if (strcmp(opt_name, "SPECIAL_LIB") == 0) {
2133 opt = SPECIAL_LIB;
2134 } else if (strcmp(opt_name, "S7_LIB_DIR") == 0) {
2135 opt = S7_LIB_DIR;
2136 } else if (strcmp(opt_name, "VERSION_REVISION_LEVEL") == 0) {
2137 opt = STRINGIFY(LEVEL);
2138 } else if (strcmp(opt_name, "REDIRECT_FILEDES_1") == 0) {
2139 opt = REDIRECT_FILEDES_1;
2140 } else if (strcmp(opt_name, "REDIRECT_FILEDES_2") == 0) {
2141 opt = REDIRECT_FILEDES_2;
2142 } else if (strcmp(opt_name, "NULL_DEVICE") == 0) {
2143 opt = NULL_DEVICE_FOR_SCRIPTS;
2144 } else if (strcmp(opt_name, "BOOLTYPE") == 0) {
2145 opt = BOOLTYPE_STRI;
2146 } else if (strcmp(opt_name, "INT32TYPE") == 0) {
2147 opt = INT32TYPE_STRI;
2148 } else if (strcmp(opt_name, "UINT32TYPE") == 0) {
2149 opt = UINT32TYPE_STRI;
2150 } else if (strcmp(opt_name, "INT64TYPE") == 0) {
2151 opt = INT64TYPE_STRI;
2152 } else if (strcmp(opt_name, "UINT64TYPE") == 0) {
2153 opt = UINT64TYPE_STRI;
2154 } else if (strcmp(opt_name, "INT128TYPE") == 0) {
2155 opt = INT128TYPE_STRI;
2156 } else if (strcmp(opt_name, "UINT128TYPE") == 0) {
2157 opt = UINT128TYPE_STRI;
2158 } else if (strcmp(opt_name, "INT32TYPE_LITERAL_SUFFIX") == 0) {
2159 opt = INT32TYPE_LITERAL_SUFFIX;
2160 } else if (strcmp(opt_name, "INT64TYPE_LITERAL_SUFFIX") == 0) {
2161 opt = INT64TYPE_LITERAL_SUFFIX;
2162 } else if (strcmp(opt_name, "INTTYPE_SIZE") == 0) {
2163 sprintf(buffer, "%d", INTTYPE_SIZE);
2164 opt = buffer;
2165 } else if (strcmp(opt_name, "FLOATTYPE_SIZE") == 0) {
2166 sprintf(buffer, "%d", FLOATTYPE_SIZE);
2167 opt = buffer;
2168 } else if (strcmp(opt_name, "POINTER_SIZE") == 0) {
2169 sprintf(buffer, "%d", POINTER_SIZE);
2170 opt = buffer;
2171 } else if (strcmp(opt_name, "INT_SIZE") == 0) {
2172 opt = STRINGIFY(INT_SIZE);
2173 } else if (strcmp(opt_name, "LONG_SIZE") == 0) {
2174 opt = STRINGIFY(LONG_SIZE);
2175 } else if (strcmp(opt_name, "FLOATTYPE_MANTISSA_BITS") == 0) {
2176 sprintf(buffer, "%d", FLOATTYPE_MANTISSA_BITS);
2177 opt = buffer;
2178 } else if (strcmp(opt_name, "FLOATTYPE_EXPONENT_OFFSET") == 0) {
2179 sprintf(buffer, "%d", FLOATTYPE_EXPONENT_OFFSET);
2180 opt = buffer;
2181 } else if (strcmp(opt_name, "INT_RANGE_IN_FLOATTYPE_MAX") == 0) {
2182 sprintf(buffer, FMT_D, INT_RANGE_IN_FLOATTYPE_MAX);
2183 opt = buffer;
2184 } else if (strcmp(opt_name, "MINIMUM_TRUNC_ARGUMENT") == 0) {
2185 #if FLOATTYPE_DOUBLE && INTTYPE_SIZE == 64
2186 opt = STRINGIFY(MINIMUM_TRUNC_ARGUMENT);
2187 #else
2188 opt = "";
2189 #endif
2190 } else if (strcmp(opt_name, "MAXIMUM_TRUNC_ARGUMENT") == 0) {
2191 #if FLOATTYPE_DOUBLE && INTTYPE_SIZE == 64
2192 opt = STRINGIFY(MAXIMUM_TRUNC_ARGUMENT);
2193 #else
2194 opt = "";
2195 #endif
2196 } else if (strcmp(opt_name, "PIXEL_RED_MASK") == 0) {
2197 opt = PIXEL_RED_MASK;
2198 } else if (strcmp(opt_name, "PIXEL_GREEN_MASK") == 0) {
2199 opt = PIXEL_GREEN_MASK;
2200 } else if (strcmp(opt_name, "PIXEL_BLUE_MASK") == 0) {
2201 opt = PIXEL_BLUE_MASK;
2202 } else if (strcmp(opt_name, "RGB_TO_PIXEL_FLAG_NAME") == 0) {
2203 opt = RGB_TO_PIXEL_FLAG_NAME;
2204 } else if (strcmp(opt_name, "RAND_MULTIPLIER") == 0) {
2205 opt = STRINGIFY(RAND_MULTIPLIER);
2206 } else if (strcmp(opt_name, "RAND_INCREMENT") == 0) {
2207 opt = STRINGIFY(RAND_INCREMENT);
2208 } else if (strcmp(opt_name, "MACRO_DEFS") == 0) {
2209 /* Use string literal concatenation: */
2210 opt = MACRO_DEFS OS_ISNAN_DEFINITION;
2211 } else if (strcmp(opt_name, "OVERFLOW_SIGNAL") == 0) {
2212 opt = OVERFLOW_SIGNAL_STR;
2213 } else if (strcmp(opt_name, "BUILTIN_ADD_OVERFLOW") == 0) {
2214 opt = BUILTIN_ADD_OVERFLOW;
2215 } else if (strcmp(opt_name, "BUILTIN_SUB_OVERFLOW") == 0) {
2216 opt = BUILTIN_SUB_OVERFLOW;
2217 } else if (strcmp(opt_name, "BUILTIN_MULT_OVERFLOW") == 0) {
2218 opt = BUILTIN_MULT_OVERFLOW;
2219 } else if (strcmp(opt_name, "FLOATTYPE_DOUBLE") == 0) {
2220 opt = FLOATTYPE_DOUBLE ? "TRUE" : "FALSE";
2221 } else if (strcmp(opt_name, "HAS_SIGSETJMP") == 0) {
2222 opt = HAS_SIGSETJMP ? "TRUE" : "FALSE";
2223 } else if (strcmp(opt_name, "CHECK_INT_DIV_BY_ZERO") == 0) {
2224 opt = CHECK_INT_DIV_BY_ZERO ? "TRUE" : "FALSE";
2225 } else if (strcmp(opt_name, "CHECK_INT_DIV_ZERO_BY_ZERO") == 0) {
2226 opt = CHECK_INT_DIV_ZERO_BY_ZERO ? "TRUE" : "FALSE";
2227 } else if (strcmp(opt_name, "CHECK_INT_REM_BY_ZERO") == 0) {
2228 opt = CHECK_INT_REM_BY_ZERO ? "TRUE" : "FALSE";
2229 } else if (strcmp(opt_name, "CHECK_INT_REM_ZERO_BY_ZERO") == 0) {
2230 opt = CHECK_INT_REM_ZERO_BY_ZERO ? "TRUE" : "FALSE";
2231 } else if (strcmp(opt_name, "HAS_EXP2") == 0) {
2232 opt = HAS_EXP2 ? "TRUE" : "FALSE";
2233 } else if (strcmp(opt_name, "HAS_EXP10") == 0) {
2234 opt = HAS_EXP10 ? "TRUE" : "FALSE";
2235 } else if (strcmp(opt_name, "HAS_EXPM1") == 0) {
2236 opt = HAS_EXPM1 ? "TRUE" : "FALSE";
2237 } else if (strcmp(opt_name, "HAS_LOG1P") == 0) {
2238 opt = HAS_LOG1P ? "TRUE" : "FALSE";
2239 } else if (strcmp(opt_name, "HAS_CBRT") == 0) {
2240 opt = HAS_CBRT ? "TRUE" : "FALSE";
2241 } else if (strcmp(opt_name, "CHECK_FLOAT_DIV_BY_ZERO") == 0) {
2242 opt = CHECK_FLOAT_DIV_BY_ZERO ? "TRUE" : "FALSE";
2243 } else if (strcmp(opt_name, "FLOAT_COMPARISON_OKAY") == 0) {
2244 opt = FLOAT_COMPARISON_OKAY ? "TRUE" : "FALSE";
2245 } else if (strcmp(opt_name, "WITH_STRI_CAPACITY") == 0) {
2246 opt = WITH_STRI_CAPACITY ? "TRUE" : "FALSE";
2247 } else if (strcmp(opt_name, "ALLOW_STRITYPE_SLICES") == 0) {
2248 opt = ALLOW_STRITYPE_SLICES ? "TRUE" : "FALSE";
2249 } else if (strcmp(opt_name, "ALLOW_BSTRITYPE_SLICES") == 0) {
2250 opt = ALLOW_BSTRITYPE_SLICES ? "TRUE" : "FALSE";
2251 } else if (strcmp(opt_name, "RSHIFT_DOES_SIGN_EXTEND") == 0) {
2252 opt = RSHIFT_DOES_SIGN_EXTEND ? "TRUE" : "FALSE";
2253 } else if (strcmp(opt_name, "TWOS_COMPLEMENT_INTTYPE") == 0) {
2254 opt = TWOS_COMPLEMENT_INTTYPE ? "TRUE" : "FALSE";
2255 } else if (strcmp(opt_name, "LITTLE_ENDIAN_INTTYPE") == 0) {
2256 opt = LITTLE_ENDIAN_INTTYPE ? "TRUE" : "FALSE";
2257 } else if (strcmp(opt_name, "POW_FUNCTION_OKAY") == 0) {
2258 opt = POW_FUNCTION_OKAY ? "TRUE" : "FALSE";
2259 } else if (strcmp(opt_name, "SQRT_FUNCTION_OKAY") == 0) {
2260 opt = SQRT_FUNCTION_OKAY ? "TRUE" : "FALSE";
2261 } else if (strcmp(opt_name, "EXP_FUNCTION_OKAY") == 0) {
2262 opt = EXP_FUNCTION_OKAY ? "TRUE" : "FALSE";
2263 } else if (strcmp(opt_name, "LOG_FUNCTION_OKAY") == 0) {
2264 opt = LOG_FUNCTION_OKAY ? "TRUE" : "FALSE";
2265 } else if (strcmp(opt_name, "LOG10_FUNCTION_OKAY") == 0) {
2266 opt = LOG10_FUNCTION_OKAY ? "TRUE" : "FALSE";
2267 } else if (strcmp(opt_name, "LOG2_FUNCTION_OKAY") == 0) {
2268 opt = LOG2_FUNCTION_OKAY ? "TRUE" : "FALSE";
2269 } else if (strcmp(opt_name, "FMOD_FUNCTION_OKAY") == 0) {
2270 opt = FMOD_FUNCTION_OKAY ? "TRUE" : "FALSE";
2271 } else if (strcmp(opt_name, "LDEXP_FUNCTION_OKAY") == 0) {
2272 opt = LDEXP_FUNCTION_OKAY ? "TRUE" : "FALSE";
2273 } else if (strcmp(opt_name, "FREXP_FUNCTION_OKAY") == 0) {
2274 opt = FREXP_FUNCTION_OKAY ? "TRUE" : "FALSE";
2275 } else if (strcmp(opt_name, "FLOAT_ZERO_DIV_ERROR") == 0) {
2276 opt = FLOAT_ZERO_DIV_ERROR ? "TRUE" : "FALSE";
2277 } else if (strcmp(opt_name, "LIMITED_CSTRI_LITERAL_LEN") == 0) {
2278 opt = LIMITED_CSTRI_LITERAL_LEN ? "TRUE" : "FALSE";
2279 } else if (strcmp(opt_name, "SWITCH_WORKS_FOR_INT64TYPE") == 0) {
2280 opt = SWITCH_WORKS_FOR_INT64TYPE ? "TRUE" : "FALSE";
2281 } else if (strcmp(opt_name, "STMT_BLOCK_IN_PARENTHESES_OK") == 0) {
2282 opt = STMT_BLOCK_IN_PARENTHESES_OK ? "TRUE" : "FALSE";
2283 } else if (strcmp(opt_name, "CC_SOURCE_UTF8") == 0) {
2284 #ifdef CC_SOURCE_UTF8
2285 opt = "TRUE";
2286 #else
2287 opt = "FALSE";
2288 #endif
2289 } else if (strcmp(opt_name, "USE_WMAIN") == 0) {
2290 #ifdef USE_WMAIN
2291 opt = "TRUE";
2292 #else
2293 opt = "FALSE";
2294 #endif
2295 } else if (strcmp(opt_name, "USE_WINMAIN") == 0) {
2296 #ifdef USE_WINMAIN
2297 opt = "TRUE";
2298 #else
2299 opt = "FALSE";
2300 #endif
2301 } else {
2302 opt = "";
2303 } /* if */
2304 if (configValue == NULL) {
2305 configValue = cstri8_or_cstri_to_stri(opt);
2306 } /* if */
2307 if (unlikely(configValue == NULL)) {
2308 raise_error(MEMORY_ERROR);
2309 } /* if */
2310 return configValue;
2311 } /* cmdConfigValue */
2312
2313
2314
2315 /**
2316 * Copy a file or directory tree.
2317 * Permissions/mode, ownership and timestamps of the destination file
2318 * are determined independent of the corresponding source properties.
2319 * The destination file gets the permissions/mode defined by umask.
2320 * The user executing the program is the owner of the destination file.
2321 * The timestamps of the destination file are set to the current time.
2322 * Symbolic links in 'sourcePath' are always followed.
2323 * Therefore 'copyFile' will never create a symbolic link.
2324 * Note that 'copyFile' does not preserve hard links (they are
2325 * resolved to distinct files).
2326 * @exception MEMORY_ERROR Not enough memory to convert 'sourcePath'
2327 * or 'destPath' to the system path type.
2328 * @exception RANGE_ERROR 'sourcePath' or 'destPath' does not use
2329 * the standard path representation or one of them cannot be
2330 * converted to the system path type.
2331 * @exception FILE_ERROR Source file does not exist, destination file
2332 * already exists or a system function returns an error.
2333 */
2334 void cmdCopyFile (const const_striType sourcePath, const const_striType destPath)
2335
2336 {
2337 os_striType os_sourcePath;
2338 os_striType os_destPath;
2339 os_stat_struct to_stat;
2340 int path_info;
2341 errInfoType err_info = OKAY_NO_ERROR;
2342
2343 /* cmdCopyFile */
2344 logFunction(printf("cmdCopyFile(\"%s\", ", striAsUnquotedCStri(sourcePath));
2345 printf("\"%s\")\n", striAsUnquotedCStri(destPath)););
2346 os_sourcePath = cp_to_os_path(sourcePath, &path_info, &err_info);
2347 if (unlikely(os_sourcePath == NULL)) {
2348 logError(printf("cmdCopyFile: cp_to_os_path(\"%s\", *, *) failed:\n"
2349 "path_info=%d, err_info=%d\n",
2350 striAsUnquotedCStri(sourcePath), path_info, err_info););
2351 } else {
2352 os_destPath = cp_to_os_path(destPath, &path_info, &err_info);
2353 if (unlikely(os_destPath == NULL)) {
2354 logError(printf("cmdCopyFile: cp_to_os_path(\"%s\", *, *) failed:\n"
2355 "path_info=%d, err_info=%d\n",
2356 striAsUnquotedCStri(destPath), path_info, err_info););
2357 } else {
2358 if (os_stat(os_destPath, &to_stat) == 0) {
2359 logError(printf("cmdCopyFile: "
2360 "Destination " FMT_S_OS " exists already.\n",
2361 os_destPath););
2362 err_info = FILE_ERROR;
2363 } else {
2364 copy_any_file(os_sourcePath, os_destPath, PRESERVE_NOTHING, &err_info);
2365 } /* if */
2366 os_stri_free(os_destPath);
2367 } /* if */
2368 os_stri_free(os_sourcePath);
2369 } /* if */
2370 if (unlikely(err_info != OKAY_NO_ERROR)) {
2371 raise_error(err_info);
2372 } /* if */
2373 } /* cmdCopyFile */
2374
2375
2376
2377 /**
2378 * Returns the list of environment variable names as array of strings.
2379 * @return the list of environment variable names.
2380 * @exception MEMORY_ERROR Not enough memory to create the result.
2381 */
2382 rtlArrayType cmdEnvironment (void)
2383
2384 {
2385 #if USE_GET_ENVIRONMENT
2386 os_striType *os_environ;
2387 #elif INITIALIZE_OS_ENVIRON
2388 static const os_charType empty_os_stri[] = {0};
2389 #endif
2390 intType used_max_position;
2391 os_striType *nameStartPos;
2392 os_striType nameEndPos;
2393 striType variableName;
2394 errInfoType err_info = OKAY_NO_ERROR;
2395 rtlArrayType environment_array;
2396
2397 /* cmdEnvironment */
2398 logFunction(printf("cmdEnvironment()\n"););
2399 #if USE_GET_ENVIRONMENT
2400 os_environ = getEnvironment();
2401 #elif INITIALIZE_OS_ENVIRON
2402 if (os_environ == NULL) {
2403 (void) os_getenv(empty_os_stri);
2404 } /* if */
2405 #endif
2406 if (unlikely(!ALLOC_RTL_ARRAY(environment_array, INITAL_ARRAY_SIZE))) {
2407 raise_error(MEMORY_ERROR);
2408 } else {
2409 environment_array->min_position = 1;
2410 environment_array->max_position = INITAL_ARRAY_SIZE;
2411 used_max_position = 0;
2412 if (os_environ != NULL) {
2413 for (nameStartPos = os_environ; *nameStartPos != NULL && environment_array != NULL;
2414 ++nameStartPos) {
2415 /* printf("nameStartPos: \"" FMT_S_OS "\"\n", *nameStartPos); */
2416 if ((*nameStartPos)[0] != '=' && (*nameStartPos)[0] != '\0') {
2417 nameEndPos = os_stri_strchr(*nameStartPos, '=');
2418 if (unlikely(nameEndPos == NULL)) {
2419 nameEndPos = *nameStartPos + os_stri_strlen(*nameStartPos);
2420 } /* if */
2421 variableName = conv_from_os_stri(*nameStartPos,
2422 (memSizeType) (nameEndPos - *nameStartPos));
2423 if (unlikely(variableName == NULL)) {
2424 err_info = MEMORY_ERROR;
2425 } else {
2426 environment_array = addStriToRtlArray(variableName, environment_array,
2427 used_max_position);
2428 used_max_position++;
2429 } /* if */
2430 } /* if */
2431 } /* for */
2432 } /* if */
2433 environment_array = completeRtlStriArray(environment_array, used_max_position);
2434 if (unlikely(environment_array == NULL)) {
2435 err_info = MEMORY_ERROR;
2436 } /* if */
2437 if (unlikely(err_info != OKAY_NO_ERROR)) {
2438 raise_error(err_info);
2439 environment_array = NULL;
2440 } /* if */
2441 } /* if */
2442 #if USE_GET_ENVIRONMENT
2443 freeEnvironment(os_environ);
2444 #endif
2445 logFunction(printf("cmdEnvironment --> " FMT_U_MEM
2446 " (size=" FMT_U_MEM ")\n",
2447 (memSizeType) environment_array,
2448 environment_array != NULL ?
2449 arraySize(environment_array) : 0););
2450 return environment_array;
2451 } /* cmdEnvironment */
2452
2453
2454
2455 /**
2456 * Determine the file mode (permissions) of a file.
2457 * @return the file mode.
2458 * @exception MEMORY_ERROR Not enough memory to convert 'filePath'
2459 * to the system path type.
2460 * @exception RANGE_ERROR 'filePath' does not use the standard path
2461 * representation or it cannot be converted to the system
2462 * path type.
2463 * @exception FILE_ERROR A system function returns an error.
2464 */
2465 setType cmdFileMode (const const_striType filePath)
2466
2467 {
2468 os_striType os_path;
2469 os_stat_struct stat_buf;
2470 int stat_result;
2471 int path_info = PATH_IS_NORMAL;
2472 errInfoType err_info = OKAY_NO_ERROR;
2473 setType file_mode;
2474
2475 /* cmdFileMode */
2476 logFunction(printf("cmdFileMode(\"%s\")\n", striAsUnquotedCStri(filePath)););
2477 os_path = cp_to_os_path(filePath, &path_info, &err_info);
2478 if (unlikely(os_path == NULL)) {
2479 #if MAP_ABSOLUTE_PATH_TO_DRIVE_LETTERS
2480 if (likely(path_info == PATH_IS_EMULATED_ROOT)) {
2481 file_mode = setIConv(0444);
2482 } else
2483 #endif
2484 {
2485 logError(printf("cmdFileMode: cp_to_os_path(\"%s\", *, *) failed:\n"
2486 "path_info=%d, err_info=%d\n",
2487 striAsUnquotedCStri(filePath), path_info, err_info););
2488 raise_error(err_info);
2489 file_mode = NULL;
2490 }
2491 } else {
2492 stat_result = os_stat(os_path, &stat_buf);
2493 if (unlikely(stat_result != 0)) {
2494 logError(printf("cmdFileMode: os_stat(\"" FMT_S_OS "\") failed:\n"
2495 "errno=%d\nerror: %s\n",
2496 os_path, errno, strerror(errno)););
2497 os_stri_free(os_path);
2498 raise_error(FILE_ERROR);
2499 file_mode = NULL;
2500 } else {
2501 os_stri_free(os_path);
2502 /* printf("cmdFileMode: st_mode=0%o\n", stat_buf.st_mode); */
2503 #if MODE_BITS_NORMAL
2504 file_mode = setIConv(0777 & stat_buf.st_mode);
2505 #else
2506 /* Force the bits to the standard sequence */
2507 file_mode = setIConv(
2508 (stat_buf.st_mode & S_IRUSR ? 0400 : 0) |
2509 (stat_buf.st_mode & S_IWUSR ? 0200 : 0) |
2510 (stat_buf.st_mode & S_IXUSR ? 0100 : 0) |
2511 (stat_buf.st_mode & S_IRGRP ? 0040 : 0) |
2512 (stat_buf.st_mode & S_IWGRP ? 0020 : 0) |
2513 (stat_buf.st_mode & S_IXGRP ? 0010 : 0) |
2514 (stat_buf.st_mode & S_IROTH ? 0004 : 0) |
2515 (stat_buf.st_mode & S_IWOTH ? 0002 : 0) |
2516 (stat_buf.st_mode & S_IXOTH ? 0001 : 0));
2517 #endif
2518 } /* if */
2519 } /* if */
2520 return file_mode;
2521 } /* cmdFileMode */
2522
2523
2524
2525 /**
2526 * Determine the size of a file.
2527 * The file size is measured in bytes.
2528 * For directories, fifos and sockets a size of 0 is returned.
2529 * @return the size of the file.
2530 * @exception MEMORY_ERROR Not enough memory to convert 'filePath'
2531 * to the system path type.
2532 * @exception RANGE_ERROR 'filePath' does not use the standard path
2533 * representation or it cannot be converted to the system
2534 * path type.
2535 * @exception RANGE_ERROR The file size is not representable as integer.
2536 * @exception FILE_ERROR It was not possible to determine the file size.
2537 */
2538 intType cmdFileSize (const const_striType filePath)
2539
2540 {
2541 os_striType os_path;
2542 os_stat_struct stat_buf;
2543 int stat_result;
2544 cFileType aFile;
2545 int path_info = PATH_IS_NORMAL;
2546 errInfoType err_info = OKAY_NO_ERROR;
2547 intType size_of_file;
2548
2549 /* cmdFileSize */
2550 logFunction(printf("cmdFileSize(\"%s\")", striAsUnquotedCStri(filePath));
2551 fflush(stdout););
2552 os_path = cp_to_os_path(filePath, &path_info, &err_info);
2553 if (unlikely(os_path == NULL)) {
2554 #if MAP_ABSOLUTE_PATH_TO_DRIVE_LETTERS
2555 if (unlikely(path_info != PATH_IS_EMULATED_ROOT))
2556 #endif
2557 {
2558 logError(printf("cmdFileSize: cp_to_os_path(\"%s\", *, *) failed:\n"
2559 "path_info=%d, err_info=%d\n",
2560 striAsUnquotedCStri(filePath), path_info, err_info););
2561 raise_error(err_info);
2562 }
2563 size_of_file = 0;
2564 } else {
2565 stat_result = os_stat(os_path, &stat_buf);
2566 if (stat_result == 0 && S_ISREG(stat_buf.st_mode)) {
2567 if (stat_buf.st_size > INTTYPE_MAX || stat_buf.st_size < 0) {
2568 logError(printf("cmdFileSize(\"%s\"): "
2569 "File size not representable as integer.\n",
2570 striAsUnquotedCStri(filePath)););
2571 err_info = RANGE_ERROR;
2572 size_of_file = 0;
2573 } else {
2574 size_of_file = (intType) stat_buf.st_size;
2575 } /* if */
2576 } else if (stat_result == 0 && (S_ISDIR(stat_buf.st_mode) ||
2577 S_ISFIFO(stat_buf.st_mode) ||
2578 S_ISSOCK(stat_buf.st_mode))) {
2579 size_of_file = 0;
2580 } else {
2581 /* printf("stat_result=%d\nerrno=%d\n", stat_result, errno); */
2582 aFile = os_fopen(os_path, os_mode_rb);
2583 if (aFile == NULL) {
2584 logError(printf("cmdFileSize: "
2585 "os_fopen(\"" FMT_S_OS "\", \"" FMT_S_OS "\") failed:\n"
2586 "errno=%d\nerror: %s\n",
2587 os_path, os_mode_rb, errno, strerror(errno)););
2588 /* if (stat_result == 0) {
2589 printf("stat_buf.st_blksize=%lu\n", stat_buf.st_blksize);
2590 printf("stat_buf.st_blocks=" FMT_U64 "\n", (uint64Type) stat_buf.st_blocks);
2591 printf("stat_buf.st_size=" FMT_U64 "\n", (uint64Type) stat_buf.st_size);
2592 } */
2593 err_info = FILE_ERROR;
2594 size_of_file = 0;
2595 } else {
2596 size_of_file = getFileLengthUsingSeek(aFile);
2597 fclose(aFile);
2598 } /* if */
2599 } /* if */
2600 os_stri_free(os_path);
2601 if (unlikely(err_info != OKAY_NO_ERROR)) {
2602 raise_error(err_info);
2603 } /* if */
2604 } /* if */
2605 logFunctionResult(printf("" FMT_D "\n", size_of_file););
2606 return size_of_file;
2607 } /* cmdFileSize */
2608
2609
2610
2611 /**
2612 * Determine the type of a file.
2613 * The function does follow symbolic links. If the chain of
2614 * symbolic links is too long the function returns 'FILE_SYMLINK'.
2615 * If a symbolic link refers to a place where the permission
2616 * is denied the function returns 'FILE_SYMLINK'.
2617 * A return value of 'FILE_ABSENT' does not imply that a file
2618 * with this name can be created, since missing directories and
2619 * illegal file names cause also 'FILE_ABSENT'.
2620 * @return the type of the file.
2621 * @exception MEMORY_ERROR Not enough memory to convert 'filePath'
2622 * to the system path type.
2623 * @exception RANGE_ERROR 'filePath' does not use the standard path
2624 * representation.
2625 * @exception FILE_ERROR The system function returns an error other
2626 * than ENOENT, ENOTDIR, ENAMETOOLONG or EACCES.
2627 */
2628 intType cmdFileType (const const_striType filePath)
2629
2630 {
2631 os_striType os_path;
2632 os_stat_struct stat_buf;
2633 int stat_result;
2634 int path_info = PATH_IS_NORMAL;
2635 errInfoType err_info = OKAY_NO_ERROR;
2636 int saved_errno;
2637 intType type_of_file;
2638
2639 /* cmdFileType */
2640 logFunction(printf("cmdFileType(\"%s\")", striAsUnquotedCStri(filePath));
2641 fflush(stdout););
2642 os_path = cp_to_os_path(filePath, &path_info, &err_info);
2643 if (unlikely(os_path == NULL)) {
2644 #if MAP_ABSOLUTE_PATH_TO_DRIVE_LETTERS
2645 if (path_info == PATH_IS_EMULATED_ROOT) {
2646 type_of_file = FILE_DIR;
2647 } else if (path_info == PATH_NOT_MAPPED) {
2648 type_of_file = FILE_ABSENT;
2649 } else
2650 #endif
2651 {
2652 logError(printf("cmdFileType: cp_to_os_path(\"%s\", *, *) failed:\n"
2653 "path_info=%d, err_info=%d\n",
2654 striAsUnquotedCStri(filePath), path_info, err_info););
2655 raise_error(err_info);
2656 type_of_file = FILE_ABSENT;
2657 }
2658 } else {
2659 stat_result = os_stat(os_path, &stat_buf);
2660 saved_errno = errno;
2661 /* printf("stat(\"" FMT_S_OS "\") returns: %d, errno=%d\n",
2662 os_path, stat_result, saved_errno); */
2663 if (stat_result == 0) {
2664 if (S_ISREG(stat_buf.st_mode)) {
2665 type_of_file = FILE_REGULAR;
2666 } else if (S_ISDIR(stat_buf.st_mode)) {
2667 type_of_file = FILE_DIR;
2668 } else if (S_ISCHR(stat_buf.st_mode)) {
2669 type_of_file = FILE_CHAR;
2670 } else if (S_ISBLK(stat_buf.st_mode)) {
2671 type_of_file = FILE_BLOCK;
2672 } else if (S_ISFIFO(stat_buf.st_mode)) {
2673 type_of_file = FILE_FIFO;
2674 } else if (S_ISLNK(stat_buf.st_mode)) {
2675 type_of_file = FILE_SYMLINK;
2676 logError(printf("cmdFileType: os_stat(\"" FMT_S_OS "\", *) "
2677 "returns a mode of S_IFLNK.\n",
2678 os_path););
2679 err_info = FILE_ERROR;
2680 } else if (S_ISSOCK(stat_buf.st_mode)) {
2681 type_of_file = FILE_SOCKET;
2682 } else {
2683 type_of_file = FILE_UNKNOWN;
2684 } /* if */
2685 #ifdef ELOOP
2686 } else if (unlikely(saved_errno == ELOOP)) {
2687 type_of_file = FILE_SYMLINK;
2688 #endif
2689 } else if (unlikely(saved_errno == EACCES) &&
2690 os_lstat(os_path, &stat_buf) == 0 &&
2691 S_ISLNK(stat_buf.st_mode)) {
2692 /* Symbolic link that refers to a place where */
2693 /* the permission is denied. */
2694 type_of_file = FILE_SYMLINK;
2695 } else {
2696 type_of_file = FILE_ABSENT;
2697 if (unlikely(filePath->size != 0 && saved_errno != ENOENT &&
2698 saved_errno != ENOTDIR && saved_errno != ENAMETOOLONG &&
2699 saved_errno != EACCES)) {
2700 logError(printf("cmdFileType: os_stat(\"" FMT_S_OS "\") failed:\n"
2701 "errno=%d\nerror: %s\n",
2702 os_path, saved_errno, strerror(saved_errno)););
2703 /* printf("filePath->size=%lu\n", filePath->size); */
2704 /* printf("strlen(os_path)=%d\n", os_stri_strlen(os_path)); */
2705 err_info = FILE_ERROR;
2706 } /* if */
2707 } /* if */
2708 os_stri_free(os_path);
2709 if (unlikely(err_info != OKAY_NO_ERROR)) {
2710 raise_error(err_info);
2711 } /* if */
2712 } /* if */
2713 logFunctionResult(printf("" FMT_D "\n", type_of_file););
2714 return type_of_file;
2715 } /* cmdFileType */
2716
2717
2718
2719 /**
2720 * Determine the type of a file.
2721 * The function does not follow symbolic links. Therefore it may
2722 * return 'FILE_SYMLINK'. A return value of 'FILE_ABSENT' does
2723 * not imply that a file with this name can be created, since missing
2724 * directories and illegal file names cause also 'FILE_ABSENT'.
2725 * @return the type of the file.
2726 * @exception MEMORY_ERROR Not enough memory to convert 'filePath'
2727 * to the system path type.
2728 * @exception RANGE_ERROR 'filePath' does not use the standard path
2729 * representation.
2730 * @exception FILE_ERROR The system function returns an error other
2731 * than ENOENT, ENOTDIR, ENAMETOOLONG or EACCES.
2732 */
2733 intType cmdFileTypeSL (const const_striType filePath)
2734
2735 {
2736 errInfoType err_info = OKAY_NO_ERROR;
2737 intType type_of_file;
2738
2739 /* cmdFileTypeSL */
2740 logFunction(printf("cmdFileTypeSL(\"%s\")", striAsUnquotedCStri(filePath));
2741 fflush(stdout););
2742 type_of_file = getFileTypeSL(filePath, &err_info);
2743 if (unlikely(err_info != OKAY_NO_ERROR)) {
2744 raise_error(err_info);
2745 } /* if */
2746 logFunctionResult(printf("" FMT_D "\n", type_of_file););
2747 return type_of_file;
2748 } /* cmdFileTypeSL */
2749
2750
2751
2752 /**
2753 * Determine the current working directory of the calling process.
2754 * @return The absolute path of the current working directory.
2755 * @exception MEMORY_ERROR Not enough memory to represent the
2756 * result string.
2757 * @exception FILE_ERROR The system function returns an error.
2758 */
2759 striType cmdGetcwd (void)
2760
2761 {
2762 errInfoType err_info = OKAY_NO_ERROR;
2763 striType cwd;
2764
2765 /* cmdGetcwd */
2766 logFunction(printf("cmdGetcwd\n"););
2767 cwd = doGetCwd(&err_info);
2768 if (unlikely(cwd == NULL)) {
2769 logError(printf("cmdGetcwd: doGetCwd() failed:\n"
2770 "err_info=%d\n", err_info););
2771 raise_error(err_info);
2772 } /* if */
2773 logFunction(printf("cmdGetcwd --> \"%s\"\n", striAsUnquotedCStri(cwd)););
2774 return cwd;
2775 } /* cmdGetcwd */
2776
2777
2778
2779 /**
2780 * Determine the value of an environment variable.
2781 * The function getenv searches the environment for an environment variable
2782 * with the given 'name'. If such an environment variable exists the
2783 * corresponding string value is returned.
2784 * @return the value of an environment variable, and
2785 * "" if the requested environment variable does not exist.
2786 * @exception MEMORY_ERROR Not enough memory to convert 'name' to the
2787 * system string type or not enough memory to represent the
2788 * result string.
2789 * @exception RANGE_ERROR 'name' cannot be converted to the system string
2790 * type or a system function returns an error.
2791 */
2792 striType cmdGetenv (const const_striType name)
2793
2794 {
2795 os_striType env_name;
2796 os_striType env_value;
2797 errInfoType err_info = OKAY_NO_ERROR;
2798 striType value;
2799
2800 /* cmdGetenv */
2801 logFunction(printf("cmdGetenv(\"%s\")", striAsUnquotedCStri(name));
2802 fflush(stdout););
2803 env_name = stri_to_os_stri(name, &err_info);
2804 if (unlikely(env_name == NULL)) {
2805 logError(printf("cmdGetenv: stri_to_os_stri(\"%s\", *, *) failed:\n"
2806 "err_info=%d\n",
2807 striAsUnquotedCStri(name), err_info););
2808 raise_error(err_info);
2809 value = NULL;
2810 } else {
2811 env_value = os_getenv(env_name);
2812 os_stri_free(env_name);
2813 if (env_value == NULL) {
2814 if (unlikely(!ALLOC_STRI_SIZE_OK(value, 0))) {
2815 err_info = MEMORY_ERROR;
2816 } else {
2817 value->size = 0;
2818 } /* if */
2819 } else {
2820 value = os_stri_to_stri(env_value, &err_info);
2821 os_getenv_string_free(env_value);
2822 } /* if */
2823 if (unlikely(value == NULL)) {
2824 raise_error(err_info);
2825 } /* if */
2826 } /* if */
2827 logFunctionResult(printf("\"%s\"\n", striAsUnquotedCStri(value)););
2828 return value;
2829 } /* cmdGetenv */
2830
2831
2832
2833 /**
2834 * Determine the access time of a file.
2835 * @return the access time of the file.
2836 * @exception MEMORY_ERROR Not enough memory to convert 'filePath'
2837 * to the system path type.
2838 * @exception RANGE_ERROR 'filePath' does not use the standard path
2839 * representation or it cannot be converted to the system
2840 * path type.
2841 * @exception FILE_ERROR A system function returns an error.
2842 */
2843 void cmdGetATime (const const_striType filePath,
2844 intType *year, intType *month, intType *day, intType *hour,
2845 intType *min, intType *sec, intType *micro_sec, intType *time_zone,
2846 boolType *is_dst)
2847
2848 {
2849 os_striType os_path;
2850 os_stat_struct stat_buf;
2851 int stat_result;
2852 int path_info = PATH_IS_NORMAL;
2853 errInfoType err_info = OKAY_NO_ERROR;
2854
2855 /* cmdGetATime */
2856 logFunction(printf("cmdGetATime(\"%s\")\n", striAsUnquotedCStri(filePath)););
2857 os_path = cp_to_os_path(filePath, &path_info, &err_info);
2858 if (unlikely(os_path == NULL)) {
2859 #if MAP_ABSOLUTE_PATH_TO_DRIVE_LETTERS
2860 if (likely(path_info == PATH_IS_EMULATED_ROOT)) {
2861 timFromTimestamp(0,
2862 year, month, day, hour,
2863 min, sec, micro_sec, time_zone, is_dst);
2864 } else
2865 #endif
2866 {
2867 logError(printf("cmdGetATime: cp_to_os_path(\"%s\", *, *) failed:\n"
2868 "path_info=%d, err_info=%d\n",
2869 striAsUnquotedCStri(filePath), path_info, err_info););
2870 raise_error(err_info);
2871 }
2872 } else {
2873 stat_result = os_stat(os_path, &stat_buf);
2874 if (unlikely(stat_result != 0)) {
2875 logError(printf("cmdGetATime: os_stat(\"" FMT_S_OS "\") failed:\n"
2876 "errno=%d\nerror: %s\n",
2877 os_path, errno, strerror(errno)););
2878 err_info = FILE_ERROR;
2879 } else {
2880 /* printf("cmdGetATime: st_atime=" FMT_T "\n", stat_buf.st_atime); */
2881 timFromTimestamp(stat_buf.st_atime,
2882 year, month, day, hour,
2883 min, sec, micro_sec, time_zone, is_dst);
2884 } /* if */
2885 os_stri_free(os_path);
2886 if (unlikely(err_info != OKAY_NO_ERROR)) {
2887 raise_error(err_info);
2888 } /* if */
2889 } /* if */
2890 logFunction(printf("cmdGetATime(" F_D(04) "-" F_D(02) "-" F_D(02) " "
2891 F_D(02) ":" F_D(02) ":" F_D(02) "." F_D(06) " " FMT_D " %d) -->\n",
2892 *year, *month, *day, *hour, *min, *sec,
2893 *micro_sec, *time_zone, *is_dst););
2894 } /* cmdGetATime */
2895
2896
2897
2898 /**
2899 * Determine the change time of a file.
2900 * @return the change time of the file.
2901 * @exception MEMORY_ERROR Not enough memory to convert 'filePath'
2902 * to the system path type.
2903 * @exception RANGE_ERROR 'filePath' does not use the standard path
2904 * representation or it cannot be converted to the system
2905 * path type.
2906 * @exception FILE_ERROR A system function returns an error.
2907 */
2908 void cmdGetCTime (const const_striType filePath,
2909 intType *year, intType *month, intType *day, intType *hour,
2910 intType *min, intType *sec, intType *micro_sec, intType *time_zone,
2911 boolType *is_dst)
2912
2913 {
2914 os_striType os_path;
2915 os_stat_struct stat_buf;
2916 int stat_result;
2917 int path_info = PATH_IS_NORMAL;
2918 errInfoType err_info = OKAY_NO_ERROR;
2919
2920 /* cmdGetCTime */
2921 logFunction(printf("cmdGetCTime(\"%s\")\n", striAsUnquotedCStri(filePath)););
2922 os_path = cp_to_os_path(filePath, &path_info, &err_info);
2923 if (unlikely(os_path == NULL)) {
2924 #if MAP_ABSOLUTE_PATH_TO_DRIVE_LETTERS
2925 if (likely(path_info == PATH_IS_EMULATED_ROOT)) {
2926 timFromTimestamp(0,
2927 year, month, day, hour,
2928 min, sec, micro_sec, time_zone, is_dst);
2929 } else
2930 #endif
2931 {
2932 logError(printf("cmdGetCTime: cp_to_os_path(\"%s\", *, *) failed:\n"
2933 "path_info=%d, err_info=%d\n",
2934 striAsUnquotedCStri(filePath), path_info, err_info););
2935 raise_error(err_info);
2936 }
2937 } else {
2938 stat_result = os_stat(os_path, &stat_buf);
2939 if (unlikely(stat_result != 0)) {
2940 logError(printf("cmdGetCTime: os_stat(\"" FMT_S_OS "\") failed:\n"
2941 "errno=%d\nerror: %s\n",
2942 os_path, errno, strerror(errno)););
2943 err_info = FILE_ERROR;
2944 } else {
2945 /* printf("cmdGetCTime: st_ctime=" FMT_T "\n", stat_buf.st_ctime); */
2946 timFromTimestamp(stat_buf.st_ctime,
2947 year, month, day, hour,
2948 min, sec, micro_sec, time_zone, is_dst);
2949 } /* if */
2950 os_stri_free(os_path);
2951 if (unlikely(err_info != OKAY_NO_ERROR)) {
2952 raise_error(err_info);
2953 } /* if */
2954 } /* if */
2955 logFunction(printf("cmdGetCTime(" F_D(04) "-" F_D(02) "-" F_D(02) " "
2956 F_D(02) ":" F_D(02) ":" F_D(02) "." F_D(06) " " FMT_D " %d) -->\n",
2957 *year, *month, *day, *hour, *min, *sec,
2958 *micro_sec, *time_zone, *is_dst););
2959 } /* cmdGetCTime */
2960
2961
2962
2963 /**
2964 * Determine the modification time of a file.
2965 * @return the modification time of the file.
2966 * @exception MEMORY_ERROR Not enough memory to convert 'filePath'
2967 * to the system path type.
2968 * @exception RANGE_ERROR 'filePath' does not use the standard path
2969 * representation or it cannot be converted to the system
2970 * path type.
2971 * @exception FILE_ERROR A system function returns an error.
2972 */
2973 void cmdGetMTime (const const_striType filePath,
2974 intType *year, intType *month, intType *day, intType *hour,
2975 intType *min, intType *sec, intType *micro_sec, intType *time_zone,
2976 boolType *is_dst)
2977
2978 {
2979 os_striType os_path;
2980 os_stat_struct stat_buf;
2981 int stat_result;
2982 int path_info = PATH_IS_NORMAL;
2983 errInfoType err_info = OKAY_NO_ERROR;
2984
2985 /* cmdGetMTime */
2986 logFunction(printf("cmdGetMTime(\"%s\")\n", striAsUnquotedCStri(filePath)););
2987 os_path = cp_to_os_path(filePath, &path_info, &err_info);
2988 if (unlikely(os_path == NULL)) {
2989 #if MAP_ABSOLUTE_PATH_TO_DRIVE_LETTERS
2990 if (likely(path_info == PATH_IS_EMULATED_ROOT)) {
2991 timFromTimestamp(0,
2992 year, month, day, hour,
2993 min, sec, micro_sec, time_zone, is_dst);
2994 } else
2995 #endif
2996 {
2997 logError(printf("cmdGetMTime: cp_to_os_path(\"%s\", *, *) failed:\n"
2998 "path_info=%d, err_info=%d\n",
2999 striAsUnquotedCStri(filePath), path_info, err_info););
3000 raise_error(err_info);
3001 }
3002 } else {
3003 stat_result = os_stat(os_path, &stat_buf);
3004 if (unlikely(stat_result != 0)) {
3005 logError(printf("cmdGetMTime: os_stat(\"" FMT_S_OS "\") failed:\n"
3006 "errno=%d\nerror: %s\n",
3007 os_path, errno, strerror(errno)););
3008 err_info = FILE_ERROR;
3009 } else {
3010 /* printf("cmdGetMTime: st_mtime=" FMT_T "\n", stat_buf.st_mtime); */
3011 timFromTimestamp(stat_buf.st_mtime,
3012 year, month, day, hour,
3013 min, sec, micro_sec, time_zone, is_dst);
3014 } /* if */
3015 os_stri_free(os_path);
3016 if (unlikely(err_info != OKAY_NO_ERROR)) {
3017 raise_error(err_info);
3018 } /* if */
3019 } /* if */
3020 logFunction(printf("cmdGetMTime(" F_D(04) "-" F_D(02) "-" F_D(02) " "
3021 F_D(02) ":" F_D(02) ":" F_D(02) "." F_D(06) " " FMT_D " %d) -->\n",
3022 *year, *month, *day, *hour, *min, *sec,
3023 *micro_sec, *time_zone, *is_dst););
3024 } /* cmdGetMTime */
3025
3026
3027
3028 /**
3029 * Returns the search path of the system as array of strings.
3030 * @return the search path of the system.
3031 * @exception MEMORY_ERROR Not enough memory to create the result.
3032 */
3033 rtlArrayType cmdGetSearchPath (void)
3034
3035 {
3036 errInfoType err_info = OKAY_NO_ERROR;
3037 rtlArrayType searchPath;
3038
3039 /* cmdGetSearchPath */
3040 logFunction(printf("cmdGetSearchPath()\n"););
3041 searchPath = getSearchPath(&err_info);
3042 if (unlikely(searchPath == NULL)) {
3043 logError(printf("cmdGetSearchPath: getSearchPath(*) failed:\n"
3044 "err_info=%d\n",
3045 err_info););
3046 raise_error(err_info);
3047 } /* if */
3048 return searchPath;
3049 } /* cmdGetSearchPath */
3050
3051
3052
3053 /**
3054 * Determine the home directory of the user.
3055 * This function should be preferred over the use of an environment
3056 * variable such as $HOME. $HOME is not supported under all operating
3057 * systems and it is not guaranteed, that it uses the standard path
3058 * representation.
3059 * @return The absolute path of the home directory.
3060 * @exception MEMORY_ERROR Not enough memory to represent the
3061 * result string.
3062 * @exception FILE_ERROR Not able to determine the home directory.
3063 */
3064 striType cmdHomeDir (void)
3065
3066 {
3067 #ifdef DETERMINE_OS_PROPERTIES_AT_RUNTIME
3068 static const os_charType home_dir_env_var_unx[] = {'H', 'O', 'M', 'E', 0};
3069 static const os_charType home_dir_env_var_win[] = {'U', 'S', 'E', 'R',
3070 'P', 'R', 'O', 'F', 'I', 'L', 'E', 0};
3071 const os_charType *home_dir_env_var;
3072 #else
3073 static const os_charType home_dir_env_var[] = HOME_DIR_ENV_VAR;
3074 #endif
3075 os_striType os_home_dir;
3076 #ifdef DEFAULT_HOME_DIR
3077 static const os_charType default_home_dir[] = DEFAULT_HOME_DIR;
3078 #endif
3079 errInfoType err_info = OKAY_NO_ERROR;
3080 striType home_dir;
3081
3082 /* cmdHomeDir */
3083 logFunction(printf("cmdHomeDir\n"););
3084 #ifdef DETERMINE_OS_PROPERTIES_AT_RUNTIME
3085 if (shellUsesDriveLetters) {
3086 home_dir_env_var = home_dir_env_var_win;
3087 } else {
3088 home_dir_env_var = home_dir_env_var_unx;
3089 } /* if */
3090 #endif
3091 os_home_dir = os_getenv(home_dir_env_var);
3092 /* printf("os_getenv(\"" FMT_S_OS "\") returns: " FMT_S_OS "\n",
3093 home_dir_env_var, os_home_dir); */
3094 if (unlikely(os_home_dir == NULL)) {
3095 #ifdef DEFAULT_HOME_DIR
3096 home_dir = cp_from_os_path(default_home_dir, &err_info);
3097 #else
3098 err_info = FILE_ERROR;
3099 home_dir = NULL;
3100 #endif
3101 } else {
3102 home_dir = cp_from_os_path(os_home_dir, &err_info);
3103 os_getenv_string_free(os_home_dir);
3104 } /* if */
3105 if (unlikely(home_dir == NULL)) {
3106 raise_error(err_info);
3107 } /* if */
3108 logFunction(printf("cmdHomeDir --> \"%s\"\n", striAsUnquotedCStri(home_dir)););
3109 return home_dir;
3110 } /* cmdHomeDir */
3111
3112
3113
3114 /**
3115 * Determine the filenames in a directory.
3116 * The files "." and ".." are left out from the result.
3117 * Note that the function returns only the filenames.
3118 * Additional information must be obtained with other calls.
3119 * @return a string-array containing the filenames in the directory.
3120 * @exception MEMORY_ERROR Not enough memory to convert 'dirPath'
3121 * to the system path type or not enough memory to
3122 * represent the result 'string array'.
3123 * @exception RANGE_ERROR 'dirPath' does not use the standard path
3124 * representation or it cannot be converted to the system
3125 * path type.
3126 * @exception FILE_ERROR A system function returns an error.
3127 */
3128 rtlArrayType cmdLs (const const_striType dirPath)
3129
3130 {
3131 errInfoType err_info = OKAY_NO_ERROR;
3132 rtlArrayType result;
3133
3134 /* cmdLs */
3135 logFunction(printf("cmdLs(\"%s\")\n", striAsUnquotedCStri(dirPath)););
3136 result = read_dir(dirPath, &err_info);
3137 if (unlikely(result == NULL)) {
3138 logError(printf("cmdLs: read_dir(\"%s\", *) failed:\n"
3139 "err_info=%d\n",
3140 striAsUnquotedCStri(dirPath), err_info););
3141 raise_error(err_info);
3142 } else {
3143 qsort((void *) result->arr,
3144 (size_t) (result->max_position - result->min_position + 1),
3145 sizeof(rtlObjectType), &cmp_mem);
3146 } /* if */
3147 logFunction(if (result == NULL) {
3148 printf("cmdLs --> NULL\n");
3149 } else {
3150 printf("cmdLs --> array[size = " FMT_U_MEM "]\n",
3151 arraySize(result));
3152 });
3153 return result;
3154 } /* cmdLs */
3155
3156
3157
3158 /**
3159 * Creates a new directory.
3160 * @exception MEMORY_ERROR Not enough memory to convert 'dirPath' to
3161 * the system path type.
3162 * @exception RANGE_ERROR 'dirPath' does not use the standard path
3163 * representation or it cannot be converted to the system
3164 * path type.
3165 * @exception FILE_ERROR A system function returns an error.
3166 */
3167 void cmdMkdir (const const_striType dirPath)
3168
3169 {
3170 os_striType os_path;
3171 int mkdir_result;
3172 int path_info;
3173 errInfoType err_info = OKAY_NO_ERROR;
3174
3175 /* cmdMkdir */
3176 logFunction(printf("cmdMkdir(\"%s\")\n", striAsUnquotedCStri(dirPath)););
3177 os_path = cp_to_os_path(dirPath, &path_info, &err_info);
3178 if (unlikely(os_path == NULL)) {
3179 logError(printf("cmdMkdir: cp_to_os_path(\"%s\", *, *) failed:\n"
3180 "path_info=%d, err_info=%d\n",
3181 striAsUnquotedCStri(dirPath), path_info, err_info););
3182 raise_error(err_info);
3183 } else {
3184 /* printf("mkdir(\"" FMT_S_OS "\")\n", os_path); */
3185 mkdir_result = os_mkdir(os_path, 0777);
3186 if (unlikely(mkdir_result != 0)) {
3187 logError(printf("cmdMkdir: os_mkdir(\"" FMT_S_OS "\", 0777) failed:\n"
3188 "errno=%d\nerror: %s\n",
3189 os_path, errno, strerror(errno)););
3190 os_stri_free(os_path);
3191 raise_error(FILE_ERROR);
3192 } else {
3193 os_stri_free(os_path);
3194 } /* if */
3195 } /* if */
3196 } /* cmdMkdir */
3197
3198
3199
3200 /**
3201 * Move and rename a file or directory tree.
3202 * The function uses the C 'rename()' function. If 'rename()' fails
3203 * the file (or directory tree) is cloned with 'cloneFile' (which
3204 * preserves permissions/mode, ownership and timestamps) to the new
3205 * place and with the new name. If 'cloneFile' succeeds the original
3206 * file is deleted. If 'cloneFile' fails (no space on device or
3207 * other reason) all remains of the failed clone are removed. Note
3208 * that 'cloneFile' works for symbolic links but does not preserve
3209 * hard links (they are resolved to distinct files).
3210 * @exception MEMORY_ERROR Not enough memory to convert 'sourcePath'
3211 * or 'destPath' to the system path type.
3212 * @exception RANGE_ERROR 'sourcePath' or 'destPath' does not use
3213 * the standard path representation or one of them cannot be
3214 * converted to the system path type.
3215 * @exception FILE_ERROR Source file does not exist, destination file
3216 * already exists or a system function returns an error.
3217 */
3218 void cmdMove (const const_striType sourcePath, const const_striType destPath)
3219
3220 {
3221 os_striType os_sourcePath;
3222 os_striType os_destPath;
3223 int path_info;
3224 errInfoType err_info = OKAY_NO_ERROR;
3225
3226 /* cmdMove */
3227 logFunction(printf("cmdMove(\"%s\", ", striAsUnquotedCStri(sourcePath));
3228 printf("\"%s\")\n", striAsUnquotedCStri(destPath)););
3229 os_sourcePath = cp_to_os_path(sourcePath, &path_info, &err_info);
3230 if (unlikely(os_sourcePath == NULL)) {
3231 logError(printf("cmdMove: cp_to_os_path(\"%s\", *, *) failed:\n"
3232 "path_info=%d, err_info=%d\n",
3233 striAsUnquotedCStri(sourcePath), path_info, err_info););
3234 } else {
3235 os_destPath = cp_to_os_path(destPath, &path_info, &err_info);
3236 if (unlikely(os_destPath == NULL)) {
3237 logError(printf("cmdMove: cp_to_os_path(\"%s\", *, *) failed:\n"
3238 "path_info=%d, err_info=%d\n",
3239 striAsUnquotedCStri(destPath), path_info, err_info););
3240 } else {
3241 move_any_file(os_sourcePath, os_destPath, &err_info);
3242 os_stri_free(os_destPath);
3243 } /* if */
3244 os_stri_free(os_sourcePath);
3245 } /* if */
3246 if (unlikely(err_info != OKAY_NO_ERROR)) {
3247 raise_error(err_info);
3248 } /* if */
3249 } /* cmdMove */
3250
3251
3252
3253 /**
3254 * Reads the destination of a symbolic link.
3255 * @return The destination referred by the symbolic link.
3256 * @exception MEMORY_ERROR Not enough memory to convert 'filePath'
3257 * to the system path type or not enough memory to
3258 * represent the result string.
3259 * @exception RANGE_ERROR 'filePath' does not use the standard path
3260 * representation or it cannot be converted to the system
3261 * path type.
3262 * @exception FILE_ERROR The file described with the path does not
3263 * exist or is not a symbolic link.
3264 */
3265 striType cmdReadLink (const const_striType filePath)
3266
3267 {
3268 errInfoType err_info = OKAY_NO_ERROR;
3269 striType destination;
3270
3271 /* cmdReadLink */
3272 logFunction(printf("cmdReadLink(\"%s\")\n",
3273 striAsUnquotedCStri(filePath)););
3274 #if HAS_READLINK
3275 destination = doReadLink(filePath, &err_info);
3276 if (unlikely(destination == NULL)) {
3277 raise_error(err_info);
3278 } /* if */
3279 #else
3280 raise_error(FILE_ERROR);
3281 destination = NULL;
3282 #endif
3283 logFunction(printf("cmdReadLink --> \"%s\"\n",
3284 striAsUnquotedCStri(destination)););
3285 return destination;
3286 } /* cmdReadLink */
3287
3288
3289
3290 /**
3291 * Remove a file of any type unless it is a directory that is not empty.
3292 * An attempt to remove a directory that is not empty triggers FILE_ERROR.
3293 * @exception MEMORY_ERROR Not enough memory to convert 'filePath' to
3294 * the system path type.
3295 * @exception RANGE_ERROR 'filePath' does not use the standard path
3296 * representation or it cannot be converted to the system
3297 * path type.
3298 * @exception FILE_ERROR The file does not exist or it is a directory
3299 * that is not empty or a system function returns an error.
3300 */
3301 void cmdRemoveFile (const const_striType filePath)
3302
3303 {
3304 os_striType os_path;
3305 int path_info;
3306 #if REMOVE_FAILS_FOR_EMPTY_DIRS
3307 os_stat_struct file_stat;
3308 #endif
3309 #ifdef RENAME_BEFORE_REMOVE
3310 os_striType temp_name;
3311 #endif
3312 errInfoType err_info = OKAY_NO_ERROR;
3313
3314 /* cmdRemoveFile */
3315 logFunction(printf("cmdRemoveFile(\"%s\")\n", striAsUnquotedCStri(filePath)););
3316 os_path = cp_to_os_path(filePath, &path_info, &err_info);
3317 if (unlikely(os_path == NULL)) {
3318 logError(printf("cmdRemoveFile: cp_to_os_path(\"%s\", *, *) failed:\n"
3319 "path_info=%d, err_info=%d\n",
3320 striAsUnquotedCStri(filePath), path_info, err_info););
3321 } else {
3322 #if REMOVE_FAILS_FOR_EMPTY_DIRS
3323 if (os_lstat(os_path, &file_stat) != 0) {
3324 logError(printf("cmdRemoveFile: os_lstat(\"" FMT_S_OS "\") failed:\n"
3325 "errno=%d\nerror: %s\n",
3326 os_path, errno, strerror(errno)););
3327 err_info = FILE_ERROR;
3328 } else {
3329 #ifdef RENAME_BEFORE_REMOVE
3330 temp_name = temp_name_in_dir(os_path);
3331 if (unlikely(temp_name == NULL)) {
3332 err_info = MEMORY_ERROR;
3333 } else {
3334 if (os_rename(os_path, temp_name) != 0) {
3335 logError(printf("cmdRemoveFile: "
3336 "os_rename(\"" FMT_S_OS "\", \"" FMT_S_OS "\") failed:\n"
3337 "errno=%d\nerror: %s\n",
3338 os_path, temp_name, errno, strerror(errno)););
3339 err_info = FILE_ERROR;
3340 } else {
3341 if (S_ISDIR(file_stat.st_mode)) {
3342 if (os_rmdir(temp_name) != 0) {
3343 logError(printf("cmdRemoveFile: os_rmdir(\"" FMT_S_OS "\") failed:\n"
3344 "errno=%d\nerror: %s\n",
3345 temp_name, errno, strerror(errno)););
3346 err_info = FILE_ERROR;
3347 } /* if */
3348 } else {
3349 if (os_remove(temp_name) != 0) {
3350 logError(printf("cmdRemoveFile: os_remove(\"" FMT_S_OS "\") failed:\n"
3351 "errno=%d\nerror: %s\n",
3352 temp_name, errno, strerror(errno)););
3353 err_info = FILE_ERROR;
3354 } /* if */
3355 } /* if */
3356 if (unlikely(err_info != OKAY_NO_ERROR)) {
3357 /* Rename back to the original name. */
3358 if (os_rename(temp_name, os_path) != 0) {
3359 logError(printf("cmdRemoveFile: "
3360 "os_rename(\"" FMT_S_OS "\", \"" FMT_S_OS "\") failed:\n"
3361 "errno=%d\nerror: %s\n",
3362 temp_name, os_path, errno, strerror(errno)););
3363 } /* if */
3364 } /* if */
3365 } /* if */
3366 os_stri_free(temp_name);
3367 } /* if */
3368 #else
3369 if (S_ISDIR(file_stat.st_mode)) {
3370 if (os_rmdir(os_path) != 0) {
3371 logError(printf("cmdRemoveFile: os_rmdir(\"" FMT_S_OS "\") failed:\n"
3372 "errno=%d\nerror: %s\n",
3373 os_path, errno, strerror(errno)););
3374 err_info = FILE_ERROR;
3375 } /* if */
3376 } else {
3377 if (os_remove(os_path) != 0) {
3378 logError(printf("cmdRemoveFile: os_remove(\"" FMT_S_OS "\") failed:\n"
3379 "errno=%d\nerror: %s\n",
3380 os_path, errno, strerror(errno)););
3381 err_info = FILE_ERROR;
3382 } /* if */
3383 } /* if */
3384 #endif
3385 } /* if */
3386 #else
3387 #ifdef RENAME_BEFORE_REMOVE
3388 temp_name = temp_name_in_dir(os_path);
3389 if (unlikely(temp_name == NULL)) {
3390 err_info = MEMORY_ERROR;
3391 } else {
3392 if (os_rename(os_path, temp_name) != 0) {
3393 logError(printf("cmdRemoveFile: "
3394 "os_rename(\"" FMT_S_OS "\", \"" FMT_S_OS "\") failed:\n"
3395 "errno=%d\nerror: %s\n",
3396 os_path, temp_name, errno, strerror(errno)););
3397 err_info = FILE_ERROR;
3398 } else {
3399 if (os_remove(temp_name) != 0) {
3400 logError(printf("cmdRemoveFile: os_remove(\"" FMT_S_OS "\") failed:\n"
3401 "errno=%d\nerror: %s\n",
3402 temp_name, errno, strerror(errno)););
3403 if (os_rename(temp_name, os_path) != 0) {
3404 /* Rename back to the original name. */
3405 logError(printf("cmdRemoveFile: "
3406 "os_rename(\"" FMT_S_OS "\", \"" FMT_S_OS "\") failed:\n"
3407 "errno=%d\nerror: %s\n",
3408 temp_name, os_path, errno, strerror(errno)););
3409 } /* if */
3410 err_info = FILE_ERROR;
3411 } /* if */
3412 } /* if */
3413 os_stri_free(temp_name);
3414 } /* if */
3415 #else
3416 if (os_remove(os_path) != 0) {
3417 logError(printf("cmdRemoveFile: os_remove(\"" FMT_S_OS "\") failed:\n"
3418 "errno=%d\nerror: %s\n",
3419 os_path, errno, strerror(errno)););
3420 err_info = FILE_ERROR;
3421 } /* if */
3422 #endif
3423 #endif
3424 #ifdef CHECK_IF_FILE_IS_REMOVED
3425 if (err_info == OKAY_NO_ERROR &&
3426 os_lstat(os_path, &file_stat) == 0) {
3427 logError(printf("cmdRemoveFile: File \"" FMT_S_OS "\" still present.\n",
3428 os_path););
3429 /* err_info = FILE_ERROR; */
3430 } /* if */
3431 #endif
3432 os_stri_free(os_path);
3433 } /* if */
3434 if (unlikely(err_info != OKAY_NO_ERROR)) {
3435 raise_error(err_info);
3436 } /* if */
3437 } /* cmdRemoveFile */
3438
3439
3440
3441 /**
3442 * Remove a file of any type inclusive a directory tree.
3443 * @exception MEMORY_ERROR Not enough memory to convert 'filePath' to
3444 * the system path type.
3445 * @exception RANGE_ERROR 'filePath' does not use the standard path
3446 * representation or it cannot be converted to the system
3447 * path type.
3448 * @exception FILE_ERROR The file does not exist or a system function
3449 * returns an error.
3450 */
3451 void cmdRemoveTree (const const_striType filePath)
3452
3453 {
3454 os_striType os_path;
3455 int path_info;
3456 os_stat_struct file_stat;
3457 #ifdef RENAME_BEFORE_REMOVE
3458 os_striType temp_name;
3459 #endif
3460 errInfoType err_info = OKAY_NO_ERROR;
3461
3462 /* cmdRemoveTree */
3463 logFunction(printf("cmdRemoveTree(\"%s\")\n", striAsUnquotedCStri(filePath)););
3464 os_path = cp_to_os_path(filePath, &path_info, &err_info);
3465 if (unlikely(os_path == NULL)) {
3466 logError(printf("cmdRemoveTree: cp_to_os_path(\"%s\", *, *) failed:\n"
3467 "path_info=%d, err_info=%d\n",
3468 striAsUnquotedCStri(filePath), path_info, err_info););
3469 } else {
3470 if (os_lstat(os_path, &file_stat) != 0) {
3471 logError(printf("cmdRemoveTree: os_lstat(\"" FMT_S_OS "\") failed:\n"
3472 "errno=%d\nerror: %s\n",
3473 os_path, errno, strerror(errno)););
3474 err_info = FILE_ERROR;
3475 } else {
3476 #ifdef RENAME_BEFORE_REMOVE
3477 temp_name = temp_name_in_dir(os_path);
3478 if (unlikely(temp_name == NULL)) {
3479 err_info = MEMORY_ERROR;
3480 } else {
3481 if (os_rename(os_path, temp_name) != 0) {
3482 logError(printf("cmdRemoveTree: "
3483 "os_rename(\"" FMT_S_OS "\", \"" FMT_S_OS "\") failed:\n"
3484 "errno=%d\nerror: %s\n",
3485 os_path, temp_name, errno, strerror(errno)););
3486 err_info = FILE_ERROR;
3487 } else {
3488 if (S_ISDIR(file_stat.st_mode)) {
3489 remove_dir(temp_name, &err_info);
3490 } else {
3491 if (os_remove(temp_name) != 0) {
3492 logError(printf("cmdRemoveTree: os_remove(\"" FMT_S_OS "\") failed:\n"
3493 "errno=%d\nerror: %s\n",
3494 os_path, errno, strerror(errno)););
3495 err_info = FILE_ERROR;
3496 } /* if */
3497 } /* if */
3498 if (unlikely(err_info != OKAY_NO_ERROR)) {
3499 if (os_rename(temp_name, os_path) != 0) {
3500 /* Rename back to the original name. */
3501 logError(printf("cmdRemoveTree: "
3502 "os_rename(\"" FMT_S_OS "\", \"" FMT_S_OS "\") failed:\n"
3503 "errno=%d\nerror: %s\n",
3504 temp_name, os_path, errno, strerror(errno)););
3505 } /* if */
3506 } /* if */
3507 } /* if */
3508 os_stri_free(temp_name);
3509 } /* if */
3510 #else
3511 if (S_ISDIR(file_stat.st_mode)) {
3512 remove_dir(os_path, &err_info);
3513 } else {
3514 if (os_remove(os_path) != 0) {
3515 logError(printf("cmdRemoveTree: os_remove(\"" FMT_S_OS "\") failed:\n"
3516 "errno=%d\nerror: %s\n",
3517 os_path, errno, strerror(errno)););
3518 err_info = FILE_ERROR;
3519 } /* if */
3520 } /* if */
3521 #endif
3522 } /* if */
3523 #ifdef CHECK_IF_FILE_IS_REMOVED
3524 if (err_info == OKAY_NO_ERROR &&
3525 os_lstat(os_path, &file_stat) == 0) {
3526 logError(printf("cmdRemoveTree: File \"" FMT_S_OS "\" still present.\n",
3527 os_path););
3528 /* err_info = FILE_ERROR; */
3529 } /* if */
3530 #endif
3531 os_stri_free(os_path);
3532 } /* if */
3533 if (unlikely(err_info != OKAY_NO_ERROR)) {
3534 raise_error(err_info);
3535 } /* if */
3536 } /* cmdRemoveTree */
3537
3538
3539
3540 /**
3541 * Add or change an environment variable.
3542 * The function searches the environment for an environment variable
3543 * with the given 'name'. If such an environment variable exists the
3544 * corresponding value is changed to 'value'. If no environment variable
3545 * with the given 'name' exists a new environment variable 'name' with
3546 * the value 'value' is created.
3547 * @exception MEMORY_ERROR Not enough memory to convert 'name' or 'value'
3548 * to the system string type.
3549 * @exception RANGE_ERROR 'name' or 'value' cannot be converted to the
3550 * system string type or a system function returns an error.
3551 */
3552 void cmdSetenv (const const_striType name, const const_striType value)
3553
3554 {
3555 errInfoType err_info = OKAY_NO_ERROR;
3556
3557 /* cmdSetenv */
3558 setEnvironmentVariable(name, value, &err_info);
3559 if (unlikely(err_info != OKAY_NO_ERROR)) {
3560 raise_error(err_info);
3561 } /* if */
3562 } /* cmdSetenv */
3563
3564
3565
3566 /**
3567 * Set the access time of a file.
3568 * @exception MEMORY_ERROR Not enough memory to convert 'filePath'
3569 * to the system path type.
3570 * @exception RANGE_ERROR 'filePath' does not use the standard path
3571 * representation or it cannot be converted to the system
3572 * path type.
3573 * @exception RANGE_ERROR 'aTime' is invalid or cannot be
3574 * converted to the system file time.
3575 * @exception FILE_ERROR A system function returns an error.
3576 */
3577 void cmdSetATime (const const_striType filePath,
3578 intType year, intType month, intType day, intType hour,
3579 intType min, intType sec, intType micro_sec, intType time_zone)
3580
3581 {
3582 const_os_striType os_path;
3583 os_stat_struct stat_buf;
3584 os_utimbuf_struct utime_buf;
3585 int path_info;
3586 errInfoType err_info = OKAY_NO_ERROR;
3587
3588 /* cmdSetATime */
3589 logFunction(printf("cmdSetATime(\"%s\", " F_D(04) "-" F_D(02) "-" F_D(02) " "
3590 F_D(02) ":" F_D(02) ":" F_D(02) "." F_D(06) " " FMT_D ")\n",
3591 striAsUnquotedCStri(filePath), year, month, day,
3592 hour, min, sec, micro_sec, time_zone););
3593 os_path = cp_to_os_path(filePath, &path_info, &err_info);
3594 if (unlikely(os_path == NULL)) {
3595 logError(printf("cmdSetATime: cp_to_os_path(\"%s\", *, *) failed:\n"
3596 "path_info=%d, err_info=%d\n",
3597 striAsUnquotedCStri(filePath), path_info, err_info););
3598 } else {
3599 if (os_stat(os_path, &stat_buf) == 0) {
3600 utime_buf.actime = timToOsTimestamp(year, month, day, hour,
3601 min, sec, time_zone);
3602 /* printf("cmdSetATime: actime=" FMT_T "\n", utime_buf.actime); */
3603 utime_buf.modtime = stat_buf.st_mtime;
3604 if (unlikely(utime_buf.actime == (time_t) TIME_T_ERROR)) {
3605 logError(printf("cmdSetATime: timToOsTimestamp("
3606 F_D(04) "-" F_D(02) "-" F_D(02) " " F_D(02) ":"
3607 F_D(02) ":" F_D(02) "." F_D(06) " " FMT_D ") failed.\n",
3608 year, month, day, hour, min, sec,
3609 micro_sec, time_zone););
3610 err_info = RANGE_ERROR;
3611 } else if (unlikely(os_utime(os_path, &utime_buf) != 0)) {
3612 logError(printf("cmdSetATime: os_utime(\"" FMT_S_OS "\") failed:\n"
3613 "errno=%d\nerror: %s\n",
3614 os_path, errno, strerror(errno)););
3615 err_info = FILE_ERROR;
3616 } /* if */
3617 } else {
3618 err_info = FILE_ERROR;
3619 } /* if */
3620 os_stri_free(os_path);
3621 } /* if */
3622 if (unlikely(err_info != OKAY_NO_ERROR)) {
3623 raise_error(err_info);
3624 } /* if */
3625 logFunction(printf("cmdSetATime -->\n"););
3626 } /* cmdSetATime */
3627
3628
3629
3630 /**
3631 * Change the file mode (permissions) of a file.
3632 * @exception MEMORY_ERROR Not enough memory to convert 'filePath'
3633 * to the system path type.
3634 * @exception RANGE_ERROR 'filePath' does not use the standard path
3635 * representation or it cannot be converted to the system
3636 * path type.
3637 * @exception FILE_ERROR A system function returns an error.
3638 */
3639 void cmdSetFileMode (const const_striType filePath, const const_setType mode)
3640
3641 {
3642 os_striType os_path;
3643 intType intType_mode;
3644 int int_mode;
3645 int chmod_result;
3646 int path_info;
3647 errInfoType err_info = OKAY_NO_ERROR;
3648
3649 /* cmdSetFileMode */
3650 logFunction(printf("cmdSetFileMode(\"%s\", 0x" F_X(3) ")\n",
3651 striAsUnquotedCStri(filePath), setSConv(mode)););
3652 os_path = cp_to_os_path(filePath, &path_info, &err_info);
3653 if (unlikely(os_path == NULL)) {
3654 logError(printf("cmdSetFileMode: cp_to_os_path(\"%s\", *, *) failed:\n"
3655 "path_info=%d, err_info=%d\n",
3656 striAsUnquotedCStri(filePath), path_info, err_info););
3657 } else {
3658 intType_mode = setSConv(mode);
3659 if (intType_mode >= 0 && intType_mode <= 0777) {
3660 /* Just the read, write and execute permissions are accepted */
3661 int_mode = (int) intType_mode;
3662 /* printf("cmdSetFileMode: mode=0%o\n", int_mode); */
3663 #if MODE_BITS_NORMAL
3664 chmod_result = os_chmod(os_path, int_mode);
3665 #else
3666 /* Force the bits to the standard sequence */
3667 chmod_result = os_chmod(os_path,
3668 (int_mode & 0400 ? S_IRUSR : 0) |
3669 (int_mode & 0200 ? S_IWUSR : 0) |
3670 (int_mode & 0100 ? S_IXUSR : 0) |
3671 (int_mode & 0040 ? S_IRGRP : 0) |
3672 (int_mode & 0020 ? S_IWGRP : 0) |
3673 (int_mode & 0010 ? S_IXGRP : 0) |
3674 (int_mode & 0004 ? S_IROTH : 0) |
3675 (int_mode & 0002 ? S_IWOTH : 0) |
3676 (int_mode & 0001 ? S_IXOTH : 0));
3677 #endif
3678 if (chmod_result != 0) {
3679 logError(printf("cmdSetFileMode: os_chmod(\"" FMT_S_OS "\") failed:\n"
3680 "errno=%d\nerror: %s\n",
3681 os_path, errno, strerror(errno)););
3682 err_info = FILE_ERROR;
3683 } /* if */
3684 } else {
3685 logError(printf("cmdSetFileMode(\"%s\", 0x" F_X(3) ") failed:\n"
3686 "Mode outside allowed range.\n",
3687 striAsUnquotedCStri(filePath), setSConv(mode)););
3688 err_info = RANGE_ERROR;
3689 } /* if */
3690 os_stri_free(os_path);
3691 } /* if */
3692 if (unlikely(err_info != OKAY_NO_ERROR)) {
3693 raise_error(err_info);
3694 } /* if */
3695 } /* cmdSetFileMode */
3696
3697
3698
3699 /**
3700 * Set the modification time of a file.
3701 * @exception MEMORY_ERROR Not enough memory to convert 'filePath'
3702 * to the system path type.
3703 * @exception RANGE_ERROR 'filePath' does not use the standard path
3704 * representation or it cannot be converted to the system
3705 * path type.
3706 * @exception RANGE_ERROR 'aTime' is invalid or cannot be
3707 * converted to the system file time.
3708 * @exception FILE_ERROR A system function returns an error.
3709 */
3710 void cmdSetMTime (const const_striType filePath,
3711 intType year, intType month, intType day, intType hour,
3712 intType min, intType sec, intType micro_sec, intType time_zone)
3713
3714 {
3715 const_os_striType os_path;
3716 os_stat_struct stat_buf;
3717 os_utimbuf_struct utime_buf;
3718 int path_info;
3719 errInfoType err_info = OKAY_NO_ERROR;
3720
3721 /* cmdSetMTime */
3722 logFunction(printf("cmdSetMTime(\"%s\", " F_D(04) "-" F_D(02) "-" F_D(02) " "
3723 F_D(02) ":" F_D(02) ":" F_D(02) "." F_D(06) " " FMT_D ")\n",
3724 striAsUnquotedCStri(filePath), year, month,
3725 day, hour, min, sec, micro_sec, time_zone););
3726 os_path = cp_to_os_path(filePath, &path_info, &err_info);
3727 if (unlikely(os_path == NULL)) {
3728 logError(printf("cmdSetMTime: cp_to_os_path(\"%s\", *, *) failed:\n"
3729 "path_info=%d, err_info=%d\n",
3730 striAsUnquotedCStri(filePath), path_info, err_info););
3731 } else {
3732 if (os_stat(os_path, &stat_buf) == 0) {
3733 utime_buf.actime = stat_buf.st_atime;
3734 utime_buf.modtime = timToOsTimestamp(year, month, day, hour,
3735 min, sec, time_zone);
3736 /* printf("cmdSetMTime: modtime=" FMT_T "\n", utime_buf.modtime); */
3737 if (unlikely(utime_buf.modtime == (time_t) TIME_T_ERROR)) {
3738 logError(printf("cmdSetMTime: timToOsTimestamp("
3739 F_D(04) "-" F_D(02) "-" F_D(02) " " F_D(02) ":"
3740 F_D(02) ":" F_D(02) "." F_D(06) " " FMT_D ") failed.\n",
3741 year, month, day, hour, min, sec,
3742 micro_sec, time_zone););
3743 err_info = RANGE_ERROR;
3744 } else if (unlikely(os_utime(os_path, &utime_buf) != 0)) {
3745 logError(printf("cmdSetMTime: os_utime(\"" FMT_S_OS "\") failed:\n"
3746 "errno=%d\nerror: %s\n",
3747 os_path, errno, strerror(errno)););
3748 err_info = FILE_ERROR;
3749 } /* if */
3750 } else {
3751 err_info = FILE_ERROR;
3752 } /* if */
3753 os_stri_free(os_path);
3754 } /* if */
3755 if (unlikely(err_info != OKAY_NO_ERROR)) {
3756 raise_error(err_info);
3757 } /* if */
3758 logFunction(printf("cmdSetMTime -->\n"););
3759 } /* cmdSetMTime */
3760
3761
3762
3763 /**
3764 * Sets the search path from an array of strings.
3765 * The search path is used by the current process and its sub processes.
3766 * The path of parent processes is not affected by this function.
3767 * @exception MEMORY_ERROR Not enough memory to convert the path
3768 * to the system string type.
3769 * @exception RANGE_ERROR The path cannot be converted to the
3770 * system string type or a system function returns an error.
3771 */
3772 void cmdSetSearchPath (rtlArrayType searchPath)
3773
3774 {
3775 errInfoType err_info = OKAY_NO_ERROR;
3776
3777 /* cmdSetSearchPath */
3778 setSearchPath(searchPath, &err_info);
3779 if (unlikely(err_info != OKAY_NO_ERROR)) {
3780 raise_error(err_info);
3781 } /* if */
3782 } /* cmdSetSearchPath */
3783
3784
3785
3786 /**
3787 * Use the shell to execute a 'command' with 'parameters'.
3788 * Parameters which contain a space must be enclosed in double
3789 * quotes (E.g.: shell("aCommand", "\"par 1\" par2"); ). The
3790 * commands supported and the format of the 'parameters' are not
3791 * covered by the description of the 'shell' function. Due to the
3792 * usage of the operating system shell and external programs, it is
3793 * hard to write portable programs, which use the 'shell' function.
3794 * @param command Name of the command to be executed. A path must
3795 * use the standard path representation.
3796 * @param parameters Space separated list of parameters for the
3797 * 'command', or "" if there are no parameters.
3798 * @return the return code of the executed command or of the shell.
3799 */
3800 intType cmdShell (const const_striType command, const const_striType parameters)
3801
3802 {
3803 os_striType os_command;
3804 errInfoType err_info = OKAY_NO_ERROR;
3805 intType result;
3806
3807 /* cmdShell */
3808 logFunction(printf("cmdShell(\"%s\", ", striAsUnquotedCStri(command));
3809 printf("\"%s\")\n", striAsUnquotedCStri(parameters)););
3810 #if defined USE_EXTENDED_LENGTH_PATH && USE_EXTENDED_LENGTH_PATH
3811 adjustCwdForShell(&err_info);
3812 #endif
3813 os_command = cp_to_command(command, parameters, &err_info);
3814 if (unlikely(os_command == NULL)) {
3815 logError(printf("cmdShell: cp_to_command(\"%s\", ",
3816 striAsUnquotedCStri(command));
3817 printf("\"%s\", *) failed:\n"
3818 "err_info=%d\n",
3819 striAsUnquotedCStri(parameters), err_info););
3820 raise_error(err_info);
3821 result = 0;
3822 } else {
3823 logMessage(printf("cmdShell: os_command: \"" FMT_S_OS "\"\n", os_command););
3824 result = (intType) os_system(os_command);
3825 /* if (result != 0) {
3826 printf("errno=%d\nerror: %s\n", errno, strerror(errno));
3827 printf("result=" FMT_D "\n", result);
3828 } */
3829 FREE_OS_STRI(os_command);
3830 } /* if */
3831 logFunction(printf("cmdShell --> " FMT_D "\n", result););
3832 return result;
3833 } /* cmdShell */
3834
3835
3836
3837 #ifdef ESCAPE_SHELL_COMMANDS
3838 /**
3839 * Convert a string, such that it can be used as shell parameter.
3840 * The function adds escape characters or quotations to a string.
3841 * The result is useable as parameter for the functions 'cmdShell'
3842 * and 'filPopen'. Shell parameters must be escaped individually.
3843 * Afterwards escaped parameters are joined to a space separated
3844 * list of parameters.
3845 * @return a string which can be used as shell parameter.
3846 * @exception MEMORY_ERROR Not enough memory to convert 'stri'.
3847 */
3848 striType cmdShellEscape (const const_striType stri)
3849
3850 {
3851 /* A shell parameter might start and end with quote ("): */
3852 const memSizeType numOfQuotes = 0;
3853 /* Maximum escape sequence length in shell parameter: */
3854 const memSizeType escSequenceMax = STRLEN("\\=");
3855 memSizeType inPos;
3856 memSizeType outPos;
3857 errInfoType err_info = OKAY_NO_ERROR;
3858 striType resized_result;
3859 striType result;
3860
3861 /* cmdShellEscape */
3862 logFunction(printf("cmdShellEscape(\"%s\")", striAsUnquotedCStri(stri));
3863 fflush(stdout););
3864 if (unlikely(stri->size > (MAX_STRI_LEN - numOfQuotes) / escSequenceMax ||
3865 !ALLOC_STRI_SIZE_OK(result, escSequenceMax * stri->size + numOfQuotes))) {
3866 raise_error(MEMORY_ERROR);
3867 result = NULL;
3868 } else {
3869 for (inPos = 0, outPos = 0; inPos < stri->size; inPos++, outPos++) {
3870 switch (stri->mem[inPos]) {
3871 case '\t': case ' ': case '!': case '\"': case '#':
3872 case '$': case '&': case '\'': case '(': case ')':
3873 case '*': case ',': case ':': case ';': case '<':
3874 case '=': case '>': case '?': case '[': case '\\':
3875 case ']': case '^': case '`': case '{': case '|':
3876 case '}': case '~':
3877 result->mem[outPos] = '\\';
3878 outPos++;
3879 result->mem[outPos] = stri->mem[inPos];
3880 break;
3881 case '\0': case '\n':
3882 logError(printf("cmdShellEscape: "
3883 "Illegal character in string ('\\" FMT_U32 ";').\n",
3884 stri->mem[inPos]););
3885 err_info = RANGE_ERROR;
3886 break;
3887 default:
3888 result->mem[outPos] = stri->mem[inPos];
3889 break;
3890 } /* switch */
3891 } /* for */
3892 if (unlikely(err_info != OKAY_NO_ERROR)) {
3893 FREE_STRI(result, escSequenceMax * stri->size + numOfQuotes);
3894 raise_error(err_info);
3895 result = NULL;
3896 } else {
3897 REALLOC_STRI_SIZE_SMALLER(resized_result, result,
3898 escSequenceMax * stri->size + numOfQuotes, outPos);
3899 if (unlikely(resized_result == NULL)) {
3900 FREE_STRI(result, escSequenceMax * stri->size + numOfQuotes);
3901 raise_error(MEMORY_ERROR);
3902 result = NULL;
3903 } else {
3904 result = resized_result;
3905 COUNT3_STRI(escSequenceMax * stri->size + numOfQuotes, outPos);
3906 result->size = outPos;
3907 } /* if */
3908 } /* if */
3909 } /* if */
3910 logFunctionResult(printf("\"%s\"\n", striAsUnquotedCStri(result)););
3911 return result;
3912 } /* cmdShellEscape */
3913
3914 #else
3915
3916
3917
3918 /**
3919 * Convert a string, such that it can be used as shell parameter.
3920 * The function adds escape characters or quotations to a string.
3921 * The result is useable as parameter for the functions 'cmdShell'
3922 * and 'filPopen'. Shell parameters must be escaped individually.
3923 * Afterwards escaped parameters are joined to a space separated
3924 * list of parameters.
3925 * @return a string which can be used as shell parameter.
3926 * @exception MEMORY_ERROR Not enough memory to convert 'stri'.
3927 */
3928 striType cmdShellEscape (const const_striType stri)
3929
3930 {
3931 /* A shell parameter might start and end with quote ("): */
3932 const memSizeType numOfQuotes = 2;
3933 /* Maximum escape sequence length in shell parameter: */
3934 const memSizeType escSequenceMax = 4;
3935 memSizeType inPos;
3936 memSizeType outPos;
3937 boolType quotation_mode = FALSE;
3938 boolType in_escaped_quotation = FALSE;
3939 memSizeType countBackslash;
3940 errInfoType err_info = OKAY_NO_ERROR;
3941 striType resized_result;
3942 striType result;
3943
3944 /* cmdShellEscape */
3945 logFunction(printf("cmdShellEscape(\"%s\")", striAsUnquotedCStri(stri));
3946 fflush(stdout););
3947 if (unlikely(stri->size > (MAX_STRI_LEN - numOfQuotes) / escSequenceMax ||
3948 !ALLOC_STRI_SIZE_OK(result, escSequenceMax * stri->size + numOfQuotes))) {
3949 raise_error(MEMORY_ERROR);
3950 result = NULL;
3951 } else {
3952 for (inPos = 0, outPos = 0; inPos < stri->size; inPos++, outPos++) {
3953 switch (stri->mem[inPos]) {
3954 case '\t': case '\f': case ' ': case '%': case '*':
3955 case ',': case ';': case '=': case '~': case 160:
3956 if (!quotation_mode) {
3957 quotation_mode = TRUE;
3958 result->mem[outPos] = '"';
3959 outPos++;
3960 } /* if */
3961 result->mem[outPos] = stri->mem[inPos];
3962 break;
3963 case '&': case '<': case '>': case '^': case '|':
3964 if (!quotation_mode) {
3965 quotation_mode = TRUE;
3966 result->mem[outPos] = '"';
3967 outPos++;
3968 } /* if */
3969 if (in_escaped_quotation) {
3970 result->mem[outPos] = '^';
3971 outPos++;
3972 } /* if */
3973 result->mem[outPos] = stri->mem[inPos];
3974 break;
3975 case '\"':
3976 if (!quotation_mode) {
3977 quotation_mode = TRUE;
3978 result->mem[outPos] = '"';
3979 outPos++;
3980 } /* if */
3981 result->mem[outPos] = '\\';
3982 outPos++;
3983 result->mem[outPos] = stri->mem[inPos];
3984 in_escaped_quotation = !in_escaped_quotation;
3985 break;
3986 case '\\':
3987 result->mem[outPos] = '\\';
3988 outPos++;
3989 result->mem[outPos] = stri->mem[inPos];
3990 break;
3991 case '\0': case '\n': case '\r':
3992 logError(printf("cmdShellEscape: "
3993 "Illegal character in string ('\\" FMT_U32 ";').\n",
3994 stri->mem[inPos]););
3995 err_info = RANGE_ERROR;
3996 break;
3997 default:
3998 if (quotation_mode) {
3999 quotation_mode = FALSE;
4000 result->mem[outPos] = '"';
4001 outPos++;
4002 } /* if */
4003 result->mem[outPos] = stri->mem[inPos];
4004 break;
4005 } /* switch */
4006 } /* for */
4007 if (unlikely(err_info != OKAY_NO_ERROR)) {
4008 FREE_STRI(result, escSequenceMax * stri->size + numOfQuotes);
4009 raise_error(err_info);
4010 result = NULL;
4011 } else {
4012 if (quotation_mode) {
4013 result->mem[outPos] = '"';
4014 outPos++;
4015 } /* if */
4016 for (inPos = 0; inPos < outPos; inPos++) {
4017 if (result->mem[inPos] == '\\') {
4018 inPos++;
4019 countBackslash = 1;
4020 while (inPos < outPos && result->mem[inPos] == '\\') {
4021 inPos++;
4022 countBackslash++;
4023 } /* while */
4024 if (inPos == outPos || result->mem[inPos] != '"') {
4025 countBackslash /= 2;
4026 memcpy(&result->mem[inPos - countBackslash], &result->mem[inPos],
4027 (outPos - inPos) * sizeof(strElemType));
4028 inPos -= countBackslash;
4029 outPos -= countBackslash;
4030 } /* if */
4031 inPos--;
4032 } /* if */
4033 } /* for */
4034 REALLOC_STRI_SIZE_SMALLER(resized_result, result,
4035 escSequenceMax * stri->size + numOfQuotes, outPos);
4036 if (unlikely(resized_result == NULL)) {
4037 FREE_STRI(result, escSequenceMax * stri->size + numOfQuotes);
4038 raise_error(MEMORY_ERROR);
4039 result = NULL;
4040 } else {
4041 result = resized_result;
4042 COUNT3_STRI(escSequenceMax * stri->size + numOfQuotes, outPos);
4043 result->size = outPos;
4044 } /* if */
4045 } /* if */
4046 } /* if */
4047 logFunctionResult(printf("\"%s\"\n", striAsUnquotedCStri(result)););
4048 return result;
4049 } /* cmdShellEscape */
4050
4051 #endif
4052
4053
4054
4055 /**
4056 * Create a symbolic link.
4057 * The symbolic link 'destPath' will refer to 'sourcePath' afterwards.
4058 * @param sourcePath String to be contained in the symbolic link.
4059 * @param destPath Name of the symbolic link to be created.
4060 * @exception MEMORY_ERROR Not enough memory to convert sourcePath or
4061 * destPath to the system path type.
4062 * @exception RANGE_ERROR 'sourcePath' or 'destPath' does not use the
4063 * standard path representation or one of them cannot be
4064 * converted to the system path type.
4065 * @exception FILE_ERROR A system function returns an error.
4066 */
4067 void cmdSymlink (const const_striType sourcePath, const const_striType destPath)
4068
4069 {
4070 #if HAS_SYMBOLIC_LINKS
4071 os_striType os_sourcePath;
4072 os_striType os_destPath;
4073 int path_info;
4074 #endif
4075 errInfoType err_info = OKAY_NO_ERROR;
4076
4077 /* cmdSymlink */
4078 logFunction(printf("cmdSymlink(\"%s\", ", striAsUnquotedCStri(sourcePath));
4079 printf("\"%s\")\n", striAsUnquotedCStri(destPath)););
4080 #if HAS_SYMBOLIC_LINKS
4081 os_sourcePath = cp_to_os_path(sourcePath, &path_info, &err_info);
4082 if (likely(os_sourcePath != NULL)) {
4083 os_destPath = cp_to_os_path(destPath, &path_info, &err_info);
4084 if (likely(os_destPath != NULL)) {
4085 if (symlink(os_sourcePath, os_destPath) != 0) {
4086 err_info = FILE_ERROR;
4087 } /* if */
4088 os_stri_free(os_destPath);
4089 } /* if */
4090 os_stri_free(os_sourcePath);
4091 } /* if */
4092 #else
4093 err_info = FILE_ERROR;
4094 #endif
4095 if (unlikely(err_info != OKAY_NO_ERROR)) {
4096 raise_error(err_info);
4097 } /* if */
4098 } /* cmdSymlink */
4099
4100
4101
4102 /**
4103 * Convert a standard path to the path of the operating system.
4104 * The result must be escaped with 'cmdShellEscape' to be useable as
4105 * parameter for the functions 'cmdShell' and 'filPopen'.
4106 * @param standardPath Path in the standard path representation.
4107 * @return a string containing an operating system path.
4108 * @exception MEMORY_ERROR Not enough memory to convert 'standardPath'.
4109 * @exception RANGE_ERROR 'standardPath' is not representable as operating
4110 * system path.
4111 */
4112 striType cmdToOsPath (const const_striType standardPath)
4113
4114 {
4115 errInfoType err_info = OKAY_NO_ERROR;
4116 striType result;
4117
4118 /* cmdToOsPath */
4119 logFunction(printf("cmdToOsPath(\"%s\")", striAsUnquotedCStri(standardPath));
4120 fflush(stdout););
4121 if (unlikely(pathIsWrong(standardPath))) {
4122 logError(printf("cmdToOsPath: "
4123 "\"%s\" uses a drive letter or ends with slash.\n",
4124 striAsUnquotedCStri(standardPath)););
4125 err_info = RANGE_ERROR;
4126 } else {
4127 if_mapAbsoluteShellPathToDriveLetters(
4128 standardPath->size >= 1 && standardPath->mem[0] == '/', {
4129 /* Absolute path: Try to map the path to a drive letter */
4130 if (unlikely(standardPath->size == 1)) {
4131 /* "/" cannot be mapped to a drive letter */
4132 logError(printf("cmdToOsPath: "
4133 "\"%s\" cannot be mapped to a drive letter.\n",
4134 striAsUnquotedCStri(standardPath)););
4135 err_info = RANGE_ERROR;
4136 } else if (standardPath->mem[1] >= 'a' && standardPath->mem[1] <= 'z') {
4137 if (standardPath->size == 2) {
4138 /* "/c" is mapped to "c:/" */
4139 if (unlikely(!ALLOC_STRI_SIZE_OK(result, 3))) {
4140 err_info = MEMORY_ERROR;
4141 } else {
4142 result->size = 3;
4143 result->mem[0] = standardPath->mem[1];
4144 result->mem[1] = ':';
4145 result->mem[2] = '/';
4146 } /* if */
4147 } else if (unlikely(standardPath->mem[2] != '/')) {
4148 /* "/cd" cannot be mapped to a drive letter */
4149 logError(printf("cmdToOsPath: "
4150 "\"%s\" cannot be mapped to a drive letter.\n",
4151 striAsUnquotedCStri(standardPath)););
4152 err_info = RANGE_ERROR;
4153 } else {
4154 /* "/c/d" is mapped to "c:/d" */
4155 if (unlikely(!ALLOC_STRI_SIZE_OK(result, standardPath->size))) {
4156 err_info = MEMORY_ERROR;
4157 } else {
4158 result->size = standardPath->size;
4159 result->mem[0] = standardPath->mem[1];
4160 result->mem[1] = ':';
4161 result->mem[2] = '/';
4162 memcpy(&result->mem[3], &standardPath->mem[3],
4163 (standardPath->size - 3) * sizeof(strElemType));
4164 } /* if */
4165 } /* if */
4166 } else {
4167 /* "/C" cannot be mapped to a drive letter */
4168 logError(printf("cmdToOsPath: "
4169 "\"%s\" cannot be mapped to a drive letter.\n",
4170 striAsUnquotedCStri(standardPath)););
4171 err_info = RANGE_ERROR;
4172 } /* if */
4173 }, /* else */ {
4174 if (unlikely(!ALLOC_STRI_SIZE_OK(result, standardPath->size))) {
4175 err_info = MEMORY_ERROR;
4176 } else {
4177 result->size = standardPath->size;
4178 memcpy(result->mem, standardPath->mem, standardPath->size * sizeof(strElemType));
4179 } /* if */
4180 });
4181 } /* if */
4182 if (unlikely(err_info != OKAY_NO_ERROR)) {
4183 raise_error(err_info);
4184 result = NULL;
4185 } else {
4186 if_pathDelimiterNotSlash({
4187 memSizeType position;
4188
4189 for (position = 0; position < result->size; position++) {
4190 if (result->mem[position] == '/') {
4191 result->mem[position] = SHELL_PATH_DELIMITER;
4192 } /* if */
4193 } /* for */
4194 });
4195 } /* if */
4196 logFunctionResult(printf("\"%s\"\n", striAsUnquotedCStri(result)););
4197 return result;
4198 } /* cmdToOsPath */
4199
4200
4201
4202 #ifdef os_unsetenv
4203 /**
4204 * Deletes the variable 'name' from the environment.
4205 * If 'name' does not exist in the environment,
4206 * then the function succeeds, and the environment is unchanged.
4207 * @exception MEMORY_ERROR Not enough memory to convert 'name' to the
4208 * system string type.
4209 * @exception RANGE_ERROR 'name' cannot be converted to the system string
4210 * type or a system function returns an error.
4211 */
4212 void cmdUnsetenv (const const_striType name)
4213
4214 {
4215 os_striType env_name;
4216 int unsetenv_result;
4217 errInfoType err_info = OKAY_NO_ERROR;
4218
4219 /* cmdUnsetenv */
4220 logFunction(printf("cmdUnsetenv(\"%s\")", striAsUnquotedCStri(name));
4221 fflush(stdout););
4222 env_name = stri_to_os_stri(name, &err_info);
4223 if (unlikely(env_name == NULL)) {
4224 logError(printf("cmdUnsetenv: stri_to_os_stri(\"%s\", *, *) failed:\n"
4225 "err_info=%d\n",
4226 striAsUnquotedCStri(name), err_info););
4227 raise_error(err_info);
4228 } else {
4229 unsetenv_result = os_unsetenv(env_name);
4230 if (unlikely(unsetenv_result != 0)) {
4231 logError(printf("cmdUnsetenv: os_unsetenv(\"" FMT_S_OS "\") failed:\n"
4232 "errno=%d\nerror: %s\n",
4233 env_name, errno, strerror(errno)););
4234 err_info = RANGE_ERROR;
4235 } /* if */
4236 os_stri_free(env_name);
4237 if (unlikely(err_info != OKAY_NO_ERROR)) {
4238 raise_error(err_info);
4239 } /* if */
4240 } /* if */
4241 logFunction(printf("cmdUnsetenv -->\n"););
4242 } /* cmdUnsetenv */
4243
4244 #else
4245
4246
4247
4248 /**
4249 * Deletes the variable 'name' from the environment.
4250 * If 'name' does not exist in the environment,
4251 * then the function succeeds, and the environment is unchanged.
4252 * @exception MEMORY_ERROR Not enough memory to convert 'name' to the
4253 * system string type.
4254 * @exception RANGE_ERROR 'name' cannot be converted to the system string
4255 * type or a system function returns an error.
4256 */
4257 void cmdUnsetenv (const const_striType name)
4258
4259 {
4260 memSizeType stri_size;
4261 striType stri;
4262 os_striType env_stri;
4263 int putenv_result;
4264 errInfoType err_info = OKAY_NO_ERROR;
4265
4266 /* cmdUnsetenv */
4267 logFunction(printf("cmdUnsetenv(\"%s\")", striAsUnquotedCStri(name));
4268 fflush(stdout););
4269 if (strChPos(name, (charType) '=') != 0) {
4270 logError(printf("cmdUnsetenv(\"%s\"): "
4271 "Name contains '=' (putenv() works with \"name=value\").\n",
4272 striAsUnquotedCStri(name)););
4273 err_info = RANGE_ERROR;
4274 } else if (unlikely(name->size > MAX_STRI_LEN - 1)) {
4275 /* Number of bytes does not fit into memSizeType. */
4276 err_info = MEMORY_ERROR;
4277 } else {
4278 stri_size = name->size + 1;
4279 if (unlikely(!ALLOC_STRI_SIZE_OK(stri, stri_size))) {
4280 err_info = MEMORY_ERROR;
4281 } else {
4282 stri->size = stri_size;
4283 memcpy(stri->mem, name->mem,
4284 name->size * sizeof(strElemType));
4285 stri->mem[name->size] = (strElemType) '=';
4286 env_stri = stri_to_os_stri(stri, &err_info);
4287 FREE_STRI(stri, stri->size);
4288 if (likely(env_stri != NULL)) {
4289 /* printf("os_putenv(\"" FMT_S_OS "\")\n", env_stri); */
4290 putenv_result = os_putenv(env_stri);
4291 if (unlikely(putenv_result != 0)) {
4292 logError(printf("cmdUnsetenv: os_putenv(\"" FMT_S_OS "\") failed:\n"
4293 "errno=%d\nerror: %s\n",
4294 env_stri, errno, strerror(errno)););
4295 err_info = RANGE_ERROR;
4296 } /* if */
4297 #if DELETE_PUTENV_ARGUMENT
4298 os_stri_free(env_stri);
4299 #endif
4300 } /* if */
4301 } /* if */
4302 } /* if */
4303 if (unlikely(err_info != OKAY_NO_ERROR)) {
4304 raise_error(err_info);
4305 } /* if */
4306 logFunction(printf("cmdUnsetenv -->\n"););
4307 } /* cmdUnsetenv */
4308
4309 #endif
4310