1 /****************************************************************************
3 * GNAT COMPILER COMPONENTS *
7 * C Implementation File *
9 * Copyright (C) 1992-2015, 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__) || defined (__CYGWIN__)
113 /* Current code page and CCS encoding to use, set in initialize.c. */
114 UINT CurrentCodePage
;
115 UINT CurrentCCSEncoding
;
117 #include <sys/utime.h>
119 /* For isalpha-like tests in the compiler, we're expected to resort to
120 safe-ctype.h/ISALPHA. This isn't available for the runtime library
121 build, so we fallback on ctype.h/isalpha there. */
125 #define ISALPHA isalpha
128 #elif defined (__Lynx__)
130 /* Lynx utime.h only defines the entities of interest to us if
131 defined (VMOS_DEV), so ... */
140 /* wait.h processing */
143 # include <sys/wait.h>
145 #elif defined (__vxworks) && defined (__RTP__)
147 #elif defined (__Lynx__)
148 /* ??? We really need wait.h and it includes resource.h on Lynx. GCC
149 has a resource.h header as well, included instead of the lynx
150 version in our setup, causing lots of errors. We don't really need
151 the lynx contents of this file, so just workaround the issue by
152 preventing the inclusion of the GCC header from doing anything. */
153 # define GCC_RESOURCE_H
154 # include <sys/wait.h>
155 #elif defined (__PikeOS__)
156 /* No wait() or waitpid() calls available. */
159 #include <sys/wait.h>
170 #define DIR_SEPARATOR '\\'
178 /* Define symbols O_BINARY and O_TEXT as harmless zeroes if they are not
179 defined in the current system. On DOS-like systems these flags control
180 whether the file is opened/created in text-translation mode (CR/LF in
181 external file mapped to LF in internal file), but in Unix-like systems,
182 no text translation is required, so these flags have no effect. */
192 #ifndef HOST_EXECUTABLE_SUFFIX
193 #define HOST_EXECUTABLE_SUFFIX ""
196 #ifndef HOST_OBJECT_SUFFIX
197 #define HOST_OBJECT_SUFFIX ".o"
200 #ifndef PATH_SEPARATOR
201 #define PATH_SEPARATOR ':'
204 #ifndef DIR_SEPARATOR
205 #define DIR_SEPARATOR '/'
208 /* Check for cross-compilation. */
209 #if defined (CROSS_COMPILE) || defined (CROSS_DIRECTORY_STRUCTURE)
211 int __gnat_is_cross_compiler
= 1;
214 int __gnat_is_cross_compiler
= 0;
217 char __gnat_dir_separator
= DIR_SEPARATOR
;
219 char __gnat_path_separator
= PATH_SEPARATOR
;
221 /* The GNAT_LIBRARY_TEMPLATE contains a list of expressions that define
222 the base filenames that libraries specified with -lsomelib options
223 may have. This is used by GNATMAKE to check whether an executable
224 is up-to-date or not. The syntax is
226 library_template ::= { pattern ; } pattern NUL
227 pattern ::= [ prefix ] * [ postfix ]
229 These should only specify names of static libraries as it makes
230 no sense to determine at link time if dynamic-link libraries are
231 up to date or not. Any libraries that are not found are supposed
234 * if they are needed but not present, the link
237 * otherwise they are libraries in the system paths and so
238 they are considered part of the system and not checked
241 ??? This should be part of a GNAT host-specific compiler
242 file instead of being included in all user applications
243 as well. This is only a temporary work-around for 3.11b. */
245 #ifndef GNAT_LIBRARY_TEMPLATE
246 #define GNAT_LIBRARY_TEMPLATE "lib*.a"
249 const char *__gnat_library_template
= GNAT_LIBRARY_TEMPLATE
;
251 #if defined (__vxworks)
252 #define GNAT_MAX_PATH_LEN PATH_MAX
256 #if defined (__MINGW32__)
260 #include <sys/param.h>
264 #include <sys/param.h>
268 #define GNAT_MAX_PATH_LEN MAXPATHLEN
270 #define GNAT_MAX_PATH_LEN 256
275 /* Used for runtime check that Ada constant File_Attributes_Size is no
276 less than the actual size of struct file_attributes (see Osint
278 int __gnat_size_of_file_attributes
= sizeof (struct file_attributes
);
280 void __gnat_stat_to_attr (int fd
, char* name
, struct file_attributes
* attr
);
282 /* The __gnat_max_path_len variable is used to export the maximum
283 length of a path name to Ada code. max_path_len is also provided
284 for compatibility with older GNAT versions, please do not use
287 int __gnat_max_path_len
= GNAT_MAX_PATH_LEN
;
288 int max_path_len
= GNAT_MAX_PATH_LEN
;
290 /* Control whether we can use ACL on Windows. */
292 int __gnat_use_acl
= 1;
294 /* The following macro HAVE_READDIR_R should be defined if the
295 system provides the routine readdir_r.
296 ... but we never define it anywhere??? */
297 #undef HAVE_READDIR_R
299 #define MAYBE_TO_PTR32(argv) argv
301 static const char ATTR_UNSET
= 127;
303 /* Reset the file attributes as if no system call had been performed */
306 __gnat_reset_attributes (struct file_attributes
* attr
)
308 attr
->exists
= ATTR_UNSET
;
309 attr
->error
= EINVAL
;
311 attr
->writable
= ATTR_UNSET
;
312 attr
->readable
= ATTR_UNSET
;
313 attr
->executable
= ATTR_UNSET
;
315 attr
->regular
= ATTR_UNSET
;
316 attr
->symbolic_link
= ATTR_UNSET
;
317 attr
->directory
= ATTR_UNSET
;
319 attr
->timestamp
= (OS_Time
)-2;
320 attr
->file_length
= -1;
324 __gnat_error_attributes (struct file_attributes
*attr
) {
329 __gnat_current_time (void)
331 time_t res
= time (NULL
);
332 return (OS_Time
) res
;
335 /* Return the current local time as a string in the ISO 8601 format of
336 "YYYY-MM-DD HH:MM:SS.SS". The returned string is 22 + 1 (NULL) characters
340 __gnat_current_time_string (char *result
)
342 const char *format
= "%Y-%m-%d %H:%M:%S";
343 /* Format string necessary to describe the ISO 8601 format */
345 const time_t t_val
= time (NULL
);
347 strftime (result
, 22, format
, localtime (&t_val
));
348 /* Convert the local time into a string following the ISO format, copying
349 at most 22 characters into the result string. */
354 /* The sub-seconds are manually set to zero since type time_t lacks the
355 precision necessary for nanoseconds. */
359 __gnat_to_gm_time (OS_Time
*p_time
, int *p_year
, int *p_month
, int *p_day
,
360 int *p_hours
, int *p_mins
, int *p_secs
)
363 time_t time
= (time_t) *p_time
;
366 /* On Windows systems, the time is sometimes rounded up to the nearest
367 even second, so if the number of seconds is odd, increment it. */
372 res
= gmtime (&time
);
375 *p_year
= res
->tm_year
;
376 *p_month
= res
->tm_mon
;
377 *p_day
= res
->tm_mday
;
378 *p_hours
= res
->tm_hour
;
379 *p_mins
= res
->tm_min
;
380 *p_secs
= res
->tm_sec
;
383 *p_year
= *p_month
= *p_day
= *p_hours
= *p_mins
= *p_secs
= 0;
387 __gnat_to_os_time (OS_Time
*p_time
, int year
, int month
, int day
,
388 int hours
, int mins
, int secs
)
400 /* returns -1 of failing, this is s-os_lib Invalid_Time */
402 *p_time
= (OS_Time
) mktime (&v
);
405 /* Place the contents of the symbolic link named PATH in the buffer BUF,
406 which has size BUFSIZ. If PATH is a symbolic link, then return the number
407 of characters of its content in BUF. Otherwise, return -1.
408 For systems not supporting symbolic links, always return -1. */
411 __gnat_readlink (char *path ATTRIBUTE_UNUSED
,
412 char *buf ATTRIBUTE_UNUSED
,
413 size_t bufsiz ATTRIBUTE_UNUSED
)
415 #if defined (_WIN32) \
416 || defined(__vxworks) || defined (__PikeOS__)
419 return readlink (path
, buf
, bufsiz
);
423 /* Creates a symbolic link named NEWPATH which contains the string OLDPATH.
424 If NEWPATH exists it will NOT be overwritten.
425 For systems not supporting symbolic links, always return -1. */
428 __gnat_symlink (char *oldpath ATTRIBUTE_UNUSED
,
429 char *newpath ATTRIBUTE_UNUSED
)
431 #if defined (_WIN32) \
432 || defined(__vxworks) || defined (__PikeOS__)
435 return symlink (oldpath
, newpath
);
439 /* Try to lock a file, return 1 if success. */
441 #if defined (__vxworks) \
442 || defined (_WIN32) || defined (__PikeOS__)
444 /* Version that does not use link. */
447 __gnat_try_lock (char *dir
, char *file
)
451 TCHAR wfull_path
[GNAT_MAX_PATH_LEN
];
452 TCHAR wfile
[GNAT_MAX_PATH_LEN
];
453 TCHAR wdir
[GNAT_MAX_PATH_LEN
];
455 S2WSC (wdir
, dir
, GNAT_MAX_PATH_LEN
);
456 S2WSC (wfile
, file
, GNAT_MAX_PATH_LEN
);
458 /* ??? the code below crash on MingW64 for obscure reasons, a ticket
459 has been opened here:
461 https://sourceforge.net/p/mingw-w64/bugs/414/
463 As a workaround an equivalent set of code has been put in place below.
465 _stprintf (wfull_path, _T("%s%c%s"), wdir, _T(DIR_SEPARATOR), wfile);
468 _tcscpy (wfull_path
, wdir
);
469 _tcscat (wfull_path
, L
"\\");
470 _tcscat (wfull_path
, wfile
);
472 fd
= _topen (wfull_path
, O_CREAT
| O_EXCL
, 0600);
476 sprintf (full_path
, "%s%c%s", dir
, DIR_SEPARATOR
, file
);
477 fd
= open (full_path
, O_CREAT
| O_EXCL
, 0600);
489 /* Version using link(), more secure over NFS. */
490 /* See TN 6913-016 for discussion ??? */
493 __gnat_try_lock (char *dir
, char *file
)
497 GNAT_STRUCT_STAT stat_result
;
500 sprintf (full_path
, "%s%c%s", dir
, DIR_SEPARATOR
, file
);
501 sprintf (temp_file
, "%s%cTMP-%ld-%ld",
502 dir
, DIR_SEPARATOR
, (long)getpid(), (long)getppid ());
504 /* Create the temporary file and write the process number. */
505 fd
= open (temp_file
, O_CREAT
| O_WRONLY
, 0600);
511 /* Link it with the new file. */
512 link (temp_file
, full_path
);
514 /* Count the references on the old one. If we have a count of two, then
515 the link did succeed. Remove the temporary file before returning. */
516 __gnat_stat (temp_file
, &stat_result
);
518 return stat_result
.st_nlink
== 2;
522 /* Return the maximum file name length. */
525 __gnat_get_maximum_file_name_length (void)
530 /* Return nonzero if file names are case sensitive. */
532 static int file_names_case_sensitive_cache
= -1;
535 __gnat_get_file_names_case_sensitive (void)
537 if (file_names_case_sensitive_cache
== -1)
539 const char *sensitive
= getenv ("GNAT_FILE_NAME_CASE_SENSITIVE");
541 if (sensitive
!= NULL
542 && (sensitive
[0] == '0' || sensitive
[0] == '1')
543 && sensitive
[1] == '\0')
544 file_names_case_sensitive_cache
= sensitive
[0] - '0';
547 /* By default, we suppose filesystems aren't case sensitive on
548 Windows and Darwin (but they are on arm-darwin). */
549 #if defined (WINNT) || (defined (__APPLE__) && !defined (__arm__))
550 file_names_case_sensitive_cache
= 0;
552 file_names_case_sensitive_cache
= 1;
556 return file_names_case_sensitive_cache
;
559 /* Return nonzero if environment variables are case sensitive. */
562 __gnat_get_env_vars_case_sensitive (void)
572 __gnat_get_default_identifier_character_set (void)
577 /* Return the current working directory. */
580 __gnat_get_current_dir (char *dir
, int *length
)
582 #if defined (__MINGW32__)
583 TCHAR wdir
[GNAT_MAX_PATH_LEN
];
585 _tgetcwd (wdir
, *length
);
587 WS2SC (dir
, wdir
, GNAT_MAX_PATH_LEN
);
590 getcwd (dir
, *length
);
593 *length
= strlen (dir
);
595 if (dir
[*length
- 1] != DIR_SEPARATOR
)
597 dir
[*length
] = DIR_SEPARATOR
;
603 /* Return the suffix for object files. */
606 __gnat_get_object_suffix_ptr (int *len
, const char **value
)
608 *value
= HOST_OBJECT_SUFFIX
;
613 *len
= strlen (*value
);
618 /* Return the suffix for executable files. */
621 __gnat_get_executable_suffix_ptr (int *len
, const char **value
)
623 *value
= HOST_EXECUTABLE_SUFFIX
;
627 *len
= strlen (*value
);
632 /* Return the suffix for debuggable files. Usually this is the same as the
633 executable extension. */
636 __gnat_get_debuggable_suffix_ptr (int *len
, const char **value
)
638 *value
= HOST_EXECUTABLE_SUFFIX
;
643 *len
= strlen (*value
);
648 /* Returns the OS filename and corresponding encoding. */
651 __gnat_os_filename (char *filename ATTRIBUTE_UNUSED
,
652 char *w_filename ATTRIBUTE_UNUSED
,
653 char *os_name
, int *o_length
,
654 char *encoding ATTRIBUTE_UNUSED
, int *e_length
)
656 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (IS_CROSS)
657 WS2SC (os_name
, (TCHAR
*)w_filename
, (DWORD
)*o_length
);
658 *o_length
= strlen (os_name
);
659 strcpy (encoding
, "encoding=utf8");
660 *e_length
= strlen (encoding
);
662 strcpy (os_name
, filename
);
663 *o_length
= strlen (filename
);
671 __gnat_unlink (char *path
)
673 #if defined (__MINGW32__) && ! defined (__vxworks) && ! defined (IS_CROSS)
675 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
677 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
678 return _tunlink (wpath
);
681 return unlink (path
);
688 __gnat_rename (char *from
, char *to
)
690 #if defined (__MINGW32__) && ! defined (__vxworks) && ! defined (IS_CROSS)
692 TCHAR wfrom
[GNAT_MAX_PATH_LEN
], wto
[GNAT_MAX_PATH_LEN
];
694 S2WSC (wfrom
, from
, GNAT_MAX_PATH_LEN
);
695 S2WSC (wto
, to
, GNAT_MAX_PATH_LEN
);
696 return _trename (wfrom
, wto
);
699 return rename (from
, to
);
703 /* Changing directory. */
706 __gnat_chdir (char *path
)
708 #if defined (__MINGW32__) && ! defined (__vxworks) && ! defined (IS_CROSS)
710 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
712 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
713 return _tchdir (wpath
);
720 /* Removing a directory. */
723 __gnat_rmdir (char *path
)
725 #if defined (__MINGW32__) && ! defined (__vxworks) && ! defined (IS_CROSS)
727 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
729 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
730 return _trmdir (wpath
);
732 #elif defined (VTHREADS)
733 /* rmdir not available */
740 #if defined (_WIN32) || defined (linux) || defined (sun) \
741 || defined (__FreeBSD__)
742 #define HAS_TARGET_WCHAR_T
745 #ifdef HAS_TARGET_WCHAR_T
750 __gnat_fputwc(int c
, FILE *stream
)
752 #ifdef HAS_TARGET_WCHAR_T
753 return fputwc ((wchar_t)c
, stream
);
755 return fputc (c
, stream
);
760 __gnat_fopen (char *path
, char *mode
, int encoding ATTRIBUTE_UNUSED
)
762 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (IS_CROSS)
763 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
766 S2WS (wmode
, mode
, 10);
768 if (encoding
== Encoding_Unspecified
)
769 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
770 else if (encoding
== Encoding_UTF8
)
771 S2WSU (wpath
, path
, GNAT_MAX_PATH_LEN
);
773 S2WS (wpath
, path
, GNAT_MAX_PATH_LEN
);
775 return _tfopen (wpath
, wmode
);
778 return GNAT_FOPEN (path
, mode
);
783 __gnat_freopen (char *path
,
786 int encoding ATTRIBUTE_UNUSED
)
788 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (IS_CROSS)
789 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
792 S2WS (wmode
, mode
, 10);
794 if (encoding
== Encoding_Unspecified
)
795 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
796 else if (encoding
== Encoding_UTF8
)
797 S2WSU (wpath
, path
, GNAT_MAX_PATH_LEN
);
799 S2WS (wpath
, path
, GNAT_MAX_PATH_LEN
);
801 return _tfreopen (wpath
, wmode
, stream
);
803 return freopen (path
, mode
, stream
);
808 __gnat_open_read (char *path
, int fmode
)
811 int o_fmode
= O_BINARY
;
816 #if defined (__vxworks)
817 fd
= open (path
, O_RDONLY
| o_fmode
, 0444);
818 #elif defined (__MINGW32__)
820 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
822 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
823 fd
= _topen (wpath
, O_RDONLY
| o_fmode
, 0444);
826 fd
= GNAT_OPEN (path
, O_RDONLY
| o_fmode
);
829 return fd
< 0 ? -1 : fd
;
832 #if defined (__MINGW32__)
833 #define PERM (S_IREAD | S_IWRITE)
835 #define PERM (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
839 __gnat_open_rw (char *path
, int fmode
)
842 int o_fmode
= O_BINARY
;
847 #if defined (__MINGW32__)
849 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
851 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
852 fd
= _topen (wpath
, O_RDWR
| o_fmode
, PERM
);
855 fd
= GNAT_OPEN (path
, O_RDWR
| o_fmode
, PERM
);
858 return fd
< 0 ? -1 : fd
;
862 __gnat_open_create (char *path
, int fmode
)
865 int o_fmode
= O_BINARY
;
870 #if defined (__MINGW32__)
872 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
874 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
875 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_TRUNC
| o_fmode
, PERM
);
878 fd
= GNAT_OPEN (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| o_fmode
, PERM
);
881 return fd
< 0 ? -1 : fd
;
885 __gnat_create_output_file (char *path
)
888 #if defined (__MINGW32__)
890 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
892 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
893 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
, PERM
);
896 fd
= GNAT_OPEN (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
, PERM
);
899 return fd
< 0 ? -1 : fd
;
903 __gnat_create_output_file_new (char *path
)
906 #if defined (__MINGW32__)
908 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
910 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
911 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
| O_EXCL
, PERM
);
914 fd
= GNAT_OPEN (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
| O_EXCL
, PERM
);
917 return fd
< 0 ? -1 : fd
;
921 __gnat_open_append (char *path
, int fmode
)
924 int o_fmode
= O_BINARY
;
929 #if defined (__MINGW32__)
931 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
933 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
934 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_APPEND
| o_fmode
, PERM
);
937 fd
= GNAT_OPEN (path
, O_WRONLY
| O_CREAT
| O_APPEND
| o_fmode
, PERM
);
940 return fd
< 0 ? -1 : fd
;
943 /* Open a new file. Return error (-1) if the file already exists. */
946 __gnat_open_new (char *path
, int fmode
)
949 int o_fmode
= O_BINARY
;
954 #if defined (__MINGW32__)
956 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
958 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
959 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
);
962 fd
= GNAT_OPEN (path
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
);
965 return fd
< 0 ? -1 : fd
;
968 /* Open a new temp file. Return error (-1) if the file already exists. */
971 __gnat_open_new_temp (char *path
, int fmode
)
974 int o_fmode
= O_BINARY
;
976 strcpy (path
, "GNAT-XXXXXX");
978 #if (defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) \
979 || defined (linux) || defined(__GLIBC__)) && !defined (__vxworks)
980 return mkstemp (path
);
981 #elif defined (__Lynx__)
984 if (mktemp (path
) == NULL
)
991 fd
= GNAT_OPEN (path
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
);
992 return fd
< 0 ? -1 : fd
;
996 __gnat_open (char *path
, int fmode
)
1000 #if defined (__MINGW32__)
1002 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
1004 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
1005 fd
= _topen (wpath
, fmode
, PERM
);
1008 fd
= GNAT_OPEN (path
, fmode
, PERM
);
1011 return fd
< 0 ? -1 : fd
;
1014 /****************************************************************
1015 ** Perform a call to GNAT_STAT or GNAT_FSTAT, and extract as much information
1016 ** as possible from it, storing the result in a cache for later reuse
1017 ****************************************************************/
1020 __gnat_stat_to_attr (int fd
, char* name
, struct file_attributes
* attr
)
1022 GNAT_STRUCT_STAT statbuf
;
1026 /* GNAT_FSTAT returns -1 and sets errno for failure */
1027 ret
= GNAT_FSTAT (fd
, &statbuf
);
1028 error
= ret
? errno
: 0;
1031 /* __gnat_stat returns errno value directly */
1032 error
= __gnat_stat (name
, &statbuf
);
1033 ret
= error
? -1 : 0;
1037 * A missing file is reported as an attr structure with error == 0 and
1041 if (error
== 0 || error
== ENOENT
)
1044 attr
->error
= error
;
1046 attr
->regular
= (!ret
&& S_ISREG (statbuf
.st_mode
));
1047 attr
->directory
= (!ret
&& S_ISDIR (statbuf
.st_mode
));
1050 attr
->file_length
= 0;
1052 /* st_size may be 32 bits, or 64 bits which is converted to long. We
1053 don't return a useful value for files larger than 2 gigabytes in
1055 attr
->file_length
= statbuf
.st_size
; /* all systems */
1057 attr
->exists
= !ret
;
1059 #if !defined (_WIN32)
1060 /* on Windows requires extra system call, see __gnat_is_readable_file_attr */
1061 attr
->readable
= (!ret
&& (statbuf
.st_mode
& S_IRUSR
));
1062 attr
->writable
= (!ret
&& (statbuf
.st_mode
& S_IWUSR
));
1063 attr
->executable
= (!ret
&& (statbuf
.st_mode
& S_IXUSR
));
1067 attr
->timestamp
= (OS_Time
)-1;
1069 attr
->timestamp
= (OS_Time
)statbuf
.st_mtime
;
1073 /****************************************************************
1074 ** Return the number of bytes in the specified file
1075 ****************************************************************/
1078 __gnat_file_length_attr (int fd
, char* name
, struct file_attributes
* attr
)
1080 if (attr
->file_length
== -1) {
1081 __gnat_stat_to_attr (fd
, name
, attr
);
1084 return attr
->file_length
;
1088 __gnat_file_length (int fd
)
1090 struct file_attributes attr
;
1091 __gnat_reset_attributes (&attr
);
1092 return __gnat_file_length_attr (fd
, NULL
, &attr
);
1096 __gnat_file_length_long (int fd
)
1098 struct file_attributes attr
;
1099 __gnat_reset_attributes (&attr
);
1100 return (long)__gnat_file_length_attr (fd
, NULL
, &attr
);
1104 __gnat_named_file_length (char *name
)
1106 struct file_attributes attr
;
1107 __gnat_reset_attributes (&attr
);
1108 return __gnat_file_length_attr (-1, name
, &attr
);
1111 /* Create a temporary filename and put it in string pointed to by
1115 __gnat_tmp_name (char *tmp_filename
)
1117 #if defined (__MINGW32__)
1122 /* tempnam tries to create a temporary file in directory pointed to by
1123 TMP environment variable, in c:\temp if TMP is not set, and in
1124 directory specified by P_tmpdir in stdio.h if c:\temp does not
1125 exist. The filename will be created with the prefix "gnat-". */
1127 sprintf (prefix
, "gnat-%d-", (int)getpid());
1128 pname
= (char *) _tempnam ("c:\\temp", prefix
);
1130 /* if pname is NULL, the file was not created properly, the disk is full
1131 or there is no more free temporary files */
1134 *tmp_filename
= '\0';
1136 /* If pname start with a back slash and not path information it means that
1137 the filename is valid for the current working directory. */
1139 else if (pname
[0] == '\\')
1141 strcpy (tmp_filename
, ".\\");
1142 strcat (tmp_filename
, pname
+1);
1145 strcpy (tmp_filename
, pname
);
1150 #elif defined (linux) || defined (__FreeBSD__) || defined (__NetBSD__) \
1151 || defined (__OpenBSD__) || defined(__GLIBC__) || defined (__ANDROID__)
1152 #define MAX_SAFE_PATH 1000
1153 char *tmpdir
= getenv ("TMPDIR");
1155 /* If tmpdir is longer than MAX_SAFE_PATH, revert to default value to avoid
1156 a buffer overflow. */
1157 if (tmpdir
== NULL
|| strlen (tmpdir
) > MAX_SAFE_PATH
)
1159 strcpy (tmp_filename
, "/cache/gnat-XXXXXX");
1161 strcpy (tmp_filename
, "/tmp/gnat-XXXXXX");
1164 sprintf (tmp_filename
, "%s/gnat-XXXXXX", tmpdir
);
1166 close (mkstemp(tmp_filename
));
1167 #elif defined (__vxworks) && !(defined (__RTP__) || defined (VTHREADS))
1171 static ushort_t seed
= 0; /* used to generate unique name */
1173 /* generate unique name */
1174 strcpy (tmp_filename
, "tmp");
1176 /* fill up the name buffer from the last position */
1178 pos
= tmp_filename
+ strlen (tmp_filename
) + index
;
1182 for (t
= seed
; 0 <= --index
; t
>>= 3)
1183 *--pos
= '0' + (t
& 07);
1185 tmpnam (tmp_filename
);
1189 /* Open directory and returns a DIR pointer. */
1191 DIR* __gnat_opendir (char *name
)
1193 #if defined (__MINGW32__)
1194 TCHAR wname
[GNAT_MAX_PATH_LEN
];
1196 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
);
1197 return (DIR*)_topendir (wname
);
1200 return opendir (name
);
1204 /* Read the next entry in a directory. The returned string points somewhere
1207 #if defined (sun) && defined (__SVR4)
1208 /* For Solaris, be sure to use the 64-bit version, otherwise NFS reads may
1209 fail with EOVERFLOW if the server uses 64-bit cookies. */
1210 #define dirent dirent64
1211 #define readdir readdir64
1215 __gnat_readdir (DIR *dirp
, char *buffer
, int *len
)
1217 #if defined (__MINGW32__)
1218 struct _tdirent
*dirent
= _treaddir ((_TDIR
*)dirp
);
1222 WS2SC (buffer
, dirent
->d_name
, GNAT_MAX_PATH_LEN
);
1223 *len
= strlen (buffer
);
1230 #elif defined (HAVE_READDIR_R)
1231 /* If possible, try to use the thread-safe version. */
1232 if (readdir_r (dirp
, buffer
) != NULL
)
1234 *len
= strlen (((struct dirent
*) buffer
)->d_name
);
1235 return ((struct dirent
*) buffer
)->d_name
;
1241 struct dirent
*dirent
= (struct dirent
*) readdir (dirp
);
1245 strcpy (buffer
, dirent
->d_name
);
1246 *len
= strlen (buffer
);
1255 /* Close a directory entry. */
1257 int __gnat_closedir (DIR *dirp
)
1259 #if defined (__MINGW32__)
1260 return _tclosedir ((_TDIR
*)dirp
);
1263 return closedir (dirp
);
1267 /* Returns 1 if readdir is thread safe, 0 otherwise. */
1270 __gnat_readdir_is_thread_safe (void)
1272 #ifdef HAVE_READDIR_R
1279 #if defined (_WIN32)
1280 /* Number of seconds between <Jan 1st 1601> and <Jan 1st 1970>. */
1281 static const unsigned long long w32_epoch_offset
= 11644473600ULL;
1283 /* Returns the file modification timestamp using Win32 routines which are
1284 immune against daylight saving time change. It is in fact not possible to
1285 use fstat for this purpose as the DST modify the st_mtime field of the
1289 win32_filetime (HANDLE h
)
1294 unsigned long long ull_time
;
1297 /* GetFileTime returns FILETIME data which are the number of 100 nanosecs
1298 since <Jan 1st 1601>. This function must return the number of seconds
1299 since <Jan 1st 1970>. */
1301 if (GetFileTime (h
, NULL
, NULL
, &t_write
.ft_time
))
1302 return (time_t) (t_write
.ull_time
/ 10000000ULL - w32_epoch_offset
);
1306 /* As above but starting from a FILETIME. */
1308 f2t (const FILETIME
*ft
, __time64_t
*t
)
1313 unsigned long long ull_time
;
1316 t_write
.ft_time
= *ft
;
1317 *t
= (__time64_t
) (t_write
.ull_time
/ 10000000ULL - w32_epoch_offset
);
1321 /* Return a GNAT time stamp given a file name. */
1324 __gnat_file_time_name_attr (char* name
, struct file_attributes
* attr
)
1326 if (attr
->timestamp
== (OS_Time
)-2) {
1327 #if defined (_WIN32)
1329 WIN32_FILE_ATTRIBUTE_DATA fad
;
1330 __time64_t ret
= -1;
1331 TCHAR wname
[GNAT_MAX_PATH_LEN
];
1332 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
);
1334 if ((res
= GetFileAttributesEx (wname
, GetFileExInfoStandard
, &fad
)))
1335 f2t (&fad
.ftLastWriteTime
, &ret
);
1336 attr
->timestamp
= (OS_Time
) ret
;
1338 __gnat_stat_to_attr (-1, name
, attr
);
1341 return attr
->timestamp
;
1345 __gnat_file_time_name (char *name
)
1347 struct file_attributes attr
;
1348 __gnat_reset_attributes (&attr
);
1349 return __gnat_file_time_name_attr (name
, &attr
);
1352 /* Return a GNAT time stamp given a file descriptor. */
1355 __gnat_file_time_fd_attr (int fd
, struct file_attributes
* attr
)
1357 if (attr
->timestamp
== (OS_Time
)-2) {
1358 #if defined (_WIN32)
1359 HANDLE h
= (HANDLE
) _get_osfhandle (fd
);
1360 time_t ret
= win32_filetime (h
);
1361 attr
->timestamp
= (OS_Time
) ret
;
1364 __gnat_stat_to_attr (fd
, NULL
, attr
);
1368 return attr
->timestamp
;
1372 __gnat_file_time_fd (int fd
)
1374 struct file_attributes attr
;
1375 __gnat_reset_attributes (&attr
);
1376 return __gnat_file_time_fd_attr (fd
, &attr
);
1379 /* Set the file time stamp. */
1382 __gnat_set_file_time_name (char *name
, time_t time_stamp
)
1384 #if defined (__vxworks)
1386 /* Code to implement __gnat_set_file_time_name for these systems. */
1388 #elif defined (_WIN32)
1392 unsigned long long ull_time
;
1394 TCHAR wname
[GNAT_MAX_PATH_LEN
];
1396 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
);
1398 HANDLE h
= CreateFile
1399 (wname
, GENERIC_WRITE
, FILE_SHARE_WRITE
, NULL
,
1400 OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
,
1402 if (h
== INVALID_HANDLE_VALUE
)
1404 /* Add number of seconds between <Jan 1st 1601> and <Jan 1st 1970> */
1405 t_write
.ull_time
= ((unsigned long long)time_stamp
+ w32_epoch_offset
);
1406 /* Convert to 100 nanosecond units */
1407 t_write
.ull_time
*= 10000000ULL;
1409 SetFileTime(h
, NULL
, NULL
, &t_write
.ft_time
);
1414 struct utimbuf utimbuf
;
1417 /* Set modification time to requested time. */
1418 utimbuf
.modtime
= time_stamp
;
1420 /* Set access time to now in local time. */
1421 t
= time ((time_t) 0);
1422 utimbuf
.actime
= mktime (localtime (&t
));
1424 utime (name
, &utimbuf
);
1428 /* Get the list of installed standard libraries from the
1429 HKEY_LOCAL_MACHINE\SOFTWARE\Ada Core Technologies\GNAT\Standard Libraries
1433 __gnat_get_libraries_from_registry (void)
1435 char *result
= (char *) xmalloc (1);
1439 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (IS_CROSS)
1442 DWORD name_size
, value_size
;
1449 /* First open the key. */
1450 res
= RegOpenKeyExA (HKEY_LOCAL_MACHINE
, "SOFTWARE", 0, KEY_READ
, ®_key
);
1452 if (res
== ERROR_SUCCESS
)
1453 res
= RegOpenKeyExA (reg_key
, "Ada Core Technologies", 0,
1454 KEY_READ
, ®_key
);
1456 if (res
== ERROR_SUCCESS
)
1457 res
= RegOpenKeyExA (reg_key
, "GNAT", 0, KEY_READ
, ®_key
);
1459 if (res
== ERROR_SUCCESS
)
1460 res
= RegOpenKeyExA (reg_key
, "Standard Libraries", 0, KEY_READ
, ®_key
);
1462 /* If the key exists, read out all the values in it and concatenate them
1464 for (index
= 0; res
== ERROR_SUCCESS
; index
++)
1466 value_size
= name_size
= 256;
1467 res
= RegEnumValueA (reg_key
, index
, name
, &name_size
, 0,
1468 &type
, (LPBYTE
)value
, &value_size
);
1470 if (res
== ERROR_SUCCESS
&& type
== REG_SZ
)
1472 char *old_result
= result
;
1474 result
= (char *) xmalloc (strlen (old_result
) + value_size
+ 2);
1475 strcpy (result
, old_result
);
1476 strcat (result
, value
);
1477 strcat (result
, ";");
1482 /* Remove the trailing ";". */
1484 result
[strlen (result
) - 1] = 0;
1490 /* Query information for the given file NAME and return it in STATBUF.
1491 * Returns 0 for success, or errno value for failure.
1494 __gnat_stat (char *name
, GNAT_STRUCT_STAT
*statbuf
)
1497 WIN32_FILE_ATTRIBUTE_DATA fad
;
1498 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
1503 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
1504 name_len
= _tcslen (wname
);
1506 if (name_len
> GNAT_MAX_PATH_LEN
)
1509 ZeroMemory (statbuf
, sizeof(GNAT_STRUCT_STAT
));
1511 res
= GetFileAttributesEx (wname
, GetFileExInfoStandard
, &fad
);
1514 error
= GetLastError();
1516 /* Check file existence using GetFileAttributes() which does not fail on
1517 special Windows files like con:, aux:, nul: etc... */
1519 if (GetFileAttributes(wname
) != INVALID_FILE_ATTRIBUTES
) {
1520 /* Just pretend that it is a regular and readable file */
1521 statbuf
->st_mode
= S_IFREG
| S_IREAD
| S_IWRITE
;
1526 case ERROR_ACCESS_DENIED
:
1527 case ERROR_SHARING_VIOLATION
:
1528 case ERROR_LOCK_VIOLATION
:
1529 case ERROR_SHARING_BUFFER_EXCEEDED
:
1531 case ERROR_BUFFER_OVERFLOW
:
1532 return ENAMETOOLONG
;
1533 case ERROR_NOT_ENOUGH_MEMORY
:
1540 f2t (&fad
.ftCreationTime
, &statbuf
->st_ctime
);
1541 f2t (&fad
.ftLastWriteTime
, &statbuf
->st_mtime
);
1542 f2t (&fad
.ftLastAccessTime
, &statbuf
->st_atime
);
1545 (__int64
)fad
.nFileSizeLow
| (__int64
)fad
.nFileSizeHigh
<< 32;
1547 /* We do not have the S_IEXEC attribute, but this is not used on GNAT. */
1548 statbuf
->st_mode
= S_IREAD
;
1550 if (fad
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
1551 statbuf
->st_mode
|= S_IFDIR
;
1553 statbuf
->st_mode
|= S_IFREG
;
1555 if (!(fad
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
))
1556 statbuf
->st_mode
|= S_IWRITE
;
1561 return GNAT_STAT (name
, statbuf
) == 0 ? 0 : errno
;
1565 /*************************************************************************
1566 ** Check whether a file exists
1567 *************************************************************************/
1570 __gnat_file_exists_attr (char* name
, struct file_attributes
* attr
)
1572 if (attr
->exists
== ATTR_UNSET
)
1573 __gnat_stat_to_attr (-1, name
, attr
);
1575 return attr
->exists
;
1579 __gnat_file_exists (char *name
)
1581 struct file_attributes attr
;
1582 __gnat_reset_attributes (&attr
);
1583 return __gnat_file_exists_attr (name
, &attr
);
1586 /**********************************************************************
1587 ** Whether name is an absolute path
1588 **********************************************************************/
1591 __gnat_is_absolute_path (char *name
, int length
)
1594 /* On VxWorks systems, an absolute path can be represented (depending on
1595 the host platform) as either /dir/file, or device:/dir/file, or
1596 device:drive_letter:/dir/file. */
1603 for (index
= 0; index
< length
; index
++)
1605 if (name
[index
] == ':' &&
1606 ((name
[index
+ 1] == '/') ||
1607 (isalpha (name
[index
+ 1]) && index
+ 2 <= length
&&
1608 name
[index
+ 2] == '/')))
1611 else if (name
[index
] == '/')
1616 return (length
!= 0) &&
1617 (*name
== '/' || *name
== DIR_SEPARATOR
1619 || (length
> 1 && ISALPHA (name
[0]) && name
[1] == ':')
1626 __gnat_is_regular_file_attr (char* name
, struct file_attributes
* attr
)
1628 if (attr
->regular
== ATTR_UNSET
)
1629 __gnat_stat_to_attr (-1, name
, attr
);
1631 return attr
->regular
;
1635 __gnat_is_regular_file (char *name
)
1637 struct file_attributes attr
;
1639 __gnat_reset_attributes (&attr
);
1640 return __gnat_is_regular_file_attr (name
, &attr
);
1644 __gnat_is_regular_file_fd (int fd
)
1647 GNAT_STRUCT_STAT statbuf
;
1649 ret
= GNAT_FSTAT (fd
, &statbuf
);
1650 return (!ret
&& S_ISREG (statbuf
.st_mode
));
1654 __gnat_is_directory_attr (char* name
, struct file_attributes
* attr
)
1656 if (attr
->directory
== ATTR_UNSET
)
1657 __gnat_stat_to_attr (-1, name
, attr
);
1659 return attr
->directory
;
1663 __gnat_is_directory (char *name
)
1665 struct file_attributes attr
;
1667 __gnat_reset_attributes (&attr
);
1668 return __gnat_is_directory_attr (name
, &attr
);
1671 #if defined (_WIN32)
1673 /* Returns the same constant as GetDriveType but takes a pathname as
1677 GetDriveTypeFromPath (TCHAR
*wfullpath
)
1679 TCHAR wdrv
[MAX_PATH
];
1680 TCHAR wpath
[MAX_PATH
];
1681 TCHAR wfilename
[MAX_PATH
];
1682 TCHAR wext
[MAX_PATH
];
1684 _tsplitpath (wfullpath
, wdrv
, wpath
, wfilename
, wext
);
1686 if (_tcslen (wdrv
) != 0)
1688 /* we have a drive specified. */
1689 _tcscat (wdrv
, _T("\\"));
1690 return GetDriveType (wdrv
);
1694 /* No drive specified. */
1696 /* Is this a relative path, if so get current drive type. */
1697 if (wpath
[0] != _T('\\') ||
1698 (_tcslen (wpath
) > 2 && wpath
[0] == _T('\\')
1699 && wpath
[1] != _T('\\')))
1700 return GetDriveType (NULL
);
1702 UINT result
= GetDriveType (wpath
);
1704 /* Cannot guess the drive type, is this \\.\ ? */
1706 if (result
== DRIVE_NO_ROOT_DIR
&&
1707 _tcslen (wpath
) >= 4 && wpath
[0] == _T('\\') && wpath
[1] == _T('\\')
1708 && wpath
[2] == _T('.') && wpath
[3] == _T('\\'))
1710 if (_tcslen (wpath
) == 4)
1711 _tcscat (wpath
, wfilename
);
1713 LPTSTR p
= &wpath
[4];
1714 LPTSTR b
= _tcschr (p
, _T('\\'));
1718 /* logical drive \\.\c\dir\file */
1724 _tcscat (p
, _T(":\\"));
1726 return GetDriveType (p
);
1733 /* This MingW section contains code to work with ACL. */
1735 __gnat_check_OWNER_ACL (TCHAR
*wname
,
1736 DWORD CheckAccessDesired
,
1737 GENERIC_MAPPING CheckGenericMapping
)
1739 DWORD dwAccessDesired
, dwAccessAllowed
;
1740 PRIVILEGE_SET PrivilegeSet
;
1741 DWORD dwPrivSetSize
= sizeof (PRIVILEGE_SET
);
1742 BOOL fAccessGranted
= FALSE
;
1743 HANDLE hToken
= NULL
;
1745 PSECURITY_DESCRIPTOR pSD
= NULL
;
1748 (wname
, OWNER_SECURITY_INFORMATION
|
1749 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
,
1752 if ((pSD
= (SECURITY_DESCRIPTOR
*) HeapAlloc
1753 (GetProcessHeap (), HEAP_ZERO_MEMORY
, nLength
)) == NULL
)
1756 /* Obtain the security descriptor. */
1758 if (!GetFileSecurity
1759 (wname
, OWNER_SECURITY_INFORMATION
|
1760 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
,
1761 pSD
, nLength
, &nLength
))
1764 if (!ImpersonateSelf (SecurityImpersonation
))
1767 if (!OpenThreadToken
1768 (GetCurrentThread(), TOKEN_DUPLICATE
| TOKEN_QUERY
, FALSE
, &hToken
))
1771 /* Undoes the effect of ImpersonateSelf. */
1775 /* We want to test for write permissions. */
1777 dwAccessDesired
= CheckAccessDesired
;
1779 MapGenericMask (&dwAccessDesired
, &CheckGenericMapping
);
1782 (pSD
, /* security descriptor to check */
1783 hToken
, /* impersonation token */
1784 dwAccessDesired
, /* requested access rights */
1785 &CheckGenericMapping
, /* pointer to GENERIC_MAPPING */
1786 &PrivilegeSet
, /* receives privileges used in check */
1787 &dwPrivSetSize
, /* size of PrivilegeSet buffer */
1788 &dwAccessAllowed
, /* receives mask of allowed access rights */
1792 CloseHandle (hToken
);
1793 HeapFree (GetProcessHeap (), 0, pSD
);
1794 return fAccessGranted
;
1798 CloseHandle (hToken
);
1799 HeapFree (GetProcessHeap (), 0, pSD
);
1804 __gnat_set_OWNER_ACL (TCHAR
*wname
,
1805 ACCESS_MODE AccessMode
,
1806 DWORD AccessPermissions
)
1808 PACL pOldDACL
= NULL
;
1809 PACL pNewDACL
= NULL
;
1810 PSECURITY_DESCRIPTOR pSD
= NULL
;
1812 TCHAR username
[100];
1815 /* Get current user, he will act as the owner */
1817 if (!GetUserName (username
, &unsize
))
1820 if (GetNamedSecurityInfo
1823 DACL_SECURITY_INFORMATION
,
1824 NULL
, NULL
, &pOldDACL
, NULL
, &pSD
) != ERROR_SUCCESS
)
1827 BuildExplicitAccessWithName
1828 (&ea
, username
, AccessPermissions
, (ACCESS_MODE
) AccessMode
, NO_INHERITANCE
);
1830 if (AccessMode
== SET_ACCESS
)
1832 /* SET_ACCESS, we want to set an explicte set of permissions, do not
1833 merge with current DACL. */
1834 if (SetEntriesInAcl (1, &ea
, NULL
, &pNewDACL
) != ERROR_SUCCESS
)
1838 if (SetEntriesInAcl (1, &ea
, pOldDACL
, &pNewDACL
) != ERROR_SUCCESS
)
1841 if (SetNamedSecurityInfo
1842 (wname
, SE_FILE_OBJECT
,
1843 DACL_SECURITY_INFORMATION
, NULL
, NULL
, pNewDACL
, NULL
) != ERROR_SUCCESS
)
1847 LocalFree (pNewDACL
);
1850 /* Check if it is possible to use ACL for wname, the file must not be on a
1854 __gnat_can_use_acl (TCHAR
*wname
)
1856 return __gnat_use_acl
&& GetDriveTypeFromPath (wname
) != DRIVE_REMOTE
;
1859 #endif /* defined (_WIN32) */
1862 __gnat_is_readable_file_attr (char* name
, struct file_attributes
* attr
)
1864 if (attr
->readable
== ATTR_UNSET
)
1866 #if defined (_WIN32)
1867 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
1868 GENERIC_MAPPING GenericMapping
;
1870 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
1872 if (__gnat_can_use_acl (wname
))
1874 ZeroMemory (&GenericMapping
, sizeof (GENERIC_MAPPING
));
1875 GenericMapping
.GenericRead
= GENERIC_READ
;
1877 __gnat_check_OWNER_ACL (wname
, FILE_READ_DATA
, GenericMapping
);
1880 attr
->readable
= GetFileAttributes (wname
) != INVALID_FILE_ATTRIBUTES
;
1882 __gnat_stat_to_attr (-1, name
, attr
);
1886 return attr
->readable
;
1890 __gnat_is_readable_file (char *name
)
1892 struct file_attributes attr
;
1894 __gnat_reset_attributes (&attr
);
1895 return __gnat_is_readable_file_attr (name
, &attr
);
1899 __gnat_is_writable_file_attr (char* name
, struct file_attributes
* attr
)
1901 if (attr
->writable
== ATTR_UNSET
)
1903 #if defined (_WIN32)
1904 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
1905 GENERIC_MAPPING GenericMapping
;
1907 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
1909 if (__gnat_can_use_acl (wname
))
1911 ZeroMemory (&GenericMapping
, sizeof (GENERIC_MAPPING
));
1912 GenericMapping
.GenericWrite
= GENERIC_WRITE
;
1914 attr
->writable
= __gnat_check_OWNER_ACL
1915 (wname
, FILE_WRITE_DATA
| FILE_APPEND_DATA
, GenericMapping
)
1916 && !(GetFileAttributes (wname
) & FILE_ATTRIBUTE_READONLY
);
1920 !(GetFileAttributes (wname
) & FILE_ATTRIBUTE_READONLY
);
1923 __gnat_stat_to_attr (-1, name
, attr
);
1927 return attr
->writable
;
1931 __gnat_is_writable_file (char *name
)
1933 struct file_attributes attr
;
1935 __gnat_reset_attributes (&attr
);
1936 return __gnat_is_writable_file_attr (name
, &attr
);
1940 __gnat_is_executable_file_attr (char* name
, struct file_attributes
* attr
)
1942 if (attr
->executable
== ATTR_UNSET
)
1944 #if defined (_WIN32)
1945 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
1946 GENERIC_MAPPING GenericMapping
;
1948 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
1950 if (__gnat_can_use_acl (wname
))
1952 ZeroMemory (&GenericMapping
, sizeof (GENERIC_MAPPING
));
1953 GenericMapping
.GenericExecute
= GENERIC_EXECUTE
;
1956 __gnat_check_OWNER_ACL (wname
, FILE_EXECUTE
, GenericMapping
);
1960 TCHAR
*l
, *last
= _tcsstr(wname
, _T(".exe"));
1962 /* look for last .exe */
1964 while ((l
= _tcsstr(last
+1, _T(".exe"))))
1968 GetFileAttributes (wname
) != INVALID_FILE_ATTRIBUTES
1969 && (last
- wname
) == (int) (_tcslen (wname
) - 4);
1972 __gnat_stat_to_attr (-1, name
, attr
);
1976 return attr
->regular
&& attr
->executable
;
1980 __gnat_is_executable_file (char *name
)
1982 struct file_attributes attr
;
1984 __gnat_reset_attributes (&attr
);
1985 return __gnat_is_executable_file_attr (name
, &attr
);
1989 __gnat_set_writable (char *name
)
1991 #if defined (_WIN32)
1992 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
1994 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
1996 if (__gnat_can_use_acl (wname
))
1997 __gnat_set_OWNER_ACL (wname
, GRANT_ACCESS
, FILE_GENERIC_WRITE
);
2000 (wname
, GetFileAttributes (wname
) & ~FILE_ATTRIBUTE_READONLY
);
2001 #elif ! (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 6)
2002 GNAT_STRUCT_STAT statbuf
;
2004 if (GNAT_STAT (name
, &statbuf
) == 0)
2006 statbuf
.st_mode
= statbuf
.st_mode
| S_IWUSR
;
2007 chmod (name
, statbuf
.st_mode
);
2012 /* must match definition in s-os_lib.ads */
2018 __gnat_set_executable (char *name
, int mode ATTRIBUTE_UNUSED
)
2020 #if defined (_WIN32)
2021 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2023 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2025 if (__gnat_can_use_acl (wname
))
2026 __gnat_set_OWNER_ACL (wname
, GRANT_ACCESS
, FILE_GENERIC_EXECUTE
);
2028 #elif ! (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 6)
2029 GNAT_STRUCT_STAT statbuf
;
2031 if (GNAT_STAT (name
, &statbuf
) == 0)
2034 statbuf
.st_mode
= statbuf
.st_mode
| S_IXUSR
;
2036 statbuf
.st_mode
= statbuf
.st_mode
| S_IXGRP
;
2037 if (mode
& S_OTHERS
)
2038 statbuf
.st_mode
= statbuf
.st_mode
| S_IXOTH
;
2039 chmod (name
, statbuf
.st_mode
);
2045 __gnat_set_non_writable (char *name
)
2047 #if defined (_WIN32)
2048 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2050 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2052 if (__gnat_can_use_acl (wname
))
2053 __gnat_set_OWNER_ACL
2054 (wname
, DENY_ACCESS
,
2055 FILE_WRITE_DATA
| FILE_APPEND_DATA
|
2056 FILE_WRITE_EA
| FILE_WRITE_ATTRIBUTES
);
2059 (wname
, GetFileAttributes (wname
) | FILE_ATTRIBUTE_READONLY
);
2060 #elif ! (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 6)
2061 GNAT_STRUCT_STAT statbuf
;
2063 if (GNAT_STAT (name
, &statbuf
) == 0)
2065 statbuf
.st_mode
= statbuf
.st_mode
& 07577;
2066 chmod (name
, statbuf
.st_mode
);
2072 __gnat_set_readable (char *name
)
2074 #if defined (_WIN32)
2075 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2077 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2079 if (__gnat_can_use_acl (wname
))
2080 __gnat_set_OWNER_ACL (wname
, GRANT_ACCESS
, FILE_GENERIC_READ
);
2082 #elif ! (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 6)
2083 GNAT_STRUCT_STAT statbuf
;
2085 if (GNAT_STAT (name
, &statbuf
) == 0)
2087 chmod (name
, statbuf
.st_mode
| S_IREAD
);
2093 __gnat_set_non_readable (char *name
)
2095 #if defined (_WIN32)
2096 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2098 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2100 if (__gnat_can_use_acl (wname
))
2101 __gnat_set_OWNER_ACL (wname
, DENY_ACCESS
, FILE_GENERIC_READ
);
2103 #elif ! (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 6)
2104 GNAT_STRUCT_STAT statbuf
;
2106 if (GNAT_STAT (name
, &statbuf
) == 0)
2108 chmod (name
, statbuf
.st_mode
& (~S_IREAD
));
2114 __gnat_is_symbolic_link_attr (char* name ATTRIBUTE_UNUSED
,
2115 struct file_attributes
* attr
)
2117 if (attr
->symbolic_link
== ATTR_UNSET
)
2119 #if defined (__vxworks)
2120 attr
->symbolic_link
= 0;
2122 #elif defined (_AIX) || defined (__APPLE__) || defined (__unix__)
2124 GNAT_STRUCT_STAT statbuf
;
2125 ret
= GNAT_LSTAT (name
, &statbuf
);
2126 attr
->symbolic_link
= (!ret
&& S_ISLNK (statbuf
.st_mode
));
2128 attr
->symbolic_link
= 0;
2131 return attr
->symbolic_link
;
2135 __gnat_is_symbolic_link (char *name ATTRIBUTE_UNUSED
)
2137 struct file_attributes attr
;
2139 __gnat_reset_attributes (&attr
);
2140 return __gnat_is_symbolic_link_attr (name
, &attr
);
2143 #if defined (sun) && defined (__SVR4)
2144 /* Using fork on Solaris will duplicate all the threads. fork1, which
2145 duplicates only the active thread, must be used instead, or spawning
2146 subprocess from a program with tasking will lead into numerous problems. */
2151 __gnat_portable_spawn (char *args
[] ATTRIBUTE_UNUSED
)
2153 int status ATTRIBUTE_UNUSED
= 0;
2154 int finished ATTRIBUTE_UNUSED
;
2155 int pid ATTRIBUTE_UNUSED
;
2157 #if defined (__vxworks) || defined(__PikeOS__)
2160 #elif defined (_WIN32)
2161 /* args[0] must be quotes as it could contain a full pathname with spaces */
2162 char *args_0
= args
[0];
2163 args
[0] = (char *)xmalloc (strlen (args_0
) + 3);
2164 strcpy (args
[0], "\"");
2165 strcat (args
[0], args_0
);
2166 strcat (args
[0], "\"");
2168 status
= spawnvp (P_WAIT
, args_0
, (char ** const)args
);
2170 /* restore previous value */
2172 args
[0] = (char *)args_0
;
2188 if (execv (args
[0], MAYBE_TO_PTR32 (args
)) != 0)
2193 finished
= waitpid (pid
, &status
, 0);
2195 if (finished
!= pid
|| WIFEXITED (status
) == 0)
2198 return WEXITSTATUS (status
);
2204 /* Create a copy of the given file descriptor.
2205 Return -1 if an error occurred. */
2208 __gnat_dup (int oldfd
)
2210 #if defined (__vxworks) && !defined (__RTP__)
2211 /* Not supported on VxWorks 5.x, but supported on VxWorks 6.0 when using
2219 /* Make newfd be the copy of oldfd, closing newfd first if necessary.
2220 Return -1 if an error occurred. */
2223 __gnat_dup2 (int oldfd ATTRIBUTE_UNUSED
, int newfd ATTRIBUTE_UNUSED
)
2225 #if defined (__vxworks) && !defined (__RTP__)
2226 /* Not supported on VxWorks 5.x, but supported on VxWorks 6.0 when using
2229 #elif defined (__PikeOS__)
2230 /* Not supported. */
2232 #elif defined (_WIN32)
2233 /* Special case when oldfd and newfd are identical and are the standard
2234 input, output or error as this makes Windows XP hangs. Note that we
2235 do that only for standard file descriptors that are known to be valid. */
2236 if (oldfd
== newfd
&& newfd
>= 0 && newfd
<= 2)
2239 return dup2 (oldfd
, newfd
);
2241 return dup2 (oldfd
, newfd
);
2246 __gnat_number_of_cpus (void)
2250 #if defined (linux) || defined (sun) || defined (AIX) || defined (__APPLE__)
2251 cores
= (int) sysconf (_SC_NPROCESSORS_ONLN
);
2253 #elif defined (__hpux__)
2254 struct pst_dynamic psd
;
2255 if (pstat_getdynamic (&psd
, sizeof (psd
), 1, 0) != -1)
2256 cores
= (int) psd
.psd_proc_cnt
;
2258 #elif defined (_WIN32)
2259 SYSTEM_INFO sysinfo
;
2260 GetSystemInfo (&sysinfo
);
2261 cores
= (int) sysinfo
.dwNumberOfProcessors
;
2263 #elif defined (_WRS_CONFIG_SMP)
2264 unsigned int vxCpuConfiguredGet (void);
2266 cores
= vxCpuConfiguredGet ();
2273 /* WIN32 code to implement a wait call that wait for any child process. */
2275 #if defined (_WIN32)
2277 /* Synchronization code, to be thread safe. */
2281 /* For the Cert run times on native Windows we use dummy functions
2282 for locking and unlocking tasks since we do not support multiple
2283 threads on this configuration (Cert run time on native Windows). */
2285 static void EnterCS (void) {}
2286 static void LeaveCS (void) {}
2287 static void SignalListChanged (void) {}
2291 CRITICAL_SECTION ProcListCS
;
2292 HANDLE ProcListEvt
= NULL
;
2294 static void EnterCS (void)
2296 EnterCriticalSection(&ProcListCS
);
2299 static void LeaveCS (void)
2301 LeaveCriticalSection(&ProcListCS
);
2304 static void SignalListChanged (void)
2306 SetEvent (ProcListEvt
);
2311 static HANDLE
*HANDLES_LIST
= NULL
;
2312 static int *PID_LIST
= NULL
, plist_length
= 0, plist_max_length
= 0;
2315 add_handle (HANDLE h
, int pid
)
2317 /* -------------------- critical section -------------------- */
2320 if (plist_length
== plist_max_length
)
2322 plist_max_length
+= 100;
2324 (HANDLE
*) xrealloc (HANDLES_LIST
, sizeof (HANDLE
) * plist_max_length
);
2326 (int *) xrealloc (PID_LIST
, sizeof (int) * plist_max_length
);
2329 HANDLES_LIST
[plist_length
] = h
;
2330 PID_LIST
[plist_length
] = pid
;
2333 SignalListChanged();
2335 /* -------------------- critical section -------------------- */
2339 __gnat_win32_remove_handle (HANDLE h
, int pid
)
2344 /* -------------------- critical section -------------------- */
2347 for (j
= 0; j
< plist_length
; j
++)
2349 if ((HANDLES_LIST
[j
] == h
) || (PID_LIST
[j
] == pid
))
2353 HANDLES_LIST
[j
] = HANDLES_LIST
[plist_length
];
2354 PID_LIST
[j
] = PID_LIST
[plist_length
];
2361 /* -------------------- critical section -------------------- */
2364 SignalListChanged();
2370 win32_no_block_spawn (char *command
, char *args
[], HANDLE
*h
, int *pid
)
2374 PROCESS_INFORMATION PI
;
2375 SECURITY_ATTRIBUTES SA
;
2380 /* compute the total command line length */
2384 csize
+= strlen (args
[k
]) + 1;
2388 full_command
= (char *) xmalloc (csize
);
2391 SI
.cb
= sizeof (STARTUPINFO
);
2392 SI
.lpReserved
= NULL
;
2393 SI
.lpReserved2
= NULL
;
2394 SI
.lpDesktop
= NULL
;
2398 SI
.wShowWindow
= SW_HIDE
;
2400 /* Security attributes. */
2401 SA
.nLength
= sizeof (SECURITY_ATTRIBUTES
);
2402 SA
.bInheritHandle
= TRUE
;
2403 SA
.lpSecurityDescriptor
= NULL
;
2405 /* Prepare the command string. */
2406 strcpy (full_command
, command
);
2407 strcat (full_command
, " ");
2412 strcat (full_command
, args
[k
]);
2413 strcat (full_command
, " ");
2418 int wsize
= csize
* 2;
2419 TCHAR
*wcommand
= (TCHAR
*) xmalloc (wsize
);
2421 S2WSC (wcommand
, full_command
, wsize
);
2423 free (full_command
);
2425 result
= CreateProcess
2426 (NULL
, wcommand
, &SA
, NULL
, TRUE
,
2427 GetPriorityClass (GetCurrentProcess()), NULL
, NULL
, &SI
, &PI
);
2434 CloseHandle (PI
.hThread
);
2436 *pid
= PI
.dwProcessId
;
2446 win32_wait (int *status
)
2448 DWORD exitcode
, pid
;
2458 if (plist_length
== 0)
2464 /* -------------------- critical section -------------------- */
2467 hl_len
= plist_length
;
2470 hl
= (HANDLE
*) xmalloc (sizeof (HANDLE
) * hl_len
);
2471 memmove (hl
, HANDLES_LIST
, sizeof (HANDLE
) * hl_len
);
2472 pidl
= (int *) xmalloc (sizeof (int) * hl_len
);
2473 memmove (pidl
, PID_LIST
, sizeof (int) * hl_len
);
2475 /* Note that index 0 contains the event handle that is signaled when the
2476 process list has changed */
2477 hl
= (HANDLE
*) xmalloc (sizeof (HANDLE
) * hl_len
+ 1);
2478 hl
[0] = ProcListEvt
;
2479 memmove (&hl
[1], HANDLES_LIST
, sizeof (HANDLE
) * hl_len
);
2480 pidl
= (int *) xmalloc (sizeof (int) * hl_len
+ 1);
2481 memmove (&pidl
[1], PID_LIST
, sizeof (int) * hl_len
);
2486 /* -------------------- critical section -------------------- */
2488 res
= WaitForMultipleObjects (hl_len
, hl
, FALSE
, INFINITE
);
2490 /* if the ProcListEvt has been signaled then the list of processes has been
2491 updated to add or remove a handle, just loop over */
2493 if (res
- WAIT_OBJECT_0
== 0)
2500 h
= hl
[res
- WAIT_OBJECT_0
];
2501 GetExitCodeProcess (h
, &exitcode
);
2502 pid
= pidl
[res
- WAIT_OBJECT_0
];
2504 found
= __gnat_win32_remove_handle (h
, -1);
2509 /* if not found another process waiting has already handled this process */
2516 *status
= (int) exitcode
;
2523 __gnat_portable_no_block_spawn (char *args
[] ATTRIBUTE_UNUSED
)
2526 #if defined (__vxworks) || defined (__PikeOS__)
2527 /* Not supported. */
2530 #elif defined (_WIN32)
2535 win32_no_block_spawn (args
[0], args
, &h
, &pid
);
2538 add_handle (h
, pid
);
2551 if (execv (args
[0], MAYBE_TO_PTR32 (args
)) != 0)
2561 __gnat_portable_wait (int *process_status
)
2566 #if defined (__vxworks) || defined (__PikeOS__)
2567 /* Not sure what to do here, so do nothing but return zero. */
2569 #elif defined (_WIN32)
2571 pid
= win32_wait (&status
);
2575 pid
= waitpid (-1, &status
, 0);
2576 status
= status
& 0xffff;
2579 *process_status
= status
;
2584 __gnat_os_exit (int status
)
2589 /* Locate file on path, that matches a predicate */
2592 __gnat_locate_file_with_predicate (char *file_name
, char *path_val
,
2593 int (*predicate
)(char *))
2596 char *file_path
= (char *) alloca (strlen (file_name
) + 1);
2599 /* Return immediately if file_name is empty */
2601 if (*file_name
== '\0')
2604 /* Remove quotes around file_name if present */
2610 strcpy (file_path
, ptr
);
2612 ptr
= file_path
+ strlen (file_path
) - 1;
2617 /* Handle absolute pathnames. */
2619 absolute
= __gnat_is_absolute_path (file_path
, strlen (file_name
));
2623 if (predicate (file_path
))
2624 return xstrdup (file_path
);
2629 /* If file_name include directory separator(s), try it first as
2630 a path name relative to the current directory */
2631 for (ptr
= file_name
; *ptr
&& *ptr
!= '/' && *ptr
!= DIR_SEPARATOR
; ptr
++)
2636 if (predicate (file_name
))
2637 return xstrdup (file_name
);
2644 /* The result has to be smaller than path_val + file_name. */
2646 (char *) alloca (strlen (path_val
) + strlen (file_name
) + 2);
2650 /* Skip the starting quote */
2652 if (*path_val
== '"')
2655 for (ptr
= file_path
; *path_val
&& *path_val
!= PATH_SEPARATOR
; )
2656 *ptr
++ = *path_val
++;
2658 /* If directory is empty, it is the current directory*/
2660 if (ptr
== file_path
)
2667 /* Skip the ending quote */
2672 if (*ptr
!= '/' && *ptr
!= DIR_SEPARATOR
)
2673 *++ptr
= DIR_SEPARATOR
;
2675 strcpy (++ptr
, file_name
);
2677 if (predicate (file_path
))
2678 return xstrdup (file_path
);
2683 /* Skip path separator */
2692 /* Locate an executable file, give a Path value. */
2695 __gnat_locate_executable_file (char *file_name
, char *path_val
)
2697 return __gnat_locate_file_with_predicate
2698 (file_name
, path_val
, &__gnat_is_executable_file
);
2701 /* Locate a regular file, give a Path value. */
2704 __gnat_locate_regular_file (char *file_name
, char *path_val
)
2706 return __gnat_locate_file_with_predicate
2707 (file_name
, path_val
, &__gnat_is_regular_file
);
2710 /* Locate an executable given a Path argument. This routine is only used by
2711 gnatbl and should not be used otherwise. Use locate_exec_on_path
2715 __gnat_locate_exec (char *exec_name
, char *path_val
)
2718 if (!strstr (exec_name
, HOST_EXECUTABLE_SUFFIX
))
2720 char *full_exec_name
=
2722 (strlen (exec_name
) + strlen (HOST_EXECUTABLE_SUFFIX
) + 1);
2724 strcpy (full_exec_name
, exec_name
);
2725 strcat (full_exec_name
, HOST_EXECUTABLE_SUFFIX
);
2726 ptr
= __gnat_locate_executable_file (full_exec_name
, path_val
);
2729 return __gnat_locate_executable_file (exec_name
, path_val
);
2733 return __gnat_locate_executable_file (exec_name
, path_val
);
2736 /* Locate an executable using the Systems default PATH. */
2739 __gnat_locate_exec_on_path (char *exec_name
)
2743 #if defined (_WIN32)
2744 TCHAR
*wpath_val
= _tgetenv (_T("PATH"));
2746 /* In Win32 systems we expand the PATH as for XP environment
2747 variables are not automatically expanded. We also prepend the
2748 ".;" to the path to match normal NT path search semantics */
2750 #define EXPAND_BUFFER_SIZE 32767
2752 wapath_val
= (TCHAR
*) alloca (EXPAND_BUFFER_SIZE
);
2754 wapath_val
[0] = '.';
2755 wapath_val
[1] = ';';
2757 DWORD res
= ExpandEnvironmentStrings
2758 (wpath_val
, &wapath_val
[2], EXPAND_BUFFER_SIZE
- 2);
2760 if (!res
) wapath_val
[0] = _T('\0');
2762 apath_val
= (char *) alloca (EXPAND_BUFFER_SIZE
);
2764 WS2SC (apath_val
, wapath_val
, EXPAND_BUFFER_SIZE
);
2765 return __gnat_locate_exec (exec_name
, apath_val
);
2768 char *path_val
= getenv ("PATH");
2770 if (path_val
== NULL
) return NULL
;
2771 apath_val
= (char *) alloca (strlen (path_val
) + 1);
2772 strcpy (apath_val
, path_val
);
2773 return __gnat_locate_exec (exec_name
, apath_val
);
2777 /* Dummy functions for Osint import for non-VMS systems.
2778 ??? To be removed. */
2781 __gnat_to_canonical_file_list_init (char *dirspec ATTRIBUTE_UNUSED
,
2782 int onlydirs ATTRIBUTE_UNUSED
)
2788 __gnat_to_canonical_file_list_next (void)
2790 static char empty
[] = "";
2795 __gnat_to_canonical_file_list_free (void)
2800 __gnat_to_canonical_dir_spec (char *dirspec
, int prefixflag ATTRIBUTE_UNUSED
)
2806 __gnat_to_canonical_file_spec (char *filespec
)
2812 __gnat_to_canonical_path_spec (char *pathspec
)
2818 __gnat_to_host_dir_spec (char *dirspec
, int prefixflag ATTRIBUTE_UNUSED
)
2824 __gnat_to_host_file_spec (char *filespec
)
2830 __gnat_adjust_os_resource_limits (void)
2834 #if defined (__mips_vxworks)
2838 CACHE_USER_FLUSH (0, ENTIRE_CACHE
);
2842 #if defined (_WIN32)
2843 int __gnat_argument_needs_quote
= 1;
2845 int __gnat_argument_needs_quote
= 0;
2848 /* This option is used to enable/disable object files handling from the
2849 binder file by the GNAT Project module. For example, this is disabled on
2850 Windows (prior to GCC 3.4) as it is already done by the mdll module.
2851 Stating with GCC 3.4 the shared libraries are not based on mdll
2852 anymore as it uses the GCC's -shared option */
2853 #if defined (_WIN32) \
2854 && ((__GNUC__ < 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ < 4)))
2855 int __gnat_prj_add_obj_files
= 0;
2857 int __gnat_prj_add_obj_files
= 1;
2860 /* char used as prefix/suffix for environment variables */
2861 #if defined (_WIN32)
2862 char __gnat_environment_char
= '%';
2864 char __gnat_environment_char
= '$';
2867 /* This functions copy the file attributes from a source file to a
2870 mode = 0 : In this mode copy only the file time stamps (last access and
2871 last modification time stamps).
2873 mode = 1 : In this mode, time stamps and read/write/execute attributes are
2876 Returns 0 if operation was successful and -1 in case of error. */
2879 __gnat_copy_attribs (char *from ATTRIBUTE_UNUSED
, char *to ATTRIBUTE_UNUSED
,
2880 int mode ATTRIBUTE_UNUSED
)
2882 #if (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 6)
2885 #elif defined (_WIN32)
2886 TCHAR wfrom
[GNAT_MAX_PATH_LEN
+ 2];
2887 TCHAR wto
[GNAT_MAX_PATH_LEN
+ 2];
2889 FILETIME fct
, flat
, flwt
;
2892 S2WSC (wfrom
, from
, GNAT_MAX_PATH_LEN
+ 2);
2893 S2WSC (wto
, to
, GNAT_MAX_PATH_LEN
+ 2);
2895 /* retrieve from times */
2898 (wfrom
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2900 if (hfrom
== INVALID_HANDLE_VALUE
)
2903 res
= GetFileTime (hfrom
, &fct
, &flat
, &flwt
);
2905 CloseHandle (hfrom
);
2910 /* retrieve from times */
2913 (wto
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2915 if (hto
== INVALID_HANDLE_VALUE
)
2918 res
= SetFileTime (hto
, NULL
, &flat
, &flwt
);
2925 /* Set file attributes in full mode. */
2929 DWORD attribs
= GetFileAttributes (wfrom
);
2931 if (attribs
== INVALID_FILE_ATTRIBUTES
)
2934 res
= SetFileAttributes (wto
, attribs
);
2942 GNAT_STRUCT_STAT fbuf
;
2943 struct utimbuf tbuf
;
2945 if (GNAT_STAT (from
, &fbuf
) == -1)
2950 tbuf
.actime
= fbuf
.st_atime
;
2951 tbuf
.modtime
= fbuf
.st_mtime
;
2953 if (utime (to
, &tbuf
) == -1)
2960 if (chmod (to
, fbuf
.st_mode
) == -1)
2971 __gnat_lseek (int fd
, long offset
, int whence
)
2973 return (int) lseek (fd
, offset
, whence
);
2976 /* This function returns the major version number of GCC being used. */
2978 get_gcc_version (void)
2983 return (int) (version_string
[0] - '0');
2988 * Set Close_On_Exec as indicated.
2989 * Note: this is used for both GNAT.OS_Lib and GNAT.Sockets.
2993 __gnat_set_close_on_exec (int fd ATTRIBUTE_UNUSED
,
2994 int close_on_exec_p ATTRIBUTE_UNUSED
)
2996 #if defined (F_GETFD) && defined (FD_CLOEXEC) && ! defined (__vxworks)
2997 int flags
= fcntl (fd
, F_GETFD
, 0);
3000 if (close_on_exec_p
)
3001 flags
|= FD_CLOEXEC
;
3003 flags
&= ~FD_CLOEXEC
;
3004 return fcntl (fd
, F_SETFD
, flags
);
3005 #elif defined(_WIN32)
3006 HANDLE h
= (HANDLE
) _get_osfhandle (fd
);
3007 if (h
== (HANDLE
) -1)
3009 if (close_on_exec_p
)
3010 return ! SetHandleInformation (h
, HANDLE_FLAG_INHERIT
, 0);
3011 return ! SetHandleInformation (h
, HANDLE_FLAG_INHERIT
,
3012 HANDLE_FLAG_INHERIT
);
3014 /* TODO: Unimplemented. */
3019 /* Indicates if platforms supports automatic initialization through the
3020 constructor mechanism */
3022 __gnat_binder_supports_auto_init (void)
3027 /* Indicates that Stand-Alone Libraries are automatically initialized through
3028 the constructor mechanism */
3030 __gnat_sals_init_using_constructors (void)
3032 #if defined (__vxworks) || defined (__Lynx__)
3039 #if defined (__ANDROID__)
3041 #include <pthread.h>
3044 __gnat_lwp_self (void)
3046 return (void *) pthread_self ();
3049 #elif defined (linux)
3050 /* There is no function in the glibc to retrieve the LWP of the current
3051 thread. We need to do a system call in order to retrieve this
3053 #include <sys/syscall.h>
3055 __gnat_lwp_self (void)
3057 return (void *) syscall (__NR_gettid
);
3062 /* glibc versions earlier than 2.7 do not define the routines to handle
3063 dynamically allocated CPU sets. For these targets, we use the static
3068 /* Dynamic cpu sets */
3071 __gnat_cpu_alloc (size_t count
)
3073 return CPU_ALLOC (count
);
3077 __gnat_cpu_alloc_size (size_t count
)
3079 return CPU_ALLOC_SIZE (count
);
3083 __gnat_cpu_free (cpu_set_t
*set
)
3089 __gnat_cpu_zero (size_t count
, cpu_set_t
*set
)
3091 CPU_ZERO_S (count
, set
);
3095 __gnat_cpu_set (int cpu
, size_t count
, cpu_set_t
*set
)
3097 /* Ada handles CPU numbers starting from 1, while C identifies the first
3098 CPU by a 0, so we need to adjust. */
3099 CPU_SET_S (cpu
- 1, count
, set
);
3102 #else /* !CPU_ALLOC */
3104 /* Static cpu sets */
3107 __gnat_cpu_alloc (size_t count ATTRIBUTE_UNUSED
)
3109 return (cpu_set_t
*) xmalloc (sizeof (cpu_set_t
));
3113 __gnat_cpu_alloc_size (size_t count ATTRIBUTE_UNUSED
)
3115 return sizeof (cpu_set_t
);
3119 __gnat_cpu_free (cpu_set_t
*set
)
3125 __gnat_cpu_zero (size_t count ATTRIBUTE_UNUSED
, cpu_set_t
*set
)
3131 __gnat_cpu_set (int cpu
, size_t count ATTRIBUTE_UNUSED
, cpu_set_t
*set
)
3133 /* Ada handles CPU numbers starting from 1, while C identifies the first
3134 CPU by a 0, so we need to adjust. */
3135 CPU_SET (cpu
- 1, set
);
3137 #endif /* !CPU_ALLOC */
3140 /* Return the load address of the executable, or 0 if not known. In the
3141 specific case of error, (void *)-1 can be returned. Beware: this unit may
3142 be in a shared library. As low-level units are needed, we allow #include
3145 #if defined (__APPLE__)
3146 #include <mach-o/dyld.h>
3147 #elif 0 && defined (__linux__)
3152 __gnat_get_executable_load_address (void)
3154 #if defined (__APPLE__)
3155 return _dyld_get_image_header (0);
3157 #elif 0 && defined (__linux__)
3158 /* Currently disabled as it needs at least -ldl. */
3159 struct link_map
*map
= _r_debug
.r_map
;
3161 return (const void *)map
->l_addr
;