1 /****************************************************************************
3 * GNAT COMPILER COMPONENTS *
7 * C Implementation File *
9 * Copyright (C) 1992-2010, 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. */
39 /* No need to redefine exit here. */
42 /* We want to use the POSIX variants of include files. */
46 #if defined (__mips_vxworks)
48 #endif /* __mips_vxworks */
52 #if (defined (__mips) && defined (__sgi)) || defined (__APPLE__)
56 #if defined (__hpux__)
57 #include <sys/param.h>
58 #include <sys/pstat.h>
63 #define HOST_EXECUTABLE_SUFFIX ".exe"
64 #define HOST_OBJECT_SUFFIX ".obj"
78 /* We don't have libiberty, so use malloc. */
79 #define xmalloc(S) malloc (S)
80 #define xrealloc(V,S) realloc (V,S)
87 #if defined (__MINGW32__)
95 /* Current code page to use, set in initialize.c. */
99 #include <sys/utime.h>
101 /* For isalpha-like tests in the compiler, we're expected to resort to
102 safe-ctype.h/ISALPHA. This isn't available for the runtime library
103 build, so we fallback on ctype.h/isalpha there. */
107 #define ISALPHA isalpha
110 #elif defined (__Lynx__)
112 /* Lynx utime.h only defines the entities of interest to us if
113 defined (VMOS_DEV), so ... */
122 /* wait.h processing */
125 #include <sys/wait.h>
127 #elif defined (__vxworks) && defined (__RTP__)
129 #elif defined (__Lynx__)
130 /* ??? We really need wait.h and it includes resource.h on Lynx. GCC
131 has a resource.h header as well, included instead of the lynx
132 version in our setup, causing lots of errors. We don't really need
133 the lynx contents of this file, so just workaround the issue by
134 preventing the inclusion of the GCC header from doing anything. */
135 #define GCC_RESOURCE_H
136 #include <sys/wait.h>
137 #elif defined (__nucleus__)
138 /* No wait() or waitpid() calls available */
141 #include <sys/wait.h>
147 /* Header files and definitions for __gnat_set_file_time_name. */
149 #define __NEW_STARLET 1
151 #include <vms/atrdef.h>
152 #include <vms/fibdef.h>
153 #include <vms/stsdef.h>
154 #include <vms/iodef.h>
156 #include <vms/descrip.h>
160 /* Use native 64-bit arithmetic. */
161 #define unix_time_to_vms(X,Y) \
162 { unsigned long long reftime, tmptime = (X); \
163 $DESCRIPTOR (unixtime,"1-JAN-1970 0:00:00.00"); \
164 SYS$BINTIM (&unixtime, &reftime); \
165 Y = tmptime * 10000000 + reftime; }
167 /* descrip.h doesn't have everything ... */
168 typedef struct fibdef
* __fibdef_ptr32
__attribute__ (( mode (SI
) ));
169 struct dsc$descriptor_fib
171 unsigned int fib$l_len
;
172 __fibdef_ptr32 fib$l_addr
;
175 /* I/O Status Block. */
178 unsigned short status
, count
;
182 static char *tryfile
;
184 /* Variable length string. */
188 char string
[NAM$C_MAXRSS
+1];
191 #define SYI$_ACTIVECPU_CNT 0x111e
192 extern int LIB$
GETSYI (int *, unsigned int *);
209 #define DIR_SEPARATOR '\\'
214 /* Define symbols O_BINARY and O_TEXT as harmless zeroes if they are not
215 defined in the current system. On DOS-like systems these flags control
216 whether the file is opened/created in text-translation mode (CR/LF in
217 external file mapped to LF in internal file), but in Unix-like systems,
218 no text translation is required, so these flags have no effect. */
228 #ifndef HOST_EXECUTABLE_SUFFIX
229 #define HOST_EXECUTABLE_SUFFIX ""
232 #ifndef HOST_OBJECT_SUFFIX
233 #define HOST_OBJECT_SUFFIX ".o"
236 #ifndef PATH_SEPARATOR
237 #define PATH_SEPARATOR ':'
240 #ifndef DIR_SEPARATOR
241 #define DIR_SEPARATOR '/'
244 /* Check for cross-compilation */
245 #if defined (CROSS_COMPILE) || defined (CROSS_DIRECTORY_STRUCTURE)
247 int __gnat_is_cross_compiler
= 1;
250 int __gnat_is_cross_compiler
= 0;
253 char __gnat_dir_separator
= DIR_SEPARATOR
;
255 char __gnat_path_separator
= PATH_SEPARATOR
;
257 /* The GNAT_LIBRARY_TEMPLATE contains a list of expressions that define
258 the base filenames that libraries specified with -lsomelib options
259 may have. This is used by GNATMAKE to check whether an executable
260 is up-to-date or not. The syntax is
262 library_template ::= { pattern ; } pattern NUL
263 pattern ::= [ prefix ] * [ postfix ]
265 These should only specify names of static libraries as it makes
266 no sense to determine at link time if dynamic-link libraries are
267 up to date or not. Any libraries that are not found are supposed
270 * if they are needed but not present, the link
273 * otherwise they are libraries in the system paths and so
274 they are considered part of the system and not checked
277 ??? This should be part of a GNAT host-specific compiler
278 file instead of being included in all user applications
279 as well. This is only a temporary work-around for 3.11b. */
281 #ifndef GNAT_LIBRARY_TEMPLATE
283 #define GNAT_LIBRARY_TEMPLATE "*.olb"
285 #define GNAT_LIBRARY_TEMPLATE "lib*.a"
289 const char *__gnat_library_template
= GNAT_LIBRARY_TEMPLATE
;
291 /* This variable is used in hostparm.ads to say whether the host is a VMS
294 const int __gnat_vmsp
= 1;
296 const int __gnat_vmsp
= 0;
300 #define GNAT_MAX_PATH_LEN 256 /* PATH_MAX */
302 #elif defined (__vxworks) || defined (__OPENNT) || defined(__nucleus__)
303 #define GNAT_MAX_PATH_LEN PATH_MAX
307 #if defined (__MINGW32__)
311 #include <sys/param.h>
315 #include <sys/param.h>
319 #define GNAT_MAX_PATH_LEN MAXPATHLEN
321 #define GNAT_MAX_PATH_LEN 256
326 /* Used for Ada bindings */
327 const int __gnat_size_of_file_attributes
= sizeof (struct file_attributes
);
329 /* Reset the file attributes as if no system call had been performed */
330 void __gnat_stat_to_attr (int fd
, char* name
, struct file_attributes
* attr
);
332 /* The __gnat_max_path_len variable is used to export the maximum
333 length of a path name to Ada code. max_path_len is also provided
334 for compatibility with older GNAT versions, please do not use
337 int __gnat_max_path_len
= GNAT_MAX_PATH_LEN
;
338 int max_path_len
= GNAT_MAX_PATH_LEN
;
340 /* Control whether we can use ACL on Windows. */
342 int __gnat_use_acl
= 1;
344 /* The following macro HAVE_READDIR_R should be defined if the
345 system provides the routine readdir_r. */
346 #undef HAVE_READDIR_R
348 #if defined(VMS) && defined (__LONG_POINTERS)
350 /* Return a 32 bit pointer to an array of 32 bit pointers
351 given a 64 bit pointer to an array of 64 bit pointers */
353 typedef __char_ptr32
*__char_ptr_char_ptr32
__attribute__ ((mode (SI
)));
355 static __char_ptr_char_ptr32
356 to_ptr32 (char **ptr64
)
359 __char_ptr_char_ptr32 short_argv
;
361 for (argc
=0; ptr64
[argc
]; argc
++);
363 /* Reallocate argv with 32 bit pointers. */
364 short_argv
= (__char_ptr_char_ptr32
) decc$malloc
365 (sizeof (__char_ptr32
) * (argc
+ 1));
367 for (argc
=0; ptr64
[argc
]; argc
++)
368 short_argv
[argc
] = (__char_ptr32
) decc$
strdup (ptr64
[argc
]);
370 short_argv
[argc
] = (__char_ptr32
) 0;
374 #define MAYBE_TO_PTR32(argv) to_ptr32 (argv)
376 #define MAYBE_TO_PTR32(argv) argv
379 static const char ATTR_UNSET
= 127;
382 __gnat_reset_attributes
383 (struct file_attributes
* attr
)
385 attr
->exists
= ATTR_UNSET
;
387 attr
->writable
= ATTR_UNSET
;
388 attr
->readable
= ATTR_UNSET
;
389 attr
->executable
= ATTR_UNSET
;
391 attr
->regular
= ATTR_UNSET
;
392 attr
->symbolic_link
= ATTR_UNSET
;
393 attr
->directory
= ATTR_UNSET
;
395 attr
->timestamp
= (OS_Time
)-2;
396 attr
->file_length
= -1;
403 time_t res
= time (NULL
);
404 return (OS_Time
) res
;
407 /* Return the current local time as a string in the ISO 8601 format of
408 "YYYY-MM-DD HH:MM:SS.SS". The returned string is 22 + 1 (NULL) characters
412 __gnat_current_time_string
415 const char *format
= "%Y-%m-%d %H:%M:%S";
416 /* Format string necessary to describe the ISO 8601 format */
418 const time_t t_val
= time (NULL
);
420 strftime (result
, 22, format
, localtime (&t_val
));
421 /* Convert the local time into a string following the ISO format, copying
422 at most 22 characters into the result string. */
427 /* The sub-seconds are manually set to zero since type time_t lacks the
428 precision necessary for nanoseconds. */
442 time_t time
= (time_t) *p_time
;
445 /* On Windows systems, the time is sometimes rounded up to the nearest
446 even second, so if the number of seconds is odd, increment it. */
452 res
= localtime (&time
);
454 res
= gmtime (&time
);
459 *p_year
= res
->tm_year
;
460 *p_month
= res
->tm_mon
;
461 *p_day
= res
->tm_mday
;
462 *p_hours
= res
->tm_hour
;
463 *p_mins
= res
->tm_min
;
464 *p_secs
= res
->tm_sec
;
467 *p_year
= *p_month
= *p_day
= *p_hours
= *p_mins
= *p_secs
= 0;
470 /* Place the contents of the symbolic link named PATH in the buffer BUF,
471 which has size BUFSIZ. If PATH is a symbolic link, then return the number
472 of characters of its content in BUF. Otherwise, return -1.
473 For systems not supporting symbolic links, always return -1. */
476 __gnat_readlink (char *path ATTRIBUTE_UNUSED
,
477 char *buf ATTRIBUTE_UNUSED
,
478 size_t bufsiz ATTRIBUTE_UNUSED
)
480 #if defined (_WIN32) || defined (VMS) \
481 || defined(__vxworks) || defined (__nucleus__)
484 return readlink (path
, buf
, bufsiz
);
488 /* Creates a symbolic link named NEWPATH which contains the string OLDPATH.
489 If NEWPATH exists it will NOT be overwritten.
490 For systems not supporting symbolic links, always return -1. */
493 __gnat_symlink (char *oldpath ATTRIBUTE_UNUSED
,
494 char *newpath ATTRIBUTE_UNUSED
)
496 #if defined (_WIN32) || defined (VMS) \
497 || defined(__vxworks) || defined (__nucleus__)
500 return symlink (oldpath
, newpath
);
504 /* Try to lock a file, return 1 if success. */
506 #if defined (__vxworks) || defined (__nucleus__) \
507 || defined (_WIN32) || defined (VMS)
509 /* Version that does not use link. */
512 __gnat_try_lock (char *dir
, char *file
)
516 TCHAR wfull_path
[GNAT_MAX_PATH_LEN
];
517 TCHAR wfile
[GNAT_MAX_PATH_LEN
];
518 TCHAR wdir
[GNAT_MAX_PATH_LEN
];
520 S2WSC (wdir
, dir
, GNAT_MAX_PATH_LEN
);
521 S2WSC (wfile
, file
, GNAT_MAX_PATH_LEN
);
523 _stprintf (wfull_path
, _T("%s%c%s"), wdir
, _T(DIR_SEPARATOR
), wfile
);
524 fd
= _topen (wfull_path
, O_CREAT
| O_EXCL
, 0600);
528 sprintf (full_path
, "%s%c%s", dir
, DIR_SEPARATOR
, file
);
529 fd
= open (full_path
, O_CREAT
| O_EXCL
, 0600);
541 /* Version using link(), more secure over NFS. */
542 /* See TN 6913-016 for discussion ??? */
545 __gnat_try_lock (char *dir
, char *file
)
549 GNAT_STRUCT_STAT stat_result
;
552 sprintf (full_path
, "%s%c%s", dir
, DIR_SEPARATOR
, file
);
553 sprintf (temp_file
, "%s%cTMP-%ld-%ld",
554 dir
, DIR_SEPARATOR
, (long)getpid(), (long)getppid ());
556 /* Create the temporary file and write the process number. */
557 fd
= open (temp_file
, O_CREAT
| O_WRONLY
, 0600);
563 /* Link it with the new file. */
564 link (temp_file
, full_path
);
566 /* Count the references on the old one. If we have a count of two, then
567 the link did succeed. Remove the temporary file before returning. */
568 __gnat_stat (temp_file
, &stat_result
);
570 return stat_result
.st_nlink
== 2;
574 /* Return the maximum file name length. */
577 __gnat_get_maximum_file_name_length (void)
580 if (getenv ("GNAT$EXTENDED_FILE_SPECIFICATIONS"))
589 /* Return nonzero if file names are case sensitive. */
592 __gnat_get_file_names_case_sensitive (void)
594 const char *sensitive
= getenv ("GNAT_FILE_NAME_CASE_SENSITIVE");
596 if (sensitive
!= NULL
597 && (sensitive
[0] == '0' || sensitive
[0] == '1')
598 && sensitive
[1] == '\0')
599 return sensitive
[0] - '0';
601 #if defined (VMS) || defined (WINNT) || defined (__APPLE__)
608 /* Return nonzero if environment variables are case sensitive. */
611 __gnat_get_env_vars_case_sensitive (void)
613 #if defined (VMS) || defined (WINNT)
621 __gnat_get_default_identifier_character_set (void)
626 /* Return the current working directory. */
629 __gnat_get_current_dir (char *dir
, int *length
)
631 #if defined (__MINGW32__)
632 TCHAR wdir
[GNAT_MAX_PATH_LEN
];
634 _tgetcwd (wdir
, *length
);
636 WS2SC (dir
, wdir
, GNAT_MAX_PATH_LEN
);
639 /* Force Unix style, which is what GNAT uses internally. */
640 getcwd (dir
, *length
, 0);
642 getcwd (dir
, *length
);
645 *length
= strlen (dir
);
647 if (dir
[*length
- 1] != DIR_SEPARATOR
)
649 dir
[*length
] = DIR_SEPARATOR
;
655 /* Return the suffix for object files. */
658 __gnat_get_object_suffix_ptr (int *len
, const char **value
)
660 *value
= HOST_OBJECT_SUFFIX
;
665 *len
= strlen (*value
);
670 /* Return the suffix for executable files. */
673 __gnat_get_executable_suffix_ptr (int *len
, const char **value
)
675 *value
= HOST_EXECUTABLE_SUFFIX
;
679 *len
= strlen (*value
);
684 /* Return the suffix for debuggable files. Usually this is the same as the
685 executable extension. */
688 __gnat_get_debuggable_suffix_ptr (int *len
, const char **value
)
690 *value
= HOST_EXECUTABLE_SUFFIX
;
695 *len
= strlen (*value
);
700 /* Returns the OS filename and corresponding encoding. */
703 __gnat_os_filename (char *filename ATTRIBUTE_UNUSED
,
704 char *w_filename ATTRIBUTE_UNUSED
,
705 char *os_name
, int *o_length
,
706 char *encoding ATTRIBUTE_UNUSED
, int *e_length
)
708 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (IS_CROSS)
709 WS2SC (os_name
, (TCHAR
*)w_filename
, (DWORD
)*o_length
);
710 *o_length
= strlen (os_name
);
711 strcpy (encoding
, "encoding=utf8");
712 *e_length
= strlen (encoding
);
714 strcpy (os_name
, filename
);
715 *o_length
= strlen (filename
);
723 __gnat_unlink (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 _tunlink (wpath
);
733 return unlink (path
);
740 __gnat_rename (char *from
, char *to
)
742 #if defined (__MINGW32__) && ! defined (__vxworks) && ! defined (IS_CROSS)
744 TCHAR wfrom
[GNAT_MAX_PATH_LEN
], wto
[GNAT_MAX_PATH_LEN
];
746 S2WSC (wfrom
, from
, GNAT_MAX_PATH_LEN
);
747 S2WSC (wto
, to
, GNAT_MAX_PATH_LEN
);
748 return _trename (wfrom
, wto
);
751 return rename (from
, to
);
755 /* Changing directory. */
758 __gnat_chdir (char *path
)
760 #if defined (__MINGW32__) && ! defined (__vxworks) && ! defined (IS_CROSS)
762 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
764 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
765 return _tchdir (wpath
);
772 /* Removing a directory. */
775 __gnat_rmdir (char *path
)
777 #if defined (__MINGW32__) && ! defined (__vxworks) && ! defined (IS_CROSS)
779 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
781 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
782 return _trmdir (wpath
);
784 #elif defined (VTHREADS)
785 /* rmdir not available */
793 __gnat_fopen (char *path
, char *mode
, int encoding ATTRIBUTE_UNUSED
)
795 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (IS_CROSS)
796 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
799 S2WS (wmode
, mode
, 10);
801 if (encoding
== Encoding_Unspecified
)
802 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
803 else if (encoding
== Encoding_UTF8
)
804 S2WSU (wpath
, path
, GNAT_MAX_PATH_LEN
);
806 S2WS (wpath
, path
, GNAT_MAX_PATH_LEN
);
808 return _tfopen (wpath
, wmode
);
810 return decc$
fopen (path
, mode
);
812 return GNAT_FOPEN (path
, mode
);
817 __gnat_freopen (char *path
,
820 int encoding ATTRIBUTE_UNUSED
)
822 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (IS_CROSS)
823 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
826 S2WS (wmode
, mode
, 10);
828 if (encoding
== Encoding_Unspecified
)
829 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
830 else if (encoding
== Encoding_UTF8
)
831 S2WSU (wpath
, path
, GNAT_MAX_PATH_LEN
);
833 S2WS (wpath
, path
, GNAT_MAX_PATH_LEN
);
835 return _tfreopen (wpath
, wmode
, stream
);
837 return decc$
freopen (path
, mode
, stream
);
839 return freopen (path
, mode
, stream
);
844 __gnat_open_read (char *path
, int fmode
)
847 int o_fmode
= O_BINARY
;
853 /* Optional arguments mbc,deq,fop increase read performance. */
854 fd
= open (path
, O_RDONLY
| o_fmode
, 0444,
855 "mbc=16", "deq=64", "fop=tef");
856 #elif defined (__vxworks)
857 fd
= open (path
, O_RDONLY
| o_fmode
, 0444);
858 #elif defined (__MINGW32__)
860 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
862 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
863 fd
= _topen (wpath
, O_RDONLY
| o_fmode
, 0444);
866 fd
= open (path
, O_RDONLY
| o_fmode
);
869 return fd
< 0 ? -1 : fd
;
872 #if defined (__MINGW32__)
873 #define PERM (S_IREAD | S_IWRITE)
875 /* Excerpt from DECC C RTL Reference Manual:
876 To create files with OpenVMS RMS default protections using the UNIX
877 system-call functions umask, mkdir, creat, and open, call mkdir, creat,
878 and open with a file-protection mode argument of 0777 in a program
879 that never specifically calls umask. These default protections include
880 correctly establishing protections based on ACLs, previous versions of
884 #define PERM (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
888 __gnat_open_rw (char *path
, int fmode
)
891 int o_fmode
= O_BINARY
;
897 fd
= open (path
, O_RDWR
| o_fmode
, PERM
,
898 "mbc=16", "deq=64", "fop=tef");
899 #elif defined (__MINGW32__)
901 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
903 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
904 fd
= _topen (wpath
, O_RDWR
| o_fmode
, PERM
);
907 fd
= open (path
, O_RDWR
| o_fmode
, PERM
);
910 return fd
< 0 ? -1 : fd
;
914 __gnat_open_create (char *path
, int fmode
)
917 int o_fmode
= O_BINARY
;
923 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| o_fmode
, PERM
,
924 "mbc=16", "deq=64", "fop=tef");
925 #elif defined (__MINGW32__)
927 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
929 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
930 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_TRUNC
| o_fmode
, PERM
);
933 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| o_fmode
, PERM
);
936 return fd
< 0 ? -1 : fd
;
940 __gnat_create_output_file (char *path
)
944 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
, PERM
,
945 "rfm=stmlf", "ctx=rec", "rat=none", "rop=nlk",
946 "shr=del,get,put,upd");
947 #elif defined (__MINGW32__)
949 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
951 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
952 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
, PERM
);
955 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
, PERM
);
958 return fd
< 0 ? -1 : fd
;
962 __gnat_create_output_file_new (char *path
)
966 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
| O_EXCL
, PERM
,
967 "rfm=stmlf", "ctx=rec", "rat=none", "rop=nlk",
968 "shr=del,get,put,upd");
969 #elif defined (__MINGW32__)
971 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
973 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
974 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
| O_EXCL
, PERM
);
977 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
| O_EXCL
, PERM
);
980 return fd
< 0 ? -1 : fd
;
984 __gnat_open_append (char *path
, int fmode
)
987 int o_fmode
= O_BINARY
;
993 fd
= open (path
, O_WRONLY
| O_CREAT
| O_APPEND
| o_fmode
, PERM
,
994 "mbc=16", "deq=64", "fop=tef");
995 #elif defined (__MINGW32__)
997 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
999 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
1000 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_APPEND
| o_fmode
, PERM
);
1003 fd
= open (path
, O_WRONLY
| O_CREAT
| O_APPEND
| o_fmode
, PERM
);
1006 return fd
< 0 ? -1 : fd
;
1009 /* Open a new file. Return error (-1) if the file already exists. */
1012 __gnat_open_new (char *path
, int fmode
)
1015 int o_fmode
= O_BINARY
;
1021 fd
= open (path
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
,
1022 "mbc=16", "deq=64", "fop=tef");
1023 #elif defined (__MINGW32__)
1025 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
1027 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
1028 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
);
1031 fd
= open (path
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
);
1034 return fd
< 0 ? -1 : fd
;
1037 /* Open a new temp file. Return error (-1) if the file already exists.
1038 Special options for VMS allow the file to be shared between parent and child
1039 processes, however they really slow down output. Used in gnatchop. */
1042 __gnat_open_new_temp (char *path
, int fmode
)
1045 int o_fmode
= O_BINARY
;
1047 strcpy (path
, "GNAT-XXXXXX");
1049 #if (defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) \
1050 || defined (linux) || defined(__GLIBC__)) && !defined (__vxworks)
1051 return mkstemp (path
);
1052 #elif defined (__Lynx__)
1054 #elif defined (__nucleus__)
1057 if (mktemp (path
) == NULL
)
1065 fd
= open (path
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
,
1066 "rfm=stmlf", "ctx=rec", "rat=none", "shr=del,get,put,upd",
1067 "mbc=16", "deq=64", "fop=tef");
1069 fd
= open (path
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
);
1072 return fd
< 0 ? -1 : fd
;
1075 /****************************************************************
1076 ** Perform a call to GNAT_STAT or GNAT_FSTAT, and extract as much information
1077 ** as possible from it, storing the result in a cache for later reuse
1078 ****************************************************************/
1081 __gnat_stat_to_attr (int fd
, char* name
, struct file_attributes
* attr
)
1083 GNAT_STRUCT_STAT statbuf
;
1087 ret
= GNAT_FSTAT (fd
, &statbuf
);
1089 ret
= __gnat_stat (name
, &statbuf
);
1091 attr
->regular
= (!ret
&& S_ISREG (statbuf
.st_mode
));
1092 attr
->directory
= (!ret
&& S_ISDIR (statbuf
.st_mode
));
1095 attr
->file_length
= 0;
1097 /* st_size may be 32 bits, or 64 bits which is converted to long. We
1098 don't return a useful value for files larger than 2 gigabytes in
1100 attr
->file_length
= statbuf
.st_size
; /* all systems */
1102 attr
->exists
= !ret
;
1104 #if !defined (_WIN32) || defined (RTX)
1105 /* on Windows requires extra system call, see __gnat_is_readable_file_attr */
1106 attr
->readable
= (!ret
&& (statbuf
.st_mode
& S_IRUSR
));
1107 attr
->writable
= (!ret
&& (statbuf
.st_mode
& S_IWUSR
));
1108 attr
->executable
= (!ret
&& (statbuf
.st_mode
& S_IXUSR
));
1112 attr
->timestamp
= (OS_Time
)-1;
1115 /* VMS has file versioning. */
1116 attr
->timestamp
= (OS_Time
)statbuf
.st_ctime
;
1118 attr
->timestamp
= (OS_Time
)statbuf
.st_mtime
;
1123 /****************************************************************
1124 ** Return the number of bytes in the specified file
1125 ****************************************************************/
1128 __gnat_file_length_attr (int fd
, char* name
, struct file_attributes
* attr
)
1130 if (attr
->file_length
== -1) {
1131 __gnat_stat_to_attr (fd
, name
, attr
);
1134 return attr
->file_length
;
1138 __gnat_file_length (int fd
)
1140 struct file_attributes attr
;
1141 __gnat_reset_attributes (&attr
);
1142 return __gnat_file_length_attr (fd
, NULL
, &attr
);
1146 __gnat_named_file_length (char *name
)
1148 struct file_attributes attr
;
1149 __gnat_reset_attributes (&attr
);
1150 return __gnat_file_length_attr (-1, name
, &attr
);
1153 /* Create a temporary filename and put it in string pointed to by
1157 __gnat_tmp_name (char *tmp_filename
)
1160 /* Variable used to create a series of unique names */
1161 static int counter
= 0;
1163 /* RTX in RTSS mode does not support tempnam nor tmpnam so we emulate it */
1164 strcpy (tmp_filename
, "c:\\WINDOWS\\Temp\\gnat-");
1165 sprintf (&tmp_filename
[strlen (tmp_filename
)], "%d\0", counter
++);
1167 #elif defined (__MINGW32__)
1171 /* tempnam tries to create a temporary file in directory pointed to by
1172 TMP environment variable, in c:\temp if TMP is not set, and in
1173 directory specified by P_tmpdir in stdio.h if c:\temp does not
1174 exist. The filename will be created with the prefix "gnat-". */
1176 pname
= (char *) tempnam ("c:\\temp", "gnat-");
1178 /* if pname is NULL, the file was not created properly, the disk is full
1179 or there is no more free temporary files */
1182 *tmp_filename
= '\0';
1184 /* If pname start with a back slash and not path information it means that
1185 the filename is valid for the current working directory. */
1187 else if (pname
[0] == '\\')
1189 strcpy (tmp_filename
, ".\\");
1190 strcat (tmp_filename
, pname
+1);
1193 strcpy (tmp_filename
, pname
);
1198 #elif defined (linux) || defined (__FreeBSD__) || defined (__NetBSD__) \
1199 || defined (__OpenBSD__) || defined(__GLIBC__)
1200 #define MAX_SAFE_PATH 1000
1201 char *tmpdir
= getenv ("TMPDIR");
1203 /* If tmpdir is longer than MAX_SAFE_PATH, revert to default value to avoid
1204 a buffer overflow. */
1205 if (tmpdir
== NULL
|| strlen (tmpdir
) > MAX_SAFE_PATH
)
1206 strcpy (tmp_filename
, "/tmp/gnat-XXXXXX");
1208 sprintf (tmp_filename
, "%s/gnat-XXXXXX", tmpdir
);
1210 close (mkstemp(tmp_filename
));
1212 tmpnam (tmp_filename
);
1216 /* Open directory and returns a DIR pointer. */
1218 DIR* __gnat_opendir (char *name
)
1221 /* Not supported in RTX */
1225 #elif defined (__MINGW32__)
1226 TCHAR wname
[GNAT_MAX_PATH_LEN
];
1228 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
);
1229 return (DIR*)_topendir (wname
);
1232 return opendir (name
);
1236 /* Read the next entry in a directory. The returned string points somewhere
1240 __gnat_readdir (DIR *dirp
, char *buffer
, int *len
)
1243 /* Not supported in RTX */
1247 #elif defined (__MINGW32__)
1248 struct _tdirent
*dirent
= _treaddir ((_TDIR
*)dirp
);
1252 WS2SC (buffer
, dirent
->d_name
, GNAT_MAX_PATH_LEN
);
1253 *len
= strlen (buffer
);
1260 #elif defined (HAVE_READDIR_R)
1261 /* If possible, try to use the thread-safe version. */
1262 if (readdir_r (dirp
, buffer
) != NULL
)
1264 *len
= strlen (((struct dirent
*) buffer
)->d_name
);
1265 return ((struct dirent
*) buffer
)->d_name
;
1271 struct dirent
*dirent
= (struct dirent
*) readdir (dirp
);
1275 strcpy (buffer
, dirent
->d_name
);
1276 *len
= strlen (buffer
);
1285 /* Close a directory entry. */
1287 int __gnat_closedir (DIR *dirp
)
1290 /* Not supported in RTX */
1294 #elif defined (__MINGW32__)
1295 return _tclosedir ((_TDIR
*)dirp
);
1298 return closedir (dirp
);
1302 /* Returns 1 if readdir is thread safe, 0 otherwise. */
1305 __gnat_readdir_is_thread_safe (void)
1307 #ifdef HAVE_READDIR_R
1314 #if defined (_WIN32) && !defined (RTX)
1315 /* Number of seconds between <Jan 1st 1601> and <Jan 1st 1970>. */
1316 static const unsigned long long w32_epoch_offset
= 11644473600ULL;
1318 /* Returns the file modification timestamp using Win32 routines which are
1319 immune against daylight saving time change. It is in fact not possible to
1320 use fstat for this purpose as the DST modify the st_mtime field of the
1324 win32_filetime (HANDLE h
)
1329 unsigned long long ull_time
;
1332 /* GetFileTime returns FILETIME data which are the number of 100 nanosecs
1333 since <Jan 1st 1601>. This function must return the number of seconds
1334 since <Jan 1st 1970>. */
1336 if (GetFileTime (h
, NULL
, NULL
, &t_write
.ft_time
))
1337 return (time_t) (t_write
.ull_time
/ 10000000ULL - w32_epoch_offset
);
1341 /* As above but starting from a FILETIME. */
1343 f2t (const FILETIME
*ft
, time_t *t
)
1348 unsigned long long ull_time
;
1351 t_write
.ft_time
= *ft
;
1352 *t
= (time_t) (t_write
.ull_time
/ 10000000ULL - w32_epoch_offset
);
1356 /* Return a GNAT time stamp given a file name. */
1359 __gnat_file_time_name_attr (char* name
, struct file_attributes
* attr
)
1361 if (attr
->timestamp
== (OS_Time
)-2) {
1362 #if defined (_WIN32) && !defined (RTX)
1364 WIN32_FILE_ATTRIBUTE_DATA fad
;
1366 TCHAR wname
[GNAT_MAX_PATH_LEN
];
1367 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
);
1369 if (res
= GetFileAttributesEx (wname
, GetFileExInfoStandard
, &fad
))
1370 f2t (&fad
.ftLastWriteTime
, &ret
);
1371 attr
->timestamp
= (OS_Time
) ret
;
1373 __gnat_stat_to_attr (-1, name
, attr
);
1376 return attr
->timestamp
;
1380 __gnat_file_time_name (char *name
)
1382 struct file_attributes attr
;
1383 __gnat_reset_attributes (&attr
);
1384 return __gnat_file_time_name_attr (name
, &attr
);
1387 /* Return a GNAT time stamp given a file descriptor. */
1390 __gnat_file_time_fd_attr (int fd
, struct file_attributes
* attr
)
1392 if (attr
->timestamp
== (OS_Time
)-2) {
1393 #if defined (_WIN32) && !defined (RTX)
1394 HANDLE h
= (HANDLE
) _get_osfhandle (fd
);
1395 time_t ret
= win32_filetime (h
);
1396 attr
->timestamp
= (OS_Time
) ret
;
1399 __gnat_stat_to_attr (fd
, NULL
, attr
);
1403 return attr
->timestamp
;
1407 __gnat_file_time_fd (int fd
)
1409 struct file_attributes attr
;
1410 __gnat_reset_attributes (&attr
);
1411 return __gnat_file_time_fd_attr (fd
, &attr
);
1414 /* Set the file time stamp. */
1417 __gnat_set_file_time_name (char *name
, time_t time_stamp
)
1419 #if defined (__vxworks)
1421 /* Code to implement __gnat_set_file_time_name for these systems. */
1423 #elif defined (_WIN32) && !defined (RTX)
1427 unsigned long long ull_time
;
1429 TCHAR wname
[GNAT_MAX_PATH_LEN
];
1431 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
);
1433 HANDLE h
= CreateFile
1434 (wname
, GENERIC_WRITE
, FILE_SHARE_WRITE
, NULL
,
1435 OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
,
1437 if (h
== INVALID_HANDLE_VALUE
)
1439 /* Add number of seconds between <Jan 1st 1601> and <Jan 1st 1970> */
1440 t_write
.ull_time
= ((unsigned long long)time_stamp
+ w32_epoch_offset
);
1441 /* Convert to 100 nanosecond units */
1442 t_write
.ull_time
*= 10000000ULL;
1444 SetFileTime(h
, NULL
, NULL
, &t_write
.ft_time
);
1454 unsigned long long backup
, create
, expire
, revise
;
1458 unsigned short value
;
1461 unsigned system
: 4;
1467 } Fat
= { 0, 0, 0, 0, 0, { 0 }};
1471 { ATR$S_CREDATE
, ATR$C_CREDATE
, &Fat
.create
},
1472 { ATR$S_REVDATE
, ATR$C_REVDATE
, &Fat
.revise
},
1473 { ATR$S_EXPDATE
, ATR$C_EXPDATE
, &Fat
.expire
},
1474 { ATR$S_BAKDATE
, ATR$C_BAKDATE
, &Fat
.backup
},
1475 { ATR$S_FPRO
, ATR$C_FPRO
, &Fat
.prot
},
1476 { ATR$S_UIC
, ATR$C_UIC
, &Fat
.uic
},
1481 struct dsc$descriptor_fib fibdsc
= {sizeof (fib
), (void *) &fib
};
1485 unsigned long long newtime
;
1486 unsigned long long revtime
;
1490 struct vstring file
;
1491 struct dsc$descriptor_s filedsc
1492 = {NAM$C_MAXRSS
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, (void *) file
.string
};
1493 struct vstring device
;
1494 struct dsc$descriptor_s devicedsc
1495 = {NAM$C_MAXRSS
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, (void *) device
.string
};
1496 struct vstring timev
;
1497 struct dsc$descriptor_s timedsc
1498 = {NAM$C_MAXRSS
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, (void *) timev
.string
};
1499 struct vstring result
;
1500 struct dsc$descriptor_s resultdsc
1501 = {NAM$C_MAXRSS
, DSC$K_DTYPE_VT
, DSC$K_CLASS_VS
, (void *) result
.string
};
1503 /* Convert parameter name (a file spec) to host file form. Note that this
1504 is needed on VMS to prepare for subsequent calls to VMS RMS library
1505 routines. Note that it would not work to call __gnat_to_host_dir_spec
1506 as was done in a previous version, since this fails silently unless
1507 the feature logical DECC$EFS_CHARSET is enabled, in which case a DNF
1508 (directory not found) condition is signalled. */
1509 tryfile
= (char *) __gnat_to_host_file_spec (name
);
1511 /* Allocate and initialize a FAB and NAM structures. */
1515 nam
.nam$l_esa
= file
.string
;
1516 nam
.nam$b_ess
= NAM$C_MAXRSS
;
1517 nam
.nam$l_rsa
= result
.string
;
1518 nam
.nam$b_rss
= NAM$C_MAXRSS
;
1519 fab
.fab$l_fna
= tryfile
;
1520 fab
.fab$b_fns
= strlen (tryfile
);
1521 fab
.fab$l_nam
= &nam
;
1523 /* Validate filespec syntax and device existence. */
1524 status
= SYS$
PARSE (&fab
, 0, 0);
1525 if ((status
& 1) != 1)
1526 LIB$
SIGNAL (status
);
1528 file
.string
[nam
.nam$b_esl
] = 0;
1530 /* Find matching filespec. */
1531 status
= SYS$
SEARCH (&fab
, 0, 0);
1532 if ((status
& 1) != 1)
1533 LIB$
SIGNAL (status
);
1535 file
.string
[nam
.nam$b_esl
] = 0;
1536 result
.string
[result
.length
=nam
.nam$b_rsl
] = 0;
1538 /* Get the device name and assign an IO channel. */
1539 strncpy (device
.string
, nam
.nam$l_dev
, nam
.nam$b_dev
);
1540 devicedsc
.dsc$w_length
= nam
.nam$b_dev
;
1542 status
= SYS$
ASSIGN (&devicedsc
, &chan
, 0, 0, 0);
1543 if ((status
& 1) != 1)
1544 LIB$
SIGNAL (status
);
1546 /* Initialize the FIB and fill in the directory id field. */
1547 memset (&fib
, 0, sizeof (fib
));
1548 fib
.fib$w_did
[0] = nam
.nam$w_did
[0];
1549 fib
.fib$w_did
[1] = nam
.nam$w_did
[1];
1550 fib
.fib$w_did
[2] = nam
.nam$w_did
[2];
1551 fib
.fib$l_acctl
= 0;
1553 strcpy (file
.string
, (strrchr (result
.string
, ']') + 1));
1554 filedsc
.dsc$w_length
= strlen (file
.string
);
1555 result
.string
[result
.length
= 0] = 0;
1557 /* Open and close the file to fill in the attributes. */
1559 = SYS$
QIOW (0, chan
, IO$_ACCESS
|IO$M_ACCESS
, &iosb
, 0, 0,
1560 &fibdsc
, &filedsc
, &result
.length
, &resultdsc
, &atrlst
, 0);
1561 if ((status
& 1) != 1)
1562 LIB$
SIGNAL (status
);
1563 if ((iosb
.status
& 1) != 1)
1564 LIB$
SIGNAL (iosb
.status
);
1566 result
.string
[result
.length
] = 0;
1567 status
= SYS$
QIOW (0, chan
, IO$_DEACCESS
, &iosb
, 0, 0, &fibdsc
, 0, 0, 0,
1569 if ((status
& 1) != 1)
1570 LIB$
SIGNAL (status
);
1571 if ((iosb
.status
& 1) != 1)
1572 LIB$
SIGNAL (iosb
.status
);
1577 /* Set creation time to requested time. */
1578 unix_time_to_vms (time_stamp
, newtime
);
1580 t
= time ((time_t) 0);
1582 /* Set revision time to now in local time. */
1583 unix_time_to_vms (t
, revtime
);
1586 /* Reopen the file, modify the times and then close. */
1587 fib
.fib$l_acctl
= FIB$M_WRITE
;
1589 = SYS$
QIOW (0, chan
, IO$_ACCESS
|IO$M_ACCESS
, &iosb
, 0, 0,
1590 &fibdsc
, &filedsc
, &result
.length
, &resultdsc
, &atrlst
, 0);
1591 if ((status
& 1) != 1)
1592 LIB$
SIGNAL (status
);
1593 if ((iosb
.status
& 1) != 1)
1594 LIB$
SIGNAL (iosb
.status
);
1596 Fat
.create
= newtime
;
1597 Fat
.revise
= revtime
;
1599 status
= SYS$
QIOW (0, chan
, IO$_DEACCESS
, &iosb
, 0, 0,
1600 &fibdsc
, 0, 0, 0, &atrlst
, 0);
1601 if ((status
& 1) != 1)
1602 LIB$
SIGNAL (status
);
1603 if ((iosb
.status
& 1) != 1)
1604 LIB$
SIGNAL (iosb
.status
);
1606 /* Deassign the channel and exit. */
1607 status
= SYS$
DASSGN (chan
);
1608 if ((status
& 1) != 1)
1609 LIB$
SIGNAL (status
);
1611 struct utimbuf utimbuf
;
1614 /* Set modification time to requested time. */
1615 utimbuf
.modtime
= time_stamp
;
1617 /* Set access time to now in local time. */
1618 t
= time ((time_t) 0);
1619 utimbuf
.actime
= mktime (localtime (&t
));
1621 utime (name
, &utimbuf
);
1625 /* Get the list of installed standard libraries from the
1626 HKEY_LOCAL_MACHINE\SOFTWARE\Ada Core Technologies\GNAT\Standard Libraries
1630 __gnat_get_libraries_from_registry (void)
1632 char *result
= (char *) xmalloc (1);
1636 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (IS_CROSS) \
1640 DWORD name_size
, value_size
;
1647 /* First open the key. */
1648 res
= RegOpenKeyExA (HKEY_LOCAL_MACHINE
, "SOFTWARE", 0, KEY_READ
, ®_key
);
1650 if (res
== ERROR_SUCCESS
)
1651 res
= RegOpenKeyExA (reg_key
, "Ada Core Technologies", 0,
1652 KEY_READ
, ®_key
);
1654 if (res
== ERROR_SUCCESS
)
1655 res
= RegOpenKeyExA (reg_key
, "GNAT", 0, KEY_READ
, ®_key
);
1657 if (res
== ERROR_SUCCESS
)
1658 res
= RegOpenKeyExA (reg_key
, "Standard Libraries", 0, KEY_READ
, ®_key
);
1660 /* If the key exists, read out all the values in it and concatenate them
1662 for (index
= 0; res
== ERROR_SUCCESS
; index
++)
1664 value_size
= name_size
= 256;
1665 res
= RegEnumValueA (reg_key
, index
, name
, &name_size
, 0,
1666 &type
, (LPBYTE
)value
, &value_size
);
1668 if (res
== ERROR_SUCCESS
&& type
== REG_SZ
)
1670 char *old_result
= result
;
1672 result
= (char *) xmalloc (strlen (old_result
) + value_size
+ 2);
1673 strcpy (result
, old_result
);
1674 strcat (result
, value
);
1675 strcat (result
, ";");
1680 /* Remove the trailing ";". */
1682 result
[strlen (result
) - 1] = 0;
1689 __gnat_stat (char *name
, GNAT_STRUCT_STAT
*statbuf
)
1692 WIN32_FILE_ATTRIBUTE_DATA fad
;
1693 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
1697 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
1698 name_len
= _tcslen (wname
);
1700 if (name_len
> GNAT_MAX_PATH_LEN
)
1703 ZeroMemory (statbuf
, sizeof(GNAT_STRUCT_STAT
));
1705 res
= GetFileAttributesEx (wname
, GetFileExInfoStandard
, &fad
);
1708 switch (GetLastError()) {
1709 case ERROR_ACCESS_DENIED
:
1710 case ERROR_SHARING_VIOLATION
:
1711 case ERROR_LOCK_VIOLATION
:
1712 case ERROR_SHARING_BUFFER_EXCEEDED
:
1714 case ERROR_BUFFER_OVERFLOW
:
1715 return ENAMETOOLONG
;
1716 case ERROR_NOT_ENOUGH_MEMORY
:
1722 f2t (&fad
.ftCreationTime
, &statbuf
->st_ctime
);
1723 f2t (&fad
.ftLastWriteTime
, &statbuf
->st_mtime
);
1724 f2t (&fad
.ftLastAccessTime
, &statbuf
->st_atime
);
1726 statbuf
->st_size
= (off_t
)fad
.nFileSizeLow
;
1728 /* We do not have the S_IEXEC attribute, but this is not used on GNAT. */
1729 statbuf
->st_mode
= S_IREAD
;
1731 if (fad
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
1732 statbuf
->st_mode
|= S_IFDIR
;
1734 statbuf
->st_mode
|= S_IFREG
;
1736 if (!(fad
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
))
1737 statbuf
->st_mode
|= S_IWRITE
;
1742 return GNAT_STAT (name
, statbuf
);
1746 /*************************************************************************
1747 ** Check whether a file exists
1748 *************************************************************************/
1751 __gnat_file_exists_attr (char* name
, struct file_attributes
* attr
)
1753 if (attr
->exists
== ATTR_UNSET
) {
1754 __gnat_stat_to_attr (-1, name
, attr
);
1757 return attr
->exists
;
1761 __gnat_file_exists (char *name
)
1763 struct file_attributes attr
;
1764 __gnat_reset_attributes (&attr
);
1765 return __gnat_file_exists_attr (name
, &attr
);
1768 /**********************************************************************
1769 ** Whether name is an absolute path
1770 **********************************************************************/
1773 __gnat_is_absolute_path (char *name
, int length
)
1776 /* On VxWorks systems, an absolute path can be represented (depending on
1777 the host platform) as either /dir/file, or device:/dir/file, or
1778 device:drive_letter:/dir/file. */
1785 for (index
= 0; index
< length
; index
++)
1787 if (name
[index
] == ':' &&
1788 ((name
[index
+ 1] == '/') ||
1789 (isalpha (name
[index
+ 1]) && index
+ 2 <= length
&&
1790 name
[index
+ 2] == '/')))
1793 else if (name
[index
] == '/')
1798 return (length
!= 0) &&
1799 (*name
== '/' || *name
== DIR_SEPARATOR
1801 || (length
> 1 && ISALPHA (name
[0]) && name
[1] == ':')
1808 __gnat_is_regular_file_attr (char* name
, struct file_attributes
* attr
)
1810 if (attr
->regular
== ATTR_UNSET
) {
1811 __gnat_stat_to_attr (-1, name
, attr
);
1814 return attr
->regular
;
1818 __gnat_is_regular_file (char *name
)
1820 struct file_attributes attr
;
1821 __gnat_reset_attributes (&attr
);
1822 return __gnat_is_regular_file_attr (name
, &attr
);
1826 __gnat_is_directory_attr (char* name
, struct file_attributes
* attr
)
1828 if (attr
->directory
== ATTR_UNSET
) {
1829 __gnat_stat_to_attr (-1, name
, attr
);
1832 return attr
->directory
;
1836 __gnat_is_directory (char *name
)
1838 struct file_attributes attr
;
1839 __gnat_reset_attributes (&attr
);
1840 return __gnat_is_directory_attr (name
, &attr
);
1843 #if defined (_WIN32) && !defined (RTX)
1845 /* Returns the same constant as GetDriveType but takes a pathname as
1849 GetDriveTypeFromPath (TCHAR
*wfullpath
)
1851 TCHAR wdrv
[MAX_PATH
];
1852 TCHAR wpath
[MAX_PATH
];
1853 TCHAR wfilename
[MAX_PATH
];
1854 TCHAR wext
[MAX_PATH
];
1856 _tsplitpath (wfullpath
, wdrv
, wpath
, wfilename
, wext
);
1858 if (_tcslen (wdrv
) != 0)
1860 /* we have a drive specified. */
1861 _tcscat (wdrv
, _T("\\"));
1862 return GetDriveType (wdrv
);
1866 /* No drive specified. */
1868 /* Is this a relative path, if so get current drive type. */
1869 if (wpath
[0] != _T('\\') ||
1870 (_tcslen (wpath
) > 2 && wpath
[0] == _T('\\') && wpath
[1] != _T('\\')))
1871 return GetDriveType (NULL
);
1873 UINT result
= GetDriveType (wpath
);
1875 /* Cannot guess the drive type, is this \\.\ ? */
1877 if (result
== DRIVE_NO_ROOT_DIR
&&
1878 _tcslen (wpath
) >= 4 && wpath
[0] == _T('\\') && wpath
[1] == _T('\\')
1879 && wpath
[2] == _T('.') && wpath
[3] == _T('\\'))
1881 if (_tcslen (wpath
) == 4)
1882 _tcscat (wpath
, wfilename
);
1884 LPTSTR p
= &wpath
[4];
1885 LPTSTR b
= _tcschr (p
, _T('\\'));
1888 { /* logical drive \\.\c\dir\file */
1894 _tcscat (p
, _T(":\\"));
1896 return GetDriveType (p
);
1903 /* This MingW section contains code to work with ACL. */
1905 __gnat_check_OWNER_ACL
1907 DWORD CheckAccessDesired
,
1908 GENERIC_MAPPING CheckGenericMapping
)
1910 DWORD dwAccessDesired
, dwAccessAllowed
;
1911 PRIVILEGE_SET PrivilegeSet
;
1912 DWORD dwPrivSetSize
= sizeof (PRIVILEGE_SET
);
1913 BOOL fAccessGranted
= FALSE
;
1914 HANDLE hToken
= NULL
;
1916 SECURITY_DESCRIPTOR
* pSD
= NULL
;
1919 (wname
, OWNER_SECURITY_INFORMATION
|
1920 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
,
1923 if ((pSD
= (PSECURITY_DESCRIPTOR
) HeapAlloc
1924 (GetProcessHeap (), HEAP_ZERO_MEMORY
, nLength
)) == NULL
)
1927 /* Obtain the security descriptor. */
1929 if (!GetFileSecurity
1930 (wname
, OWNER_SECURITY_INFORMATION
|
1931 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
,
1932 pSD
, nLength
, &nLength
))
1935 if (!ImpersonateSelf (SecurityImpersonation
))
1938 if (!OpenThreadToken
1939 (GetCurrentThread(), TOKEN_DUPLICATE
| TOKEN_QUERY
, FALSE
, &hToken
))
1942 /* Undoes the effect of ImpersonateSelf. */
1946 /* We want to test for write permissions. */
1948 dwAccessDesired
= CheckAccessDesired
;
1950 MapGenericMask (&dwAccessDesired
, &CheckGenericMapping
);
1953 (pSD
, /* security descriptor to check */
1954 hToken
, /* impersonation token */
1955 dwAccessDesired
, /* requested access rights */
1956 &CheckGenericMapping
, /* pointer to GENERIC_MAPPING */
1957 &PrivilegeSet
, /* receives privileges used in check */
1958 &dwPrivSetSize
, /* size of PrivilegeSet buffer */
1959 &dwAccessAllowed
, /* receives mask of allowed access rights */
1963 CloseHandle (hToken
);
1964 HeapFree (GetProcessHeap (), 0, pSD
);
1965 return fAccessGranted
;
1969 CloseHandle (hToken
);
1970 HeapFree (GetProcessHeap (), 0, pSD
);
1975 __gnat_set_OWNER_ACL
1978 DWORD AccessPermissions
)
1980 PACL pOldDACL
= NULL
;
1981 PACL pNewDACL
= NULL
;
1982 PSECURITY_DESCRIPTOR pSD
= NULL
;
1984 TCHAR username
[100];
1987 /* Get current user, he will act as the owner */
1989 if (!GetUserName (username
, &unsize
))
1992 if (GetNamedSecurityInfo
1995 DACL_SECURITY_INFORMATION
,
1996 NULL
, NULL
, &pOldDACL
, NULL
, &pSD
) != ERROR_SUCCESS
)
1999 BuildExplicitAccessWithName
2000 (&ea
, username
, AccessPermissions
, AccessMode
, NO_INHERITANCE
);
2002 if (AccessMode
== SET_ACCESS
)
2004 /* SET_ACCESS, we want to set an explicte set of permissions, do not
2005 merge with current DACL. */
2006 if (SetEntriesInAcl (1, &ea
, NULL
, &pNewDACL
) != ERROR_SUCCESS
)
2010 if (SetEntriesInAcl (1, &ea
, pOldDACL
, &pNewDACL
) != ERROR_SUCCESS
)
2013 if (SetNamedSecurityInfo
2014 (wname
, SE_FILE_OBJECT
,
2015 DACL_SECURITY_INFORMATION
, NULL
, NULL
, pNewDACL
, NULL
) != ERROR_SUCCESS
)
2019 LocalFree (pNewDACL
);
2022 /* Check if it is possible to use ACL for wname, the file must not be on a
2026 __gnat_can_use_acl (TCHAR
*wname
)
2028 return __gnat_use_acl
&& GetDriveTypeFromPath (wname
) != DRIVE_REMOTE
;
2031 #endif /* defined (_WIN32) && !defined (RTX) */
2034 __gnat_is_readable_file_attr (char* name
, struct file_attributes
* attr
)
2036 if (attr
->readable
== ATTR_UNSET
) {
2037 #if defined (_WIN32) && !defined (RTX)
2038 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2039 GENERIC_MAPPING GenericMapping
;
2041 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2043 if (__gnat_can_use_acl (wname
))
2045 ZeroMemory (&GenericMapping
, sizeof (GENERIC_MAPPING
));
2046 GenericMapping
.GenericRead
= GENERIC_READ
;
2048 __gnat_check_OWNER_ACL (wname
, FILE_READ_DATA
, GenericMapping
);
2051 attr
->readable
= GetFileAttributes (wname
) != INVALID_FILE_ATTRIBUTES
;
2053 __gnat_stat_to_attr (-1, name
, attr
);
2057 return attr
->readable
;
2061 __gnat_is_readable_file (char *name
)
2063 struct file_attributes attr
;
2064 __gnat_reset_attributes (&attr
);
2065 return __gnat_is_readable_file_attr (name
, &attr
);
2069 __gnat_is_writable_file_attr (char* name
, struct file_attributes
* attr
)
2071 if (attr
->writable
== ATTR_UNSET
) {
2072 #if defined (_WIN32) && !defined (RTX)
2073 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2074 GENERIC_MAPPING GenericMapping
;
2076 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2078 if (__gnat_can_use_acl (wname
))
2080 ZeroMemory (&GenericMapping
, sizeof (GENERIC_MAPPING
));
2081 GenericMapping
.GenericWrite
= GENERIC_WRITE
;
2083 attr
->writable
= __gnat_check_OWNER_ACL
2084 (wname
, FILE_WRITE_DATA
| FILE_APPEND_DATA
, GenericMapping
)
2085 && !(GetFileAttributes (wname
) & FILE_ATTRIBUTE_READONLY
);
2088 attr
->writable
= !(GetFileAttributes (wname
) & FILE_ATTRIBUTE_READONLY
);
2091 __gnat_stat_to_attr (-1, name
, attr
);
2095 return attr
->writable
;
2099 __gnat_is_writable_file (char *name
)
2101 struct file_attributes attr
;
2102 __gnat_reset_attributes (&attr
);
2103 return __gnat_is_writable_file_attr (name
, &attr
);
2107 __gnat_is_executable_file_attr (char* name
, struct file_attributes
* attr
)
2109 if (attr
->executable
== ATTR_UNSET
) {
2110 #if defined (_WIN32) && !defined (RTX)
2111 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2112 GENERIC_MAPPING GenericMapping
;
2114 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2116 if (__gnat_can_use_acl (wname
))
2118 ZeroMemory (&GenericMapping
, sizeof (GENERIC_MAPPING
));
2119 GenericMapping
.GenericExecute
= GENERIC_EXECUTE
;
2122 __gnat_check_OWNER_ACL (wname
, FILE_EXECUTE
, GenericMapping
);
2125 attr
->executable
= GetFileAttributes (wname
) != INVALID_FILE_ATTRIBUTES
2126 && _tcsstr (wname
, _T(".exe")) - wname
== (int) (_tcslen (wname
) - 4);
2128 __gnat_stat_to_attr (-1, name
, attr
);
2132 return attr
->executable
;
2136 __gnat_is_executable_file (char *name
)
2138 struct file_attributes attr
;
2139 __gnat_reset_attributes (&attr
);
2140 return __gnat_is_executable_file_attr (name
, &attr
);
2144 __gnat_set_writable (char *name
)
2146 #if defined (_WIN32) && !defined (RTX)
2147 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2149 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2151 if (__gnat_can_use_acl (wname
))
2152 __gnat_set_OWNER_ACL (wname
, GRANT_ACCESS
, FILE_GENERIC_WRITE
);
2155 (wname
, GetFileAttributes (wname
) & ~FILE_ATTRIBUTE_READONLY
);
2156 #elif ! defined (__vxworks) && ! defined(__nucleus__)
2157 GNAT_STRUCT_STAT statbuf
;
2159 if (GNAT_STAT (name
, &statbuf
) == 0)
2161 statbuf
.st_mode
= statbuf
.st_mode
| S_IWUSR
;
2162 chmod (name
, statbuf
.st_mode
);
2168 __gnat_set_executable (char *name
)
2170 #if defined (_WIN32) && !defined (RTX)
2171 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2173 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2175 if (__gnat_can_use_acl (wname
))
2176 __gnat_set_OWNER_ACL (wname
, GRANT_ACCESS
, FILE_GENERIC_EXECUTE
);
2178 #elif ! defined (__vxworks) && ! defined(__nucleus__)
2179 GNAT_STRUCT_STAT statbuf
;
2181 if (GNAT_STAT (name
, &statbuf
) == 0)
2183 statbuf
.st_mode
= statbuf
.st_mode
| S_IXUSR
;
2184 chmod (name
, statbuf
.st_mode
);
2190 __gnat_set_non_writable (char *name
)
2192 #if defined (_WIN32) && !defined (RTX)
2193 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2195 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2197 if (__gnat_can_use_acl (wname
))
2198 __gnat_set_OWNER_ACL
2199 (wname
, DENY_ACCESS
,
2200 FILE_WRITE_DATA
| FILE_APPEND_DATA
|
2201 FILE_WRITE_EA
| FILE_WRITE_ATTRIBUTES
);
2204 (wname
, GetFileAttributes (wname
) | FILE_ATTRIBUTE_READONLY
);
2205 #elif ! defined (__vxworks) && ! defined(__nucleus__)
2206 GNAT_STRUCT_STAT statbuf
;
2208 if (GNAT_STAT (name
, &statbuf
) == 0)
2210 statbuf
.st_mode
= statbuf
.st_mode
& 07577;
2211 chmod (name
, statbuf
.st_mode
);
2217 __gnat_set_readable (char *name
)
2219 #if defined (_WIN32) && !defined (RTX)
2220 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2222 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2224 if (__gnat_can_use_acl (wname
))
2225 __gnat_set_OWNER_ACL (wname
, GRANT_ACCESS
, FILE_GENERIC_READ
);
2227 #elif ! defined (__vxworks) && ! defined(__nucleus__)
2228 GNAT_STRUCT_STAT statbuf
;
2230 if (GNAT_STAT (name
, &statbuf
) == 0)
2232 chmod (name
, statbuf
.st_mode
| S_IREAD
);
2238 __gnat_set_non_readable (char *name
)
2240 #if defined (_WIN32) && !defined (RTX)
2241 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2243 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2245 if (__gnat_can_use_acl (wname
))
2246 __gnat_set_OWNER_ACL (wname
, DENY_ACCESS
, FILE_GENERIC_READ
);
2248 #elif ! defined (__vxworks) && ! defined(__nucleus__)
2249 GNAT_STRUCT_STAT statbuf
;
2251 if (GNAT_STAT (name
, &statbuf
) == 0)
2253 chmod (name
, statbuf
.st_mode
& (~S_IREAD
));
2259 __gnat_is_symbolic_link_attr (char* name
, struct file_attributes
* attr
)
2261 if (attr
->symbolic_link
== ATTR_UNSET
) {
2262 #if defined (__vxworks) || defined (__nucleus__)
2263 attr
->symbolic_link
= 0;
2265 #elif defined (_AIX) || defined (__APPLE__) || defined (__unix__)
2267 GNAT_STRUCT_STAT statbuf
;
2268 ret
= GNAT_LSTAT (name
, &statbuf
);
2269 attr
->symbolic_link
= (!ret
&& S_ISLNK (statbuf
.st_mode
));
2271 attr
->symbolic_link
= 0;
2274 return attr
->symbolic_link
;
2278 __gnat_is_symbolic_link (char *name ATTRIBUTE_UNUSED
)
2280 struct file_attributes attr
;
2281 __gnat_reset_attributes (&attr
);
2282 return __gnat_is_symbolic_link_attr (name
, &attr
);
2286 #if defined (sun) && defined (__SVR4)
2287 /* Using fork on Solaris will duplicate all the threads. fork1, which
2288 duplicates only the active thread, must be used instead, or spawning
2289 subprocess from a program with tasking will lead into numerous problems. */
2294 __gnat_portable_spawn (char *args
[])
2297 int finished ATTRIBUTE_UNUSED
;
2298 int pid ATTRIBUTE_UNUSED
;
2300 #if defined (__vxworks) || defined(__nucleus__) || defined(RTX)
2303 #elif defined (_WIN32)
2304 /* args[0] must be quotes as it could contain a full pathname with spaces */
2305 char *args_0
= args
[0];
2306 args
[0] = (char *)xmalloc (strlen (args_0
) + 3);
2307 strcpy (args
[0], "\"");
2308 strcat (args
[0], args_0
);
2309 strcat (args
[0], "\"");
2311 status
= spawnvp (P_WAIT
, args_0
, (const char* const*)args
);
2313 /* restore previous value */
2315 args
[0] = (char *)args_0
;
2331 if (execv (args
[0], MAYBE_TO_PTR32 (args
)) != 0)
2333 return -1; /* execv is in parent context on VMS. */
2340 finished
= waitpid (pid
, &status
, 0);
2342 if (finished
!= pid
|| WIFEXITED (status
) == 0)
2345 return WEXITSTATUS (status
);
2351 /* Create a copy of the given file descriptor.
2352 Return -1 if an error occurred. */
2355 __gnat_dup (int oldfd
)
2357 #if defined (__vxworks) && !defined (__RTP__)
2358 /* Not supported on VxWorks 5.x, but supported on VxWorks 6.0 when using
2366 /* Make newfd be the copy of oldfd, closing newfd first if necessary.
2367 Return -1 if an error occurred. */
2370 __gnat_dup2 (int oldfd
, int newfd
)
2372 #if defined (__vxworks) && !defined (__RTP__)
2373 /* Not supported on VxWorks 5.x, but supported on VxWorks 6.0 when using
2377 return dup2 (oldfd
, newfd
);
2382 __gnat_number_of_cpus (void)
2386 #if defined (linux) || defined (sun) || defined (AIX) \
2387 || (defined (__alpha__) && defined (_osf_)) || defined (__APPLE__)
2388 cores
= (int) sysconf (_SC_NPROCESSORS_ONLN
);
2390 #elif (defined (__mips) && defined (__sgi))
2391 cores
= (int) sysconf (_SC_NPROC_ONLN
);
2393 #elif defined (__hpux__)
2394 struct pst_dynamic psd
;
2395 if (pstat_getdynamic (&psd
, sizeof (psd
), 1, 0) != -1)
2396 cores
= (int) psd
.psd_proc_cnt
;
2398 #elif defined (_WIN32)
2399 SYSTEM_INFO sysinfo
;
2400 GetSystemInfo (&sysinfo
);
2401 cores
= (int) sysinfo
.dwNumberOfProcessors
;
2404 int code
= SYI$_ACTIVECPU_CNT
;
2408 status
= LIB$
GETSYI (&code
, &res
);
2409 if ((status
& 1) != 0)
2416 /* WIN32 code to implement a wait call that wait for any child process. */
2418 #if defined (_WIN32) && !defined (RTX)
2420 /* Synchronization code, to be thread safe. */
2424 /* For the Cert run times on native Windows we use dummy functions
2425 for locking and unlocking tasks since we do not support multiple
2426 threads on this configuration (Cert run time on native Windows). */
2428 void dummy (void) {}
2430 void (*Lock_Task
) () = &dummy
;
2431 void (*Unlock_Task
) () = &dummy
;
2435 #define Lock_Task system__soft_links__lock_task
2436 extern void (*Lock_Task
) (void);
2438 #define Unlock_Task system__soft_links__unlock_task
2439 extern void (*Unlock_Task
) (void);
2443 static HANDLE
*HANDLES_LIST
= NULL
;
2444 static int *PID_LIST
= NULL
, plist_length
= 0, plist_max_length
= 0;
2447 add_handle (HANDLE h
, int pid
)
2450 /* -------------------- critical section -------------------- */
2453 if (plist_length
== plist_max_length
)
2455 plist_max_length
+= 1000;
2457 xrealloc (HANDLES_LIST
, sizeof (HANDLE
) * plist_max_length
);
2459 xrealloc (PID_LIST
, sizeof (int) * plist_max_length
);
2462 HANDLES_LIST
[plist_length
] = h
;
2463 PID_LIST
[plist_length
] = pid
;
2467 /* -------------------- critical section -------------------- */
2471 __gnat_win32_remove_handle (HANDLE h
, int pid
)
2475 /* -------------------- critical section -------------------- */
2478 for (j
= 0; j
< plist_length
; j
++)
2480 if ((HANDLES_LIST
[j
] == h
) || (PID_LIST
[j
] == pid
))
2484 HANDLES_LIST
[j
] = HANDLES_LIST
[plist_length
];
2485 PID_LIST
[j
] = PID_LIST
[plist_length
];
2491 /* -------------------- critical section -------------------- */
2495 win32_no_block_spawn (char *command
, char *args
[], HANDLE
*h
, int *pid
)
2499 PROCESS_INFORMATION PI
;
2500 SECURITY_ATTRIBUTES SA
;
2505 /* compute the total command line length */
2509 csize
+= strlen (args
[k
]) + 1;
2513 full_command
= (char *) xmalloc (csize
);
2516 SI
.cb
= sizeof (STARTUPINFO
);
2517 SI
.lpReserved
= NULL
;
2518 SI
.lpReserved2
= NULL
;
2519 SI
.lpDesktop
= NULL
;
2523 SI
.wShowWindow
= SW_HIDE
;
2525 /* Security attributes. */
2526 SA
.nLength
= sizeof (SECURITY_ATTRIBUTES
);
2527 SA
.bInheritHandle
= TRUE
;
2528 SA
.lpSecurityDescriptor
= NULL
;
2530 /* Prepare the command string. */
2531 strcpy (full_command
, command
);
2532 strcat (full_command
, " ");
2537 strcat (full_command
, args
[k
]);
2538 strcat (full_command
, " ");
2543 int wsize
= csize
* 2;
2544 TCHAR
*wcommand
= (TCHAR
*) xmalloc (wsize
);
2546 S2WSC (wcommand
, full_command
, wsize
);
2548 free (full_command
);
2550 result
= CreateProcess
2551 (NULL
, wcommand
, &SA
, NULL
, TRUE
,
2552 GetPriorityClass (GetCurrentProcess()), NULL
, NULL
, &SI
, &PI
);
2559 CloseHandle (PI
.hThread
);
2561 *pid
= PI
.dwProcessId
;
2571 win32_wait (int *status
)
2573 DWORD exitcode
, pid
;
2580 if (plist_length
== 0)
2588 /* -------------------- critical section -------------------- */
2591 hl_len
= plist_length
;
2593 hl
= (HANDLE
*) xmalloc (sizeof (HANDLE
) * hl_len
);
2595 memmove (hl
, HANDLES_LIST
, sizeof (HANDLE
) * hl_len
);
2598 /* -------------------- critical section -------------------- */
2600 res
= WaitForMultipleObjects (hl_len
, hl
, FALSE
, INFINITE
);
2601 h
= hl
[res
- WAIT_OBJECT_0
];
2603 GetExitCodeProcess (h
, &exitcode
);
2604 pid
= PID_LIST
[res
- WAIT_OBJECT_0
];
2605 __gnat_win32_remove_handle (h
, -1);
2609 *status
= (int) exitcode
;
2616 __gnat_portable_no_block_spawn (char *args
[])
2619 #if defined (__vxworks) || defined (__nucleus__) || defined (RTX)
2622 #elif defined (_WIN32)
2627 win32_no_block_spawn (args
[0], args
, &h
, &pid
);
2630 add_handle (h
, pid
);
2643 if (execv (args
[0], MAYBE_TO_PTR32 (args
)) != 0)
2645 return -1; /* execv is in parent context on VMS. */
2657 __gnat_portable_wait (int *process_status
)
2662 #if defined (__vxworks) || defined (__nucleus__) || defined (RTX)
2663 /* Not sure what to do here, so do nothing but return zero. */
2665 #elif defined (_WIN32)
2667 pid
= win32_wait (&status
);
2671 pid
= waitpid (-1, &status
, 0);
2672 status
= status
& 0xffff;
2675 *process_status
= status
;
2680 __gnat_os_exit (int status
)
2685 /* Locate a regular file, give a Path value. */
2688 __gnat_locate_regular_file (char *file_name
, char *path_val
)
2691 char *file_path
= (char *) alloca (strlen (file_name
) + 1);
2694 /* Return immediately if file_name is empty */
2696 if (*file_name
== '\0')
2699 /* Remove quotes around file_name if present */
2705 strcpy (file_path
, ptr
);
2707 ptr
= file_path
+ strlen (file_path
) - 1;
2712 /* Handle absolute pathnames. */
2714 absolute
= __gnat_is_absolute_path (file_path
, strlen (file_name
));
2718 if (__gnat_is_regular_file (file_path
))
2719 return xstrdup (file_path
);
2724 /* If file_name include directory separator(s), try it first as
2725 a path name relative to the current directory */
2726 for (ptr
= file_name
; *ptr
&& *ptr
!= '/' && *ptr
!= DIR_SEPARATOR
; ptr
++)
2731 if (__gnat_is_regular_file (file_name
))
2732 return xstrdup (file_name
);
2739 /* The result has to be smaller than path_val + file_name. */
2741 (char *) alloca (strlen (path_val
) + strlen (file_name
) + 2);
2745 /* Skip the starting quote */
2747 if (*path_val
== '"')
2750 for (ptr
= file_path
; *path_val
&& *path_val
!= PATH_SEPARATOR
; )
2751 *ptr
++ = *path_val
++;
2753 /* If directory is empty, it is the current directory*/
2755 if (ptr
== file_path
)
2762 /* Skip the ending quote */
2767 if (*ptr
!= '/' && *ptr
!= DIR_SEPARATOR
)
2768 *++ptr
= DIR_SEPARATOR
;
2770 strcpy (++ptr
, file_name
);
2772 if (__gnat_is_regular_file (file_path
))
2773 return xstrdup (file_path
);
2778 /* Skip path separator */
2787 /* Locate an executable given a Path argument. This routine is only used by
2788 gnatbl and should not be used otherwise. Use locate_exec_on_path
2792 __gnat_locate_exec (char *exec_name
, char *path_val
)
2795 if (!strstr (exec_name
, HOST_EXECUTABLE_SUFFIX
))
2797 char *full_exec_name
=
2799 (strlen (exec_name
) + strlen (HOST_EXECUTABLE_SUFFIX
) + 1);
2801 strcpy (full_exec_name
, exec_name
);
2802 strcat (full_exec_name
, HOST_EXECUTABLE_SUFFIX
);
2803 ptr
= __gnat_locate_regular_file (full_exec_name
, path_val
);
2806 return __gnat_locate_regular_file (exec_name
, path_val
);
2810 return __gnat_locate_regular_file (exec_name
, path_val
);
2813 /* Locate an executable using the Systems default PATH. */
2816 __gnat_locate_exec_on_path (char *exec_name
)
2820 #if defined (_WIN32) && !defined (RTX)
2821 TCHAR
*wpath_val
= _tgetenv (_T("PATH"));
2823 /* In Win32 systems we expand the PATH as for XP environment
2824 variables are not automatically expanded. We also prepend the
2825 ".;" to the path to match normal NT path search semantics */
2827 #define EXPAND_BUFFER_SIZE 32767
2829 wapath_val
= alloca (EXPAND_BUFFER_SIZE
);
2831 wapath_val
[0] = '.';
2832 wapath_val
[1] = ';';
2834 DWORD res
= ExpandEnvironmentStrings
2835 (wpath_val
, &wapath_val
[2], EXPAND_BUFFER_SIZE
- 2);
2837 if (!res
) wapath_val
[0] = _T('\0');
2839 apath_val
= alloca (EXPAND_BUFFER_SIZE
);
2841 WS2SC (apath_val
, wapath_val
, EXPAND_BUFFER_SIZE
);
2842 return __gnat_locate_exec (exec_name
, apath_val
);
2847 char *path_val
= "/VAXC$PATH";
2849 char *path_val
= getenv ("PATH");
2851 if (path_val
== NULL
) return NULL
;
2852 apath_val
= (char *) alloca (strlen (path_val
) + 1);
2853 strcpy (apath_val
, path_val
);
2854 return __gnat_locate_exec (exec_name
, apath_val
);
2860 /* These functions are used to translate to and from VMS and Unix syntax
2861 file, directory and path specifications. */
2864 #define MAXNAMES 256
2865 #define NEW_CANONICAL_FILELIST_INCREMENT 64
2867 static char new_canonical_dirspec
[MAXPATH
];
2868 static char new_canonical_filespec
[MAXPATH
];
2869 static char new_canonical_pathspec
[MAXNAMES
*MAXPATH
];
2870 static unsigned new_canonical_filelist_index
;
2871 static unsigned new_canonical_filelist_in_use
;
2872 static unsigned new_canonical_filelist_allocated
;
2873 static char **new_canonical_filelist
;
2874 static char new_host_pathspec
[MAXNAMES
*MAXPATH
];
2875 static char new_host_dirspec
[MAXPATH
];
2876 static char new_host_filespec
[MAXPATH
];
2878 /* Routine is called repeatedly by decc$from_vms via
2879 __gnat_to_canonical_file_list_init until it returns 0 or the expansion
2883 wildcard_translate_unix (char *name
)
2886 char buff
[MAXPATH
];
2888 strncpy (buff
, name
, MAXPATH
);
2889 buff
[MAXPATH
- 1] = (char) 0;
2890 ver
= strrchr (buff
, '.');
2892 /* Chop off the version. */
2896 /* Dynamically extend the allocation by the increment. */
2897 if (new_canonical_filelist_in_use
== new_canonical_filelist_allocated
)
2899 new_canonical_filelist_allocated
+= NEW_CANONICAL_FILELIST_INCREMENT
;
2900 new_canonical_filelist
= (char **) xrealloc
2901 (new_canonical_filelist
,
2902 new_canonical_filelist_allocated
* sizeof (char *));
2905 new_canonical_filelist
[new_canonical_filelist_in_use
++] = xstrdup (buff
);
2910 /* Translate a wildcard VMS file spec into a list of Unix file specs. First do
2911 full translation and copy the results into a list (_init), then return them
2912 one at a time (_next). If onlydirs set, only expand directory files. */
2915 __gnat_to_canonical_file_list_init (char *filespec
, int onlydirs
)
2918 char buff
[MAXPATH
];
2920 len
= strlen (filespec
);
2921 strncpy (buff
, filespec
, MAXPATH
);
2923 /* Only look for directories */
2924 if (onlydirs
&& !strstr (&buff
[len
-5], "*.dir"))
2925 strncat (buff
, "*.dir", MAXPATH
);
2927 buff
[MAXPATH
- 1] = (char) 0;
2929 decc$
from_vms (buff
, wildcard_translate_unix
, 1);
2931 /* Remove the .dir extension. */
2937 for (i
= 0; i
< new_canonical_filelist_in_use
; i
++)
2939 ext
= strstr (new_canonical_filelist
[i
], ".dir");
2945 return new_canonical_filelist_in_use
;
2948 /* Return the next filespec in the list. */
2951 __gnat_to_canonical_file_list_next ()
2953 return new_canonical_filelist
[new_canonical_filelist_index
++];
2956 /* Free storage used in the wildcard expansion. */
2959 __gnat_to_canonical_file_list_free ()
2963 for (i
= 0; i
< new_canonical_filelist_in_use
; i
++)
2964 free (new_canonical_filelist
[i
]);
2966 free (new_canonical_filelist
);
2968 new_canonical_filelist_in_use
= 0;
2969 new_canonical_filelist_allocated
= 0;
2970 new_canonical_filelist_index
= 0;
2971 new_canonical_filelist
= 0;
2974 /* The functional equivalent of decc$translate_vms routine.
2975 Designed to produce the same output, but is protected against
2976 malformed paths (original version ACCVIOs in this case) and
2977 does not require VMS-specific DECC RTL */
2979 #define NAM$C_MAXRSS 1024
2982 __gnat_translate_vms (char *src
)
2984 static char retbuf
[NAM$C_MAXRSS
+1];
2985 char *srcendpos
, *pos1
, *pos2
, *retpos
;
2986 int disp
, path_present
= 0;
2988 if (!src
) return NULL
;
2990 srcendpos
= strchr (src
, '\0');
2993 /* Look for the node and/or device in front of the path */
2995 pos2
= strchr (pos1
, ':');
2997 if (pos2
&& (pos2
< srcendpos
) && (*(pos2
+ 1) == ':')) {
2998 /* There is a node name. "node_name::" becomes "node_name!" */
3000 strncpy (retbuf
, pos1
, disp
);
3001 retpos
[disp
] = '!';
3002 retpos
= retpos
+ disp
+ 1;
3004 pos2
= strchr (pos1
, ':');
3008 /* There is a device name. "dev_name:" becomes "/dev_name/" */
3011 strncpy (retpos
, pos1
, disp
);
3012 retpos
= retpos
+ disp
;
3017 /* No explicit device; we must look ahead and prepend /sys$disk/ if
3018 the path is absolute */
3019 if ((*pos1
== '[' || *pos1
== '<') && (pos1
< srcendpos
)
3020 && !strchr (".-]>", *(pos1
+ 1))) {
3021 strncpy (retpos
, "/sys$disk/", 10);
3025 /* Process the path part */
3026 while (*pos1
== '[' || *pos1
== '<') {
3029 if (*pos1
== ']' || *pos1
== '>') {
3030 /* Special case, [] translates to '.' */
3035 /* '[000000' means root dir. It can be present in the middle of
3036 the path due to expansion of logical devices, in which case
3038 if (!strncmp (pos1
, "000000", 6) && path_present
> 1 &&
3039 (*(pos1
+ 6) == ']' || *(pos1
+ 6) == '>' || *(pos1
+ 6) == '.')) {
3041 if (*pos1
== '.') pos1
++;
3043 else if (*pos1
== '.') {
3048 /* There is a qualified path */
3049 while (*pos1
&& *pos1
!= ']' && *pos1
!= '>') {
3052 /* '.' is used to separate directories. Replace it with '/' but
3053 only if there isn't already '/' just before */
3054 if (*(retpos
- 1) != '/') *(retpos
++) = '/';
3056 if (pos1
+ 1 < srcendpos
&& *pos1
== '.' && *(pos1
+ 1) == '.') {
3057 /* ellipsis refers to entire subtree; replace with '**' */
3058 *(retpos
++) = '*'; *(retpos
++) = '*'; *(retpos
++) = '/';
3063 /* When after '.' '[' '<' is equivalent to Unix ".." but there
3064 may be several in a row */
3065 if (*(pos1
- 1) == '.' || *(pos1
- 1) == '[' ||
3066 *(pos1
- 1) == '<') {
3067 while (*pos1
== '-') {
3069 *(retpos
++) = '.'; *(retpos
++) = '.'; *(retpos
++) = '/';
3074 /* otherwise fall through to default */
3076 *(retpos
++) = *(pos1
++);
3083 if (pos1
< srcendpos
) {
3084 /* Now add the actual file name, until the version suffix if any */
3085 if (path_present
) *(retpos
++) = '/';
3086 pos2
= strchr (pos1
, ';');
3087 disp
= pos2
? (pos2
- pos1
) : (srcendpos
- pos1
);
3088 strncpy (retpos
, pos1
, disp
);
3090 if (pos2
&& pos2
< srcendpos
) {
3091 /* There is a non-empty version suffix. ";<ver>" becomes ".<ver>" */
3093 disp
= srcendpos
- pos2
- 1;
3094 strncpy (retpos
, pos2
+ 1, disp
);
3105 /* Translate a VMS syntax directory specification in to Unix syntax. If
3106 PREFIXFLAG is set, append an underscore "/". If no indicators of VMS syntax
3107 found, return input string. Also translate a dirname that contains no
3108 slashes, in case it's a logical name. */
3111 __gnat_to_canonical_dir_spec (char *dirspec
, int prefixflag
)
3115 strcpy (new_canonical_dirspec
, "");
3116 if (strlen (dirspec
))
3120 if (strchr (dirspec
, ']') || strchr (dirspec
, ':'))
3122 strncpy (new_canonical_dirspec
,
3123 __gnat_translate_vms (dirspec
),
3126 else if (!strchr (dirspec
, '/') && (dirspec1
= getenv (dirspec
)) != 0)
3128 strncpy (new_canonical_dirspec
,
3129 __gnat_translate_vms (dirspec1
),
3134 strncpy (new_canonical_dirspec
, dirspec
, MAXPATH
);
3138 len
= strlen (new_canonical_dirspec
);
3139 if (prefixflag
&& new_canonical_dirspec
[len
-1] != '/')
3140 strncat (new_canonical_dirspec
, "/", MAXPATH
);
3142 new_canonical_dirspec
[MAXPATH
- 1] = (char) 0;
3144 return new_canonical_dirspec
;
3148 /* Translate a VMS syntax file specification into Unix syntax.
3149 If no indicators of VMS syntax found, check if it's an uppercase
3150 alphanumeric_ name and if so try it out as an environment
3151 variable (logical name). If all else fails return the
3155 __gnat_to_canonical_file_spec (char *filespec
)
3159 strncpy (new_canonical_filespec
, "", MAXPATH
);
3161 if (strchr (filespec
, ']') || strchr (filespec
, ':'))
3163 char *tspec
= (char *) __gnat_translate_vms (filespec
);
3165 if (tspec
!= (char *) -1)
3166 strncpy (new_canonical_filespec
, tspec
, MAXPATH
);
3168 else if ((strlen (filespec
) == strspn (filespec
,
3169 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"))
3170 && (filespec1
= getenv (filespec
)))
3172 char *tspec
= (char *) __gnat_translate_vms (filespec1
);
3174 if (tspec
!= (char *) -1)
3175 strncpy (new_canonical_filespec
, tspec
, MAXPATH
);
3179 strncpy (new_canonical_filespec
, filespec
, MAXPATH
);
3182 new_canonical_filespec
[MAXPATH
- 1] = (char) 0;
3184 return new_canonical_filespec
;
3187 /* Translate a VMS syntax path specification into Unix syntax.
3188 If no indicators of VMS syntax found, return input string. */
3191 __gnat_to_canonical_path_spec (char *pathspec
)
3193 char *curr
, *next
, buff
[MAXPATH
];
3198 /* If there are /'s, assume it's a Unix path spec and return. */
3199 if (strchr (pathspec
, '/'))
3202 new_canonical_pathspec
[0] = 0;
3207 next
= strchr (curr
, ',');
3209 next
= strchr (curr
, 0);
3211 strncpy (buff
, curr
, next
- curr
);
3212 buff
[next
- curr
] = 0;
3214 /* Check for wildcards and expand if present. */
3215 if (strchr (buff
, '*') || strchr (buff
, '%') || strstr (buff
, "..."))
3219 dirs
= __gnat_to_canonical_file_list_init (buff
, 1);
3220 for (i
= 0; i
< dirs
; i
++)
3224 next_dir
= __gnat_to_canonical_file_list_next ();
3225 strncat (new_canonical_pathspec
, next_dir
, MAXPATH
);
3227 /* Don't append the separator after the last expansion. */
3229 strncat (new_canonical_pathspec
, ":", MAXPATH
);
3232 __gnat_to_canonical_file_list_free ();
3235 strncat (new_canonical_pathspec
,
3236 __gnat_to_canonical_dir_spec (buff
, 0), MAXPATH
);
3241 strncat (new_canonical_pathspec
, ":", MAXPATH
);
3245 new_canonical_pathspec
[MAXPATH
- 1] = (char) 0;
3247 return new_canonical_pathspec
;
3250 static char filename_buff
[MAXPATH
];
3253 translate_unix (char *name
, int type
)
3255 strncpy (filename_buff
, name
, MAXPATH
);
3256 filename_buff
[MAXPATH
- 1] = (char) 0;
3260 /* Translate a Unix syntax path spec into a VMS style (comma separated list of
3264 to_host_path_spec (char *pathspec
)
3266 char *curr
, *next
, buff
[MAXPATH
];
3271 /* Can't very well test for colons, since that's the Unix separator! */
3272 if (strchr (pathspec
, ']') || strchr (pathspec
, ','))
3275 new_host_pathspec
[0] = 0;
3280 next
= strchr (curr
, ':');
3282 next
= strchr (curr
, 0);
3284 strncpy (buff
, curr
, next
- curr
);
3285 buff
[next
- curr
] = 0;
3287 strncat (new_host_pathspec
, __gnat_to_host_dir_spec (buff
, 0), MAXPATH
);
3290 strncat (new_host_pathspec
, ",", MAXPATH
);
3294 new_host_pathspec
[MAXPATH
- 1] = (char) 0;
3296 return new_host_pathspec
;
3299 /* Translate a Unix syntax directory specification into VMS syntax. The
3300 PREFIXFLAG has no effect, but is kept for symmetry with
3301 to_canonical_dir_spec. If indicators of VMS syntax found, return input
3305 __gnat_to_host_dir_spec (char *dirspec
, int prefixflag ATTRIBUTE_UNUSED
)
3307 int len
= strlen (dirspec
);
3309 strncpy (new_host_dirspec
, dirspec
, MAXPATH
);
3310 new_host_dirspec
[MAXPATH
- 1] = (char) 0;
3312 if (strchr (new_host_dirspec
, ']') || strchr (new_host_dirspec
, ':'))
3313 return new_host_dirspec
;
3315 while (len
> 1 && new_host_dirspec
[len
- 1] == '/')
3317 new_host_dirspec
[len
- 1] = 0;
3321 decc$
to_vms (new_host_dirspec
, translate_unix
, 1, 2);
3322 strncpy (new_host_dirspec
, filename_buff
, MAXPATH
);
3323 new_host_dirspec
[MAXPATH
- 1] = (char) 0;
3325 return new_host_dirspec
;
3328 /* Translate a Unix syntax file specification into VMS syntax.
3329 If indicators of VMS syntax found, return input string. */
3332 __gnat_to_host_file_spec (char *filespec
)
3334 strncpy (new_host_filespec
, "", MAXPATH
);
3335 if (strchr (filespec
, ']') || strchr (filespec
, ':'))
3337 strncpy (new_host_filespec
, filespec
, MAXPATH
);
3341 decc$
to_vms (filespec
, translate_unix
, 1, 1);
3342 strncpy (new_host_filespec
, filename_buff
, MAXPATH
);
3345 new_host_filespec
[MAXPATH
- 1] = (char) 0;
3347 return new_host_filespec
;
3351 __gnat_adjust_os_resource_limits ()
3353 SYS$
ADJWSL (131072, 0);
3358 /* Dummy functions for Osint import for non-VMS systems. */
3361 __gnat_to_canonical_file_list_init
3362 (char *dirspec ATTRIBUTE_UNUSED
, int onlydirs ATTRIBUTE_UNUSED
)
3368 __gnat_to_canonical_file_list_next (void)
3370 static char *empty
= "";
3375 __gnat_to_canonical_file_list_free (void)
3380 __gnat_to_canonical_dir_spec (char *dirspec
, int prefixflag ATTRIBUTE_UNUSED
)
3386 __gnat_to_canonical_file_spec (char *filespec
)
3392 __gnat_to_canonical_path_spec (char *pathspec
)
3398 __gnat_to_host_dir_spec (char *dirspec
, int prefixflag ATTRIBUTE_UNUSED
)
3404 __gnat_to_host_file_spec (char *filespec
)
3410 __gnat_adjust_os_resource_limits (void)
3416 #if defined (__mips_vxworks)
3420 CACHE_USER_FLUSH (0, ENTIRE_CACHE
);
3424 #if defined (IS_CROSS) \
3425 || (! ((defined (sparc) || defined (i386)) && defined (sun) \
3426 && defined (__SVR4)) \
3427 && ! (defined (linux) && (defined (i386) || defined (__x86_64__))) \
3428 && ! (defined (linux) && defined (__ia64__)) \
3429 && ! (defined (linux) && defined (powerpc)) \
3430 && ! defined (__FreeBSD__) \
3431 && ! defined (__Lynx__) \
3432 && ! defined (__hpux__) \
3433 && ! defined (__APPLE__) \
3434 && ! defined (_AIX) \
3435 && ! (defined (__alpha__) && defined (__osf__)) \
3436 && ! defined (VMS) \
3437 && ! defined (__MINGW32__) \
3438 && ! (defined (__mips) && defined (__sgi)))
3440 /* Dummy function to satisfy g-trasym.o. See the preprocessor conditional
3441 just above for a list of native platforms that provide a non-dummy
3442 version of this procedure in libaddr2line.a. */
3445 convert_addresses (const char *file_name ATTRIBUTE_UNUSED
,
3446 void *addrs ATTRIBUTE_UNUSED
,
3447 int n_addr ATTRIBUTE_UNUSED
,
3448 void *buf ATTRIBUTE_UNUSED
,
3449 int *len ATTRIBUTE_UNUSED
)
3455 #if defined (_WIN32)
3456 int __gnat_argument_needs_quote
= 1;
3458 int __gnat_argument_needs_quote
= 0;
3461 /* This option is used to enable/disable object files handling from the
3462 binder file by the GNAT Project module. For example, this is disabled on
3463 Windows (prior to GCC 3.4) as it is already done by the mdll module.
3464 Stating with GCC 3.4 the shared libraries are not based on mdll
3465 anymore as it uses the GCC's -shared option */
3466 #if defined (_WIN32) \
3467 && ((__GNUC__ < 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ < 4)))
3468 int __gnat_prj_add_obj_files
= 0;
3470 int __gnat_prj_add_obj_files
= 1;
3473 /* char used as prefix/suffix for environment variables */
3474 #if defined (_WIN32)
3475 char __gnat_environment_char
= '%';
3477 char __gnat_environment_char
= '$';
3480 /* This functions copy the file attributes from a source file to a
3483 mode = 0 : In this mode copy only the file time stamps (last access and
3484 last modification time stamps).
3486 mode = 1 : In this mode, time stamps and read/write/execute attributes are
3489 Returns 0 if operation was successful and -1 in case of error. */
3492 __gnat_copy_attribs (char *from
, char *to
, int mode
)
3494 #if defined (VMS) || defined (__vxworks) || defined (__nucleus__)
3497 #elif defined (_WIN32) && !defined (RTX)
3498 TCHAR wfrom
[GNAT_MAX_PATH_LEN
+ 2];
3499 TCHAR wto
[GNAT_MAX_PATH_LEN
+ 2];
3501 FILETIME fct
, flat
, flwt
;
3504 S2WSC (wfrom
, from
, GNAT_MAX_PATH_LEN
+ 2);
3505 S2WSC (wto
, to
, GNAT_MAX_PATH_LEN
+ 2);
3507 /* retrieve from times */
3510 (wfrom
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3512 if (hfrom
== INVALID_HANDLE_VALUE
)
3515 res
= GetFileTime (hfrom
, &fct
, &flat
, &flwt
);
3517 CloseHandle (hfrom
);
3522 /* retrieve from times */
3525 (wto
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3527 if (hto
== INVALID_HANDLE_VALUE
)
3530 res
= SetFileTime (hto
, NULL
, &flat
, &flwt
);
3537 /* Set file attributes in full mode. */
3541 DWORD attribs
= GetFileAttributes (wfrom
);
3543 if (attribs
== INVALID_FILE_ATTRIBUTES
)
3546 res
= SetFileAttributes (wto
, attribs
);
3554 GNAT_STRUCT_STAT fbuf
;
3555 struct utimbuf tbuf
;
3557 if (GNAT_STAT (from
, &fbuf
) == -1)
3562 tbuf
.actime
= fbuf
.st_atime
;
3563 tbuf
.modtime
= fbuf
.st_mtime
;
3565 if (utime (to
, &tbuf
) == -1)
3572 if (chmod (to
, fbuf
.st_mode
) == -1)
3583 __gnat_lseek (int fd
, long offset
, int whence
)
3585 return (int) lseek (fd
, offset
, whence
);
3588 /* This function returns the major version number of GCC being used. */
3590 get_gcc_version (void)
3595 return (int) (version_string
[0] - '0');
3600 __gnat_set_close_on_exec (int fd ATTRIBUTE_UNUSED
,
3601 int close_on_exec_p ATTRIBUTE_UNUSED
)
3603 #if defined (F_GETFD) && defined (FD_CLOEXEC) && ! defined (__vxworks)
3604 int flags
= fcntl (fd
, F_GETFD
, 0);
3607 if (close_on_exec_p
)
3608 flags
|= FD_CLOEXEC
;
3610 flags
&= ~FD_CLOEXEC
;
3611 return fcntl (fd
, F_SETFD
, flags
| FD_CLOEXEC
);
3612 #elif defined(_WIN32)
3613 HANDLE h
= (HANDLE
) _get_osfhandle (fd
);
3614 if (h
== (HANDLE
) -1)
3616 if (close_on_exec_p
)
3617 return ! SetHandleInformation (h
, HANDLE_FLAG_INHERIT
, 0);
3618 return ! SetHandleInformation (h
, HANDLE_FLAG_INHERIT
,
3619 HANDLE_FLAG_INHERIT
);
3621 /* TODO: Unimplemented. */
3626 /* Indicates if platforms supports automatic initialization through the
3627 constructor mechanism */
3629 __gnat_binder_supports_auto_init (void)
3638 /* Indicates that Stand-Alone Libraries are automatically initialized through
3639 the constructor mechanism */
3641 __gnat_sals_init_using_constructors (void)
3643 #if defined (__vxworks) || defined (__Lynx__) || defined (VMS)
3652 /* In RTX mode, the procedure to get the time (as file time) is different
3653 in RTSS mode and Win32 mode. In order to avoid duplicating an Ada file,
3654 we introduce an intermediate procedure to link against the corresponding
3655 one in each situation. */
3657 extern void GetTimeAsFileTime(LPFILETIME pTime
);
3659 void GetTimeAsFileTime(LPFILETIME pTime
)
3662 RtGetRtssTimeAsFileTime (pTime
); /* RTSS interface */
3664 GetSystemTimeAsFileTime (pTime
); /* w32 interface */
3669 /* Add symbol that is required to link. It would otherwise be taken from
3670 libgcc.a and it would try to use the gcc constructors that are not
3671 supported by Microsoft linker. */
3673 extern void __main (void);
3675 void __main (void) {}
3680 /* There is no function in the glibc to retrieve the LWP of the current
3681 thread. We need to do a system call in order to retrieve this
3683 #include <sys/syscall.h>
3684 void *__gnat_lwp_self (void)
3686 return (void *) syscall (__NR_gettid
);