1 /****************************************************************************
3 * GNAT COMPILER COMPONENTS *
7 * C Implementation File *
9 * Copyright (C) 1992-2011, 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. */
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 */
56 #if (defined (__mips) && defined (__sgi)) || defined (__APPLE__)
60 #if defined (__hpux__)
61 #include <sys/param.h>
62 #include <sys/pstat.h>
67 #define HOST_EXECUTABLE_SUFFIX ".exe"
68 #define HOST_OBJECT_SUFFIX ".obj"
82 /* We don't have libiberty, so use malloc. */
83 #define xmalloc(S) malloc (S)
84 #define xrealloc(V,S) realloc (V,S)
91 #if defined (__MINGW32__)
99 /* Current code page to use, set in initialize.c. */
100 UINT CurrentCodePage
;
103 #include <sys/utime.h>
105 /* For isalpha-like tests in the compiler, we're expected to resort to
106 safe-ctype.h/ISALPHA. This isn't available for the runtime library
107 build, so we fallback on ctype.h/isalpha there. */
111 #define ISALPHA isalpha
114 #elif defined (__Lynx__)
116 /* Lynx utime.h only defines the entities of interest to us if
117 defined (VMOS_DEV), so ... */
126 /* wait.h processing */
129 #include <sys/wait.h>
131 #elif defined (__vxworks) && defined (__RTP__)
133 #elif defined (__Lynx__)
134 /* ??? We really need wait.h and it includes resource.h on Lynx. GCC
135 has a resource.h header as well, included instead of the lynx
136 version in our setup, causing lots of errors. We don't really need
137 the lynx contents of this file, so just workaround the issue by
138 preventing the inclusion of the GCC header from doing anything. */
139 #define GCC_RESOURCE_H
140 #include <sys/wait.h>
141 #elif defined (__nucleus__)
142 /* No wait() or waitpid() calls available */
145 #include <sys/wait.h>
151 /* Header files and definitions for __gnat_set_file_time_name. */
153 #define __NEW_STARLET 1
155 #include <vms/atrdef.h>
156 #include <vms/fibdef.h>
157 #include <vms/stsdef.h>
158 #include <vms/iodef.h>
160 #include <vms/descrip.h>
164 /* Use native 64-bit arithmetic. */
165 #define unix_time_to_vms(X,Y) \
166 { unsigned long long reftime, tmptime = (X); \
167 $DESCRIPTOR (unixtime,"1-JAN-1970 0:00:00.00"); \
168 SYS$BINTIM (&unixtime, &reftime); \
169 Y = tmptime * 10000000 + reftime; }
171 /* descrip.h doesn't have everything ... */
172 typedef struct fibdef
* __fibdef_ptr32
__attribute__ (( mode (SI
) ));
173 struct dsc$descriptor_fib
175 unsigned int fib$l_len
;
176 __fibdef_ptr32 fib$l_addr
;
179 /* I/O Status Block. */
182 unsigned short status
, count
;
186 static char *tryfile
;
188 /* Variable length string. */
192 char string
[NAM$C_MAXRSS
+1];
195 #define SYI$_ACTIVECPU_CNT 0x111e
196 extern int LIB$
GETSYI (int *, unsigned int *);
213 #define DIR_SEPARATOR '\\'
218 /* Define symbols O_BINARY and O_TEXT as harmless zeroes if they are not
219 defined in the current system. On DOS-like systems these flags control
220 whether the file is opened/created in text-translation mode (CR/LF in
221 external file mapped to LF in internal file), but in Unix-like systems,
222 no text translation is required, so these flags have no effect. */
232 #ifndef HOST_EXECUTABLE_SUFFIX
233 #define HOST_EXECUTABLE_SUFFIX ""
236 #ifndef HOST_OBJECT_SUFFIX
237 #define HOST_OBJECT_SUFFIX ".o"
240 #ifndef PATH_SEPARATOR
241 #define PATH_SEPARATOR ':'
244 #ifndef DIR_SEPARATOR
245 #define DIR_SEPARATOR '/'
248 /* Check for cross-compilation */
249 #if defined (CROSS_COMPILE) || defined (CROSS_DIRECTORY_STRUCTURE)
251 int __gnat_is_cross_compiler
= 1;
254 int __gnat_is_cross_compiler
= 0;
257 char __gnat_dir_separator
= DIR_SEPARATOR
;
259 char __gnat_path_separator
= PATH_SEPARATOR
;
261 /* The GNAT_LIBRARY_TEMPLATE contains a list of expressions that define
262 the base filenames that libraries specified with -lsomelib options
263 may have. This is used by GNATMAKE to check whether an executable
264 is up-to-date or not. The syntax is
266 library_template ::= { pattern ; } pattern NUL
267 pattern ::= [ prefix ] * [ postfix ]
269 These should only specify names of static libraries as it makes
270 no sense to determine at link time if dynamic-link libraries are
271 up to date or not. Any libraries that are not found are supposed
274 * if they are needed but not present, the link
277 * otherwise they are libraries in the system paths and so
278 they are considered part of the system and not checked
281 ??? This should be part of a GNAT host-specific compiler
282 file instead of being included in all user applications
283 as well. This is only a temporary work-around for 3.11b. */
285 #ifndef GNAT_LIBRARY_TEMPLATE
287 #define GNAT_LIBRARY_TEMPLATE "*.olb"
289 #define GNAT_LIBRARY_TEMPLATE "lib*.a"
293 const char *__gnat_library_template
= GNAT_LIBRARY_TEMPLATE
;
295 /* This variable is used in hostparm.ads to say whether the host is a VMS
304 #define GNAT_MAX_PATH_LEN 256 /* PATH_MAX */
306 #elif defined (__vxworks) || defined (__OPENNT) || defined(__nucleus__)
307 #define GNAT_MAX_PATH_LEN PATH_MAX
311 #if defined (__MINGW32__)
315 #include <sys/param.h>
319 #include <sys/param.h>
323 #define GNAT_MAX_PATH_LEN MAXPATHLEN
325 #define GNAT_MAX_PATH_LEN 256
330 /* Used for Ada bindings */
331 int __gnat_size_of_file_attributes
= sizeof (struct file_attributes
);
333 /* Reset the file attributes as if no system call had been performed */
334 void __gnat_stat_to_attr (int fd
, char* name
, struct file_attributes
* attr
);
336 /* The __gnat_max_path_len variable is used to export the maximum
337 length of a path name to Ada code. max_path_len is also provided
338 for compatibility with older GNAT versions, please do not use
341 int __gnat_max_path_len
= GNAT_MAX_PATH_LEN
;
342 int max_path_len
= GNAT_MAX_PATH_LEN
;
344 /* Control whether we can use ACL on Windows. */
346 int __gnat_use_acl
= 1;
348 /* The following macro HAVE_READDIR_R should be defined if the
349 system provides the routine readdir_r. */
350 #undef HAVE_READDIR_R
352 #if defined(VMS) && defined (__LONG_POINTERS)
354 /* Return a 32 bit pointer to an array of 32 bit pointers
355 given a 64 bit pointer to an array of 64 bit pointers */
357 typedef __char_ptr32
*__char_ptr_char_ptr32
__attribute__ ((mode (SI
)));
359 static __char_ptr_char_ptr32
360 to_ptr32 (char **ptr64
)
363 __char_ptr_char_ptr32 short_argv
;
365 for (argc
=0; ptr64
[argc
]; argc
++);
367 /* Reallocate argv with 32 bit pointers. */
368 short_argv
= (__char_ptr_char_ptr32
) decc$malloc
369 (sizeof (__char_ptr32
) * (argc
+ 1));
371 for (argc
=0; ptr64
[argc
]; argc
++)
372 short_argv
[argc
] = (__char_ptr32
) decc$
strdup (ptr64
[argc
]);
374 short_argv
[argc
] = (__char_ptr32
) 0;
378 #define MAYBE_TO_PTR32(argv) to_ptr32 (argv)
380 #define MAYBE_TO_PTR32(argv) argv
383 static const char ATTR_UNSET
= 127;
386 __gnat_reset_attributes
387 (struct file_attributes
* attr
)
389 attr
->exists
= ATTR_UNSET
;
391 attr
->writable
= ATTR_UNSET
;
392 attr
->readable
= ATTR_UNSET
;
393 attr
->executable
= ATTR_UNSET
;
395 attr
->regular
= ATTR_UNSET
;
396 attr
->symbolic_link
= ATTR_UNSET
;
397 attr
->directory
= ATTR_UNSET
;
399 attr
->timestamp
= (OS_Time
)-2;
400 attr
->file_length
= -1;
407 time_t res
= time (NULL
);
408 return (OS_Time
) res
;
411 /* Return the current local time as a string in the ISO 8601 format of
412 "YYYY-MM-DD HH:MM:SS.SS". The returned string is 22 + 1 (NULL) characters
416 __gnat_current_time_string
419 const char *format
= "%Y-%m-%d %H:%M:%S";
420 /* Format string necessary to describe the ISO 8601 format */
422 const time_t t_val
= time (NULL
);
424 strftime (result
, 22, format
, localtime (&t_val
));
425 /* Convert the local time into a string following the ISO format, copying
426 at most 22 characters into the result string. */
431 /* The sub-seconds are manually set to zero since type time_t lacks the
432 precision necessary for nanoseconds. */
446 time_t time
= (time_t) *p_time
;
449 /* On Windows systems, the time is sometimes rounded up to the nearest
450 even second, so if the number of seconds is odd, increment it. */
456 res
= localtime (&time
);
458 res
= gmtime (&time
);
463 *p_year
= res
->tm_year
;
464 *p_month
= res
->tm_mon
;
465 *p_day
= res
->tm_mday
;
466 *p_hours
= res
->tm_hour
;
467 *p_mins
= res
->tm_min
;
468 *p_secs
= res
->tm_sec
;
471 *p_year
= *p_month
= *p_day
= *p_hours
= *p_mins
= *p_secs
= 0;
474 /* Place the contents of the symbolic link named PATH in the buffer BUF,
475 which has size BUFSIZ. If PATH is a symbolic link, then return the number
476 of characters of its content in BUF. Otherwise, return -1.
477 For systems not supporting symbolic links, always return -1. */
480 __gnat_readlink (char *path ATTRIBUTE_UNUSED
,
481 char *buf ATTRIBUTE_UNUSED
,
482 size_t bufsiz ATTRIBUTE_UNUSED
)
484 #if defined (_WIN32) || defined (VMS) \
485 || defined(__vxworks) || defined (__nucleus__)
488 return readlink (path
, buf
, bufsiz
);
492 /* Creates a symbolic link named NEWPATH which contains the string OLDPATH.
493 If NEWPATH exists it will NOT be overwritten.
494 For systems not supporting symbolic links, always return -1. */
497 __gnat_symlink (char *oldpath ATTRIBUTE_UNUSED
,
498 char *newpath ATTRIBUTE_UNUSED
)
500 #if defined (_WIN32) || defined (VMS) \
501 || defined(__vxworks) || defined (__nucleus__)
504 return symlink (oldpath
, newpath
);
508 /* Try to lock a file, return 1 if success. */
510 #if defined (__vxworks) || defined (__nucleus__) \
511 || defined (_WIN32) || defined (VMS)
513 /* Version that does not use link. */
516 __gnat_try_lock (char *dir
, char *file
)
520 TCHAR wfull_path
[GNAT_MAX_PATH_LEN
];
521 TCHAR wfile
[GNAT_MAX_PATH_LEN
];
522 TCHAR wdir
[GNAT_MAX_PATH_LEN
];
524 S2WSC (wdir
, dir
, GNAT_MAX_PATH_LEN
);
525 S2WSC (wfile
, file
, GNAT_MAX_PATH_LEN
);
527 _stprintf (wfull_path
, _T("%s%c%s"), wdir
, _T(DIR_SEPARATOR
), wfile
);
528 fd
= _topen (wfull_path
, O_CREAT
| O_EXCL
, 0600);
532 sprintf (full_path
, "%s%c%s", dir
, DIR_SEPARATOR
, file
);
533 fd
= open (full_path
, O_CREAT
| O_EXCL
, 0600);
545 /* Version using link(), more secure over NFS. */
546 /* See TN 6913-016 for discussion ??? */
549 __gnat_try_lock (char *dir
, char *file
)
553 GNAT_STRUCT_STAT stat_result
;
556 sprintf (full_path
, "%s%c%s", dir
, DIR_SEPARATOR
, file
);
557 sprintf (temp_file
, "%s%cTMP-%ld-%ld",
558 dir
, DIR_SEPARATOR
, (long)getpid(), (long)getppid ());
560 /* Create the temporary file and write the process number. */
561 fd
= open (temp_file
, O_CREAT
| O_WRONLY
, 0600);
567 /* Link it with the new file. */
568 link (temp_file
, full_path
);
570 /* Count the references on the old one. If we have a count of two, then
571 the link did succeed. Remove the temporary file before returning. */
572 __gnat_stat (temp_file
, &stat_result
);
574 return stat_result
.st_nlink
== 2;
578 /* Return the maximum file name length. */
581 __gnat_get_maximum_file_name_length (void)
584 if (getenv ("GNAT$EXTENDED_FILE_SPECIFICATIONS"))
593 /* Return nonzero if file names are case sensitive. */
596 __gnat_get_file_names_case_sensitive (void)
598 const char *sensitive
= getenv ("GNAT_FILE_NAME_CASE_SENSITIVE");
600 if (sensitive
!= NULL
601 && (sensitive
[0] == '0' || sensitive
[0] == '1')
602 && sensitive
[1] == '\0')
603 return sensitive
[0] - '0';
605 #if defined (VMS) || defined (WINNT) || defined (__APPLE__)
612 /* Return nonzero if environment variables are case sensitive. */
615 __gnat_get_env_vars_case_sensitive (void)
617 #if defined (VMS) || defined (WINNT)
625 __gnat_get_default_identifier_character_set (void)
630 /* Return the current working directory. */
633 __gnat_get_current_dir (char *dir
, int *length
)
635 #if defined (__MINGW32__)
636 TCHAR wdir
[GNAT_MAX_PATH_LEN
];
638 _tgetcwd (wdir
, *length
);
640 WS2SC (dir
, wdir
, GNAT_MAX_PATH_LEN
);
643 /* Force Unix style, which is what GNAT uses internally. */
644 getcwd (dir
, *length
, 0);
646 getcwd (dir
, *length
);
649 *length
= strlen (dir
);
651 if (dir
[*length
- 1] != DIR_SEPARATOR
)
653 dir
[*length
] = DIR_SEPARATOR
;
659 /* Return the suffix for object files. */
662 __gnat_get_object_suffix_ptr (int *len
, const char **value
)
664 *value
= HOST_OBJECT_SUFFIX
;
669 *len
= strlen (*value
);
674 /* Return the suffix for executable files. */
677 __gnat_get_executable_suffix_ptr (int *len
, const char **value
)
679 *value
= HOST_EXECUTABLE_SUFFIX
;
683 *len
= strlen (*value
);
688 /* Return the suffix for debuggable files. Usually this is the same as the
689 executable extension. */
692 __gnat_get_debuggable_suffix_ptr (int *len
, const char **value
)
694 *value
= HOST_EXECUTABLE_SUFFIX
;
699 *len
= strlen (*value
);
704 /* Returns the OS filename and corresponding encoding. */
707 __gnat_os_filename (char *filename ATTRIBUTE_UNUSED
,
708 char *w_filename ATTRIBUTE_UNUSED
,
709 char *os_name
, int *o_length
,
710 char *encoding ATTRIBUTE_UNUSED
, int *e_length
)
712 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (IS_CROSS)
713 WS2SC (os_name
, (TCHAR
*)w_filename
, (DWORD
)*o_length
);
714 *o_length
= strlen (os_name
);
715 strcpy (encoding
, "encoding=utf8");
716 *e_length
= strlen (encoding
);
718 strcpy (os_name
, filename
);
719 *o_length
= strlen (filename
);
727 __gnat_unlink (char *path
)
729 #if defined (__MINGW32__) && ! defined (__vxworks) && ! defined (IS_CROSS)
731 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
733 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
734 return _tunlink (wpath
);
737 return unlink (path
);
744 __gnat_rename (char *from
, char *to
)
746 #if defined (__MINGW32__) && ! defined (__vxworks) && ! defined (IS_CROSS)
748 TCHAR wfrom
[GNAT_MAX_PATH_LEN
], wto
[GNAT_MAX_PATH_LEN
];
750 S2WSC (wfrom
, from
, GNAT_MAX_PATH_LEN
);
751 S2WSC (wto
, to
, GNAT_MAX_PATH_LEN
);
752 return _trename (wfrom
, wto
);
755 return rename (from
, to
);
759 /* Changing directory. */
762 __gnat_chdir (char *path
)
764 #if defined (__MINGW32__) && ! defined (__vxworks) && ! defined (IS_CROSS)
766 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
768 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
769 return _tchdir (wpath
);
776 /* Removing a directory. */
779 __gnat_rmdir (char *path
)
781 #if defined (__MINGW32__) && ! defined (__vxworks) && ! defined (IS_CROSS)
783 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
785 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
786 return _trmdir (wpath
);
788 #elif defined (VTHREADS)
789 /* rmdir not available */
797 __gnat_fopen (char *path
, char *mode
, int encoding ATTRIBUTE_UNUSED
)
799 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (IS_CROSS)
800 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
803 S2WS (wmode
, mode
, 10);
805 if (encoding
== Encoding_Unspecified
)
806 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
807 else if (encoding
== Encoding_UTF8
)
808 S2WSU (wpath
, path
, GNAT_MAX_PATH_LEN
);
810 S2WS (wpath
, path
, GNAT_MAX_PATH_LEN
);
812 return _tfopen (wpath
, wmode
);
814 return decc$
fopen (path
, mode
);
816 return GNAT_FOPEN (path
, mode
);
821 __gnat_freopen (char *path
,
824 int encoding ATTRIBUTE_UNUSED
)
826 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (IS_CROSS)
827 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
830 S2WS (wmode
, mode
, 10);
832 if (encoding
== Encoding_Unspecified
)
833 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
834 else if (encoding
== Encoding_UTF8
)
835 S2WSU (wpath
, path
, GNAT_MAX_PATH_LEN
);
837 S2WS (wpath
, path
, GNAT_MAX_PATH_LEN
);
839 return _tfreopen (wpath
, wmode
, stream
);
841 return decc$
freopen (path
, mode
, stream
);
843 return freopen (path
, mode
, stream
);
848 __gnat_open_read (char *path
, int fmode
)
851 int o_fmode
= O_BINARY
;
857 /* Optional arguments mbc,deq,fop increase read performance. */
858 fd
= open (path
, O_RDONLY
| o_fmode
, 0444,
859 "mbc=16", "deq=64", "fop=tef");
860 #elif defined (__vxworks)
861 fd
= open (path
, O_RDONLY
| o_fmode
, 0444);
862 #elif defined (__MINGW32__)
864 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
866 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
867 fd
= _topen (wpath
, O_RDONLY
| o_fmode
, 0444);
870 fd
= open (path
, O_RDONLY
| o_fmode
);
873 return fd
< 0 ? -1 : fd
;
876 #if defined (__MINGW32__)
877 #define PERM (S_IREAD | S_IWRITE)
879 /* Excerpt from DECC C RTL Reference Manual:
880 To create files with OpenVMS RMS default protections using the UNIX
881 system-call functions umask, mkdir, creat, and open, call mkdir, creat,
882 and open with a file-protection mode argument of 0777 in a program
883 that never specifically calls umask. These default protections include
884 correctly establishing protections based on ACLs, previous versions of
888 #define PERM (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
892 __gnat_open_rw (char *path
, int fmode
)
895 int o_fmode
= O_BINARY
;
901 fd
= open (path
, O_RDWR
| o_fmode
, PERM
,
902 "mbc=16", "deq=64", "fop=tef");
903 #elif defined (__MINGW32__)
905 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
907 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
908 fd
= _topen (wpath
, O_RDWR
| o_fmode
, PERM
);
911 fd
= open (path
, O_RDWR
| o_fmode
, PERM
);
914 return fd
< 0 ? -1 : fd
;
918 __gnat_open_create (char *path
, int fmode
)
921 int o_fmode
= O_BINARY
;
927 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| o_fmode
, PERM
,
928 "mbc=16", "deq=64", "fop=tef");
929 #elif 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_TRUNC
| o_fmode
, PERM
);
937 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| o_fmode
, PERM
);
940 return fd
< 0 ? -1 : fd
;
944 __gnat_create_output_file (char *path
)
948 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
, PERM
,
949 "rfm=stmlf", "ctx=rec", "rat=none", "rop=nlk",
950 "shr=del,get,put,upd");
951 #elif defined (__MINGW32__)
953 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
955 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
956 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
, PERM
);
959 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
, PERM
);
962 return fd
< 0 ? -1 : fd
;
966 __gnat_create_output_file_new (char *path
)
970 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
| O_EXCL
, PERM
,
971 "rfm=stmlf", "ctx=rec", "rat=none", "rop=nlk",
972 "shr=del,get,put,upd");
973 #elif defined (__MINGW32__)
975 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
977 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
978 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
| O_EXCL
, PERM
);
981 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
| O_EXCL
, PERM
);
984 return fd
< 0 ? -1 : fd
;
988 __gnat_open_append (char *path
, int fmode
)
991 int o_fmode
= O_BINARY
;
997 fd
= open (path
, O_WRONLY
| O_CREAT
| O_APPEND
| o_fmode
, PERM
,
998 "mbc=16", "deq=64", "fop=tef");
999 #elif defined (__MINGW32__)
1001 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
1003 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
1004 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_APPEND
| o_fmode
, PERM
);
1007 fd
= open (path
, O_WRONLY
| O_CREAT
| O_APPEND
| o_fmode
, PERM
);
1010 return fd
< 0 ? -1 : fd
;
1013 /* Open a new file. Return error (-1) if the file already exists. */
1016 __gnat_open_new (char *path
, int fmode
)
1019 int o_fmode
= O_BINARY
;
1025 fd
= open (path
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
,
1026 "mbc=16", "deq=64", "fop=tef");
1027 #elif defined (__MINGW32__)
1029 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
1031 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
1032 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
);
1035 fd
= open (path
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
);
1038 return fd
< 0 ? -1 : fd
;
1041 /* Open a new temp file. Return error (-1) if the file already exists.
1042 Special options for VMS allow the file to be shared between parent and child
1043 processes, however they really slow down output. Used in gnatchop. */
1046 __gnat_open_new_temp (char *path
, int fmode
)
1049 int o_fmode
= O_BINARY
;
1051 strcpy (path
, "GNAT-XXXXXX");
1053 #if (defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) \
1054 || defined (linux) || defined(__GLIBC__)) && !defined (__vxworks)
1055 return mkstemp (path
);
1056 #elif defined (__Lynx__)
1058 #elif defined (__nucleus__)
1061 if (mktemp (path
) == NULL
)
1069 fd
= open (path
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
,
1070 "rfm=stmlf", "ctx=rec", "rat=none", "shr=del,get,put,upd",
1071 "mbc=16", "deq=64", "fop=tef");
1073 fd
= open (path
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
);
1076 return fd
< 0 ? -1 : fd
;
1079 /****************************************************************
1080 ** Perform a call to GNAT_STAT or GNAT_FSTAT, and extract as much information
1081 ** as possible from it, storing the result in a cache for later reuse
1082 ****************************************************************/
1085 __gnat_stat_to_attr (int fd
, char* name
, struct file_attributes
* attr
)
1087 GNAT_STRUCT_STAT statbuf
;
1091 ret
= GNAT_FSTAT (fd
, &statbuf
);
1093 ret
= __gnat_stat (name
, &statbuf
);
1095 attr
->regular
= (!ret
&& S_ISREG (statbuf
.st_mode
));
1096 attr
->directory
= (!ret
&& S_ISDIR (statbuf
.st_mode
));
1099 attr
->file_length
= 0;
1101 /* st_size may be 32 bits, or 64 bits which is converted to long. We
1102 don't return a useful value for files larger than 2 gigabytes in
1104 attr
->file_length
= statbuf
.st_size
; /* all systems */
1106 attr
->exists
= !ret
;
1108 #if !defined (_WIN32) || defined (RTX)
1109 /* on Windows requires extra system call, see __gnat_is_readable_file_attr */
1110 attr
->readable
= (!ret
&& (statbuf
.st_mode
& S_IRUSR
));
1111 attr
->writable
= (!ret
&& (statbuf
.st_mode
& S_IWUSR
));
1112 attr
->executable
= (!ret
&& (statbuf
.st_mode
& S_IXUSR
));
1116 attr
->timestamp
= (OS_Time
)-1;
1119 /* VMS has file versioning. */
1120 attr
->timestamp
= (OS_Time
)statbuf
.st_ctime
;
1122 attr
->timestamp
= (OS_Time
)statbuf
.st_mtime
;
1127 /****************************************************************
1128 ** Return the number of bytes in the specified file
1129 ****************************************************************/
1132 __gnat_file_length_attr (int fd
, char* name
, struct file_attributes
* attr
)
1134 if (attr
->file_length
== -1) {
1135 __gnat_stat_to_attr (fd
, name
, attr
);
1138 return attr
->file_length
;
1142 __gnat_file_length (int fd
)
1144 struct file_attributes attr
;
1145 __gnat_reset_attributes (&attr
);
1146 return __gnat_file_length_attr (fd
, NULL
, &attr
);
1150 __gnat_named_file_length (char *name
)
1152 struct file_attributes attr
;
1153 __gnat_reset_attributes (&attr
);
1154 return __gnat_file_length_attr (-1, name
, &attr
);
1157 /* Create a temporary filename and put it in string pointed to by
1161 __gnat_tmp_name (char *tmp_filename
)
1164 /* Variable used to create a series of unique names */
1165 static int counter
= 0;
1167 /* RTX in RTSS mode does not support tempnam nor tmpnam so we emulate it */
1168 strcpy (tmp_filename
, "c:\\WINDOWS\\Temp\\gnat-");
1169 sprintf (&tmp_filename
[strlen (tmp_filename
)], "%d\0", counter
++);
1171 #elif defined (__MINGW32__)
1175 /* tempnam tries to create a temporary file in directory pointed to by
1176 TMP environment variable, in c:\temp if TMP is not set, and in
1177 directory specified by P_tmpdir in stdio.h if c:\temp does not
1178 exist. The filename will be created with the prefix "gnat-". */
1180 pname
= (char *) tempnam ("c:\\temp", "gnat-");
1182 /* if pname is NULL, the file was not created properly, the disk is full
1183 or there is no more free temporary files */
1186 *tmp_filename
= '\0';
1188 /* If pname start with a back slash and not path information it means that
1189 the filename is valid for the current working directory. */
1191 else if (pname
[0] == '\\')
1193 strcpy (tmp_filename
, ".\\");
1194 strcat (tmp_filename
, pname
+1);
1197 strcpy (tmp_filename
, pname
);
1202 #elif defined (linux) || defined (__FreeBSD__) || defined (__NetBSD__) \
1203 || defined (__OpenBSD__) || defined(__GLIBC__)
1204 #define MAX_SAFE_PATH 1000
1205 char *tmpdir
= getenv ("TMPDIR");
1207 /* If tmpdir is longer than MAX_SAFE_PATH, revert to default value to avoid
1208 a buffer overflow. */
1209 if (tmpdir
== NULL
|| strlen (tmpdir
) > MAX_SAFE_PATH
)
1210 strcpy (tmp_filename
, "/tmp/gnat-XXXXXX");
1212 sprintf (tmp_filename
, "%s/gnat-XXXXXX", tmpdir
);
1214 close (mkstemp(tmp_filename
));
1216 tmpnam (tmp_filename
);
1220 /* Open directory and returns a DIR pointer. */
1222 DIR* __gnat_opendir (char *name
)
1225 /* Not supported in RTX */
1229 #elif defined (__MINGW32__)
1230 TCHAR wname
[GNAT_MAX_PATH_LEN
];
1232 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
);
1233 return (DIR*)_topendir (wname
);
1236 return opendir (name
);
1240 /* Read the next entry in a directory. The returned string points somewhere
1244 __gnat_readdir (DIR *dirp
, char *buffer
, int *len
)
1247 /* Not supported in RTX */
1251 #elif defined (__MINGW32__)
1252 struct _tdirent
*dirent
= _treaddir ((_TDIR
*)dirp
);
1256 WS2SC (buffer
, dirent
->d_name
, GNAT_MAX_PATH_LEN
);
1257 *len
= strlen (buffer
);
1264 #elif defined (HAVE_READDIR_R)
1265 /* If possible, try to use the thread-safe version. */
1266 if (readdir_r (dirp
, buffer
) != NULL
)
1268 *len
= strlen (((struct dirent
*) buffer
)->d_name
);
1269 return ((struct dirent
*) buffer
)->d_name
;
1275 struct dirent
*dirent
= (struct dirent
*) readdir (dirp
);
1279 strcpy (buffer
, dirent
->d_name
);
1280 *len
= strlen (buffer
);
1289 /* Close a directory entry. */
1291 int __gnat_closedir (DIR *dirp
)
1294 /* Not supported in RTX */
1298 #elif defined (__MINGW32__)
1299 return _tclosedir ((_TDIR
*)dirp
);
1302 return closedir (dirp
);
1306 /* Returns 1 if readdir is thread safe, 0 otherwise. */
1309 __gnat_readdir_is_thread_safe (void)
1311 #ifdef HAVE_READDIR_R
1318 #if defined (_WIN32) && !defined (RTX)
1319 /* Number of seconds between <Jan 1st 1601> and <Jan 1st 1970>. */
1320 static const unsigned long long w32_epoch_offset
= 11644473600ULL;
1322 /* Returns the file modification timestamp using Win32 routines which are
1323 immune against daylight saving time change. It is in fact not possible to
1324 use fstat for this purpose as the DST modify the st_mtime field of the
1328 win32_filetime (HANDLE h
)
1333 unsigned long long ull_time
;
1336 /* GetFileTime returns FILETIME data which are the number of 100 nanosecs
1337 since <Jan 1st 1601>. This function must return the number of seconds
1338 since <Jan 1st 1970>. */
1340 if (GetFileTime (h
, NULL
, NULL
, &t_write
.ft_time
))
1341 return (time_t) (t_write
.ull_time
/ 10000000ULL - w32_epoch_offset
);
1345 /* As above but starting from a FILETIME. */
1347 f2t (const FILETIME
*ft
, time_t *t
)
1352 unsigned long long ull_time
;
1355 t_write
.ft_time
= *ft
;
1356 *t
= (time_t) (t_write
.ull_time
/ 10000000ULL - w32_epoch_offset
);
1360 /* Return a GNAT time stamp given a file name. */
1363 __gnat_file_time_name_attr (char* name
, struct file_attributes
* attr
)
1365 if (attr
->timestamp
== (OS_Time
)-2) {
1366 #if defined (_WIN32) && !defined (RTX)
1368 WIN32_FILE_ATTRIBUTE_DATA fad
;
1370 TCHAR wname
[GNAT_MAX_PATH_LEN
];
1371 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
);
1373 if (res
= GetFileAttributesEx (wname
, GetFileExInfoStandard
, &fad
))
1374 f2t (&fad
.ftLastWriteTime
, &ret
);
1375 attr
->timestamp
= (OS_Time
) ret
;
1377 __gnat_stat_to_attr (-1, name
, attr
);
1380 return attr
->timestamp
;
1384 __gnat_file_time_name (char *name
)
1386 struct file_attributes attr
;
1387 __gnat_reset_attributes (&attr
);
1388 return __gnat_file_time_name_attr (name
, &attr
);
1391 /* Return a GNAT time stamp given a file descriptor. */
1394 __gnat_file_time_fd_attr (int fd
, struct file_attributes
* attr
)
1396 if (attr
->timestamp
== (OS_Time
)-2) {
1397 #if defined (_WIN32) && !defined (RTX)
1398 HANDLE h
= (HANDLE
) _get_osfhandle (fd
);
1399 time_t ret
= win32_filetime (h
);
1400 attr
->timestamp
= (OS_Time
) ret
;
1403 __gnat_stat_to_attr (fd
, NULL
, attr
);
1407 return attr
->timestamp
;
1411 __gnat_file_time_fd (int fd
)
1413 struct file_attributes attr
;
1414 __gnat_reset_attributes (&attr
);
1415 return __gnat_file_time_fd_attr (fd
, &attr
);
1418 /* Set the file time stamp. */
1421 __gnat_set_file_time_name (char *name
, time_t time_stamp
)
1423 #if defined (__vxworks)
1425 /* Code to implement __gnat_set_file_time_name for these systems. */
1427 #elif defined (_WIN32) && !defined (RTX)
1431 unsigned long long ull_time
;
1433 TCHAR wname
[GNAT_MAX_PATH_LEN
];
1435 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
);
1437 HANDLE h
= CreateFile
1438 (wname
, GENERIC_WRITE
, FILE_SHARE_WRITE
, NULL
,
1439 OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
,
1441 if (h
== INVALID_HANDLE_VALUE
)
1443 /* Add number of seconds between <Jan 1st 1601> and <Jan 1st 1970> */
1444 t_write
.ull_time
= ((unsigned long long)time_stamp
+ w32_epoch_offset
);
1445 /* Convert to 100 nanosecond units */
1446 t_write
.ull_time
*= 10000000ULL;
1448 SetFileTime(h
, NULL
, NULL
, &t_write
.ft_time
);
1458 unsigned long long backup
, create
, expire
, revise
;
1462 unsigned short value
;
1465 unsigned system
: 4;
1471 } Fat
= { 0, 0, 0, 0, 0, { 0 }};
1475 { ATR$S_CREDATE
, ATR$C_CREDATE
, &Fat
.create
},
1476 { ATR$S_REVDATE
, ATR$C_REVDATE
, &Fat
.revise
},
1477 { ATR$S_EXPDATE
, ATR$C_EXPDATE
, &Fat
.expire
},
1478 { ATR$S_BAKDATE
, ATR$C_BAKDATE
, &Fat
.backup
},
1479 { ATR$S_FPRO
, ATR$C_FPRO
, &Fat
.prot
},
1480 { ATR$S_UIC
, ATR$C_UIC
, &Fat
.uic
},
1485 struct dsc$descriptor_fib fibdsc
= {sizeof (fib
), (void *) &fib
};
1489 unsigned long long newtime
;
1490 unsigned long long revtime
;
1494 struct vstring file
;
1495 struct dsc$descriptor_s filedsc
1496 = {NAM$C_MAXRSS
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, (void *) file
.string
};
1497 struct vstring device
;
1498 struct dsc$descriptor_s devicedsc
1499 = {NAM$C_MAXRSS
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, (void *) device
.string
};
1500 struct vstring timev
;
1501 struct dsc$descriptor_s timedsc
1502 = {NAM$C_MAXRSS
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, (void *) timev
.string
};
1503 struct vstring result
;
1504 struct dsc$descriptor_s resultdsc
1505 = {NAM$C_MAXRSS
, DSC$K_DTYPE_VT
, DSC$K_CLASS_VS
, (void *) result
.string
};
1507 /* Convert parameter name (a file spec) to host file form. Note that this
1508 is needed on VMS to prepare for subsequent calls to VMS RMS library
1509 routines. Note that it would not work to call __gnat_to_host_dir_spec
1510 as was done in a previous version, since this fails silently unless
1511 the feature logical DECC$EFS_CHARSET is enabled, in which case a DNF
1512 (directory not found) condition is signalled. */
1513 tryfile
= (char *) __gnat_to_host_file_spec (name
);
1515 /* Allocate and initialize a FAB and NAM structures. */
1519 nam
.nam$l_esa
= file
.string
;
1520 nam
.nam$b_ess
= NAM$C_MAXRSS
;
1521 nam
.nam$l_rsa
= result
.string
;
1522 nam
.nam$b_rss
= NAM$C_MAXRSS
;
1523 fab
.fab$l_fna
= tryfile
;
1524 fab
.fab$b_fns
= strlen (tryfile
);
1525 fab
.fab$l_nam
= &nam
;
1527 /* Validate filespec syntax and device existence. */
1528 status
= SYS$
PARSE (&fab
, 0, 0);
1529 if ((status
& 1) != 1)
1530 LIB$
SIGNAL (status
);
1532 file
.string
[nam
.nam$b_esl
] = 0;
1534 /* Find matching filespec. */
1535 status
= SYS$
SEARCH (&fab
, 0, 0);
1536 if ((status
& 1) != 1)
1537 LIB$
SIGNAL (status
);
1539 file
.string
[nam
.nam$b_esl
] = 0;
1540 result
.string
[result
.length
=nam
.nam$b_rsl
] = 0;
1542 /* Get the device name and assign an IO channel. */
1543 strncpy (device
.string
, nam
.nam$l_dev
, nam
.nam$b_dev
);
1544 devicedsc
.dsc$w_length
= nam
.nam$b_dev
;
1546 status
= SYS$
ASSIGN (&devicedsc
, &chan
, 0, 0, 0);
1547 if ((status
& 1) != 1)
1548 LIB$
SIGNAL (status
);
1550 /* Initialize the FIB and fill in the directory id field. */
1551 memset (&fib
, 0, sizeof (fib
));
1552 fib
.fib$w_did
[0] = nam
.nam$w_did
[0];
1553 fib
.fib$w_did
[1] = nam
.nam$w_did
[1];
1554 fib
.fib$w_did
[2] = nam
.nam$w_did
[2];
1555 fib
.fib$l_acctl
= 0;
1557 strcpy (file
.string
, (strrchr (result
.string
, ']') + 1));
1558 filedsc
.dsc$w_length
= strlen (file
.string
);
1559 result
.string
[result
.length
= 0] = 0;
1561 /* Open and close the file to fill in the attributes. */
1563 = SYS$
QIOW (0, chan
, IO$_ACCESS
|IO$M_ACCESS
, &iosb
, 0, 0,
1564 &fibdsc
, &filedsc
, &result
.length
, &resultdsc
, &atrlst
, 0);
1565 if ((status
& 1) != 1)
1566 LIB$
SIGNAL (status
);
1567 if ((iosb
.status
& 1) != 1)
1568 LIB$
SIGNAL (iosb
.status
);
1570 result
.string
[result
.length
] = 0;
1571 status
= SYS$
QIOW (0, chan
, IO$_DEACCESS
, &iosb
, 0, 0, &fibdsc
, 0, 0, 0,
1573 if ((status
& 1) != 1)
1574 LIB$
SIGNAL (status
);
1575 if ((iosb
.status
& 1) != 1)
1576 LIB$
SIGNAL (iosb
.status
);
1581 /* Set creation time to requested time. */
1582 unix_time_to_vms (time_stamp
, newtime
);
1584 t
= time ((time_t) 0);
1586 /* Set revision time to now in local time. */
1587 unix_time_to_vms (t
, revtime
);
1590 /* Reopen the file, modify the times and then close. */
1591 fib
.fib$l_acctl
= FIB$M_WRITE
;
1593 = SYS$
QIOW (0, chan
, IO$_ACCESS
|IO$M_ACCESS
, &iosb
, 0, 0,
1594 &fibdsc
, &filedsc
, &result
.length
, &resultdsc
, &atrlst
, 0);
1595 if ((status
& 1) != 1)
1596 LIB$
SIGNAL (status
);
1597 if ((iosb
.status
& 1) != 1)
1598 LIB$
SIGNAL (iosb
.status
);
1600 Fat
.create
= newtime
;
1601 Fat
.revise
= revtime
;
1603 status
= SYS$
QIOW (0, chan
, IO$_DEACCESS
, &iosb
, 0, 0,
1604 &fibdsc
, 0, 0, 0, &atrlst
, 0);
1605 if ((status
& 1) != 1)
1606 LIB$
SIGNAL (status
);
1607 if ((iosb
.status
& 1) != 1)
1608 LIB$
SIGNAL (iosb
.status
);
1610 /* Deassign the channel and exit. */
1611 status
= SYS$
DASSGN (chan
);
1612 if ((status
& 1) != 1)
1613 LIB$
SIGNAL (status
);
1615 struct utimbuf utimbuf
;
1618 /* Set modification time to requested time. */
1619 utimbuf
.modtime
= time_stamp
;
1621 /* Set access time to now in local time. */
1622 t
= time ((time_t) 0);
1623 utimbuf
.actime
= mktime (localtime (&t
));
1625 utime (name
, &utimbuf
);
1629 /* Get the list of installed standard libraries from the
1630 HKEY_LOCAL_MACHINE\SOFTWARE\Ada Core Technologies\GNAT\Standard Libraries
1634 __gnat_get_libraries_from_registry (void)
1636 char *result
= (char *) xmalloc (1);
1640 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (IS_CROSS) \
1644 DWORD name_size
, value_size
;
1651 /* First open the key. */
1652 res
= RegOpenKeyExA (HKEY_LOCAL_MACHINE
, "SOFTWARE", 0, KEY_READ
, ®_key
);
1654 if (res
== ERROR_SUCCESS
)
1655 res
= RegOpenKeyExA (reg_key
, "Ada Core Technologies", 0,
1656 KEY_READ
, ®_key
);
1658 if (res
== ERROR_SUCCESS
)
1659 res
= RegOpenKeyExA (reg_key
, "GNAT", 0, KEY_READ
, ®_key
);
1661 if (res
== ERROR_SUCCESS
)
1662 res
= RegOpenKeyExA (reg_key
, "Standard Libraries", 0, KEY_READ
, ®_key
);
1664 /* If the key exists, read out all the values in it and concatenate them
1666 for (index
= 0; res
== ERROR_SUCCESS
; index
++)
1668 value_size
= name_size
= 256;
1669 res
= RegEnumValueA (reg_key
, index
, name
, &name_size
, 0,
1670 &type
, (LPBYTE
)value
, &value_size
);
1672 if (res
== ERROR_SUCCESS
&& type
== REG_SZ
)
1674 char *old_result
= result
;
1676 result
= (char *) xmalloc (strlen (old_result
) + value_size
+ 2);
1677 strcpy (result
, old_result
);
1678 strcat (result
, value
);
1679 strcat (result
, ";");
1684 /* Remove the trailing ";". */
1686 result
[strlen (result
) - 1] = 0;
1693 __gnat_stat (char *name
, GNAT_STRUCT_STAT
*statbuf
)
1696 WIN32_FILE_ATTRIBUTE_DATA fad
;
1697 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
1702 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
1703 name_len
= _tcslen (wname
);
1705 if (name_len
> GNAT_MAX_PATH_LEN
)
1708 ZeroMemory (statbuf
, sizeof(GNAT_STRUCT_STAT
));
1710 res
= GetFileAttributesEx (wname
, GetFileExInfoStandard
, &fad
);
1713 error
= GetLastError();
1715 /* Check file existence using GetFileAttributes() which does not fail on
1716 special Windows files like con:, aux:, nul: etc... */
1718 if (GetFileAttributes(wname
) != INVALID_FILE_ATTRIBUTES
) {
1719 /* Just pretend that it is a regular and readable file */
1720 statbuf
->st_mode
= S_IFREG
| S_IREAD
| S_IWRITE
;
1725 case ERROR_ACCESS_DENIED
:
1726 case ERROR_SHARING_VIOLATION
:
1727 case ERROR_LOCK_VIOLATION
:
1728 case ERROR_SHARING_BUFFER_EXCEEDED
:
1730 case ERROR_BUFFER_OVERFLOW
:
1731 return ENAMETOOLONG
;
1732 case ERROR_NOT_ENOUGH_MEMORY
:
1739 f2t (&fad
.ftCreationTime
, &statbuf
->st_ctime
);
1740 f2t (&fad
.ftLastWriteTime
, &statbuf
->st_mtime
);
1741 f2t (&fad
.ftLastAccessTime
, &statbuf
->st_atime
);
1743 statbuf
->st_size
= (off_t
)fad
.nFileSizeLow
;
1745 /* We do not have the S_IEXEC attribute, but this is not used on GNAT. */
1746 statbuf
->st_mode
= S_IREAD
;
1748 if (fad
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
1749 statbuf
->st_mode
|= S_IFDIR
;
1751 statbuf
->st_mode
|= S_IFREG
;
1753 if (!(fad
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
))
1754 statbuf
->st_mode
|= S_IWRITE
;
1759 return GNAT_STAT (name
, statbuf
);
1763 /*************************************************************************
1764 ** Check whether a file exists
1765 *************************************************************************/
1768 __gnat_file_exists_attr (char* name
, struct file_attributes
* attr
)
1770 if (attr
->exists
== ATTR_UNSET
) {
1771 __gnat_stat_to_attr (-1, name
, attr
);
1774 return attr
->exists
;
1778 __gnat_file_exists (char *name
)
1780 struct file_attributes attr
;
1781 __gnat_reset_attributes (&attr
);
1782 return __gnat_file_exists_attr (name
, &attr
);
1785 /**********************************************************************
1786 ** Whether name is an absolute path
1787 **********************************************************************/
1790 __gnat_is_absolute_path (char *name
, int length
)
1793 /* On VxWorks systems, an absolute path can be represented (depending on
1794 the host platform) as either /dir/file, or device:/dir/file, or
1795 device:drive_letter:/dir/file. */
1802 for (index
= 0; index
< length
; index
++)
1804 if (name
[index
] == ':' &&
1805 ((name
[index
+ 1] == '/') ||
1806 (isalpha (name
[index
+ 1]) && index
+ 2 <= length
&&
1807 name
[index
+ 2] == '/')))
1810 else if (name
[index
] == '/')
1815 return (length
!= 0) &&
1816 (*name
== '/' || *name
== DIR_SEPARATOR
1818 || (length
> 1 && ISALPHA (name
[0]) && name
[1] == ':')
1825 __gnat_is_regular_file_attr (char* name
, struct file_attributes
* attr
)
1827 if (attr
->regular
== ATTR_UNSET
) {
1828 __gnat_stat_to_attr (-1, name
, attr
);
1831 return attr
->regular
;
1835 __gnat_is_regular_file (char *name
)
1837 struct file_attributes attr
;
1838 __gnat_reset_attributes (&attr
);
1839 return __gnat_is_regular_file_attr (name
, &attr
);
1843 __gnat_is_directory_attr (char* name
, struct file_attributes
* attr
)
1845 if (attr
->directory
== ATTR_UNSET
) {
1846 __gnat_stat_to_attr (-1, name
, attr
);
1849 return attr
->directory
;
1853 __gnat_is_directory (char *name
)
1855 struct file_attributes attr
;
1856 __gnat_reset_attributes (&attr
);
1857 return __gnat_is_directory_attr (name
, &attr
);
1860 #if defined (_WIN32) && !defined (RTX)
1862 /* Returns the same constant as GetDriveType but takes a pathname as
1866 GetDriveTypeFromPath (TCHAR
*wfullpath
)
1868 TCHAR wdrv
[MAX_PATH
];
1869 TCHAR wpath
[MAX_PATH
];
1870 TCHAR wfilename
[MAX_PATH
];
1871 TCHAR wext
[MAX_PATH
];
1873 _tsplitpath (wfullpath
, wdrv
, wpath
, wfilename
, wext
);
1875 if (_tcslen (wdrv
) != 0)
1877 /* we have a drive specified. */
1878 _tcscat (wdrv
, _T("\\"));
1879 return GetDriveType (wdrv
);
1883 /* No drive specified. */
1885 /* Is this a relative path, if so get current drive type. */
1886 if (wpath
[0] != _T('\\') ||
1887 (_tcslen (wpath
) > 2 && wpath
[0] == _T('\\') && wpath
[1] != _T('\\')))
1888 return GetDriveType (NULL
);
1890 UINT result
= GetDriveType (wpath
);
1892 /* Cannot guess the drive type, is this \\.\ ? */
1894 if (result
== DRIVE_NO_ROOT_DIR
&&
1895 _tcslen (wpath
) >= 4 && wpath
[0] == _T('\\') && wpath
[1] == _T('\\')
1896 && wpath
[2] == _T('.') && wpath
[3] == _T('\\'))
1898 if (_tcslen (wpath
) == 4)
1899 _tcscat (wpath
, wfilename
);
1901 LPTSTR p
= &wpath
[4];
1902 LPTSTR b
= _tcschr (p
, _T('\\'));
1905 { /* logical drive \\.\c\dir\file */
1911 _tcscat (p
, _T(":\\"));
1913 return GetDriveType (p
);
1920 /* This MingW section contains code to work with ACL. */
1922 __gnat_check_OWNER_ACL
1924 DWORD CheckAccessDesired
,
1925 GENERIC_MAPPING CheckGenericMapping
)
1927 DWORD dwAccessDesired
, dwAccessAllowed
;
1928 PRIVILEGE_SET PrivilegeSet
;
1929 DWORD dwPrivSetSize
= sizeof (PRIVILEGE_SET
);
1930 BOOL fAccessGranted
= FALSE
;
1931 HANDLE hToken
= NULL
;
1933 SECURITY_DESCRIPTOR
* pSD
= NULL
;
1936 (wname
, OWNER_SECURITY_INFORMATION
|
1937 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
,
1940 if ((pSD
= (PSECURITY_DESCRIPTOR
) HeapAlloc
1941 (GetProcessHeap (), HEAP_ZERO_MEMORY
, nLength
)) == NULL
)
1944 /* Obtain the security descriptor. */
1946 if (!GetFileSecurity
1947 (wname
, OWNER_SECURITY_INFORMATION
|
1948 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
,
1949 pSD
, nLength
, &nLength
))
1952 if (!ImpersonateSelf (SecurityImpersonation
))
1955 if (!OpenThreadToken
1956 (GetCurrentThread(), TOKEN_DUPLICATE
| TOKEN_QUERY
, FALSE
, &hToken
))
1959 /* Undoes the effect of ImpersonateSelf. */
1963 /* We want to test for write permissions. */
1965 dwAccessDesired
= CheckAccessDesired
;
1967 MapGenericMask (&dwAccessDesired
, &CheckGenericMapping
);
1970 (pSD
, /* security descriptor to check */
1971 hToken
, /* impersonation token */
1972 dwAccessDesired
, /* requested access rights */
1973 &CheckGenericMapping
, /* pointer to GENERIC_MAPPING */
1974 &PrivilegeSet
, /* receives privileges used in check */
1975 &dwPrivSetSize
, /* size of PrivilegeSet buffer */
1976 &dwAccessAllowed
, /* receives mask of allowed access rights */
1980 CloseHandle (hToken
);
1981 HeapFree (GetProcessHeap (), 0, pSD
);
1982 return fAccessGranted
;
1986 CloseHandle (hToken
);
1987 HeapFree (GetProcessHeap (), 0, pSD
);
1992 __gnat_set_OWNER_ACL
1995 DWORD AccessPermissions
)
1997 PACL pOldDACL
= NULL
;
1998 PACL pNewDACL
= NULL
;
1999 PSECURITY_DESCRIPTOR pSD
= NULL
;
2001 TCHAR username
[100];
2004 /* Get current user, he will act as the owner */
2006 if (!GetUserName (username
, &unsize
))
2009 if (GetNamedSecurityInfo
2012 DACL_SECURITY_INFORMATION
,
2013 NULL
, NULL
, &pOldDACL
, NULL
, &pSD
) != ERROR_SUCCESS
)
2016 BuildExplicitAccessWithName
2017 (&ea
, username
, AccessPermissions
, AccessMode
, NO_INHERITANCE
);
2019 if (AccessMode
== SET_ACCESS
)
2021 /* SET_ACCESS, we want to set an explicte set of permissions, do not
2022 merge with current DACL. */
2023 if (SetEntriesInAcl (1, &ea
, NULL
, &pNewDACL
) != ERROR_SUCCESS
)
2027 if (SetEntriesInAcl (1, &ea
, pOldDACL
, &pNewDACL
) != ERROR_SUCCESS
)
2030 if (SetNamedSecurityInfo
2031 (wname
, SE_FILE_OBJECT
,
2032 DACL_SECURITY_INFORMATION
, NULL
, NULL
, pNewDACL
, NULL
) != ERROR_SUCCESS
)
2036 LocalFree (pNewDACL
);
2039 /* Check if it is possible to use ACL for wname, the file must not be on a
2043 __gnat_can_use_acl (TCHAR
*wname
)
2045 return __gnat_use_acl
&& GetDriveTypeFromPath (wname
) != DRIVE_REMOTE
;
2048 #endif /* defined (_WIN32) && !defined (RTX) */
2051 __gnat_is_readable_file_attr (char* name
, struct file_attributes
* attr
)
2053 if (attr
->readable
== ATTR_UNSET
) {
2054 #if defined (_WIN32) && !defined (RTX)
2055 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2056 GENERIC_MAPPING GenericMapping
;
2058 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2060 if (__gnat_can_use_acl (wname
))
2062 ZeroMemory (&GenericMapping
, sizeof (GENERIC_MAPPING
));
2063 GenericMapping
.GenericRead
= GENERIC_READ
;
2065 __gnat_check_OWNER_ACL (wname
, FILE_READ_DATA
, GenericMapping
);
2068 attr
->readable
= GetFileAttributes (wname
) != INVALID_FILE_ATTRIBUTES
;
2070 __gnat_stat_to_attr (-1, name
, attr
);
2074 return attr
->readable
;
2078 __gnat_is_readable_file (char *name
)
2080 struct file_attributes attr
;
2081 __gnat_reset_attributes (&attr
);
2082 return __gnat_is_readable_file_attr (name
, &attr
);
2086 __gnat_is_writable_file_attr (char* name
, struct file_attributes
* attr
)
2088 if (attr
->writable
== ATTR_UNSET
) {
2089 #if defined (_WIN32) && !defined (RTX)
2090 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2091 GENERIC_MAPPING GenericMapping
;
2093 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2095 if (__gnat_can_use_acl (wname
))
2097 ZeroMemory (&GenericMapping
, sizeof (GENERIC_MAPPING
));
2098 GenericMapping
.GenericWrite
= GENERIC_WRITE
;
2100 attr
->writable
= __gnat_check_OWNER_ACL
2101 (wname
, FILE_WRITE_DATA
| FILE_APPEND_DATA
, GenericMapping
)
2102 && !(GetFileAttributes (wname
) & FILE_ATTRIBUTE_READONLY
);
2105 attr
->writable
= !(GetFileAttributes (wname
) & FILE_ATTRIBUTE_READONLY
);
2108 __gnat_stat_to_attr (-1, name
, attr
);
2112 return attr
->writable
;
2116 __gnat_is_writable_file (char *name
)
2118 struct file_attributes attr
;
2119 __gnat_reset_attributes (&attr
);
2120 return __gnat_is_writable_file_attr (name
, &attr
);
2124 __gnat_is_executable_file_attr (char* name
, struct file_attributes
* attr
)
2126 if (attr
->executable
== ATTR_UNSET
) {
2127 #if defined (_WIN32) && !defined (RTX)
2128 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2129 GENERIC_MAPPING GenericMapping
;
2131 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2133 if (__gnat_can_use_acl (wname
))
2135 ZeroMemory (&GenericMapping
, sizeof (GENERIC_MAPPING
));
2136 GenericMapping
.GenericExecute
= GENERIC_EXECUTE
;
2139 __gnat_check_OWNER_ACL (wname
, FILE_EXECUTE
, GenericMapping
);
2142 attr
->executable
= GetFileAttributes (wname
) != INVALID_FILE_ATTRIBUTES
2143 && _tcsstr (wname
, _T(".exe")) - wname
== (int) (_tcslen (wname
) - 4);
2145 __gnat_stat_to_attr (-1, name
, attr
);
2149 return attr
->executable
;
2153 __gnat_is_executable_file (char *name
)
2155 struct file_attributes attr
;
2156 __gnat_reset_attributes (&attr
);
2157 return __gnat_is_executable_file_attr (name
, &attr
);
2161 __gnat_set_writable (char *name
)
2163 #if defined (_WIN32) && !defined (RTX)
2164 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2166 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2168 if (__gnat_can_use_acl (wname
))
2169 __gnat_set_OWNER_ACL (wname
, GRANT_ACCESS
, FILE_GENERIC_WRITE
);
2172 (wname
, GetFileAttributes (wname
) & ~FILE_ATTRIBUTE_READONLY
);
2173 #elif ! defined (__vxworks) && ! defined(__nucleus__)
2174 GNAT_STRUCT_STAT statbuf
;
2176 if (GNAT_STAT (name
, &statbuf
) == 0)
2178 statbuf
.st_mode
= statbuf
.st_mode
| S_IWUSR
;
2179 chmod (name
, statbuf
.st_mode
);
2185 __gnat_set_executable (char *name
)
2187 #if defined (_WIN32) && !defined (RTX)
2188 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2190 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2192 if (__gnat_can_use_acl (wname
))
2193 __gnat_set_OWNER_ACL (wname
, GRANT_ACCESS
, FILE_GENERIC_EXECUTE
);
2195 #elif ! defined (__vxworks) && ! defined(__nucleus__)
2196 GNAT_STRUCT_STAT statbuf
;
2198 if (GNAT_STAT (name
, &statbuf
) == 0)
2200 statbuf
.st_mode
= statbuf
.st_mode
| S_IXUSR
;
2201 chmod (name
, statbuf
.st_mode
);
2207 __gnat_set_non_writable (char *name
)
2209 #if defined (_WIN32) && !defined (RTX)
2210 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2212 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2214 if (__gnat_can_use_acl (wname
))
2215 __gnat_set_OWNER_ACL
2216 (wname
, DENY_ACCESS
,
2217 FILE_WRITE_DATA
| FILE_APPEND_DATA
|
2218 FILE_WRITE_EA
| FILE_WRITE_ATTRIBUTES
);
2221 (wname
, GetFileAttributes (wname
) | FILE_ATTRIBUTE_READONLY
);
2222 #elif ! defined (__vxworks) && ! defined(__nucleus__)
2223 GNAT_STRUCT_STAT statbuf
;
2225 if (GNAT_STAT (name
, &statbuf
) == 0)
2227 statbuf
.st_mode
= statbuf
.st_mode
& 07577;
2228 chmod (name
, statbuf
.st_mode
);
2234 __gnat_set_readable (char *name
)
2236 #if defined (_WIN32) && !defined (RTX)
2237 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2239 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2241 if (__gnat_can_use_acl (wname
))
2242 __gnat_set_OWNER_ACL (wname
, GRANT_ACCESS
, FILE_GENERIC_READ
);
2244 #elif ! defined (__vxworks) && ! defined(__nucleus__)
2245 GNAT_STRUCT_STAT statbuf
;
2247 if (GNAT_STAT (name
, &statbuf
) == 0)
2249 chmod (name
, statbuf
.st_mode
| S_IREAD
);
2255 __gnat_set_non_readable (char *name
)
2257 #if defined (_WIN32) && !defined (RTX)
2258 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2260 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2262 if (__gnat_can_use_acl (wname
))
2263 __gnat_set_OWNER_ACL (wname
, DENY_ACCESS
, FILE_GENERIC_READ
);
2265 #elif ! defined (__vxworks) && ! defined(__nucleus__)
2266 GNAT_STRUCT_STAT statbuf
;
2268 if (GNAT_STAT (name
, &statbuf
) == 0)
2270 chmod (name
, statbuf
.st_mode
& (~S_IREAD
));
2276 __gnat_is_symbolic_link_attr (char* name
, struct file_attributes
* attr
)
2278 if (attr
->symbolic_link
== ATTR_UNSET
) {
2279 #if defined (__vxworks) || defined (__nucleus__)
2280 attr
->symbolic_link
= 0;
2282 #elif defined (_AIX) || defined (__APPLE__) || defined (__unix__)
2284 GNAT_STRUCT_STAT statbuf
;
2285 ret
= GNAT_LSTAT (name
, &statbuf
);
2286 attr
->symbolic_link
= (!ret
&& S_ISLNK (statbuf
.st_mode
));
2288 attr
->symbolic_link
= 0;
2291 return attr
->symbolic_link
;
2295 __gnat_is_symbolic_link (char *name ATTRIBUTE_UNUSED
)
2297 struct file_attributes attr
;
2298 __gnat_reset_attributes (&attr
);
2299 return __gnat_is_symbolic_link_attr (name
, &attr
);
2303 #if defined (sun) && defined (__SVR4)
2304 /* Using fork on Solaris will duplicate all the threads. fork1, which
2305 duplicates only the active thread, must be used instead, or spawning
2306 subprocess from a program with tasking will lead into numerous problems. */
2311 __gnat_portable_spawn (char *args
[])
2314 int finished ATTRIBUTE_UNUSED
;
2315 int pid ATTRIBUTE_UNUSED
;
2317 #if defined (__vxworks) || defined(__nucleus__) || defined(RTX)
2320 #elif defined (_WIN32)
2321 /* args[0] must be quotes as it could contain a full pathname with spaces */
2322 char *args_0
= args
[0];
2323 args
[0] = (char *)xmalloc (strlen (args_0
) + 3);
2324 strcpy (args
[0], "\"");
2325 strcat (args
[0], args_0
);
2326 strcat (args
[0], "\"");
2328 status
= spawnvp (P_WAIT
, args_0
, (const char* const*)args
);
2330 /* restore previous value */
2332 args
[0] = (char *)args_0
;
2348 if (execv (args
[0], MAYBE_TO_PTR32 (args
)) != 0)
2350 return -1; /* execv is in parent context on VMS. */
2357 finished
= waitpid (pid
, &status
, 0);
2359 if (finished
!= pid
|| WIFEXITED (status
) == 0)
2362 return WEXITSTATUS (status
);
2368 /* Create a copy of the given file descriptor.
2369 Return -1 if an error occurred. */
2372 __gnat_dup (int oldfd
)
2374 #if defined (__vxworks) && !defined (__RTP__)
2375 /* Not supported on VxWorks 5.x, but supported on VxWorks 6.0 when using
2383 /* Make newfd be the copy of oldfd, closing newfd first if necessary.
2384 Return -1 if an error occurred. */
2387 __gnat_dup2 (int oldfd
, int newfd
)
2389 #if defined (__vxworks) && !defined (__RTP__)
2390 /* Not supported on VxWorks 5.x, but supported on VxWorks 6.0 when using
2394 return dup2 (oldfd
, newfd
);
2399 __gnat_number_of_cpus (void)
2403 #if defined (linux) || defined (sun) || defined (AIX) \
2404 || (defined (__alpha__) && defined (_osf_)) || defined (__APPLE__)
2405 cores
= (int) sysconf (_SC_NPROCESSORS_ONLN
);
2407 #elif (defined (__mips) && defined (__sgi))
2408 cores
= (int) sysconf (_SC_NPROC_ONLN
);
2410 #elif defined (__hpux__)
2411 struct pst_dynamic psd
;
2412 if (pstat_getdynamic (&psd
, sizeof (psd
), 1, 0) != -1)
2413 cores
= (int) psd
.psd_proc_cnt
;
2415 #elif defined (_WIN32)
2416 SYSTEM_INFO sysinfo
;
2417 GetSystemInfo (&sysinfo
);
2418 cores
= (int) sysinfo
.dwNumberOfProcessors
;
2421 int code
= SYI$_ACTIVECPU_CNT
;
2425 status
= LIB$
GETSYI (&code
, &res
);
2426 if ((status
& 1) != 0)
2433 /* WIN32 code to implement a wait call that wait for any child process. */
2435 #if defined (_WIN32) && !defined (RTX)
2437 /* Synchronization code, to be thread safe. */
2441 /* For the Cert run times on native Windows we use dummy functions
2442 for locking and unlocking tasks since we do not support multiple
2443 threads on this configuration (Cert run time on native Windows). */
2445 void dummy (void) {}
2447 void (*Lock_Task
) () = &dummy
;
2448 void (*Unlock_Task
) () = &dummy
;
2452 #define Lock_Task system__soft_links__lock_task
2453 extern void (*Lock_Task
) (void);
2455 #define Unlock_Task system__soft_links__unlock_task
2456 extern void (*Unlock_Task
) (void);
2460 static HANDLE
*HANDLES_LIST
= NULL
;
2461 static int *PID_LIST
= NULL
, plist_length
= 0, plist_max_length
= 0;
2464 add_handle (HANDLE h
, int pid
)
2467 /* -------------------- critical section -------------------- */
2470 if (plist_length
== plist_max_length
)
2472 plist_max_length
+= 1000;
2474 xrealloc (HANDLES_LIST
, sizeof (HANDLE
) * plist_max_length
);
2476 xrealloc (PID_LIST
, sizeof (int) * plist_max_length
);
2479 HANDLES_LIST
[plist_length
] = h
;
2480 PID_LIST
[plist_length
] = pid
;
2484 /* -------------------- critical section -------------------- */
2488 __gnat_win32_remove_handle (HANDLE h
, int pid
)
2492 /* -------------------- critical section -------------------- */
2495 for (j
= 0; j
< plist_length
; j
++)
2497 if ((HANDLES_LIST
[j
] == h
) || (PID_LIST
[j
] == pid
))
2501 HANDLES_LIST
[j
] = HANDLES_LIST
[plist_length
];
2502 PID_LIST
[j
] = PID_LIST
[plist_length
];
2508 /* -------------------- critical section -------------------- */
2512 win32_no_block_spawn (char *command
, char *args
[], HANDLE
*h
, int *pid
)
2516 PROCESS_INFORMATION PI
;
2517 SECURITY_ATTRIBUTES SA
;
2522 /* compute the total command line length */
2526 csize
+= strlen (args
[k
]) + 1;
2530 full_command
= (char *) xmalloc (csize
);
2533 SI
.cb
= sizeof (STARTUPINFO
);
2534 SI
.lpReserved
= NULL
;
2535 SI
.lpReserved2
= NULL
;
2536 SI
.lpDesktop
= NULL
;
2540 SI
.wShowWindow
= SW_HIDE
;
2542 /* Security attributes. */
2543 SA
.nLength
= sizeof (SECURITY_ATTRIBUTES
);
2544 SA
.bInheritHandle
= TRUE
;
2545 SA
.lpSecurityDescriptor
= NULL
;
2547 /* Prepare the command string. */
2548 strcpy (full_command
, command
);
2549 strcat (full_command
, " ");
2554 strcat (full_command
, args
[k
]);
2555 strcat (full_command
, " ");
2560 int wsize
= csize
* 2;
2561 TCHAR
*wcommand
= (TCHAR
*) xmalloc (wsize
);
2563 S2WSC (wcommand
, full_command
, wsize
);
2565 free (full_command
);
2567 result
= CreateProcess
2568 (NULL
, wcommand
, &SA
, NULL
, TRUE
,
2569 GetPriorityClass (GetCurrentProcess()), NULL
, NULL
, &SI
, &PI
);
2576 CloseHandle (PI
.hThread
);
2578 *pid
= PI
.dwProcessId
;
2588 win32_wait (int *status
)
2590 DWORD exitcode
, pid
;
2597 if (plist_length
== 0)
2605 /* -------------------- critical section -------------------- */
2608 hl_len
= plist_length
;
2610 hl
= (HANDLE
*) xmalloc (sizeof (HANDLE
) * hl_len
);
2612 memmove (hl
, HANDLES_LIST
, sizeof (HANDLE
) * hl_len
);
2615 /* -------------------- critical section -------------------- */
2617 res
= WaitForMultipleObjects (hl_len
, hl
, FALSE
, INFINITE
);
2618 h
= hl
[res
- WAIT_OBJECT_0
];
2620 GetExitCodeProcess (h
, &exitcode
);
2621 pid
= PID_LIST
[res
- WAIT_OBJECT_0
];
2622 __gnat_win32_remove_handle (h
, -1);
2626 *status
= (int) exitcode
;
2633 __gnat_portable_no_block_spawn (char *args
[])
2636 #if defined (__vxworks) || defined (__nucleus__) || defined (RTX)
2639 #elif defined (_WIN32)
2644 win32_no_block_spawn (args
[0], args
, &h
, &pid
);
2647 add_handle (h
, pid
);
2660 if (execv (args
[0], MAYBE_TO_PTR32 (args
)) != 0)
2662 return -1; /* execv is in parent context on VMS. */
2674 __gnat_portable_wait (int *process_status
)
2679 #if defined (__vxworks) || defined (__nucleus__) || defined (RTX)
2680 /* Not sure what to do here, so do nothing but return zero. */
2682 #elif defined (_WIN32)
2684 pid
= win32_wait (&status
);
2688 pid
= waitpid (-1, &status
, 0);
2689 status
= status
& 0xffff;
2692 *process_status
= status
;
2697 __gnat_os_exit (int status
)
2702 /* Locate a regular file, give a Path value. */
2705 __gnat_locate_regular_file (char *file_name
, char *path_val
)
2708 char *file_path
= (char *) alloca (strlen (file_name
) + 1);
2711 /* Return immediately if file_name is empty */
2713 if (*file_name
== '\0')
2716 /* Remove quotes around file_name if present */
2722 strcpy (file_path
, ptr
);
2724 ptr
= file_path
+ strlen (file_path
) - 1;
2729 /* Handle absolute pathnames. */
2731 absolute
= __gnat_is_absolute_path (file_path
, strlen (file_name
));
2735 if (__gnat_is_regular_file (file_path
))
2736 return xstrdup (file_path
);
2741 /* If file_name include directory separator(s), try it first as
2742 a path name relative to the current directory */
2743 for (ptr
= file_name
; *ptr
&& *ptr
!= '/' && *ptr
!= DIR_SEPARATOR
; ptr
++)
2748 if (__gnat_is_regular_file (file_name
))
2749 return xstrdup (file_name
);
2756 /* The result has to be smaller than path_val + file_name. */
2758 (char *) alloca (strlen (path_val
) + strlen (file_name
) + 2);
2762 /* Skip the starting quote */
2764 if (*path_val
== '"')
2767 for (ptr
= file_path
; *path_val
&& *path_val
!= PATH_SEPARATOR
; )
2768 *ptr
++ = *path_val
++;
2770 /* If directory is empty, it is the current directory*/
2772 if (ptr
== file_path
)
2779 /* Skip the ending quote */
2784 if (*ptr
!= '/' && *ptr
!= DIR_SEPARATOR
)
2785 *++ptr
= DIR_SEPARATOR
;
2787 strcpy (++ptr
, file_name
);
2789 if (__gnat_is_regular_file (file_path
))
2790 return xstrdup (file_path
);
2795 /* Skip path separator */
2804 /* Locate an executable given a Path argument. This routine is only used by
2805 gnatbl and should not be used otherwise. Use locate_exec_on_path
2809 __gnat_locate_exec (char *exec_name
, char *path_val
)
2812 if (!strstr (exec_name
, HOST_EXECUTABLE_SUFFIX
))
2814 char *full_exec_name
=
2816 (strlen (exec_name
) + strlen (HOST_EXECUTABLE_SUFFIX
) + 1);
2818 strcpy (full_exec_name
, exec_name
);
2819 strcat (full_exec_name
, HOST_EXECUTABLE_SUFFIX
);
2820 ptr
= __gnat_locate_regular_file (full_exec_name
, path_val
);
2823 return __gnat_locate_regular_file (exec_name
, path_val
);
2827 return __gnat_locate_regular_file (exec_name
, path_val
);
2830 /* Locate an executable using the Systems default PATH. */
2833 __gnat_locate_exec_on_path (char *exec_name
)
2837 #if defined (_WIN32) && !defined (RTX)
2838 TCHAR
*wpath_val
= _tgetenv (_T("PATH"));
2840 /* In Win32 systems we expand the PATH as for XP environment
2841 variables are not automatically expanded. We also prepend the
2842 ".;" to the path to match normal NT path search semantics */
2844 #define EXPAND_BUFFER_SIZE 32767
2846 wapath_val
= alloca (EXPAND_BUFFER_SIZE
);
2848 wapath_val
[0] = '.';
2849 wapath_val
[1] = ';';
2851 DWORD res
= ExpandEnvironmentStrings
2852 (wpath_val
, &wapath_val
[2], EXPAND_BUFFER_SIZE
- 2);
2854 if (!res
) wapath_val
[0] = _T('\0');
2856 apath_val
= alloca (EXPAND_BUFFER_SIZE
);
2858 WS2SC (apath_val
, wapath_val
, EXPAND_BUFFER_SIZE
);
2859 return __gnat_locate_exec (exec_name
, apath_val
);
2864 char *path_val
= "/VAXC$PATH";
2866 char *path_val
= getenv ("PATH");
2868 if (path_val
== NULL
) return NULL
;
2869 apath_val
= (char *) alloca (strlen (path_val
) + 1);
2870 strcpy (apath_val
, path_val
);
2871 return __gnat_locate_exec (exec_name
, apath_val
);
2877 /* These functions are used to translate to and from VMS and Unix syntax
2878 file, directory and path specifications. */
2881 #define MAXNAMES 256
2882 #define NEW_CANONICAL_FILELIST_INCREMENT 64
2884 static char new_canonical_dirspec
[MAXPATH
];
2885 static char new_canonical_filespec
[MAXPATH
];
2886 static char new_canonical_pathspec
[MAXNAMES
*MAXPATH
];
2887 static unsigned new_canonical_filelist_index
;
2888 static unsigned new_canonical_filelist_in_use
;
2889 static unsigned new_canonical_filelist_allocated
;
2890 static char **new_canonical_filelist
;
2891 static char new_host_pathspec
[MAXNAMES
*MAXPATH
];
2892 static char new_host_dirspec
[MAXPATH
];
2893 static char new_host_filespec
[MAXPATH
];
2895 /* Routine is called repeatedly by decc$from_vms via
2896 __gnat_to_canonical_file_list_init until it returns 0 or the expansion
2900 wildcard_translate_unix (char *name
)
2903 char buff
[MAXPATH
];
2905 strncpy (buff
, name
, MAXPATH
);
2906 buff
[MAXPATH
- 1] = (char) 0;
2907 ver
= strrchr (buff
, '.');
2909 /* Chop off the version. */
2913 /* Dynamically extend the allocation by the increment. */
2914 if (new_canonical_filelist_in_use
== new_canonical_filelist_allocated
)
2916 new_canonical_filelist_allocated
+= NEW_CANONICAL_FILELIST_INCREMENT
;
2917 new_canonical_filelist
= (char **) xrealloc
2918 (new_canonical_filelist
,
2919 new_canonical_filelist_allocated
* sizeof (char *));
2922 new_canonical_filelist
[new_canonical_filelist_in_use
++] = xstrdup (buff
);
2927 /* Translate a wildcard VMS file spec into a list of Unix file specs. First do
2928 full translation and copy the results into a list (_init), then return them
2929 one at a time (_next). If onlydirs set, only expand directory files. */
2932 __gnat_to_canonical_file_list_init (char *filespec
, int onlydirs
)
2935 char buff
[MAXPATH
];
2937 len
= strlen (filespec
);
2938 strncpy (buff
, filespec
, MAXPATH
);
2940 /* Only look for directories */
2941 if (onlydirs
&& !strstr (&buff
[len
-5], "*.dir"))
2942 strncat (buff
, "*.dir", MAXPATH
);
2944 buff
[MAXPATH
- 1] = (char) 0;
2946 decc$
from_vms (buff
, wildcard_translate_unix
, 1);
2948 /* Remove the .dir extension. */
2954 for (i
= 0; i
< new_canonical_filelist_in_use
; i
++)
2956 ext
= strstr (new_canonical_filelist
[i
], ".dir");
2962 return new_canonical_filelist_in_use
;
2965 /* Return the next filespec in the list. */
2968 __gnat_to_canonical_file_list_next ()
2970 return new_canonical_filelist
[new_canonical_filelist_index
++];
2973 /* Free storage used in the wildcard expansion. */
2976 __gnat_to_canonical_file_list_free ()
2980 for (i
= 0; i
< new_canonical_filelist_in_use
; i
++)
2981 free (new_canonical_filelist
[i
]);
2983 free (new_canonical_filelist
);
2985 new_canonical_filelist_in_use
= 0;
2986 new_canonical_filelist_allocated
= 0;
2987 new_canonical_filelist_index
= 0;
2988 new_canonical_filelist
= 0;
2991 /* The functional equivalent of decc$translate_vms routine.
2992 Designed to produce the same output, but is protected against
2993 malformed paths (original version ACCVIOs in this case) and
2994 does not require VMS-specific DECC RTL */
2996 #define NAM$C_MAXRSS 1024
2999 __gnat_translate_vms (char *src
)
3001 static char retbuf
[NAM$C_MAXRSS
+1];
3002 char *srcendpos
, *pos1
, *pos2
, *retpos
;
3003 int disp
, path_present
= 0;
3005 if (!src
) return NULL
;
3007 srcendpos
= strchr (src
, '\0');
3010 /* Look for the node and/or device in front of the path */
3012 pos2
= strchr (pos1
, ':');
3014 if (pos2
&& (pos2
< srcendpos
) && (*(pos2
+ 1) == ':')) {
3015 /* There is a node name. "node_name::" becomes "node_name!" */
3017 strncpy (retbuf
, pos1
, disp
);
3018 retpos
[disp
] = '!';
3019 retpos
= retpos
+ disp
+ 1;
3021 pos2
= strchr (pos1
, ':');
3025 /* There is a device name. "dev_name:" becomes "/dev_name/" */
3028 strncpy (retpos
, pos1
, disp
);
3029 retpos
= retpos
+ disp
;
3034 /* No explicit device; we must look ahead and prepend /sys$disk/ if
3035 the path is absolute */
3036 if ((*pos1
== '[' || *pos1
== '<') && (pos1
< srcendpos
)
3037 && !strchr (".-]>", *(pos1
+ 1))) {
3038 strncpy (retpos
, "/sys$disk/", 10);
3042 /* Process the path part */
3043 while (*pos1
== '[' || *pos1
== '<') {
3046 if (*pos1
== ']' || *pos1
== '>') {
3047 /* Special case, [] translates to '.' */
3052 /* '[000000' means root dir. It can be present in the middle of
3053 the path due to expansion of logical devices, in which case
3055 if (!strncmp (pos1
, "000000", 6) && path_present
> 1 &&
3056 (*(pos1
+ 6) == ']' || *(pos1
+ 6) == '>' || *(pos1
+ 6) == '.')) {
3058 if (*pos1
== '.') pos1
++;
3060 else if (*pos1
== '.') {
3065 /* There is a qualified path */
3066 while (*pos1
&& *pos1
!= ']' && *pos1
!= '>') {
3069 /* '.' is used to separate directories. Replace it with '/' but
3070 only if there isn't already '/' just before */
3071 if (*(retpos
- 1) != '/') *(retpos
++) = '/';
3073 if (pos1
+ 1 < srcendpos
&& *pos1
== '.' && *(pos1
+ 1) == '.') {
3074 /* ellipsis refers to entire subtree; replace with '**' */
3075 *(retpos
++) = '*'; *(retpos
++) = '*'; *(retpos
++) = '/';
3080 /* When after '.' '[' '<' is equivalent to Unix ".." but there
3081 may be several in a row */
3082 if (*(pos1
- 1) == '.' || *(pos1
- 1) == '[' ||
3083 *(pos1
- 1) == '<') {
3084 while (*pos1
== '-') {
3086 *(retpos
++) = '.'; *(retpos
++) = '.'; *(retpos
++) = '/';
3091 /* otherwise fall through to default */
3093 *(retpos
++) = *(pos1
++);
3100 if (pos1
< srcendpos
) {
3101 /* Now add the actual file name, until the version suffix if any */
3102 if (path_present
) *(retpos
++) = '/';
3103 pos2
= strchr (pos1
, ';');
3104 disp
= pos2
? (pos2
- pos1
) : (srcendpos
- pos1
);
3105 strncpy (retpos
, pos1
, disp
);
3107 if (pos2
&& pos2
< srcendpos
) {
3108 /* There is a non-empty version suffix. ";<ver>" becomes ".<ver>" */
3110 disp
= srcendpos
- pos2
- 1;
3111 strncpy (retpos
, pos2
+ 1, disp
);
3122 /* Translate a VMS syntax directory specification in to Unix syntax. If
3123 PREFIXFLAG is set, append an underscore "/". If no indicators of VMS syntax
3124 found, return input string. Also translate a dirname that contains no
3125 slashes, in case it's a logical name. */
3128 __gnat_to_canonical_dir_spec (char *dirspec
, int prefixflag
)
3132 strcpy (new_canonical_dirspec
, "");
3133 if (strlen (dirspec
))
3137 if (strchr (dirspec
, ']') || strchr (dirspec
, ':'))
3139 strncpy (new_canonical_dirspec
,
3140 __gnat_translate_vms (dirspec
),
3143 else if (!strchr (dirspec
, '/') && (dirspec1
= getenv (dirspec
)) != 0)
3145 strncpy (new_canonical_dirspec
,
3146 __gnat_translate_vms (dirspec1
),
3151 strncpy (new_canonical_dirspec
, dirspec
, MAXPATH
);
3155 len
= strlen (new_canonical_dirspec
);
3156 if (prefixflag
&& new_canonical_dirspec
[len
-1] != '/')
3157 strncat (new_canonical_dirspec
, "/", MAXPATH
);
3159 new_canonical_dirspec
[MAXPATH
- 1] = (char) 0;
3161 return new_canonical_dirspec
;
3165 /* Translate a VMS syntax file specification into Unix syntax.
3166 If no indicators of VMS syntax found, check if it's an uppercase
3167 alphanumeric_ name and if so try it out as an environment
3168 variable (logical name). If all else fails return the
3172 __gnat_to_canonical_file_spec (char *filespec
)
3176 strncpy (new_canonical_filespec
, "", MAXPATH
);
3178 if (strchr (filespec
, ']') || strchr (filespec
, ':'))
3180 char *tspec
= (char *) __gnat_translate_vms (filespec
);
3182 if (tspec
!= (char *) -1)
3183 strncpy (new_canonical_filespec
, tspec
, MAXPATH
);
3185 else if ((strlen (filespec
) == strspn (filespec
,
3186 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"))
3187 && (filespec1
= getenv (filespec
)))
3189 char *tspec
= (char *) __gnat_translate_vms (filespec1
);
3191 if (tspec
!= (char *) -1)
3192 strncpy (new_canonical_filespec
, tspec
, MAXPATH
);
3196 strncpy (new_canonical_filespec
, filespec
, MAXPATH
);
3199 new_canonical_filespec
[MAXPATH
- 1] = (char) 0;
3201 return new_canonical_filespec
;
3204 /* Translate a VMS syntax path specification into Unix syntax.
3205 If no indicators of VMS syntax found, return input string. */
3208 __gnat_to_canonical_path_spec (char *pathspec
)
3210 char *curr
, *next
, buff
[MAXPATH
];
3215 /* If there are /'s, assume it's a Unix path spec and return. */
3216 if (strchr (pathspec
, '/'))
3219 new_canonical_pathspec
[0] = 0;
3224 next
= strchr (curr
, ',');
3226 next
= strchr (curr
, 0);
3228 strncpy (buff
, curr
, next
- curr
);
3229 buff
[next
- curr
] = 0;
3231 /* Check for wildcards and expand if present. */
3232 if (strchr (buff
, '*') || strchr (buff
, '%') || strstr (buff
, "..."))
3236 dirs
= __gnat_to_canonical_file_list_init (buff
, 1);
3237 for (i
= 0; i
< dirs
; i
++)
3241 next_dir
= __gnat_to_canonical_file_list_next ();
3242 strncat (new_canonical_pathspec
, next_dir
, MAXPATH
);
3244 /* Don't append the separator after the last expansion. */
3246 strncat (new_canonical_pathspec
, ":", MAXPATH
);
3249 __gnat_to_canonical_file_list_free ();
3252 strncat (new_canonical_pathspec
,
3253 __gnat_to_canonical_dir_spec (buff
, 0), MAXPATH
);
3258 strncat (new_canonical_pathspec
, ":", MAXPATH
);
3262 new_canonical_pathspec
[MAXPATH
- 1] = (char) 0;
3264 return new_canonical_pathspec
;
3267 static char filename_buff
[MAXPATH
];
3270 translate_unix (char *name
, int type
)
3272 strncpy (filename_buff
, name
, MAXPATH
);
3273 filename_buff
[MAXPATH
- 1] = (char) 0;
3277 /* Translate a Unix syntax path spec into a VMS style (comma separated list of
3281 to_host_path_spec (char *pathspec
)
3283 char *curr
, *next
, buff
[MAXPATH
];
3288 /* Can't very well test for colons, since that's the Unix separator! */
3289 if (strchr (pathspec
, ']') || strchr (pathspec
, ','))
3292 new_host_pathspec
[0] = 0;
3297 next
= strchr (curr
, ':');
3299 next
= strchr (curr
, 0);
3301 strncpy (buff
, curr
, next
- curr
);
3302 buff
[next
- curr
] = 0;
3304 strncat (new_host_pathspec
, __gnat_to_host_dir_spec (buff
, 0), MAXPATH
);
3307 strncat (new_host_pathspec
, ",", MAXPATH
);
3311 new_host_pathspec
[MAXPATH
- 1] = (char) 0;
3313 return new_host_pathspec
;
3316 /* Translate a Unix syntax directory specification into VMS syntax. The
3317 PREFIXFLAG has no effect, but is kept for symmetry with
3318 to_canonical_dir_spec. If indicators of VMS syntax found, return input
3322 __gnat_to_host_dir_spec (char *dirspec
, int prefixflag ATTRIBUTE_UNUSED
)
3324 int len
= strlen (dirspec
);
3326 strncpy (new_host_dirspec
, dirspec
, MAXPATH
);
3327 new_host_dirspec
[MAXPATH
- 1] = (char) 0;
3329 if (strchr (new_host_dirspec
, ']') || strchr (new_host_dirspec
, ':'))
3330 return new_host_dirspec
;
3332 while (len
> 1 && new_host_dirspec
[len
- 1] == '/')
3334 new_host_dirspec
[len
- 1] = 0;
3338 decc$
to_vms (new_host_dirspec
, translate_unix
, 1, 2);
3339 strncpy (new_host_dirspec
, filename_buff
, MAXPATH
);
3340 new_host_dirspec
[MAXPATH
- 1] = (char) 0;
3342 return new_host_dirspec
;
3345 /* Translate a Unix syntax file specification into VMS syntax.
3346 If indicators of VMS syntax found, return input string. */
3349 __gnat_to_host_file_spec (char *filespec
)
3351 strncpy (new_host_filespec
, "", MAXPATH
);
3352 if (strchr (filespec
, ']') || strchr (filespec
, ':'))
3354 strncpy (new_host_filespec
, filespec
, MAXPATH
);
3358 decc$
to_vms (filespec
, translate_unix
, 1, 1);
3359 strncpy (new_host_filespec
, filename_buff
, MAXPATH
);
3362 new_host_filespec
[MAXPATH
- 1] = (char) 0;
3364 return new_host_filespec
;
3368 __gnat_adjust_os_resource_limits ()
3370 SYS$
ADJWSL (131072, 0);
3375 /* Dummy functions for Osint import for non-VMS systems. */
3378 __gnat_to_canonical_file_list_init
3379 (char *dirspec ATTRIBUTE_UNUSED
, int onlydirs ATTRIBUTE_UNUSED
)
3385 __gnat_to_canonical_file_list_next (void)
3387 static char empty
[] = "";
3392 __gnat_to_canonical_file_list_free (void)
3397 __gnat_to_canonical_dir_spec (char *dirspec
, int prefixflag ATTRIBUTE_UNUSED
)
3403 __gnat_to_canonical_file_spec (char *filespec
)
3409 __gnat_to_canonical_path_spec (char *pathspec
)
3415 __gnat_to_host_dir_spec (char *dirspec
, int prefixflag ATTRIBUTE_UNUSED
)
3421 __gnat_to_host_file_spec (char *filespec
)
3427 __gnat_adjust_os_resource_limits (void)
3433 #if defined (__mips_vxworks)
3437 CACHE_USER_FLUSH (0, ENTIRE_CACHE
);
3441 #if defined (IS_CROSS) \
3442 || (! ((defined (sparc) || defined (i386)) && defined (sun) \
3443 && defined (__SVR4)) \
3444 && ! (defined (linux) && (defined (i386) || defined (__x86_64__))) \
3445 && ! (defined (linux) && defined (__ia64__)) \
3446 && ! (defined (linux) && defined (powerpc)) \
3447 && ! defined (__FreeBSD__) \
3448 && ! defined (__Lynx__) \
3449 && ! defined (__hpux__) \
3450 && ! defined (__APPLE__) \
3451 && ! defined (_AIX) \
3452 && ! (defined (__alpha__) && defined (__osf__)) \
3453 && ! defined (VMS) \
3454 && ! defined (__MINGW32__) \
3455 && ! (defined (__mips) && defined (__sgi)))
3457 /* Dummy function to satisfy g-trasym.o. See the preprocessor conditional
3458 just above for a list of native platforms that provide a non-dummy
3459 version of this procedure in libaddr2line.a. */
3462 convert_addresses (const char *file_name ATTRIBUTE_UNUSED
,
3463 void *addrs ATTRIBUTE_UNUSED
,
3464 int n_addr ATTRIBUTE_UNUSED
,
3465 void *buf ATTRIBUTE_UNUSED
,
3466 int *len ATTRIBUTE_UNUSED
)
3472 #if defined (_WIN32)
3473 int __gnat_argument_needs_quote
= 1;
3475 int __gnat_argument_needs_quote
= 0;
3478 /* This option is used to enable/disable object files handling from the
3479 binder file by the GNAT Project module. For example, this is disabled on
3480 Windows (prior to GCC 3.4) as it is already done by the mdll module.
3481 Stating with GCC 3.4 the shared libraries are not based on mdll
3482 anymore as it uses the GCC's -shared option */
3483 #if defined (_WIN32) \
3484 && ((__GNUC__ < 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ < 4)))
3485 int __gnat_prj_add_obj_files
= 0;
3487 int __gnat_prj_add_obj_files
= 1;
3490 /* char used as prefix/suffix for environment variables */
3491 #if defined (_WIN32)
3492 char __gnat_environment_char
= '%';
3494 char __gnat_environment_char
= '$';
3497 /* This functions copy the file attributes from a source file to a
3500 mode = 0 : In this mode copy only the file time stamps (last access and
3501 last modification time stamps).
3503 mode = 1 : In this mode, time stamps and read/write/execute attributes are
3506 Returns 0 if operation was successful and -1 in case of error. */
3509 __gnat_copy_attribs (char *from
, char *to
, int mode
)
3511 #if defined (VMS) || defined (__vxworks) || defined (__nucleus__)
3514 #elif defined (_WIN32) && !defined (RTX)
3515 TCHAR wfrom
[GNAT_MAX_PATH_LEN
+ 2];
3516 TCHAR wto
[GNAT_MAX_PATH_LEN
+ 2];
3518 FILETIME fct
, flat
, flwt
;
3521 S2WSC (wfrom
, from
, GNAT_MAX_PATH_LEN
+ 2);
3522 S2WSC (wto
, to
, GNAT_MAX_PATH_LEN
+ 2);
3524 /* retrieve from times */
3527 (wfrom
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3529 if (hfrom
== INVALID_HANDLE_VALUE
)
3532 res
= GetFileTime (hfrom
, &fct
, &flat
, &flwt
);
3534 CloseHandle (hfrom
);
3539 /* retrieve from times */
3542 (wto
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3544 if (hto
== INVALID_HANDLE_VALUE
)
3547 res
= SetFileTime (hto
, NULL
, &flat
, &flwt
);
3554 /* Set file attributes in full mode. */
3558 DWORD attribs
= GetFileAttributes (wfrom
);
3560 if (attribs
== INVALID_FILE_ATTRIBUTES
)
3563 res
= SetFileAttributes (wto
, attribs
);
3571 GNAT_STRUCT_STAT fbuf
;
3572 struct utimbuf tbuf
;
3574 if (GNAT_STAT (from
, &fbuf
) == -1)
3579 tbuf
.actime
= fbuf
.st_atime
;
3580 tbuf
.modtime
= fbuf
.st_mtime
;
3582 if (utime (to
, &tbuf
) == -1)
3589 if (chmod (to
, fbuf
.st_mode
) == -1)
3600 __gnat_lseek (int fd
, long offset
, int whence
)
3602 return (int) lseek (fd
, offset
, whence
);
3605 /* This function returns the major version number of GCC being used. */
3607 get_gcc_version (void)
3612 return (int) (version_string
[0] - '0');
3617 __gnat_set_close_on_exec (int fd ATTRIBUTE_UNUSED
,
3618 int close_on_exec_p ATTRIBUTE_UNUSED
)
3620 #if defined (F_GETFD) && defined (FD_CLOEXEC) && ! defined (__vxworks)
3621 int flags
= fcntl (fd
, F_GETFD
, 0);
3624 if (close_on_exec_p
)
3625 flags
|= FD_CLOEXEC
;
3627 flags
&= ~FD_CLOEXEC
;
3628 return fcntl (fd
, F_SETFD
, flags
| FD_CLOEXEC
);
3629 #elif defined(_WIN32)
3630 HANDLE h
= (HANDLE
) _get_osfhandle (fd
);
3631 if (h
== (HANDLE
) -1)
3633 if (close_on_exec_p
)
3634 return ! SetHandleInformation (h
, HANDLE_FLAG_INHERIT
, 0);
3635 return ! SetHandleInformation (h
, HANDLE_FLAG_INHERIT
,
3636 HANDLE_FLAG_INHERIT
);
3638 /* TODO: Unimplemented. */
3643 /* Indicates if platforms supports automatic initialization through the
3644 constructor mechanism */
3646 __gnat_binder_supports_auto_init (void)
3655 /* Indicates that Stand-Alone Libraries are automatically initialized through
3656 the constructor mechanism */
3658 __gnat_sals_init_using_constructors (void)
3660 #if defined (__vxworks) || defined (__Lynx__) || defined (VMS)
3669 /* In RTX mode, the procedure to get the time (as file time) is different
3670 in RTSS mode and Win32 mode. In order to avoid duplicating an Ada file,
3671 we introduce an intermediate procedure to link against the corresponding
3672 one in each situation. */
3674 extern void GetTimeAsFileTime(LPFILETIME pTime
);
3676 void GetTimeAsFileTime(LPFILETIME pTime
)
3679 RtGetRtssTimeAsFileTime (pTime
); /* RTSS interface */
3681 GetSystemTimeAsFileTime (pTime
); /* w32 interface */
3686 /* Add symbol that is required to link. It would otherwise be taken from
3687 libgcc.a and it would try to use the gcc constructors that are not
3688 supported by Microsoft linker. */
3690 extern void __main (void);
3692 void __main (void) {}
3697 /* There is no function in the glibc to retrieve the LWP of the current
3698 thread. We need to do a system call in order to retrieve this
3700 #include <sys/syscall.h>
3701 void *__gnat_lwp_self (void)
3703 return (void *) syscall (__NR_gettid
);