1 /****************************************************************************
3 * GNAT COMPILER COMPONENTS *
7 * C Implementation File *
9 * Copyright (C) 1992-2014, Free Software Foundation, Inc. *
11 * GNAT is free software; you can redistribute it and/or modify it under *
12 * terms of the GNU General Public License as published by the Free Soft- *
13 * ware Foundation; either version 3, or (at your option) any later ver- *
14 * sion. GNAT is distributed in the hope that it will be useful, but WITH- *
15 * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
16 * or FITNESS FOR A PARTICULAR PURPOSE. *
18 * As a special exception under Section 7 of GPL version 3, you are granted *
19 * additional permissions described in the GCC Runtime Library Exception, *
20 * version 3.1, as published by the Free Software Foundation. *
22 * You should have received a copy of the GNU General Public License and *
23 * a copy of the GCC Runtime Library Exception along with this program; *
24 * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see *
25 * <http://www.gnu.org/licenses/>. *
27 * GNAT was originally developed by the GNAT team at New York University. *
28 * Extensive contributions were provided by Ada Core Technologies Inc. *
30 ****************************************************************************/
32 /* This file contains those routines named by Import pragmas in
33 packages in the GNAT hierarchy (especially GNAT.OS_Lib) and in
34 package Osint. Many of the subprograms in OS_Lib import standard
35 library calls directly. This file contains all other routines. */
37 /* Ensure access to errno is thread safe. */
43 /* No need to redefine exit here. */
46 /* We want to use the POSIX variants of include files. */
50 #if defined (__mips_vxworks)
52 #endif /* __mips_vxworks */
54 /* If SMP, access vxCpuConfiguredGet */
55 #ifdef _WRS_CONFIG_SMP
57 #endif /* _WRS_CONFIG_SMP */
59 /* We need to know the VxWorks version because some file operations
60 (such as chmod) are only available on VxWorks 6. */
65 #if defined (__APPLE__)
69 #if defined (__hpux__)
70 #include <sys/param.h>
71 #include <sys/pstat.h>
75 #define __BSD_VISIBLE 1
85 #if defined (__vxworks) || defined (__ANDROID__)
86 /* S_IREAD and S_IWRITE are not defined in VxWorks or Android */
88 #define S_IREAD (S_IRUSR | S_IRGRP | S_IROTH)
92 #define S_IWRITE (S_IWUSR)
96 /* We don't have libiberty, so use malloc. */
97 #define xmalloc(S) malloc (S)
98 #define xrealloc(V,S) realloc (V,S)
109 #if defined (__MINGW32__)
117 /* Current code page and CCS encoding to use, set in initialize.c. */
118 UINT CurrentCodePage
;
119 UINT CurrentCCSEncoding
;
122 #include <sys/utime.h>
124 /* For isalpha-like tests in the compiler, we're expected to resort to
125 safe-ctype.h/ISALPHA. This isn't available for the runtime library
126 build, so we fallback on ctype.h/isalpha there. */
130 #define ISALPHA isalpha
133 #elif defined (__Lynx__)
135 /* Lynx utime.h only defines the entities of interest to us if
136 defined (VMOS_DEV), so ... */
145 /* wait.h processing */
148 # include <sys/wait.h>
150 #elif defined (__vxworks) && defined (__RTP__)
152 #elif defined (__Lynx__)
153 /* ??? We really need wait.h and it includes resource.h on Lynx. GCC
154 has a resource.h header as well, included instead of the lynx
155 version in our setup, causing lots of errors. We don't really need
156 the lynx contents of this file, so just workaround the issue by
157 preventing the inclusion of the GCC header from doing anything. */
158 # define GCC_RESOURCE_H
159 # include <sys/wait.h>
160 #elif defined (__nucleus__) || defined (__PikeOS__)
161 /* No wait() or waitpid() calls available. */
164 #include <sys/wait.h>
175 #define DIR_SEPARATOR '\\'
183 /* Define symbols O_BINARY and O_TEXT as harmless zeroes if they are not
184 defined in the current system. On DOS-like systems these flags control
185 whether the file is opened/created in text-translation mode (CR/LF in
186 external file mapped to LF in internal file), but in Unix-like systems,
187 no text translation is required, so these flags have no effect. */
197 #ifndef HOST_EXECUTABLE_SUFFIX
198 #define HOST_EXECUTABLE_SUFFIX ""
201 #ifndef HOST_OBJECT_SUFFIX
202 #define HOST_OBJECT_SUFFIX ".o"
205 #ifndef PATH_SEPARATOR
206 #define PATH_SEPARATOR ':'
209 #ifndef DIR_SEPARATOR
210 #define DIR_SEPARATOR '/'
213 /* Check for cross-compilation. */
214 #if defined (CROSS_COMPILE) || defined (CROSS_DIRECTORY_STRUCTURE)
216 int __gnat_is_cross_compiler
= 1;
219 int __gnat_is_cross_compiler
= 0;
222 char __gnat_dir_separator
= DIR_SEPARATOR
;
224 char __gnat_path_separator
= PATH_SEPARATOR
;
226 /* The GNAT_LIBRARY_TEMPLATE contains a list of expressions that define
227 the base filenames that libraries specified with -lsomelib options
228 may have. This is used by GNATMAKE to check whether an executable
229 is up-to-date or not. The syntax is
231 library_template ::= { pattern ; } pattern NUL
232 pattern ::= [ prefix ] * [ postfix ]
234 These should only specify names of static libraries as it makes
235 no sense to determine at link time if dynamic-link libraries are
236 up to date or not. Any libraries that are not found are supposed
239 * if they are needed but not present, the link
242 * otherwise they are libraries in the system paths and so
243 they are considered part of the system and not checked
246 ??? This should be part of a GNAT host-specific compiler
247 file instead of being included in all user applications
248 as well. This is only a temporary work-around for 3.11b. */
250 #ifndef GNAT_LIBRARY_TEMPLATE
251 #define GNAT_LIBRARY_TEMPLATE "lib*.a"
254 const char *__gnat_library_template
= GNAT_LIBRARY_TEMPLATE
;
256 #if defined (__vxworks) || defined (__OPENNT) || defined(__nucleus__)
257 #define GNAT_MAX_PATH_LEN PATH_MAX
261 #if defined (__MINGW32__)
265 #include <sys/param.h>
269 #include <sys/param.h>
273 #define GNAT_MAX_PATH_LEN MAXPATHLEN
275 #define GNAT_MAX_PATH_LEN 256
280 /* Used for runtime check that Ada constant File_Attributes_Size is no
281 less than the actual size of struct file_attributes (see Osint
283 int __gnat_size_of_file_attributes
= sizeof (struct file_attributes
);
285 void __gnat_stat_to_attr (int fd
, char* name
, struct file_attributes
* attr
);
287 /* The __gnat_max_path_len variable is used to export the maximum
288 length of a path name to Ada code. max_path_len is also provided
289 for compatibility with older GNAT versions, please do not use
292 int __gnat_max_path_len
= GNAT_MAX_PATH_LEN
;
293 int max_path_len
= GNAT_MAX_PATH_LEN
;
295 /* Control whether we can use ACL on Windows. */
297 int __gnat_use_acl
= 1;
299 /* The following macro HAVE_READDIR_R should be defined if the
300 system provides the routine readdir_r. */
301 #undef HAVE_READDIR_R
303 #define MAYBE_TO_PTR32(argv) argv
305 static const char ATTR_UNSET
= 127;
307 /* Reset the file attributes as if no system call had been performed */
310 __gnat_reset_attributes (struct file_attributes
* attr
)
312 attr
->exists
= ATTR_UNSET
;
313 attr
->error
= EINVAL
;
315 attr
->writable
= ATTR_UNSET
;
316 attr
->readable
= ATTR_UNSET
;
317 attr
->executable
= ATTR_UNSET
;
319 attr
->regular
= ATTR_UNSET
;
320 attr
->symbolic_link
= ATTR_UNSET
;
321 attr
->directory
= ATTR_UNSET
;
323 attr
->timestamp
= (OS_Time
)-2;
324 attr
->file_length
= -1;
328 __gnat_error_attributes (struct file_attributes
*attr
) {
333 __gnat_current_time (void)
335 time_t res
= time (NULL
);
336 return (OS_Time
) res
;
339 /* Return the current local time as a string in the ISO 8601 format of
340 "YYYY-MM-DD HH:MM:SS.SS". The returned string is 22 + 1 (NULL) characters
344 __gnat_current_time_string (char *result
)
346 const char *format
= "%Y-%m-%d %H:%M:%S";
347 /* Format string necessary to describe the ISO 8601 format */
349 const time_t t_val
= time (NULL
);
351 strftime (result
, 22, format
, localtime (&t_val
));
352 /* Convert the local time into a string following the ISO format, copying
353 at most 22 characters into the result string. */
358 /* The sub-seconds are manually set to zero since type time_t lacks the
359 precision necessary for nanoseconds. */
363 __gnat_to_gm_time (OS_Time
*p_time
, int *p_year
, int *p_month
, int *p_day
,
364 int *p_hours
, int *p_mins
, int *p_secs
)
367 time_t time
= (time_t) *p_time
;
370 /* On Windows systems, the time is sometimes rounded up to the nearest
371 even second, so if the number of seconds is odd, increment it. */
376 res
= gmtime (&time
);
379 *p_year
= res
->tm_year
;
380 *p_month
= res
->tm_mon
;
381 *p_day
= res
->tm_mday
;
382 *p_hours
= res
->tm_hour
;
383 *p_mins
= res
->tm_min
;
384 *p_secs
= res
->tm_sec
;
387 *p_year
= *p_month
= *p_day
= *p_hours
= *p_mins
= *p_secs
= 0;
391 __gnat_to_os_time (OS_Time
*p_time
, int year
, int month
, int day
,
392 int hours
, int mins
, int secs
)
404 /* returns -1 of failing, this is s-os_lib Invalid_Time */
406 *p_time
= (OS_Time
) mktime (&v
);
409 /* Place the contents of the symbolic link named PATH in the buffer BUF,
410 which has size BUFSIZ. If PATH is a symbolic link, then return the number
411 of characters of its content in BUF. Otherwise, return -1.
412 For systems not supporting symbolic links, always return -1. */
415 __gnat_readlink (char *path ATTRIBUTE_UNUSED
,
416 char *buf ATTRIBUTE_UNUSED
,
417 size_t bufsiz ATTRIBUTE_UNUSED
)
419 #if defined (_WIN32) \
420 || defined(__vxworks) || defined (__nucleus__) || defined (__PikeOS__)
423 return readlink (path
, buf
, bufsiz
);
427 /* Creates a symbolic link named NEWPATH which contains the string OLDPATH.
428 If NEWPATH exists it will NOT be overwritten.
429 For systems not supporting symbolic links, always return -1. */
432 __gnat_symlink (char *oldpath ATTRIBUTE_UNUSED
,
433 char *newpath ATTRIBUTE_UNUSED
)
435 #if defined (_WIN32) \
436 || defined(__vxworks) || defined (__nucleus__) || defined (__PikeOS__)
439 return symlink (oldpath
, newpath
);
443 /* Try to lock a file, return 1 if success. */
445 #if defined (__vxworks) || defined (__nucleus__) \
446 || defined (_WIN32) || defined (__PikeOS__)
448 /* Version that does not use link. */
451 __gnat_try_lock (char *dir
, char *file
)
455 TCHAR wfull_path
[GNAT_MAX_PATH_LEN
];
456 TCHAR wfile
[GNAT_MAX_PATH_LEN
];
457 TCHAR wdir
[GNAT_MAX_PATH_LEN
];
459 S2WSC (wdir
, dir
, GNAT_MAX_PATH_LEN
);
460 S2WSC (wfile
, file
, GNAT_MAX_PATH_LEN
);
462 /* ??? the code below crash on MingW64 for obscure reasons, a ticket
463 has been opened here:
465 https://sourceforge.net/p/mingw-w64/bugs/414/
467 As a workaround an equivalent set of code has been put in place below.
469 _stprintf (wfull_path, _T("%s%c%s"), wdir, _T(DIR_SEPARATOR), wfile);
472 _tcscpy (wfull_path
, wdir
);
473 _tcscat (wfull_path
, L
"\\");
474 _tcscat (wfull_path
, wfile
);
476 fd
= _topen (wfull_path
, O_CREAT
| O_EXCL
, 0600);
480 sprintf (full_path
, "%s%c%s", dir
, DIR_SEPARATOR
, file
);
481 fd
= open (full_path
, O_CREAT
| O_EXCL
, 0600);
493 /* Version using link(), more secure over NFS. */
494 /* See TN 6913-016 for discussion ??? */
497 __gnat_try_lock (char *dir
, char *file
)
501 GNAT_STRUCT_STAT stat_result
;
504 sprintf (full_path
, "%s%c%s", dir
, DIR_SEPARATOR
, file
);
505 sprintf (temp_file
, "%s%cTMP-%ld-%ld",
506 dir
, DIR_SEPARATOR
, (long)getpid(), (long)getppid ());
508 /* Create the temporary file and write the process number. */
509 fd
= open (temp_file
, O_CREAT
| O_WRONLY
, 0600);
515 /* Link it with the new file. */
516 link (temp_file
, full_path
);
518 /* Count the references on the old one. If we have a count of two, then
519 the link did succeed. Remove the temporary file before returning. */
520 __gnat_stat (temp_file
, &stat_result
);
522 return stat_result
.st_nlink
== 2;
526 /* Return the maximum file name length. */
529 __gnat_get_maximum_file_name_length (void)
534 /* Return nonzero if file names are case sensitive. */
536 static int file_names_case_sensitive_cache
= -1;
539 __gnat_get_file_names_case_sensitive (void)
541 if (file_names_case_sensitive_cache
== -1)
543 const char *sensitive
= getenv ("GNAT_FILE_NAME_CASE_SENSITIVE");
545 if (sensitive
!= NULL
546 && (sensitive
[0] == '0' || sensitive
[0] == '1')
547 && sensitive
[1] == '\0')
548 file_names_case_sensitive_cache
= sensitive
[0] - '0';
551 /* By default, we suppose filesystems aren't case sensitive on
552 Windows and Darwin (but they are on arm-darwin). */
553 #if defined (WINNT) || (defined (__APPLE__) && !defined (__arm__))
554 file_names_case_sensitive_cache
= 0;
556 file_names_case_sensitive_cache
= 1;
560 return file_names_case_sensitive_cache
;
563 /* Return nonzero if environment variables are case sensitive. */
566 __gnat_get_env_vars_case_sensitive (void)
576 __gnat_get_default_identifier_character_set (void)
581 /* Return the current working directory. */
584 __gnat_get_current_dir (char *dir
, int *length
)
586 #if defined (__MINGW32__)
587 TCHAR wdir
[GNAT_MAX_PATH_LEN
];
589 _tgetcwd (wdir
, *length
);
591 WS2SC (dir
, wdir
, GNAT_MAX_PATH_LEN
);
594 getcwd (dir
, *length
);
597 *length
= strlen (dir
);
599 if (dir
[*length
- 1] != DIR_SEPARATOR
)
601 dir
[*length
] = DIR_SEPARATOR
;
607 /* Return the suffix for object files. */
610 __gnat_get_object_suffix_ptr (int *len
, const char **value
)
612 *value
= HOST_OBJECT_SUFFIX
;
617 *len
= strlen (*value
);
622 /* Return the suffix for executable files. */
625 __gnat_get_executable_suffix_ptr (int *len
, const char **value
)
627 *value
= HOST_EXECUTABLE_SUFFIX
;
631 *len
= strlen (*value
);
636 /* Return the suffix for debuggable files. Usually this is the same as the
637 executable extension. */
640 __gnat_get_debuggable_suffix_ptr (int *len
, const char **value
)
642 *value
= HOST_EXECUTABLE_SUFFIX
;
647 *len
= strlen (*value
);
652 /* Returns the OS filename and corresponding encoding. */
655 __gnat_os_filename (char *filename ATTRIBUTE_UNUSED
,
656 char *w_filename ATTRIBUTE_UNUSED
,
657 char *os_name
, int *o_length
,
658 char *encoding ATTRIBUTE_UNUSED
, int *e_length
)
660 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (IS_CROSS)
661 WS2SC (os_name
, (TCHAR
*)w_filename
, (DWORD
)*o_length
);
662 *o_length
= strlen (os_name
);
663 strcpy (encoding
, "encoding=utf8");
664 *e_length
= strlen (encoding
);
666 strcpy (os_name
, filename
);
667 *o_length
= strlen (filename
);
675 __gnat_unlink (char *path
)
677 #if defined (__MINGW32__) && ! defined (__vxworks) && ! defined (IS_CROSS)
679 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
681 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
682 return _tunlink (wpath
);
685 return unlink (path
);
692 __gnat_rename (char *from
, char *to
)
694 #if defined (__MINGW32__) && ! defined (__vxworks) && ! defined (IS_CROSS)
696 TCHAR wfrom
[GNAT_MAX_PATH_LEN
], wto
[GNAT_MAX_PATH_LEN
];
698 S2WSC (wfrom
, from
, GNAT_MAX_PATH_LEN
);
699 S2WSC (wto
, to
, GNAT_MAX_PATH_LEN
);
700 return _trename (wfrom
, wto
);
703 return rename (from
, to
);
707 /* Changing directory. */
710 __gnat_chdir (char *path
)
712 #if defined (__MINGW32__) && ! defined (__vxworks) && ! defined (IS_CROSS)
714 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
716 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
717 return _tchdir (wpath
);
724 /* Removing a directory. */
727 __gnat_rmdir (char *path
)
729 #if defined (__MINGW32__) && ! defined (__vxworks) && ! defined (IS_CROSS)
731 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
733 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
734 return _trmdir (wpath
);
736 #elif defined (VTHREADS)
737 /* rmdir not available */
744 #if defined (_WIN32) || defined (linux) || defined (sun) \
745 || defined (__FreeBSD__)
746 #define HAS_TARGET_WCHAR_T
749 #ifdef HAS_TARGET_WCHAR_T
754 __gnat_fputwc(int c
, FILE *stream
)
756 #ifdef HAS_TARGET_WCHAR_T
757 return fputwc ((wchar_t)c
, stream
);
759 return fputc (c
, stream
);
764 __gnat_fopen (char *path
, char *mode
, int encoding ATTRIBUTE_UNUSED
)
766 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (IS_CROSS)
767 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
770 S2WS (wmode
, mode
, 10);
772 if (encoding
== Encoding_Unspecified
)
773 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
774 else if (encoding
== Encoding_UTF8
)
775 S2WSU (wpath
, path
, GNAT_MAX_PATH_LEN
);
777 S2WS (wpath
, path
, GNAT_MAX_PATH_LEN
);
779 return _tfopen (wpath
, wmode
);
782 return GNAT_FOPEN (path
, mode
);
787 __gnat_freopen (char *path
,
790 int encoding ATTRIBUTE_UNUSED
)
792 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (IS_CROSS)
793 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
796 S2WS (wmode
, mode
, 10);
798 if (encoding
== Encoding_Unspecified
)
799 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
800 else if (encoding
== Encoding_UTF8
)
801 S2WSU (wpath
, path
, GNAT_MAX_PATH_LEN
);
803 S2WS (wpath
, path
, GNAT_MAX_PATH_LEN
);
805 return _tfreopen (wpath
, wmode
, stream
);
807 return freopen (path
, mode
, stream
);
812 __gnat_open_read (char *path
, int fmode
)
815 int o_fmode
= O_BINARY
;
820 #if defined (__vxworks)
821 fd
= open (path
, O_RDONLY
| o_fmode
, 0444);
822 #elif defined (__MINGW32__)
824 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
826 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
827 fd
= _topen (wpath
, O_RDONLY
| o_fmode
, 0444);
830 fd
= GNAT_OPEN (path
, O_RDONLY
| o_fmode
);
833 return fd
< 0 ? -1 : fd
;
836 #if defined (__MINGW32__)
837 #define PERM (S_IREAD | S_IWRITE)
839 #define PERM (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
843 __gnat_open_rw (char *path
, int fmode
)
846 int o_fmode
= O_BINARY
;
851 #if defined (__MINGW32__)
853 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
855 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
856 fd
= _topen (wpath
, O_RDWR
| o_fmode
, PERM
);
859 fd
= GNAT_OPEN (path
, O_RDWR
| o_fmode
, PERM
);
862 return fd
< 0 ? -1 : fd
;
866 __gnat_open_create (char *path
, int fmode
)
869 int o_fmode
= O_BINARY
;
874 #if defined (__MINGW32__)
876 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
878 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
879 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_TRUNC
| o_fmode
, PERM
);
882 fd
= GNAT_OPEN (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| o_fmode
, PERM
);
885 return fd
< 0 ? -1 : fd
;
889 __gnat_create_output_file (char *path
)
892 #if defined (__MINGW32__)
894 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
896 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
897 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
, PERM
);
900 fd
= GNAT_OPEN (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
, PERM
);
903 return fd
< 0 ? -1 : fd
;
907 __gnat_create_output_file_new (char *path
)
910 #if defined (__MINGW32__)
912 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
914 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
915 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
| O_EXCL
, PERM
);
918 fd
= GNAT_OPEN (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
| O_EXCL
, PERM
);
921 return fd
< 0 ? -1 : fd
;
925 __gnat_open_append (char *path
, int fmode
)
928 int o_fmode
= O_BINARY
;
933 #if defined (__MINGW32__)
935 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
937 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
938 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_APPEND
| o_fmode
, PERM
);
941 fd
= GNAT_OPEN (path
, O_WRONLY
| O_CREAT
| O_APPEND
| o_fmode
, PERM
);
944 return fd
< 0 ? -1 : fd
;
947 /* Open a new file. Return error (-1) if the file already exists. */
950 __gnat_open_new (char *path
, int fmode
)
953 int o_fmode
= O_BINARY
;
958 #if defined (__MINGW32__)
960 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
962 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
963 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
);
966 fd
= GNAT_OPEN (path
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
);
969 return fd
< 0 ? -1 : fd
;
972 /* Open a new temp file. Return error (-1) if the file already exists. */
975 __gnat_open_new_temp (char *path
, int fmode
)
978 int o_fmode
= O_BINARY
;
980 strcpy (path
, "GNAT-XXXXXX");
982 #if (defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) \
983 || defined (linux) || defined(__GLIBC__)) && !defined (__vxworks)
984 return mkstemp (path
);
985 #elif defined (__Lynx__)
987 #elif defined (__nucleus__)
990 if (mktemp (path
) == NULL
)
997 fd
= GNAT_OPEN (path
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
);
998 return fd
< 0 ? -1 : fd
;
1002 __gnat_open (char *path
, int fmode
)
1006 #if defined (__MINGW32__)
1008 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
1010 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
1011 fd
= _topen (wpath
, fmode
, PERM
);
1014 fd
= GNAT_OPEN (path
, fmode
, PERM
);
1017 return fd
< 0 ? -1 : fd
;
1020 /****************************************************************
1021 ** Perform a call to GNAT_STAT or GNAT_FSTAT, and extract as much information
1022 ** as possible from it, storing the result in a cache for later reuse
1023 ****************************************************************/
1026 __gnat_stat_to_attr (int fd
, char* name
, struct file_attributes
* attr
)
1028 GNAT_STRUCT_STAT statbuf
;
1032 /* GNAT_FSTAT returns -1 and sets errno for failure */
1033 ret
= GNAT_FSTAT (fd
, &statbuf
);
1034 error
= ret
? errno
: 0;
1037 /* __gnat_stat returns errno value directly */
1038 error
= __gnat_stat (name
, &statbuf
);
1039 ret
= error
? -1 : 0;
1043 * A missing file is reported as an attr structure with error == 0 and
1047 if (error
== 0 || error
== ENOENT
)
1050 attr
->error
= error
;
1052 attr
->regular
= (!ret
&& S_ISREG (statbuf
.st_mode
));
1053 attr
->directory
= (!ret
&& S_ISDIR (statbuf
.st_mode
));
1056 attr
->file_length
= 0;
1058 /* st_size may be 32 bits, or 64 bits which is converted to long. We
1059 don't return a useful value for files larger than 2 gigabytes in
1061 attr
->file_length
= statbuf
.st_size
; /* all systems */
1063 attr
->exists
= !ret
;
1065 #if !defined (_WIN32) || defined (RTX)
1066 /* on Windows requires extra system call, see __gnat_is_readable_file_attr */
1067 attr
->readable
= (!ret
&& (statbuf
.st_mode
& S_IRUSR
));
1068 attr
->writable
= (!ret
&& (statbuf
.st_mode
& S_IWUSR
));
1069 attr
->executable
= (!ret
&& (statbuf
.st_mode
& S_IXUSR
));
1073 attr
->timestamp
= (OS_Time
)-1;
1075 attr
->timestamp
= (OS_Time
)statbuf
.st_mtime
;
1079 /****************************************************************
1080 ** Return the number of bytes in the specified file
1081 ****************************************************************/
1084 __gnat_file_length_attr (int fd
, char* name
, struct file_attributes
* attr
)
1086 if (attr
->file_length
== -1) {
1087 __gnat_stat_to_attr (fd
, name
, attr
);
1090 return attr
->file_length
;
1094 __gnat_file_length (int fd
)
1096 struct file_attributes attr
;
1097 __gnat_reset_attributes (&attr
);
1098 return __gnat_file_length_attr (fd
, NULL
, &attr
);
1102 __gnat_file_length_long (int fd
)
1104 struct file_attributes attr
;
1105 __gnat_reset_attributes (&attr
);
1106 return (long)__gnat_file_length_attr (fd
, NULL
, &attr
);
1110 __gnat_named_file_length (char *name
)
1112 struct file_attributes attr
;
1113 __gnat_reset_attributes (&attr
);
1114 return __gnat_file_length_attr (-1, name
, &attr
);
1117 /* Create a temporary filename and put it in string pointed to by
1121 __gnat_tmp_name (char *tmp_filename
)
1124 /* Variable used to create a series of unique names */
1125 static int counter
= 0;
1127 /* RTX in RTSS mode does not support tempnam nor tmpnam so we emulate it */
1128 strcpy (tmp_filename
, "c:\\WINDOWS\\Temp\\gnat-");
1129 sprintf (&tmp_filename
[strlen (tmp_filename
)], "%d\0", counter
++);
1131 #elif defined (__MINGW32__)
1136 /* tempnam tries to create a temporary file in directory pointed to by
1137 TMP environment variable, in c:\temp if TMP is not set, and in
1138 directory specified by P_tmpdir in stdio.h if c:\temp does not
1139 exist. The filename will be created with the prefix "gnat-". */
1141 sprintf (prefix
, "gnat-%d-", (int)getpid());
1142 pname
= (char *) _tempnam ("c:\\temp", prefix
);
1144 /* if pname is NULL, the file was not created properly, the disk is full
1145 or there is no more free temporary files */
1148 *tmp_filename
= '\0';
1150 /* If pname start with a back slash and not path information it means that
1151 the filename is valid for the current working directory. */
1153 else if (pname
[0] == '\\')
1155 strcpy (tmp_filename
, ".\\");
1156 strcat (tmp_filename
, pname
+1);
1159 strcpy (tmp_filename
, pname
);
1164 #elif defined (linux) || defined (__FreeBSD__) || defined (__NetBSD__) \
1165 || defined (__OpenBSD__) || defined(__GLIBC__) || defined (__ANDROID__)
1166 #define MAX_SAFE_PATH 1000
1167 char *tmpdir
= getenv ("TMPDIR");
1169 /* If tmpdir is longer than MAX_SAFE_PATH, revert to default value to avoid
1170 a buffer overflow. */
1171 if (tmpdir
== NULL
|| strlen (tmpdir
) > MAX_SAFE_PATH
)
1173 strcpy (tmp_filename
, "/cache/gnat-XXXXXX");
1175 strcpy (tmp_filename
, "/tmp/gnat-XXXXXX");
1178 sprintf (tmp_filename
, "%s/gnat-XXXXXX", tmpdir
);
1180 close (mkstemp(tmp_filename
));
1181 #elif defined (__vxworks) && !(defined (__RTP__) || defined (VTHREADS))
1185 static ushort_t seed
= 0; /* used to generate unique name */
1187 /* generate unique name */
1188 strcpy (tmp_filename
, "tmp");
1190 /* fill up the name buffer from the last position */
1192 pos
= tmp_filename
+ strlen (tmp_filename
) + index
;
1196 for (t
= seed
; 0 <= --index
; t
>>= 3)
1197 *--pos
= '0' + (t
& 07);
1199 tmpnam (tmp_filename
);
1203 /* Open directory and returns a DIR pointer. */
1205 DIR* __gnat_opendir (char *name
)
1208 /* Not supported in RTX */
1212 #elif defined (__MINGW32__)
1213 TCHAR wname
[GNAT_MAX_PATH_LEN
];
1215 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
);
1216 return (DIR*)_topendir (wname
);
1219 return opendir (name
);
1223 /* Read the next entry in a directory. The returned string points somewhere
1227 __gnat_readdir (DIR *dirp
, char *buffer
, int *len
)
1230 /* Not supported in RTX */
1234 #elif defined (__MINGW32__)
1235 struct _tdirent
*dirent
= _treaddir ((_TDIR
*)dirp
);
1239 WS2SC (buffer
, dirent
->d_name
, GNAT_MAX_PATH_LEN
);
1240 *len
= strlen (buffer
);
1247 #elif defined (HAVE_READDIR_R)
1248 /* If possible, try to use the thread-safe version. */
1249 if (readdir_r (dirp
, buffer
) != NULL
)
1251 *len
= strlen (((struct dirent
*) buffer
)->d_name
);
1252 return ((struct dirent
*) buffer
)->d_name
;
1258 struct dirent
*dirent
= (struct dirent
*) readdir (dirp
);
1262 strcpy (buffer
, dirent
->d_name
);
1263 *len
= strlen (buffer
);
1272 /* Close a directory entry. */
1274 int __gnat_closedir (DIR *dirp
)
1277 /* Not supported in RTX */
1281 #elif defined (__MINGW32__)
1282 return _tclosedir ((_TDIR
*)dirp
);
1285 return closedir (dirp
);
1289 /* Returns 1 if readdir is thread safe, 0 otherwise. */
1292 __gnat_readdir_is_thread_safe (void)
1294 #ifdef HAVE_READDIR_R
1301 #if defined (_WIN32) && !defined (RTX)
1302 /* Number of seconds between <Jan 1st 1601> and <Jan 1st 1970>. */
1303 static const unsigned long long w32_epoch_offset
= 11644473600ULL;
1305 /* Returns the file modification timestamp using Win32 routines which are
1306 immune against daylight saving time change. It is in fact not possible to
1307 use fstat for this purpose as the DST modify the st_mtime field of the
1311 win32_filetime (HANDLE h
)
1316 unsigned long long ull_time
;
1319 /* GetFileTime returns FILETIME data which are the number of 100 nanosecs
1320 since <Jan 1st 1601>. This function must return the number of seconds
1321 since <Jan 1st 1970>. */
1323 if (GetFileTime (h
, NULL
, NULL
, &t_write
.ft_time
))
1324 return (time_t) (t_write
.ull_time
/ 10000000ULL - w32_epoch_offset
);
1328 /* As above but starting from a FILETIME. */
1330 f2t (const FILETIME
*ft
, __time64_t
*t
)
1335 unsigned long long ull_time
;
1338 t_write
.ft_time
= *ft
;
1339 *t
= (__time64_t
) (t_write
.ull_time
/ 10000000ULL - w32_epoch_offset
);
1343 /* Return a GNAT time stamp given a file name. */
1346 __gnat_file_time_name_attr (char* name
, struct file_attributes
* attr
)
1348 if (attr
->timestamp
== (OS_Time
)-2) {
1349 #if defined (_WIN32) && !defined (RTX)
1351 WIN32_FILE_ATTRIBUTE_DATA fad
;
1352 __time64_t ret
= -1;
1353 TCHAR wname
[GNAT_MAX_PATH_LEN
];
1354 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
);
1356 if ((res
= GetFileAttributesEx (wname
, GetFileExInfoStandard
, &fad
)))
1357 f2t (&fad
.ftLastWriteTime
, &ret
);
1358 attr
->timestamp
= (OS_Time
) ret
;
1360 __gnat_stat_to_attr (-1, name
, attr
);
1363 return attr
->timestamp
;
1367 __gnat_file_time_name (char *name
)
1369 struct file_attributes attr
;
1370 __gnat_reset_attributes (&attr
);
1371 return __gnat_file_time_name_attr (name
, &attr
);
1374 /* Return a GNAT time stamp given a file descriptor. */
1377 __gnat_file_time_fd_attr (int fd
, struct file_attributes
* attr
)
1379 if (attr
->timestamp
== (OS_Time
)-2) {
1380 #if defined (_WIN32) && !defined (RTX)
1381 HANDLE h
= (HANDLE
) _get_osfhandle (fd
);
1382 time_t ret
= win32_filetime (h
);
1383 attr
->timestamp
= (OS_Time
) ret
;
1386 __gnat_stat_to_attr (fd
, NULL
, attr
);
1390 return attr
->timestamp
;
1394 __gnat_file_time_fd (int fd
)
1396 struct file_attributes attr
;
1397 __gnat_reset_attributes (&attr
);
1398 return __gnat_file_time_fd_attr (fd
, &attr
);
1401 /* Set the file time stamp. */
1404 __gnat_set_file_time_name (char *name
, time_t time_stamp
)
1406 #if defined (__vxworks)
1408 /* Code to implement __gnat_set_file_time_name for these systems. */
1410 #elif defined (_WIN32) && !defined (RTX)
1414 unsigned long long ull_time
;
1416 TCHAR wname
[GNAT_MAX_PATH_LEN
];
1418 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
);
1420 HANDLE h
= CreateFile
1421 (wname
, GENERIC_WRITE
, FILE_SHARE_WRITE
, NULL
,
1422 OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
,
1424 if (h
== INVALID_HANDLE_VALUE
)
1426 /* Add number of seconds between <Jan 1st 1601> and <Jan 1st 1970> */
1427 t_write
.ull_time
= ((unsigned long long)time_stamp
+ w32_epoch_offset
);
1428 /* Convert to 100 nanosecond units */
1429 t_write
.ull_time
*= 10000000ULL;
1431 SetFileTime(h
, NULL
, NULL
, &t_write
.ft_time
);
1436 struct utimbuf utimbuf
;
1439 /* Set modification time to requested time. */
1440 utimbuf
.modtime
= time_stamp
;
1442 /* Set access time to now in local time. */
1443 t
= time ((time_t) 0);
1444 utimbuf
.actime
= mktime (localtime (&t
));
1446 utime (name
, &utimbuf
);
1450 /* Get the list of installed standard libraries from the
1451 HKEY_LOCAL_MACHINE\SOFTWARE\Ada Core Technologies\GNAT\Standard Libraries
1455 __gnat_get_libraries_from_registry (void)
1457 char *result
= (char *) xmalloc (1);
1461 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (IS_CROSS) \
1465 DWORD name_size
, value_size
;
1472 /* First open the key. */
1473 res
= RegOpenKeyExA (HKEY_LOCAL_MACHINE
, "SOFTWARE", 0, KEY_READ
, ®_key
);
1475 if (res
== ERROR_SUCCESS
)
1476 res
= RegOpenKeyExA (reg_key
, "Ada Core Technologies", 0,
1477 KEY_READ
, ®_key
);
1479 if (res
== ERROR_SUCCESS
)
1480 res
= RegOpenKeyExA (reg_key
, "GNAT", 0, KEY_READ
, ®_key
);
1482 if (res
== ERROR_SUCCESS
)
1483 res
= RegOpenKeyExA (reg_key
, "Standard Libraries", 0, KEY_READ
, ®_key
);
1485 /* If the key exists, read out all the values in it and concatenate them
1487 for (index
= 0; res
== ERROR_SUCCESS
; index
++)
1489 value_size
= name_size
= 256;
1490 res
= RegEnumValueA (reg_key
, index
, name
, &name_size
, 0,
1491 &type
, (LPBYTE
)value
, &value_size
);
1493 if (res
== ERROR_SUCCESS
&& type
== REG_SZ
)
1495 char *old_result
= result
;
1497 result
= (char *) xmalloc (strlen (old_result
) + value_size
+ 2);
1498 strcpy (result
, old_result
);
1499 strcat (result
, value
);
1500 strcat (result
, ";");
1505 /* Remove the trailing ";". */
1507 result
[strlen (result
) - 1] = 0;
1513 /* Query information for the given file NAME and return it in STATBUF.
1514 * Returns 0 for success, or errno value for failure.
1517 __gnat_stat (char *name
, GNAT_STRUCT_STAT
*statbuf
)
1520 WIN32_FILE_ATTRIBUTE_DATA fad
;
1521 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
1526 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
1527 name_len
= _tcslen (wname
);
1529 if (name_len
> GNAT_MAX_PATH_LEN
)
1532 ZeroMemory (statbuf
, sizeof(GNAT_STRUCT_STAT
));
1534 res
= GetFileAttributesEx (wname
, GetFileExInfoStandard
, &fad
);
1537 error
= GetLastError();
1539 /* Check file existence using GetFileAttributes() which does not fail on
1540 special Windows files like con:, aux:, nul: etc... */
1542 if (GetFileAttributes(wname
) != INVALID_FILE_ATTRIBUTES
) {
1543 /* Just pretend that it is a regular and readable file */
1544 statbuf
->st_mode
= S_IFREG
| S_IREAD
| S_IWRITE
;
1549 case ERROR_ACCESS_DENIED
:
1550 case ERROR_SHARING_VIOLATION
:
1551 case ERROR_LOCK_VIOLATION
:
1552 case ERROR_SHARING_BUFFER_EXCEEDED
:
1554 case ERROR_BUFFER_OVERFLOW
:
1555 return ENAMETOOLONG
;
1556 case ERROR_NOT_ENOUGH_MEMORY
:
1563 f2t (&fad
.ftCreationTime
, &statbuf
->st_ctime
);
1564 f2t (&fad
.ftLastWriteTime
, &statbuf
->st_mtime
);
1565 f2t (&fad
.ftLastAccessTime
, &statbuf
->st_atime
);
1568 (__int64
)fad
.nFileSizeLow
| (__int64
)fad
.nFileSizeHigh
<< 32;
1570 /* We do not have the S_IEXEC attribute, but this is not used on GNAT. */
1571 statbuf
->st_mode
= S_IREAD
;
1573 if (fad
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
1574 statbuf
->st_mode
|= S_IFDIR
;
1576 statbuf
->st_mode
|= S_IFREG
;
1578 if (!(fad
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
))
1579 statbuf
->st_mode
|= S_IWRITE
;
1584 return GNAT_STAT (name
, statbuf
) == 0 ? 0 : errno
;
1588 /*************************************************************************
1589 ** Check whether a file exists
1590 *************************************************************************/
1593 __gnat_file_exists_attr (char* name
, struct file_attributes
* attr
)
1595 if (attr
->exists
== ATTR_UNSET
)
1596 __gnat_stat_to_attr (-1, name
, attr
);
1598 return attr
->exists
;
1602 __gnat_file_exists (char *name
)
1604 struct file_attributes attr
;
1605 __gnat_reset_attributes (&attr
);
1606 return __gnat_file_exists_attr (name
, &attr
);
1609 /**********************************************************************
1610 ** Whether name is an absolute path
1611 **********************************************************************/
1614 __gnat_is_absolute_path (char *name
, int length
)
1617 /* On VxWorks systems, an absolute path can be represented (depending on
1618 the host platform) as either /dir/file, or device:/dir/file, or
1619 device:drive_letter:/dir/file. */
1626 for (index
= 0; index
< length
; index
++)
1628 if (name
[index
] == ':' &&
1629 ((name
[index
+ 1] == '/') ||
1630 (isalpha (name
[index
+ 1]) && index
+ 2 <= length
&&
1631 name
[index
+ 2] == '/')))
1634 else if (name
[index
] == '/')
1639 return (length
!= 0) &&
1640 (*name
== '/' || *name
== DIR_SEPARATOR
1642 || (length
> 1 && ISALPHA (name
[0]) && name
[1] == ':')
1649 __gnat_is_regular_file_attr (char* name
, struct file_attributes
* attr
)
1651 if (attr
->regular
== ATTR_UNSET
)
1652 __gnat_stat_to_attr (-1, name
, attr
);
1654 return attr
->regular
;
1658 __gnat_is_regular_file (char *name
)
1660 struct file_attributes attr
;
1662 __gnat_reset_attributes (&attr
);
1663 return __gnat_is_regular_file_attr (name
, &attr
);
1667 __gnat_is_regular_file_fd (int fd
)
1670 GNAT_STRUCT_STAT statbuf
;
1672 ret
= GNAT_FSTAT (fd
, &statbuf
);
1673 return (!ret
&& S_ISREG (statbuf
.st_mode
));
1677 __gnat_is_directory_attr (char* name
, struct file_attributes
* attr
)
1679 if (attr
->directory
== ATTR_UNSET
)
1680 __gnat_stat_to_attr (-1, name
, attr
);
1682 return attr
->directory
;
1686 __gnat_is_directory (char *name
)
1688 struct file_attributes attr
;
1690 __gnat_reset_attributes (&attr
);
1691 return __gnat_is_directory_attr (name
, &attr
);
1694 #if defined (_WIN32) && !defined (RTX)
1696 /* Returns the same constant as GetDriveType but takes a pathname as
1700 GetDriveTypeFromPath (TCHAR
*wfullpath
)
1702 TCHAR wdrv
[MAX_PATH
];
1703 TCHAR wpath
[MAX_PATH
];
1704 TCHAR wfilename
[MAX_PATH
];
1705 TCHAR wext
[MAX_PATH
];
1707 _tsplitpath (wfullpath
, wdrv
, wpath
, wfilename
, wext
);
1709 if (_tcslen (wdrv
) != 0)
1711 /* we have a drive specified. */
1712 _tcscat (wdrv
, _T("\\"));
1713 return GetDriveType (wdrv
);
1717 /* No drive specified. */
1719 /* Is this a relative path, if so get current drive type. */
1720 if (wpath
[0] != _T('\\') ||
1721 (_tcslen (wpath
) > 2 && wpath
[0] == _T('\\')
1722 && wpath
[1] != _T('\\')))
1723 return GetDriveType (NULL
);
1725 UINT result
= GetDriveType (wpath
);
1727 /* Cannot guess the drive type, is this \\.\ ? */
1729 if (result
== DRIVE_NO_ROOT_DIR
&&
1730 _tcslen (wpath
) >= 4 && wpath
[0] == _T('\\') && wpath
[1] == _T('\\')
1731 && wpath
[2] == _T('.') && wpath
[3] == _T('\\'))
1733 if (_tcslen (wpath
) == 4)
1734 _tcscat (wpath
, wfilename
);
1736 LPTSTR p
= &wpath
[4];
1737 LPTSTR b
= _tcschr (p
, _T('\\'));
1741 /* logical drive \\.\c\dir\file */
1747 _tcscat (p
, _T(":\\"));
1749 return GetDriveType (p
);
1756 /* This MingW section contains code to work with ACL. */
1758 __gnat_check_OWNER_ACL (TCHAR
*wname
,
1759 DWORD CheckAccessDesired
,
1760 GENERIC_MAPPING CheckGenericMapping
)
1762 DWORD dwAccessDesired
, dwAccessAllowed
;
1763 PRIVILEGE_SET PrivilegeSet
;
1764 DWORD dwPrivSetSize
= sizeof (PRIVILEGE_SET
);
1765 BOOL fAccessGranted
= FALSE
;
1766 HANDLE hToken
= NULL
;
1768 PSECURITY_DESCRIPTOR pSD
= NULL
;
1771 (wname
, OWNER_SECURITY_INFORMATION
|
1772 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
,
1775 if ((pSD
= (SECURITY_DESCRIPTOR
*) HeapAlloc
1776 (GetProcessHeap (), HEAP_ZERO_MEMORY
, nLength
)) == NULL
)
1779 /* Obtain the security descriptor. */
1781 if (!GetFileSecurity
1782 (wname
, OWNER_SECURITY_INFORMATION
|
1783 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
,
1784 pSD
, nLength
, &nLength
))
1787 if (!ImpersonateSelf (SecurityImpersonation
))
1790 if (!OpenThreadToken
1791 (GetCurrentThread(), TOKEN_DUPLICATE
| TOKEN_QUERY
, FALSE
, &hToken
))
1794 /* Undoes the effect of ImpersonateSelf. */
1798 /* We want to test for write permissions. */
1800 dwAccessDesired
= CheckAccessDesired
;
1802 MapGenericMask (&dwAccessDesired
, &CheckGenericMapping
);
1805 (pSD
, /* security descriptor to check */
1806 hToken
, /* impersonation token */
1807 dwAccessDesired
, /* requested access rights */
1808 &CheckGenericMapping
, /* pointer to GENERIC_MAPPING */
1809 &PrivilegeSet
, /* receives privileges used in check */
1810 &dwPrivSetSize
, /* size of PrivilegeSet buffer */
1811 &dwAccessAllowed
, /* receives mask of allowed access rights */
1815 CloseHandle (hToken
);
1816 HeapFree (GetProcessHeap (), 0, pSD
);
1817 return fAccessGranted
;
1821 CloseHandle (hToken
);
1822 HeapFree (GetProcessHeap (), 0, pSD
);
1827 __gnat_set_OWNER_ACL (TCHAR
*wname
,
1828 ACCESS_MODE AccessMode
,
1829 DWORD AccessPermissions
)
1831 PACL pOldDACL
= NULL
;
1832 PACL pNewDACL
= NULL
;
1833 PSECURITY_DESCRIPTOR pSD
= NULL
;
1835 TCHAR username
[100];
1838 /* Get current user, he will act as the owner */
1840 if (!GetUserName (username
, &unsize
))
1843 if (GetNamedSecurityInfo
1846 DACL_SECURITY_INFORMATION
,
1847 NULL
, NULL
, &pOldDACL
, NULL
, &pSD
) != ERROR_SUCCESS
)
1850 BuildExplicitAccessWithName
1851 (&ea
, username
, AccessPermissions
, (ACCESS_MODE
) AccessMode
, NO_INHERITANCE
);
1853 if (AccessMode
== SET_ACCESS
)
1855 /* SET_ACCESS, we want to set an explicte set of permissions, do not
1856 merge with current DACL. */
1857 if (SetEntriesInAcl (1, &ea
, NULL
, &pNewDACL
) != ERROR_SUCCESS
)
1861 if (SetEntriesInAcl (1, &ea
, pOldDACL
, &pNewDACL
) != ERROR_SUCCESS
)
1864 if (SetNamedSecurityInfo
1865 (wname
, SE_FILE_OBJECT
,
1866 DACL_SECURITY_INFORMATION
, NULL
, NULL
, pNewDACL
, NULL
) != ERROR_SUCCESS
)
1870 LocalFree (pNewDACL
);
1873 /* Check if it is possible to use ACL for wname, the file must not be on a
1877 __gnat_can_use_acl (TCHAR
*wname
)
1879 return __gnat_use_acl
&& GetDriveTypeFromPath (wname
) != DRIVE_REMOTE
;
1882 #endif /* defined (_WIN32) && !defined (RTX) */
1885 __gnat_is_readable_file_attr (char* name
, struct file_attributes
* attr
)
1887 if (attr
->readable
== ATTR_UNSET
)
1889 #if defined (_WIN32) && !defined (RTX)
1890 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
1891 GENERIC_MAPPING GenericMapping
;
1893 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
1895 if (__gnat_can_use_acl (wname
))
1897 ZeroMemory (&GenericMapping
, sizeof (GENERIC_MAPPING
));
1898 GenericMapping
.GenericRead
= GENERIC_READ
;
1900 __gnat_check_OWNER_ACL (wname
, FILE_READ_DATA
, GenericMapping
);
1903 attr
->readable
= GetFileAttributes (wname
) != INVALID_FILE_ATTRIBUTES
;
1905 __gnat_stat_to_attr (-1, name
, attr
);
1909 return attr
->readable
;
1913 __gnat_is_readable_file (char *name
)
1915 struct file_attributes attr
;
1917 __gnat_reset_attributes (&attr
);
1918 return __gnat_is_readable_file_attr (name
, &attr
);
1922 __gnat_is_writable_file_attr (char* name
, struct file_attributes
* attr
)
1924 if (attr
->writable
== ATTR_UNSET
)
1926 #if defined (_WIN32) && !defined (RTX)
1927 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
1928 GENERIC_MAPPING GenericMapping
;
1930 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
1932 if (__gnat_can_use_acl (wname
))
1934 ZeroMemory (&GenericMapping
, sizeof (GENERIC_MAPPING
));
1935 GenericMapping
.GenericWrite
= GENERIC_WRITE
;
1937 attr
->writable
= __gnat_check_OWNER_ACL
1938 (wname
, FILE_WRITE_DATA
| FILE_APPEND_DATA
, GenericMapping
)
1939 && !(GetFileAttributes (wname
) & FILE_ATTRIBUTE_READONLY
);
1943 !(GetFileAttributes (wname
) & FILE_ATTRIBUTE_READONLY
);
1946 __gnat_stat_to_attr (-1, name
, attr
);
1950 return attr
->writable
;
1954 __gnat_is_writable_file (char *name
)
1956 struct file_attributes attr
;
1958 __gnat_reset_attributes (&attr
);
1959 return __gnat_is_writable_file_attr (name
, &attr
);
1963 __gnat_is_executable_file_attr (char* name
, struct file_attributes
* attr
)
1965 if (attr
->executable
== ATTR_UNSET
)
1967 #if defined (_WIN32) && !defined (RTX)
1968 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
1969 GENERIC_MAPPING GenericMapping
;
1971 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
1973 if (__gnat_can_use_acl (wname
))
1975 ZeroMemory (&GenericMapping
, sizeof (GENERIC_MAPPING
));
1976 GenericMapping
.GenericExecute
= GENERIC_EXECUTE
;
1979 __gnat_check_OWNER_ACL (wname
, FILE_EXECUTE
, GenericMapping
);
1983 TCHAR
*l
, *last
= _tcsstr(wname
, _T(".exe"));
1985 /* look for last .exe */
1987 while ((l
= _tcsstr(last
+1, _T(".exe"))))
1991 GetFileAttributes (wname
) != INVALID_FILE_ATTRIBUTES
1992 && (last
- wname
) == (int) (_tcslen (wname
) - 4);
1995 __gnat_stat_to_attr (-1, name
, attr
);
1999 return attr
->regular
&& attr
->executable
;
2003 __gnat_is_executable_file (char *name
)
2005 struct file_attributes attr
;
2007 __gnat_reset_attributes (&attr
);
2008 return __gnat_is_executable_file_attr (name
, &attr
);
2012 __gnat_set_writable (char *name
)
2014 #if defined (_WIN32) && !defined (RTX)
2015 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2017 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2019 if (__gnat_can_use_acl (wname
))
2020 __gnat_set_OWNER_ACL (wname
, GRANT_ACCESS
, FILE_GENERIC_WRITE
);
2023 (wname
, GetFileAttributes (wname
) & ~FILE_ATTRIBUTE_READONLY
);
2024 #elif ! (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 6) && \
2025 ! defined(__nucleus__)
2026 GNAT_STRUCT_STAT statbuf
;
2028 if (GNAT_STAT (name
, &statbuf
) == 0)
2030 statbuf
.st_mode
= statbuf
.st_mode
| S_IWUSR
;
2031 chmod (name
, statbuf
.st_mode
);
2036 /* must match definition in s-os_lib.ads */
2042 __gnat_set_executable (char *name
, int mode ATTRIBUTE_UNUSED
)
2044 #if defined (_WIN32) && !defined (RTX)
2045 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2047 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2049 if (__gnat_can_use_acl (wname
))
2050 __gnat_set_OWNER_ACL (wname
, GRANT_ACCESS
, FILE_GENERIC_EXECUTE
);
2052 #elif ! (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 6) && \
2053 ! defined(__nucleus__)
2054 GNAT_STRUCT_STAT statbuf
;
2056 if (GNAT_STAT (name
, &statbuf
) == 0)
2059 statbuf
.st_mode
= statbuf
.st_mode
| S_IXUSR
;
2061 statbuf
.st_mode
= statbuf
.st_mode
| S_IXGRP
;
2062 if (mode
& S_OTHERS
)
2063 statbuf
.st_mode
= statbuf
.st_mode
| S_IXOTH
;
2064 chmod (name
, statbuf
.st_mode
);
2070 __gnat_set_non_writable (char *name
)
2072 #if defined (_WIN32) && !defined (RTX)
2073 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2075 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2077 if (__gnat_can_use_acl (wname
))
2078 __gnat_set_OWNER_ACL
2079 (wname
, DENY_ACCESS
,
2080 FILE_WRITE_DATA
| FILE_APPEND_DATA
|
2081 FILE_WRITE_EA
| FILE_WRITE_ATTRIBUTES
);
2084 (wname
, GetFileAttributes (wname
) | FILE_ATTRIBUTE_READONLY
);
2085 #elif ! (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 6) && \
2086 ! defined(__nucleus__)
2087 GNAT_STRUCT_STAT statbuf
;
2089 if (GNAT_STAT (name
, &statbuf
) == 0)
2091 statbuf
.st_mode
= statbuf
.st_mode
& 07577;
2092 chmod (name
, statbuf
.st_mode
);
2098 __gnat_set_readable (char *name
)
2100 #if defined (_WIN32) && !defined (RTX)
2101 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2103 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2105 if (__gnat_can_use_acl (wname
))
2106 __gnat_set_OWNER_ACL (wname
, GRANT_ACCESS
, FILE_GENERIC_READ
);
2108 #elif ! (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 6) && \
2109 ! defined(__nucleus__)
2110 GNAT_STRUCT_STAT statbuf
;
2112 if (GNAT_STAT (name
, &statbuf
) == 0)
2114 chmod (name
, statbuf
.st_mode
| S_IREAD
);
2120 __gnat_set_non_readable (char *name
)
2122 #if defined (_WIN32) && !defined (RTX)
2123 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2125 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2127 if (__gnat_can_use_acl (wname
))
2128 __gnat_set_OWNER_ACL (wname
, DENY_ACCESS
, FILE_GENERIC_READ
);
2130 #elif ! (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 6) && \
2131 ! defined(__nucleus__)
2132 GNAT_STRUCT_STAT statbuf
;
2134 if (GNAT_STAT (name
, &statbuf
) == 0)
2136 chmod (name
, statbuf
.st_mode
& (~S_IREAD
));
2142 __gnat_is_symbolic_link_attr (char* name ATTRIBUTE_UNUSED
,
2143 struct file_attributes
* attr
)
2145 if (attr
->symbolic_link
== ATTR_UNSET
)
2147 #if defined (__vxworks) || defined (__nucleus__)
2148 attr
->symbolic_link
= 0;
2150 #elif defined (_AIX) || defined (__APPLE__) || defined (__unix__)
2152 GNAT_STRUCT_STAT statbuf
;
2153 ret
= GNAT_LSTAT (name
, &statbuf
);
2154 attr
->symbolic_link
= (!ret
&& S_ISLNK (statbuf
.st_mode
));
2156 attr
->symbolic_link
= 0;
2159 return attr
->symbolic_link
;
2163 __gnat_is_symbolic_link (char *name ATTRIBUTE_UNUSED
)
2165 struct file_attributes attr
;
2167 __gnat_reset_attributes (&attr
);
2168 return __gnat_is_symbolic_link_attr (name
, &attr
);
2171 #if defined (sun) && defined (__SVR4)
2172 /* Using fork on Solaris will duplicate all the threads. fork1, which
2173 duplicates only the active thread, must be used instead, or spawning
2174 subprocess from a program with tasking will lead into numerous problems. */
2179 __gnat_portable_spawn (char *args
[] ATTRIBUTE_UNUSED
)
2181 int status ATTRIBUTE_UNUSED
= 0;
2182 int finished ATTRIBUTE_UNUSED
;
2183 int pid ATTRIBUTE_UNUSED
;
2185 #if defined (__vxworks) || defined(__nucleus__) || defined(RTX) \
2186 || defined(__PikeOS__)
2189 #elif defined (_WIN32)
2190 /* args[0] must be quotes as it could contain a full pathname with spaces */
2191 char *args_0
= args
[0];
2192 args
[0] = (char *)xmalloc (strlen (args_0
) + 3);
2193 strcpy (args
[0], "\"");
2194 strcat (args
[0], args_0
);
2195 strcat (args
[0], "\"");
2197 status
= spawnvp (P_WAIT
, args_0
, (char ** const)args
);
2199 /* restore previous value */
2201 args
[0] = (char *)args_0
;
2217 if (execv (args
[0], MAYBE_TO_PTR32 (args
)) != 0)
2222 finished
= waitpid (pid
, &status
, 0);
2224 if (finished
!= pid
|| WIFEXITED (status
) == 0)
2227 return WEXITSTATUS (status
);
2233 /* Create a copy of the given file descriptor.
2234 Return -1 if an error occurred. */
2237 __gnat_dup (int oldfd
)
2239 #if defined (__vxworks) && !defined (__RTP__)
2240 /* Not supported on VxWorks 5.x, but supported on VxWorks 6.0 when using
2248 /* Make newfd be the copy of oldfd, closing newfd first if necessary.
2249 Return -1 if an error occurred. */
2252 __gnat_dup2 (int oldfd ATTRIBUTE_UNUSED
, int newfd ATTRIBUTE_UNUSED
)
2254 #if defined (__vxworks) && !defined (__RTP__)
2255 /* Not supported on VxWorks 5.x, but supported on VxWorks 6.0 when using
2258 #elif defined (__PikeOS__)
2259 /* Not supported. */
2261 #elif defined (_WIN32)
2262 /* Special case when oldfd and newfd are identical and are the standard
2263 input, output or error as this makes Windows XP hangs. Note that we
2264 do that only for standard file descriptors that are known to be valid. */
2265 if (oldfd
== newfd
&& newfd
>= 0 && newfd
<= 2)
2268 return dup2 (oldfd
, newfd
);
2270 return dup2 (oldfd
, newfd
);
2275 __gnat_number_of_cpus (void)
2279 #if defined (linux) || defined (sun) || defined (AIX) || defined (__APPLE__)
2280 cores
= (int) sysconf (_SC_NPROCESSORS_ONLN
);
2282 #elif defined (__hpux__)
2283 struct pst_dynamic psd
;
2284 if (pstat_getdynamic (&psd
, sizeof (psd
), 1, 0) != -1)
2285 cores
= (int) psd
.psd_proc_cnt
;
2287 #elif defined (_WIN32)
2288 SYSTEM_INFO sysinfo
;
2289 GetSystemInfo (&sysinfo
);
2290 cores
= (int) sysinfo
.dwNumberOfProcessors
;
2292 #elif defined (_WRS_CONFIG_SMP)
2293 unsigned int vxCpuConfiguredGet (void);
2295 cores
= vxCpuConfiguredGet ();
2302 /* WIN32 code to implement a wait call that wait for any child process. */
2304 #if defined (_WIN32) && !defined (RTX)
2306 /* Synchronization code, to be thread safe. */
2310 /* For the Cert run times on native Windows we use dummy functions
2311 for locking and unlocking tasks since we do not support multiple
2312 threads on this configuration (Cert run time on native Windows). */
2314 static void dummy (void)
2318 void (*Lock_Task
) () = &dummy
;
2319 void (*Unlock_Task
) () = &dummy
;
2323 #define Lock_Task system__soft_links__lock_task
2324 extern void (*Lock_Task
) (void);
2326 #define Unlock_Task system__soft_links__unlock_task
2327 extern void (*Unlock_Task
) (void);
2331 static HANDLE
*HANDLES_LIST
= NULL
;
2332 static int *PID_LIST
= NULL
, plist_length
= 0, plist_max_length
= 0;
2335 add_handle (HANDLE h
, int pid
)
2338 /* -------------------- critical section -------------------- */
2341 if (plist_length
== plist_max_length
)
2343 plist_max_length
+= 1000;
2345 (HANDLE
*) xrealloc (HANDLES_LIST
, sizeof (HANDLE
) * plist_max_length
);
2347 (int *) xrealloc (PID_LIST
, sizeof (int) * plist_max_length
);
2350 HANDLES_LIST
[plist_length
] = h
;
2351 PID_LIST
[plist_length
] = pid
;
2355 /* -------------------- critical section -------------------- */
2359 __gnat_win32_remove_handle (HANDLE h
, int pid
)
2363 /* -------------------- critical section -------------------- */
2366 for (j
= 0; j
< plist_length
; j
++)
2368 if ((HANDLES_LIST
[j
] == h
) || (PID_LIST
[j
] == pid
))
2372 HANDLES_LIST
[j
] = HANDLES_LIST
[plist_length
];
2373 PID_LIST
[j
] = PID_LIST
[plist_length
];
2379 /* -------------------- critical section -------------------- */
2383 win32_no_block_spawn (char *command
, char *args
[], HANDLE
*h
, int *pid
)
2387 PROCESS_INFORMATION PI
;
2388 SECURITY_ATTRIBUTES SA
;
2393 /* compute the total command line length */
2397 csize
+= strlen (args
[k
]) + 1;
2401 full_command
= (char *) xmalloc (csize
);
2404 SI
.cb
= sizeof (STARTUPINFO
);
2405 SI
.lpReserved
= NULL
;
2406 SI
.lpReserved2
= NULL
;
2407 SI
.lpDesktop
= NULL
;
2411 SI
.wShowWindow
= SW_HIDE
;
2413 /* Security attributes. */
2414 SA
.nLength
= sizeof (SECURITY_ATTRIBUTES
);
2415 SA
.bInheritHandle
= TRUE
;
2416 SA
.lpSecurityDescriptor
= NULL
;
2418 /* Prepare the command string. */
2419 strcpy (full_command
, command
);
2420 strcat (full_command
, " ");
2425 strcat (full_command
, args
[k
]);
2426 strcat (full_command
, " ");
2431 int wsize
= csize
* 2;
2432 TCHAR
*wcommand
= (TCHAR
*) xmalloc (wsize
);
2434 S2WSC (wcommand
, full_command
, wsize
);
2436 free (full_command
);
2438 result
= CreateProcess
2439 (NULL
, wcommand
, &SA
, NULL
, TRUE
,
2440 GetPriorityClass (GetCurrentProcess()), NULL
, NULL
, &SI
, &PI
);
2447 CloseHandle (PI
.hThread
);
2449 *pid
= PI
.dwProcessId
;
2459 win32_wait (int *status
)
2461 DWORD exitcode
, pid
;
2467 if (plist_length
== 0)
2473 /* -------------------- critical section -------------------- */
2476 hl_len
= plist_length
;
2478 hl
= (HANDLE
*) xmalloc (sizeof (HANDLE
) * hl_len
);
2480 memmove (hl
, HANDLES_LIST
, sizeof (HANDLE
) * hl_len
);
2483 /* -------------------- critical section -------------------- */
2485 res
= WaitForMultipleObjects (hl_len
, hl
, FALSE
, INFINITE
);
2486 h
= hl
[res
- WAIT_OBJECT_0
];
2488 GetExitCodeProcess (h
, &exitcode
);
2489 pid
= PID_LIST
[res
- WAIT_OBJECT_0
];
2490 __gnat_win32_remove_handle (h
, -1);
2494 *status
= (int) exitcode
;
2501 __gnat_portable_no_block_spawn (char *args
[] ATTRIBUTE_UNUSED
)
2504 #if defined (__vxworks) || defined (__nucleus__) || defined (RTX) \
2505 || defined (__PikeOS__)
2506 /* Not supported. */
2509 #elif defined (_WIN32)
2514 win32_no_block_spawn (args
[0], args
, &h
, &pid
);
2517 add_handle (h
, pid
);
2530 if (execv (args
[0], MAYBE_TO_PTR32 (args
)) != 0)
2540 __gnat_portable_wait (int *process_status
)
2545 #if defined (__vxworks) || defined (__nucleus__) || defined (RTX) \
2546 || defined (__PikeOS__)
2547 /* Not sure what to do here, so do nothing but return zero. */
2549 #elif defined (_WIN32)
2551 pid
= win32_wait (&status
);
2555 pid
= waitpid (-1, &status
, 0);
2556 status
= status
& 0xffff;
2559 *process_status
= status
;
2564 __gnat_os_exit (int status
)
2569 /* Locate file on path, that matches a predicate */
2572 __gnat_locate_file_with_predicate (char *file_name
, char *path_val
,
2573 int (*predicate
)(char *))
2576 char *file_path
= (char *) alloca (strlen (file_name
) + 1);
2579 /* Return immediately if file_name is empty */
2581 if (*file_name
== '\0')
2584 /* Remove quotes around file_name if present */
2590 strcpy (file_path
, ptr
);
2592 ptr
= file_path
+ strlen (file_path
) - 1;
2597 /* Handle absolute pathnames. */
2599 absolute
= __gnat_is_absolute_path (file_path
, strlen (file_name
));
2603 if (predicate (file_path
))
2604 return xstrdup (file_path
);
2609 /* If file_name include directory separator(s), try it first as
2610 a path name relative to the current directory */
2611 for (ptr
= file_name
; *ptr
&& *ptr
!= '/' && *ptr
!= DIR_SEPARATOR
; ptr
++)
2616 if (predicate (file_name
))
2617 return xstrdup (file_name
);
2624 /* The result has to be smaller than path_val + file_name. */
2626 (char *) alloca (strlen (path_val
) + strlen (file_name
) + 2);
2630 /* Skip the starting quote */
2632 if (*path_val
== '"')
2635 for (ptr
= file_path
; *path_val
&& *path_val
!= PATH_SEPARATOR
; )
2636 *ptr
++ = *path_val
++;
2638 /* If directory is empty, it is the current directory*/
2640 if (ptr
== file_path
)
2647 /* Skip the ending quote */
2652 if (*ptr
!= '/' && *ptr
!= DIR_SEPARATOR
)
2653 *++ptr
= DIR_SEPARATOR
;
2655 strcpy (++ptr
, file_name
);
2657 if (predicate (file_path
))
2658 return xstrdup (file_path
);
2663 /* Skip path separator */
2672 /* Locate an executable file, give a Path value. */
2675 __gnat_locate_executable_file (char *file_name
, char *path_val
)
2677 return __gnat_locate_file_with_predicate
2678 (file_name
, path_val
, &__gnat_is_executable_file
);
2681 /* Locate a regular file, give a Path value. */
2684 __gnat_locate_regular_file (char *file_name
, char *path_val
)
2686 return __gnat_locate_file_with_predicate
2687 (file_name
, path_val
, &__gnat_is_regular_file
);
2690 /* Locate an executable given a Path argument. This routine is only used by
2691 gnatbl and should not be used otherwise. Use locate_exec_on_path
2695 __gnat_locate_exec (char *exec_name
, char *path_val
)
2698 if (!strstr (exec_name
, HOST_EXECUTABLE_SUFFIX
))
2700 char *full_exec_name
=
2702 (strlen (exec_name
) + strlen (HOST_EXECUTABLE_SUFFIX
) + 1);
2704 strcpy (full_exec_name
, exec_name
);
2705 strcat (full_exec_name
, HOST_EXECUTABLE_SUFFIX
);
2706 ptr
= __gnat_locate_executable_file (full_exec_name
, path_val
);
2709 return __gnat_locate_executable_file (exec_name
, path_val
);
2713 return __gnat_locate_executable_file (exec_name
, path_val
);
2716 /* Locate an executable using the Systems default PATH. */
2719 __gnat_locate_exec_on_path (char *exec_name
)
2723 #if defined (_WIN32) && !defined (RTX)
2724 TCHAR
*wpath_val
= _tgetenv (_T("PATH"));
2726 /* In Win32 systems we expand the PATH as for XP environment
2727 variables are not automatically expanded. We also prepend the
2728 ".;" to the path to match normal NT path search semantics */
2730 #define EXPAND_BUFFER_SIZE 32767
2732 wapath_val
= (TCHAR
*) alloca (EXPAND_BUFFER_SIZE
);
2734 wapath_val
[0] = '.';
2735 wapath_val
[1] = ';';
2737 DWORD res
= ExpandEnvironmentStrings
2738 (wpath_val
, &wapath_val
[2], EXPAND_BUFFER_SIZE
- 2);
2740 if (!res
) wapath_val
[0] = _T('\0');
2742 apath_val
= (char *) alloca (EXPAND_BUFFER_SIZE
);
2744 WS2SC (apath_val
, wapath_val
, EXPAND_BUFFER_SIZE
);
2745 return __gnat_locate_exec (exec_name
, apath_val
);
2748 char *path_val
= getenv ("PATH");
2750 if (path_val
== NULL
) return NULL
;
2751 apath_val
= (char *) alloca (strlen (path_val
) + 1);
2752 strcpy (apath_val
, path_val
);
2753 return __gnat_locate_exec (exec_name
, apath_val
);
2757 /* Dummy functions for Osint import for non-VMS systems.
2758 ??? To be removed. */
2761 __gnat_to_canonical_file_list_init (char *dirspec ATTRIBUTE_UNUSED
,
2762 int onlydirs ATTRIBUTE_UNUSED
)
2768 __gnat_to_canonical_file_list_next (void)
2770 static char empty
[] = "";
2775 __gnat_to_canonical_file_list_free (void)
2780 __gnat_to_canonical_dir_spec (char *dirspec
, int prefixflag ATTRIBUTE_UNUSED
)
2786 __gnat_to_canonical_file_spec (char *filespec
)
2792 __gnat_to_canonical_path_spec (char *pathspec
)
2798 __gnat_to_host_dir_spec (char *dirspec
, int prefixflag ATTRIBUTE_UNUSED
)
2804 __gnat_to_host_file_spec (char *filespec
)
2810 __gnat_adjust_os_resource_limits (void)
2814 #if defined (__mips_vxworks)
2818 CACHE_USER_FLUSH (0, ENTIRE_CACHE
);
2822 #if defined (_WIN32)
2823 int __gnat_argument_needs_quote
= 1;
2825 int __gnat_argument_needs_quote
= 0;
2828 /* This option is used to enable/disable object files handling from the
2829 binder file by the GNAT Project module. For example, this is disabled on
2830 Windows (prior to GCC 3.4) as it is already done by the mdll module.
2831 Stating with GCC 3.4 the shared libraries are not based on mdll
2832 anymore as it uses the GCC's -shared option */
2833 #if defined (_WIN32) \
2834 && ((__GNUC__ < 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ < 4)))
2835 int __gnat_prj_add_obj_files
= 0;
2837 int __gnat_prj_add_obj_files
= 1;
2840 /* char used as prefix/suffix for environment variables */
2841 #if defined (_WIN32)
2842 char __gnat_environment_char
= '%';
2844 char __gnat_environment_char
= '$';
2847 /* This functions copy the file attributes from a source file to a
2850 mode = 0 : In this mode copy only the file time stamps (last access and
2851 last modification time stamps).
2853 mode = 1 : In this mode, time stamps and read/write/execute attributes are
2856 Returns 0 if operation was successful and -1 in case of error. */
2859 __gnat_copy_attribs (char *from ATTRIBUTE_UNUSED
, char *to ATTRIBUTE_UNUSED
,
2860 int mode ATTRIBUTE_UNUSED
)
2862 #if (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 6) || \
2863 defined (__nucleus__)
2866 #elif defined (_WIN32) && !defined (RTX)
2867 TCHAR wfrom
[GNAT_MAX_PATH_LEN
+ 2];
2868 TCHAR wto
[GNAT_MAX_PATH_LEN
+ 2];
2870 FILETIME fct
, flat
, flwt
;
2873 S2WSC (wfrom
, from
, GNAT_MAX_PATH_LEN
+ 2);
2874 S2WSC (wto
, to
, GNAT_MAX_PATH_LEN
+ 2);
2876 /* retrieve from times */
2879 (wfrom
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2881 if (hfrom
== INVALID_HANDLE_VALUE
)
2884 res
= GetFileTime (hfrom
, &fct
, &flat
, &flwt
);
2886 CloseHandle (hfrom
);
2891 /* retrieve from times */
2894 (wto
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2896 if (hto
== INVALID_HANDLE_VALUE
)
2899 res
= SetFileTime (hto
, NULL
, &flat
, &flwt
);
2906 /* Set file attributes in full mode. */
2910 DWORD attribs
= GetFileAttributes (wfrom
);
2912 if (attribs
== INVALID_FILE_ATTRIBUTES
)
2915 res
= SetFileAttributes (wto
, attribs
);
2923 GNAT_STRUCT_STAT fbuf
;
2924 struct utimbuf tbuf
;
2926 if (GNAT_STAT (from
, &fbuf
) == -1)
2931 tbuf
.actime
= fbuf
.st_atime
;
2932 tbuf
.modtime
= fbuf
.st_mtime
;
2934 if (utime (to
, &tbuf
) == -1)
2941 if (chmod (to
, fbuf
.st_mode
) == -1)
2952 __gnat_lseek (int fd
, long offset
, int whence
)
2954 return (int) lseek (fd
, offset
, whence
);
2957 /* This function returns the major version number of GCC being used. */
2959 get_gcc_version (void)
2964 return (int) (version_string
[0] - '0');
2969 * Set Close_On_Exec as indicated.
2970 * Note: this is used for both GNAT.OS_Lib and GNAT.Sockets.
2974 __gnat_set_close_on_exec (int fd ATTRIBUTE_UNUSED
,
2975 int close_on_exec_p ATTRIBUTE_UNUSED
)
2977 #if defined (F_GETFD) && defined (FD_CLOEXEC) && ! defined (__vxworks)
2978 int flags
= fcntl (fd
, F_GETFD
, 0);
2981 if (close_on_exec_p
)
2982 flags
|= FD_CLOEXEC
;
2984 flags
&= ~FD_CLOEXEC
;
2985 return fcntl (fd
, F_SETFD
, flags
);
2986 #elif defined(_WIN32)
2987 HANDLE h
= (HANDLE
) _get_osfhandle (fd
);
2988 if (h
== (HANDLE
) -1)
2990 if (close_on_exec_p
)
2991 return ! SetHandleInformation (h
, HANDLE_FLAG_INHERIT
, 0);
2992 return ! SetHandleInformation (h
, HANDLE_FLAG_INHERIT
,
2993 HANDLE_FLAG_INHERIT
);
2995 /* TODO: Unimplemented. */
3000 /* Indicates if platforms supports automatic initialization through the
3001 constructor mechanism */
3003 __gnat_binder_supports_auto_init (void)
3008 /* Indicates that Stand-Alone Libraries are automatically initialized through
3009 the constructor mechanism */
3011 __gnat_sals_init_using_constructors (void)
3013 #if defined (__vxworks) || defined (__Lynx__)
3022 /* In RTX mode, the procedure to get the time (as file time) is different
3023 in RTSS mode and Win32 mode. In order to avoid duplicating an Ada file,
3024 we introduce an intermediate procedure to link against the corresponding
3025 one in each situation. */
3027 extern void GetTimeAsFileTime (LPFILETIME pTime
);
3029 void GetTimeAsFileTime (LPFILETIME pTime
)
3032 RtGetRtssTimeAsFileTime (pTime
); /* RTSS interface */
3034 GetSystemTimeAsFileTime (pTime
); /* w32 interface */
3039 /* Add symbol that is required to link. It would otherwise be taken from
3040 libgcc.a and it would try to use the gcc constructors that are not
3041 supported by Microsoft linker. */
3043 extern void __main (void);
3051 #if defined (__ANDROID__)
3053 #include <pthread.h>
3056 __gnat_lwp_self (void)
3058 return (void *) pthread_self ();
3061 #elif defined (linux)
3062 /* There is no function in the glibc to retrieve the LWP of the current
3063 thread. We need to do a system call in order to retrieve this
3065 #include <sys/syscall.h>
3067 __gnat_lwp_self (void)
3069 return (void *) syscall (__NR_gettid
);
3074 /* glibc versions earlier than 2.7 do not define the routines to handle
3075 dynamically allocated CPU sets. For these targets, we use the static
3080 /* Dynamic cpu sets */
3083 __gnat_cpu_alloc (size_t count
)
3085 return CPU_ALLOC (count
);
3089 __gnat_cpu_alloc_size (size_t count
)
3091 return CPU_ALLOC_SIZE (count
);
3095 __gnat_cpu_free (cpu_set_t
*set
)
3101 __gnat_cpu_zero (size_t count
, cpu_set_t
*set
)
3103 CPU_ZERO_S (count
, set
);
3107 __gnat_cpu_set (int cpu
, size_t count
, cpu_set_t
*set
)
3109 /* Ada handles CPU numbers starting from 1, while C identifies the first
3110 CPU by a 0, so we need to adjust. */
3111 CPU_SET_S (cpu
- 1, count
, set
);
3114 #else /* !CPU_ALLOC */
3116 /* Static cpu sets */
3119 __gnat_cpu_alloc (size_t count ATTRIBUTE_UNUSED
)
3121 return (cpu_set_t
*) xmalloc (sizeof (cpu_set_t
));
3125 __gnat_cpu_alloc_size (size_t count ATTRIBUTE_UNUSED
)
3127 return sizeof (cpu_set_t
);
3131 __gnat_cpu_free (cpu_set_t
*set
)
3137 __gnat_cpu_zero (size_t count ATTRIBUTE_UNUSED
, cpu_set_t
*set
)
3143 __gnat_cpu_set (int cpu
, size_t count ATTRIBUTE_UNUSED
, cpu_set_t
*set
)
3145 /* Ada handles CPU numbers starting from 1, while C identifies the first
3146 CPU by a 0, so we need to adjust. */
3147 CPU_SET (cpu
- 1, set
);
3149 #endif /* !CPU_ALLOC */
3152 /* Return the load address of the executable, or 0 if not known. In the
3153 specific case of error, (void *)-1 can be returned. Beware: this unit may
3154 be in a shared library. As low-level units are needed, we allow #include
3157 #if defined (__APPLE__)
3158 #include <mach-o/dyld.h>
3159 #elif 0 && defined (__linux__)
3164 __gnat_get_executable_load_address (void)
3166 #if defined (__APPLE__)
3167 return _dyld_get_image_header (0);
3169 #elif 0 && defined (__linux__)
3170 /* Currently disabled as it needs at least -ldl. */
3171 struct link_map
*map
= _r_debug
.r_map
;
3173 return (const void *)map
->l_addr
;