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 */
54 /* If SMP, access vxCpuConfiguredGet */
55 #ifdef _WRS_CONFIG_SMP
57 #endif /* _WRS_CONFIG_SMP */
59 /* We need to know the VxWorks version because some file operations
60 (such as chmod) are only available on VxWorks 6. */
65 #if (defined (__mips) && defined (__sgi)) || defined (__APPLE__)
69 #if defined (__hpux__)
70 #include <sys/param.h>
71 #include <sys/pstat.h>
76 #define HOST_EXECUTABLE_SUFFIX ".exe"
77 #define HOST_OBJECT_SUFFIX ".obj"
92 /* S_IREAD and S_IWRITE are not defined in VxWorks */
94 #define S_IREAD (S_IRUSR | S_IRGRP | S_IROTH)
98 #define S_IWRITE (S_IWUSR)
102 /* We don't have libiberty, so use malloc. */
103 #define xmalloc(S) malloc (S)
104 #define xrealloc(V,S) realloc (V,S)
111 #if defined (__MINGW32__)
119 /* Current code page to use, set in initialize.c. */
120 UINT CurrentCodePage
;
123 #include <sys/utime.h>
125 /* For isalpha-like tests in the compiler, we're expected to resort to
126 safe-ctype.h/ISALPHA. This isn't available for the runtime library
127 build, so we fallback on ctype.h/isalpha there. */
131 #define ISALPHA isalpha
134 #elif defined (__Lynx__)
136 /* Lynx utime.h only defines the entities of interest to us if
137 defined (VMOS_DEV), so ... */
146 /* wait.h processing */
149 #include <sys/wait.h>
151 #elif defined (__vxworks) && defined (__RTP__)
153 #elif defined (__Lynx__)
154 /* ??? We really need wait.h and it includes resource.h on Lynx. GCC
155 has a resource.h header as well, included instead of the lynx
156 version in our setup, causing lots of errors. We don't really need
157 the lynx contents of this file, so just workaround the issue by
158 preventing the inclusion of the GCC header from doing anything. */
159 #define GCC_RESOURCE_H
160 #include <sys/wait.h>
161 #elif defined (__nucleus__)
162 /* No wait() or waitpid() calls available */
165 #include <sys/wait.h>
171 /* Header files and definitions for __gnat_set_file_time_name. */
173 #define __NEW_STARLET 1
175 #include <vms/atrdef.h>
176 #include <vms/fibdef.h>
177 #include <vms/stsdef.h>
178 #include <vms/iodef.h>
180 #include <vms/descrip.h>
184 /* Use native 64-bit arithmetic. */
185 #define unix_time_to_vms(X,Y) \
186 { unsigned long long reftime, tmptime = (X); \
187 $DESCRIPTOR (unixtime,"1-JAN-1970 0:00:00.00"); \
188 SYS$BINTIM (&unixtime, &reftime); \
189 Y = tmptime * 10000000 + reftime; }
191 /* descrip.h doesn't have everything ... */
192 typedef struct fibdef
* __fibdef_ptr32
__attribute__ (( mode (SI
) ));
193 struct dsc$descriptor_fib
195 unsigned int fib$l_len
;
196 __fibdef_ptr32 fib$l_addr
;
199 /* I/O Status Block. */
202 unsigned short status
, count
;
206 static char *tryfile
;
208 /* Variable length string. */
212 char string
[NAM$C_MAXRSS
+1];
215 #define SYI$_ACTIVECPU_CNT 0x111e
216 extern int LIB$
GETSYI (int *, unsigned int *);
233 #define DIR_SEPARATOR '\\'
238 /* Define symbols O_BINARY and O_TEXT as harmless zeroes if they are not
239 defined in the current system. On DOS-like systems these flags control
240 whether the file is opened/created in text-translation mode (CR/LF in
241 external file mapped to LF in internal file), but in Unix-like systems,
242 no text translation is required, so these flags have no effect. */
252 #ifndef HOST_EXECUTABLE_SUFFIX
253 #define HOST_EXECUTABLE_SUFFIX ""
256 #ifndef HOST_OBJECT_SUFFIX
257 #define HOST_OBJECT_SUFFIX ".o"
260 #ifndef PATH_SEPARATOR
261 #define PATH_SEPARATOR ':'
264 #ifndef DIR_SEPARATOR
265 #define DIR_SEPARATOR '/'
268 /* Check for cross-compilation */
269 #if defined (CROSS_COMPILE) || defined (CROSS_DIRECTORY_STRUCTURE)
271 int __gnat_is_cross_compiler
= 1;
274 int __gnat_is_cross_compiler
= 0;
277 char __gnat_dir_separator
= DIR_SEPARATOR
;
279 char __gnat_path_separator
= PATH_SEPARATOR
;
281 /* The GNAT_LIBRARY_TEMPLATE contains a list of expressions that define
282 the base filenames that libraries specified with -lsomelib options
283 may have. This is used by GNATMAKE to check whether an executable
284 is up-to-date or not. The syntax is
286 library_template ::= { pattern ; } pattern NUL
287 pattern ::= [ prefix ] * [ postfix ]
289 These should only specify names of static libraries as it makes
290 no sense to determine at link time if dynamic-link libraries are
291 up to date or not. Any libraries that are not found are supposed
294 * if they are needed but not present, the link
297 * otherwise they are libraries in the system paths and so
298 they are considered part of the system and not checked
301 ??? This should be part of a GNAT host-specific compiler
302 file instead of being included in all user applications
303 as well. This is only a temporary work-around for 3.11b. */
305 #ifndef GNAT_LIBRARY_TEMPLATE
307 #define GNAT_LIBRARY_TEMPLATE "*.olb"
309 #define GNAT_LIBRARY_TEMPLATE "lib*.a"
313 const char *__gnat_library_template
= GNAT_LIBRARY_TEMPLATE
;
315 /* This variable is used in hostparm.ads to say whether the host is a VMS
324 #define GNAT_MAX_PATH_LEN 256 /* PATH_MAX */
326 #elif defined (__vxworks) || defined (__OPENNT) || defined(__nucleus__)
327 #define GNAT_MAX_PATH_LEN PATH_MAX
331 #if defined (__MINGW32__)
335 #include <sys/param.h>
339 #include <sys/param.h>
343 #define GNAT_MAX_PATH_LEN MAXPATHLEN
345 #define GNAT_MAX_PATH_LEN 256
350 /* Used for Ada bindings */
351 int __gnat_size_of_file_attributes
= sizeof (struct file_attributes
);
353 /* Reset the file attributes as if no system call had been performed */
354 void __gnat_stat_to_attr (int fd
, char* name
, struct file_attributes
* attr
);
356 /* The __gnat_max_path_len variable is used to export the maximum
357 length of a path name to Ada code. max_path_len is also provided
358 for compatibility with older GNAT versions, please do not use
361 int __gnat_max_path_len
= GNAT_MAX_PATH_LEN
;
362 int max_path_len
= GNAT_MAX_PATH_LEN
;
364 /* Control whether we can use ACL on Windows. */
366 int __gnat_use_acl
= 1;
368 /* The following macro HAVE_READDIR_R should be defined if the
369 system provides the routine readdir_r. */
370 #undef HAVE_READDIR_R
372 #if defined(VMS) && defined (__LONG_POINTERS)
374 /* Return a 32 bit pointer to an array of 32 bit pointers
375 given a 64 bit pointer to an array of 64 bit pointers */
377 typedef __char_ptr32
*__char_ptr_char_ptr32
__attribute__ ((mode (SI
)));
379 static __char_ptr_char_ptr32
380 to_ptr32 (char **ptr64
)
383 __char_ptr_char_ptr32 short_argv
;
385 for (argc
=0; ptr64
[argc
]; argc
++);
387 /* Reallocate argv with 32 bit pointers. */
388 short_argv
= (__char_ptr_char_ptr32
) decc$malloc
389 (sizeof (__char_ptr32
) * (argc
+ 1));
391 for (argc
=0; ptr64
[argc
]; argc
++)
392 short_argv
[argc
] = (__char_ptr32
) decc$
strdup (ptr64
[argc
]);
394 short_argv
[argc
] = (__char_ptr32
) 0;
398 #define MAYBE_TO_PTR32(argv) to_ptr32 (argv)
400 #define MAYBE_TO_PTR32(argv) argv
403 static const char ATTR_UNSET
= 127;
406 __gnat_reset_attributes
407 (struct file_attributes
* attr
)
409 attr
->exists
= ATTR_UNSET
;
411 attr
->writable
= ATTR_UNSET
;
412 attr
->readable
= ATTR_UNSET
;
413 attr
->executable
= ATTR_UNSET
;
415 attr
->regular
= ATTR_UNSET
;
416 attr
->symbolic_link
= ATTR_UNSET
;
417 attr
->directory
= ATTR_UNSET
;
419 attr
->timestamp
= (OS_Time
)-2;
420 attr
->file_length
= -1;
427 time_t res
= time (NULL
);
428 return (OS_Time
) res
;
431 /* Return the current local time as a string in the ISO 8601 format of
432 "YYYY-MM-DD HH:MM:SS.SS". The returned string is 22 + 1 (NULL) characters
436 __gnat_current_time_string
439 const char *format
= "%Y-%m-%d %H:%M:%S";
440 /* Format string necessary to describe the ISO 8601 format */
442 const time_t t_val
= time (NULL
);
444 strftime (result
, 22, format
, localtime (&t_val
));
445 /* Convert the local time into a string following the ISO format, copying
446 at most 22 characters into the result string. */
451 /* The sub-seconds are manually set to zero since type time_t lacks the
452 precision necessary for nanoseconds. */
466 time_t time
= (time_t) *p_time
;
469 /* On Windows systems, the time is sometimes rounded up to the nearest
470 even second, so if the number of seconds is odd, increment it. */
476 res
= localtime (&time
);
478 res
= gmtime (&time
);
483 *p_year
= res
->tm_year
;
484 *p_month
= res
->tm_mon
;
485 *p_day
= res
->tm_mday
;
486 *p_hours
= res
->tm_hour
;
487 *p_mins
= res
->tm_min
;
488 *p_secs
= res
->tm_sec
;
491 *p_year
= *p_month
= *p_day
= *p_hours
= *p_mins
= *p_secs
= 0;
494 /* Place the contents of the symbolic link named PATH in the buffer BUF,
495 which has size BUFSIZ. If PATH is a symbolic link, then return the number
496 of characters of its content in BUF. Otherwise, return -1.
497 For systems not supporting symbolic links, always return -1. */
500 __gnat_readlink (char *path ATTRIBUTE_UNUSED
,
501 char *buf ATTRIBUTE_UNUSED
,
502 size_t bufsiz ATTRIBUTE_UNUSED
)
504 #if defined (_WIN32) || defined (VMS) \
505 || defined(__vxworks) || defined (__nucleus__)
508 return readlink (path
, buf
, bufsiz
);
512 /* Creates a symbolic link named NEWPATH which contains the string OLDPATH.
513 If NEWPATH exists it will NOT be overwritten.
514 For systems not supporting symbolic links, always return -1. */
517 __gnat_symlink (char *oldpath ATTRIBUTE_UNUSED
,
518 char *newpath ATTRIBUTE_UNUSED
)
520 #if defined (_WIN32) || defined (VMS) \
521 || defined(__vxworks) || defined (__nucleus__)
524 return symlink (oldpath
, newpath
);
528 /* Try to lock a file, return 1 if success. */
530 #if defined (__vxworks) || defined (__nucleus__) \
531 || defined (_WIN32) || defined (VMS)
533 /* Version that does not use link. */
536 __gnat_try_lock (char *dir
, char *file
)
540 TCHAR wfull_path
[GNAT_MAX_PATH_LEN
];
541 TCHAR wfile
[GNAT_MAX_PATH_LEN
];
542 TCHAR wdir
[GNAT_MAX_PATH_LEN
];
544 S2WSC (wdir
, dir
, GNAT_MAX_PATH_LEN
);
545 S2WSC (wfile
, file
, GNAT_MAX_PATH_LEN
);
547 _stprintf (wfull_path
, _T("%s%c%s"), wdir
, _T(DIR_SEPARATOR
), wfile
);
548 fd
= _topen (wfull_path
, O_CREAT
| O_EXCL
, 0600);
552 sprintf (full_path
, "%s%c%s", dir
, DIR_SEPARATOR
, file
);
553 fd
= open (full_path
, O_CREAT
| O_EXCL
, 0600);
565 /* Version using link(), more secure over NFS. */
566 /* See TN 6913-016 for discussion ??? */
569 __gnat_try_lock (char *dir
, char *file
)
573 GNAT_STRUCT_STAT stat_result
;
576 sprintf (full_path
, "%s%c%s", dir
, DIR_SEPARATOR
, file
);
577 sprintf (temp_file
, "%s%cTMP-%ld-%ld",
578 dir
, DIR_SEPARATOR
, (long)getpid(), (long)getppid ());
580 /* Create the temporary file and write the process number. */
581 fd
= open (temp_file
, O_CREAT
| O_WRONLY
, 0600);
587 /* Link it with the new file. */
588 link (temp_file
, full_path
);
590 /* Count the references on the old one. If we have a count of two, then
591 the link did succeed. Remove the temporary file before returning. */
592 __gnat_stat (temp_file
, &stat_result
);
594 return stat_result
.st_nlink
== 2;
598 /* Return the maximum file name length. */
601 __gnat_get_maximum_file_name_length (void)
604 if (getenv ("GNAT$EXTENDED_FILE_SPECIFICATIONS"))
613 /* Return nonzero if file names are case sensitive. */
615 static int file_names_case_sensitive_cache
= -1;
618 __gnat_get_file_names_case_sensitive (void)
620 if (file_names_case_sensitive_cache
== -1)
622 const char *sensitive
= getenv ("GNAT_FILE_NAME_CASE_SENSITIVE");
624 if (sensitive
!= NULL
625 && (sensitive
[0] == '0' || sensitive
[0] == '1')
626 && sensitive
[1] == '\0')
627 file_names_case_sensitive_cache
= sensitive
[0] - '0';
629 #if defined (VMS) || defined (WINNT) || defined (__APPLE__)
630 file_names_case_sensitive_cache
= 0;
632 file_names_case_sensitive_cache
= 1;
635 return file_names_case_sensitive_cache
;
638 /* Return nonzero if environment variables are case sensitive. */
641 __gnat_get_env_vars_case_sensitive (void)
643 #if defined (VMS) || defined (WINNT)
651 __gnat_get_default_identifier_character_set (void)
656 /* Return the current working directory. */
659 __gnat_get_current_dir (char *dir
, int *length
)
661 #if defined (__MINGW32__)
662 TCHAR wdir
[GNAT_MAX_PATH_LEN
];
664 _tgetcwd (wdir
, *length
);
666 WS2SC (dir
, wdir
, GNAT_MAX_PATH_LEN
);
669 /* Force Unix style, which is what GNAT uses internally. */
670 getcwd (dir
, *length
, 0);
672 getcwd (dir
, *length
);
675 *length
= strlen (dir
);
677 if (dir
[*length
- 1] != DIR_SEPARATOR
)
679 dir
[*length
] = DIR_SEPARATOR
;
685 /* Return the suffix for object files. */
688 __gnat_get_object_suffix_ptr (int *len
, const char **value
)
690 *value
= HOST_OBJECT_SUFFIX
;
695 *len
= strlen (*value
);
700 /* Return the suffix for executable files. */
703 __gnat_get_executable_suffix_ptr (int *len
, const char **value
)
705 *value
= HOST_EXECUTABLE_SUFFIX
;
709 *len
= strlen (*value
);
714 /* Return the suffix for debuggable files. Usually this is the same as the
715 executable extension. */
718 __gnat_get_debuggable_suffix_ptr (int *len
, const char **value
)
720 *value
= HOST_EXECUTABLE_SUFFIX
;
725 *len
= strlen (*value
);
730 /* Returns the OS filename and corresponding encoding. */
733 __gnat_os_filename (char *filename ATTRIBUTE_UNUSED
,
734 char *w_filename ATTRIBUTE_UNUSED
,
735 char *os_name
, int *o_length
,
736 char *encoding ATTRIBUTE_UNUSED
, int *e_length
)
738 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (IS_CROSS)
739 WS2SC (os_name
, (TCHAR
*)w_filename
, (DWORD
)*o_length
);
740 *o_length
= strlen (os_name
);
741 strcpy (encoding
, "encoding=utf8");
742 *e_length
= strlen (encoding
);
744 strcpy (os_name
, filename
);
745 *o_length
= strlen (filename
);
753 __gnat_unlink (char *path
)
755 #if defined (__MINGW32__) && ! defined (__vxworks) && ! defined (IS_CROSS)
757 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
759 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
760 return _tunlink (wpath
);
763 return unlink (path
);
770 __gnat_rename (char *from
, char *to
)
772 #if defined (__MINGW32__) && ! defined (__vxworks) && ! defined (IS_CROSS)
774 TCHAR wfrom
[GNAT_MAX_PATH_LEN
], wto
[GNAT_MAX_PATH_LEN
];
776 S2WSC (wfrom
, from
, GNAT_MAX_PATH_LEN
);
777 S2WSC (wto
, to
, GNAT_MAX_PATH_LEN
);
778 return _trename (wfrom
, wto
);
781 return rename (from
, to
);
785 /* Changing directory. */
788 __gnat_chdir (char *path
)
790 #if defined (__MINGW32__) && ! defined (__vxworks) && ! defined (IS_CROSS)
792 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
794 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
795 return _tchdir (wpath
);
802 /* Removing a directory. */
805 __gnat_rmdir (char *path
)
807 #if defined (__MINGW32__) && ! defined (__vxworks) && ! defined (IS_CROSS)
809 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
811 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
812 return _trmdir (wpath
);
814 #elif defined (VTHREADS)
815 /* rmdir not available */
823 __gnat_fopen (char *path
, char *mode
, int encoding ATTRIBUTE_UNUSED
)
825 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (IS_CROSS)
826 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
829 S2WS (wmode
, mode
, 10);
831 if (encoding
== Encoding_Unspecified
)
832 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
833 else if (encoding
== Encoding_UTF8
)
834 S2WSU (wpath
, path
, GNAT_MAX_PATH_LEN
);
836 S2WS (wpath
, path
, GNAT_MAX_PATH_LEN
);
838 return _tfopen (wpath
, wmode
);
840 return decc$
fopen (path
, mode
);
842 return GNAT_FOPEN (path
, mode
);
847 __gnat_freopen (char *path
,
850 int encoding ATTRIBUTE_UNUSED
)
852 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (IS_CROSS)
853 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
856 S2WS (wmode
, mode
, 10);
858 if (encoding
== Encoding_Unspecified
)
859 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
860 else if (encoding
== Encoding_UTF8
)
861 S2WSU (wpath
, path
, GNAT_MAX_PATH_LEN
);
863 S2WS (wpath
, path
, GNAT_MAX_PATH_LEN
);
865 return _tfreopen (wpath
, wmode
, stream
);
867 return decc$
freopen (path
, mode
, stream
);
869 return freopen (path
, mode
, stream
);
874 __gnat_open_read (char *path
, int fmode
)
877 int o_fmode
= O_BINARY
;
883 /* Optional arguments mbc,deq,fop increase read performance. */
884 fd
= open (path
, O_RDONLY
| o_fmode
, 0444,
885 "mbc=16", "deq=64", "fop=tef");
886 #elif defined (__vxworks)
887 fd
= open (path
, O_RDONLY
| o_fmode
, 0444);
888 #elif defined (__MINGW32__)
890 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
892 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
893 fd
= _topen (wpath
, O_RDONLY
| o_fmode
, 0444);
896 fd
= open (path
, O_RDONLY
| o_fmode
);
899 return fd
< 0 ? -1 : fd
;
902 #if defined (__MINGW32__)
903 #define PERM (S_IREAD | S_IWRITE)
905 /* Excerpt from DECC C RTL Reference Manual:
906 To create files with OpenVMS RMS default protections using the UNIX
907 system-call functions umask, mkdir, creat, and open, call mkdir, creat,
908 and open with a file-protection mode argument of 0777 in a program
909 that never specifically calls umask. These default protections include
910 correctly establishing protections based on ACLs, previous versions of
914 #define PERM (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
918 __gnat_open_rw (char *path
, int fmode
)
921 int o_fmode
= O_BINARY
;
927 fd
= open (path
, O_RDWR
| 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_RDWR
| o_fmode
, PERM
);
937 fd
= open (path
, O_RDWR
| o_fmode
, PERM
);
940 return fd
< 0 ? -1 : fd
;
944 __gnat_open_create (char *path
, int fmode
)
947 int o_fmode
= O_BINARY
;
953 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| o_fmode
, PERM
,
954 "mbc=16", "deq=64", "fop=tef");
955 #elif defined (__MINGW32__)
957 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
959 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
960 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_TRUNC
| o_fmode
, PERM
);
963 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| o_fmode
, PERM
);
966 return fd
< 0 ? -1 : fd
;
970 __gnat_create_output_file (char *path
)
974 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
, PERM
,
975 "rfm=stmlf", "ctx=rec", "rat=none", "rop=nlk",
976 "shr=del,get,put,upd");
977 #elif defined (__MINGW32__)
979 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
981 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
982 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
, PERM
);
985 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
, PERM
);
988 return fd
< 0 ? -1 : fd
;
992 __gnat_create_output_file_new (char *path
)
996 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
| O_EXCL
, PERM
,
997 "rfm=stmlf", "ctx=rec", "rat=none", "rop=nlk",
998 "shr=del,get,put,upd");
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_TRUNC
| O_TEXT
| O_EXCL
, PERM
);
1007 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
| O_EXCL
, PERM
);
1010 return fd
< 0 ? -1 : fd
;
1014 __gnat_open_append (char *path
, int fmode
)
1017 int o_fmode
= O_BINARY
;
1023 fd
= open (path
, O_WRONLY
| O_CREAT
| O_APPEND
| o_fmode
, PERM
,
1024 "mbc=16", "deq=64", "fop=tef");
1025 #elif defined (__MINGW32__)
1027 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
1029 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
1030 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_APPEND
| o_fmode
, PERM
);
1033 fd
= open (path
, O_WRONLY
| O_CREAT
| O_APPEND
| o_fmode
, PERM
);
1036 return fd
< 0 ? -1 : fd
;
1039 /* Open a new file. Return error (-1) if the file already exists. */
1042 __gnat_open_new (char *path
, int fmode
)
1045 int o_fmode
= O_BINARY
;
1051 fd
= open (path
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
,
1052 "mbc=16", "deq=64", "fop=tef");
1053 #elif defined (__MINGW32__)
1055 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
1057 S2WSC (wpath
, path
, GNAT_MAX_PATH_LEN
);
1058 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
);
1061 fd
= open (path
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
);
1064 return fd
< 0 ? -1 : fd
;
1067 /* Open a new temp file. Return error (-1) if the file already exists.
1068 Special options for VMS allow the file to be shared between parent and child
1069 processes, however they really slow down output. Used in gnatchop. */
1072 __gnat_open_new_temp (char *path
, int fmode
)
1075 int o_fmode
= O_BINARY
;
1077 strcpy (path
, "GNAT-XXXXXX");
1079 #if (defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) \
1080 || defined (linux) || defined(__GLIBC__)) && !defined (__vxworks)
1081 return mkstemp (path
);
1082 #elif defined (__Lynx__)
1084 #elif defined (__nucleus__)
1087 if (mktemp (path
) == NULL
)
1095 fd
= open (path
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
,
1096 "rfm=stmlf", "ctx=rec", "rat=none", "shr=del,get,put,upd",
1097 "mbc=16", "deq=64", "fop=tef");
1099 fd
= open (path
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
);
1102 return fd
< 0 ? -1 : fd
;
1105 /****************************************************************
1106 ** Perform a call to GNAT_STAT or GNAT_FSTAT, and extract as much information
1107 ** as possible from it, storing the result in a cache for later reuse
1108 ****************************************************************/
1111 __gnat_stat_to_attr (int fd
, char* name
, struct file_attributes
* attr
)
1113 GNAT_STRUCT_STAT statbuf
;
1117 ret
= GNAT_FSTAT (fd
, &statbuf
);
1119 ret
= __gnat_stat (name
, &statbuf
);
1121 attr
->regular
= (!ret
&& S_ISREG (statbuf
.st_mode
));
1122 attr
->directory
= (!ret
&& S_ISDIR (statbuf
.st_mode
));
1125 attr
->file_length
= 0;
1127 /* st_size may be 32 bits, or 64 bits which is converted to long. We
1128 don't return a useful value for files larger than 2 gigabytes in
1130 attr
->file_length
= statbuf
.st_size
; /* all systems */
1132 attr
->exists
= !ret
;
1134 #if !defined (_WIN32) || defined (RTX)
1135 /* on Windows requires extra system call, see __gnat_is_readable_file_attr */
1136 attr
->readable
= (!ret
&& (statbuf
.st_mode
& S_IRUSR
));
1137 attr
->writable
= (!ret
&& (statbuf
.st_mode
& S_IWUSR
));
1138 attr
->executable
= (!ret
&& (statbuf
.st_mode
& S_IXUSR
));
1142 attr
->timestamp
= (OS_Time
)-1;
1145 /* VMS has file versioning. */
1146 attr
->timestamp
= (OS_Time
)statbuf
.st_ctime
;
1148 attr
->timestamp
= (OS_Time
)statbuf
.st_mtime
;
1153 /****************************************************************
1154 ** Return the number of bytes in the specified file
1155 ****************************************************************/
1158 __gnat_file_length_attr (int fd
, char* name
, struct file_attributes
* attr
)
1160 if (attr
->file_length
== -1) {
1161 __gnat_stat_to_attr (fd
, name
, attr
);
1164 return attr
->file_length
;
1168 __gnat_file_length (int fd
)
1170 struct file_attributes attr
;
1171 __gnat_reset_attributes (&attr
);
1172 return __gnat_file_length_attr (fd
, NULL
, &attr
);
1176 __gnat_named_file_length (char *name
)
1178 struct file_attributes attr
;
1179 __gnat_reset_attributes (&attr
);
1180 return __gnat_file_length_attr (-1, name
, &attr
);
1183 /* Create a temporary filename and put it in string pointed to by
1187 __gnat_tmp_name (char *tmp_filename
)
1190 /* Variable used to create a series of unique names */
1191 static int counter
= 0;
1193 /* RTX in RTSS mode does not support tempnam nor tmpnam so we emulate it */
1194 strcpy (tmp_filename
, "c:\\WINDOWS\\Temp\\gnat-");
1195 sprintf (&tmp_filename
[strlen (tmp_filename
)], "%d\0", counter
++);
1197 #elif defined (__MINGW32__)
1202 /* tempnam tries to create a temporary file in directory pointed to by
1203 TMP environment variable, in c:\temp if TMP is not set, and in
1204 directory specified by P_tmpdir in stdio.h if c:\temp does not
1205 exist. The filename will be created with the prefix "gnat-". */
1207 sprintf (prefix
, "gnat-%d-", (int)getpid());
1208 pname
= (char *) _tempnam ("c:\\temp", prefix
);
1210 /* if pname is NULL, the file was not created properly, the disk is full
1211 or there is no more free temporary files */
1214 *tmp_filename
= '\0';
1216 /* If pname start with a back slash and not path information it means that
1217 the filename is valid for the current working directory. */
1219 else if (pname
[0] == '\\')
1221 strcpy (tmp_filename
, ".\\");
1222 strcat (tmp_filename
, pname
+1);
1225 strcpy (tmp_filename
, pname
);
1230 #elif defined (linux) || defined (__FreeBSD__) || defined (__NetBSD__) \
1231 || defined (__OpenBSD__) || defined(__GLIBC__)
1232 #define MAX_SAFE_PATH 1000
1233 char *tmpdir
= getenv ("TMPDIR");
1235 /* If tmpdir is longer than MAX_SAFE_PATH, revert to default value to avoid
1236 a buffer overflow. */
1237 if (tmpdir
== NULL
|| strlen (tmpdir
) > MAX_SAFE_PATH
)
1238 strcpy (tmp_filename
, "/tmp/gnat-XXXXXX");
1240 sprintf (tmp_filename
, "%s/gnat-XXXXXX", tmpdir
);
1242 close (mkstemp(tmp_filename
));
1244 tmpnam (tmp_filename
);
1248 /* Open directory and returns a DIR pointer. */
1250 DIR* __gnat_opendir (char *name
)
1253 /* Not supported in RTX */
1257 #elif defined (__MINGW32__)
1258 TCHAR wname
[GNAT_MAX_PATH_LEN
];
1260 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
);
1261 return (DIR*)_topendir (wname
);
1264 return opendir (name
);
1268 /* Read the next entry in a directory. The returned string points somewhere
1272 __gnat_readdir (DIR *dirp
, char *buffer
, int *len
)
1275 /* Not supported in RTX */
1279 #elif defined (__MINGW32__)
1280 struct _tdirent
*dirent
= _treaddir ((_TDIR
*)dirp
);
1284 WS2SC (buffer
, dirent
->d_name
, GNAT_MAX_PATH_LEN
);
1285 *len
= strlen (buffer
);
1292 #elif defined (HAVE_READDIR_R)
1293 /* If possible, try to use the thread-safe version. */
1294 if (readdir_r (dirp
, buffer
) != NULL
)
1296 *len
= strlen (((struct dirent
*) buffer
)->d_name
);
1297 return ((struct dirent
*) buffer
)->d_name
;
1303 struct dirent
*dirent
= (struct dirent
*) readdir (dirp
);
1307 strcpy (buffer
, dirent
->d_name
);
1308 *len
= strlen (buffer
);
1317 /* Close a directory entry. */
1319 int __gnat_closedir (DIR *dirp
)
1322 /* Not supported in RTX */
1326 #elif defined (__MINGW32__)
1327 return _tclosedir ((_TDIR
*)dirp
);
1330 return closedir (dirp
);
1334 /* Returns 1 if readdir is thread safe, 0 otherwise. */
1337 __gnat_readdir_is_thread_safe (void)
1339 #ifdef HAVE_READDIR_R
1346 #if defined (_WIN32) && !defined (RTX)
1347 /* Number of seconds between <Jan 1st 1601> and <Jan 1st 1970>. */
1348 static const unsigned long long w32_epoch_offset
= 11644473600ULL;
1350 /* Returns the file modification timestamp using Win32 routines which are
1351 immune against daylight saving time change. It is in fact not possible to
1352 use fstat for this purpose as the DST modify the st_mtime field of the
1356 win32_filetime (HANDLE h
)
1361 unsigned long long ull_time
;
1364 /* GetFileTime returns FILETIME data which are the number of 100 nanosecs
1365 since <Jan 1st 1601>. This function must return the number of seconds
1366 since <Jan 1st 1970>. */
1368 if (GetFileTime (h
, NULL
, NULL
, &t_write
.ft_time
))
1369 return (time_t) (t_write
.ull_time
/ 10000000ULL - w32_epoch_offset
);
1373 /* As above but starting from a FILETIME. */
1375 f2t (const FILETIME
*ft
, time_t *t
)
1380 unsigned long long ull_time
;
1383 t_write
.ft_time
= *ft
;
1384 *t
= (time_t) (t_write
.ull_time
/ 10000000ULL - w32_epoch_offset
);
1388 /* Return a GNAT time stamp given a file name. */
1391 __gnat_file_time_name_attr (char* name
, struct file_attributes
* attr
)
1393 if (attr
->timestamp
== (OS_Time
)-2) {
1394 #if defined (_WIN32) && !defined (RTX)
1396 WIN32_FILE_ATTRIBUTE_DATA fad
;
1398 TCHAR wname
[GNAT_MAX_PATH_LEN
];
1399 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
);
1401 if ((res
= GetFileAttributesEx (wname
, GetFileExInfoStandard
, &fad
)))
1402 f2t (&fad
.ftLastWriteTime
, &ret
);
1403 attr
->timestamp
= (OS_Time
) ret
;
1405 __gnat_stat_to_attr (-1, name
, attr
);
1408 return attr
->timestamp
;
1412 __gnat_file_time_name (char *name
)
1414 struct file_attributes attr
;
1415 __gnat_reset_attributes (&attr
);
1416 return __gnat_file_time_name_attr (name
, &attr
);
1419 /* Return a GNAT time stamp given a file descriptor. */
1422 __gnat_file_time_fd_attr (int fd
, struct file_attributes
* attr
)
1424 if (attr
->timestamp
== (OS_Time
)-2) {
1425 #if defined (_WIN32) && !defined (RTX)
1426 HANDLE h
= (HANDLE
) _get_osfhandle (fd
);
1427 time_t ret
= win32_filetime (h
);
1428 attr
->timestamp
= (OS_Time
) ret
;
1431 __gnat_stat_to_attr (fd
, NULL
, attr
);
1435 return attr
->timestamp
;
1439 __gnat_file_time_fd (int fd
)
1441 struct file_attributes attr
;
1442 __gnat_reset_attributes (&attr
);
1443 return __gnat_file_time_fd_attr (fd
, &attr
);
1446 /* Set the file time stamp. */
1449 __gnat_set_file_time_name (char *name
, time_t time_stamp
)
1451 #if defined (__vxworks)
1453 /* Code to implement __gnat_set_file_time_name for these systems. */
1455 #elif defined (_WIN32) && !defined (RTX)
1459 unsigned long long ull_time
;
1461 TCHAR wname
[GNAT_MAX_PATH_LEN
];
1463 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
);
1465 HANDLE h
= CreateFile
1466 (wname
, GENERIC_WRITE
, FILE_SHARE_WRITE
, NULL
,
1467 OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
,
1469 if (h
== INVALID_HANDLE_VALUE
)
1471 /* Add number of seconds between <Jan 1st 1601> and <Jan 1st 1970> */
1472 t_write
.ull_time
= ((unsigned long long)time_stamp
+ w32_epoch_offset
);
1473 /* Convert to 100 nanosecond units */
1474 t_write
.ull_time
*= 10000000ULL;
1476 SetFileTime(h
, NULL
, NULL
, &t_write
.ft_time
);
1486 unsigned long long backup
, create
, expire
, revise
;
1490 unsigned short value
;
1493 unsigned system
: 4;
1499 } Fat
= { 0, 0, 0, 0, 0, { 0 }};
1503 { ATR$S_CREDATE
, ATR$C_CREDATE
, &Fat
.create
},
1504 { ATR$S_REVDATE
, ATR$C_REVDATE
, &Fat
.revise
},
1505 { ATR$S_EXPDATE
, ATR$C_EXPDATE
, &Fat
.expire
},
1506 { ATR$S_BAKDATE
, ATR$C_BAKDATE
, &Fat
.backup
},
1507 { ATR$S_FPRO
, ATR$C_FPRO
, &Fat
.prot
},
1508 { ATR$S_UIC
, ATR$C_UIC
, &Fat
.uic
},
1513 struct dsc$descriptor_fib fibdsc
= {sizeof (fib
), (void *) &fib
};
1517 unsigned long long newtime
;
1518 unsigned long long revtime
;
1522 struct vstring file
;
1523 struct dsc$descriptor_s filedsc
1524 = {NAM$C_MAXRSS
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, (void *) file
.string
};
1525 struct vstring device
;
1526 struct dsc$descriptor_s devicedsc
1527 = {NAM$C_MAXRSS
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, (void *) device
.string
};
1528 struct vstring timev
;
1529 struct dsc$descriptor_s timedsc
1530 = {NAM$C_MAXRSS
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, (void *) timev
.string
};
1531 struct vstring result
;
1532 struct dsc$descriptor_s resultdsc
1533 = {NAM$C_MAXRSS
, DSC$K_DTYPE_VT
, DSC$K_CLASS_VS
, (void *) result
.string
};
1535 /* Convert parameter name (a file spec) to host file form. Note that this
1536 is needed on VMS to prepare for subsequent calls to VMS RMS library
1537 routines. Note that it would not work to call __gnat_to_host_dir_spec
1538 as was done in a previous version, since this fails silently unless
1539 the feature logical DECC$EFS_CHARSET is enabled, in which case a DNF
1540 (directory not found) condition is signalled. */
1541 tryfile
= (char *) __gnat_to_host_file_spec (name
);
1543 /* Allocate and initialize a FAB and NAM structures. */
1547 nam
.nam$l_esa
= file
.string
;
1548 nam
.nam$b_ess
= NAM$C_MAXRSS
;
1549 nam
.nam$l_rsa
= result
.string
;
1550 nam
.nam$b_rss
= NAM$C_MAXRSS
;
1551 fab
.fab$l_fna
= tryfile
;
1552 fab
.fab$b_fns
= strlen (tryfile
);
1553 fab
.fab$l_nam
= &nam
;
1555 /* Validate filespec syntax and device existence. */
1556 status
= SYS$
PARSE (&fab
, 0, 0);
1557 if ((status
& 1) != 1)
1558 LIB$
SIGNAL (status
);
1560 file
.string
[nam
.nam$b_esl
] = 0;
1562 /* Find matching filespec. */
1563 status
= SYS$
SEARCH (&fab
, 0, 0);
1564 if ((status
& 1) != 1)
1565 LIB$
SIGNAL (status
);
1567 file
.string
[nam
.nam$b_esl
] = 0;
1568 result
.string
[result
.length
=nam
.nam$b_rsl
] = 0;
1570 /* Get the device name and assign an IO channel. */
1571 strncpy (device
.string
, nam
.nam$l_dev
, nam
.nam$b_dev
);
1572 devicedsc
.dsc$w_length
= nam
.nam$b_dev
;
1574 status
= SYS$
ASSIGN (&devicedsc
, &chan
, 0, 0, 0);
1575 if ((status
& 1) != 1)
1576 LIB$
SIGNAL (status
);
1578 /* Initialize the FIB and fill in the directory id field. */
1579 memset (&fib
, 0, sizeof (fib
));
1580 fib
.fib$w_did
[0] = nam
.nam$w_did
[0];
1581 fib
.fib$w_did
[1] = nam
.nam$w_did
[1];
1582 fib
.fib$w_did
[2] = nam
.nam$w_did
[2];
1583 fib
.fib$l_acctl
= 0;
1585 strcpy (file
.string
, (strrchr (result
.string
, ']') + 1));
1586 filedsc
.dsc$w_length
= strlen (file
.string
);
1587 result
.string
[result
.length
= 0] = 0;
1589 /* Open and close the file to fill in the attributes. */
1591 = SYS$
QIOW (0, chan
, IO$_ACCESS
|IO$M_ACCESS
, &iosb
, 0, 0,
1592 &fibdsc
, &filedsc
, &result
.length
, &resultdsc
, &atrlst
, 0);
1593 if ((status
& 1) != 1)
1594 LIB$
SIGNAL (status
);
1595 if ((iosb
.status
& 1) != 1)
1596 LIB$
SIGNAL (iosb
.status
);
1598 result
.string
[result
.length
] = 0;
1599 status
= SYS$
QIOW (0, chan
, IO$_DEACCESS
, &iosb
, 0, 0, &fibdsc
, 0, 0, 0,
1601 if ((status
& 1) != 1)
1602 LIB$
SIGNAL (status
);
1603 if ((iosb
.status
& 1) != 1)
1604 LIB$
SIGNAL (iosb
.status
);
1609 /* Set creation time to requested time. */
1610 unix_time_to_vms (time_stamp
, newtime
);
1612 t
= time ((time_t) 0);
1614 /* Set revision time to now in local time. */
1615 unix_time_to_vms (t
, revtime
);
1618 /* Reopen the file, modify the times and then close. */
1619 fib
.fib$l_acctl
= FIB$M_WRITE
;
1621 = SYS$
QIOW (0, chan
, IO$_ACCESS
|IO$M_ACCESS
, &iosb
, 0, 0,
1622 &fibdsc
, &filedsc
, &result
.length
, &resultdsc
, &atrlst
, 0);
1623 if ((status
& 1) != 1)
1624 LIB$
SIGNAL (status
);
1625 if ((iosb
.status
& 1) != 1)
1626 LIB$
SIGNAL (iosb
.status
);
1628 Fat
.create
= newtime
;
1629 Fat
.revise
= revtime
;
1631 status
= SYS$
QIOW (0, chan
, IO$_DEACCESS
, &iosb
, 0, 0,
1632 &fibdsc
, 0, 0, 0, &atrlst
, 0);
1633 if ((status
& 1) != 1)
1634 LIB$
SIGNAL (status
);
1635 if ((iosb
.status
& 1) != 1)
1636 LIB$
SIGNAL (iosb
.status
);
1638 /* Deassign the channel and exit. */
1639 status
= SYS$
DASSGN (chan
);
1640 if ((status
& 1) != 1)
1641 LIB$
SIGNAL (status
);
1643 struct utimbuf utimbuf
;
1646 /* Set modification time to requested time. */
1647 utimbuf
.modtime
= time_stamp
;
1649 /* Set access time to now in local time. */
1650 t
= time ((time_t) 0);
1651 utimbuf
.actime
= mktime (localtime (&t
));
1653 utime (name
, &utimbuf
);
1657 /* Get the list of installed standard libraries from the
1658 HKEY_LOCAL_MACHINE\SOFTWARE\Ada Core Technologies\GNAT\Standard Libraries
1662 __gnat_get_libraries_from_registry (void)
1664 char *result
= (char *) xmalloc (1);
1668 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (IS_CROSS) \
1672 DWORD name_size
, value_size
;
1679 /* First open the key. */
1680 res
= RegOpenKeyExA (HKEY_LOCAL_MACHINE
, "SOFTWARE", 0, KEY_READ
, ®_key
);
1682 if (res
== ERROR_SUCCESS
)
1683 res
= RegOpenKeyExA (reg_key
, "Ada Core Technologies", 0,
1684 KEY_READ
, ®_key
);
1686 if (res
== ERROR_SUCCESS
)
1687 res
= RegOpenKeyExA (reg_key
, "GNAT", 0, KEY_READ
, ®_key
);
1689 if (res
== ERROR_SUCCESS
)
1690 res
= RegOpenKeyExA (reg_key
, "Standard Libraries", 0, KEY_READ
, ®_key
);
1692 /* If the key exists, read out all the values in it and concatenate them
1694 for (index
= 0; res
== ERROR_SUCCESS
; index
++)
1696 value_size
= name_size
= 256;
1697 res
= RegEnumValueA (reg_key
, index
, name
, &name_size
, 0,
1698 &type
, (LPBYTE
)value
, &value_size
);
1700 if (res
== ERROR_SUCCESS
&& type
== REG_SZ
)
1702 char *old_result
= result
;
1704 result
= (char *) xmalloc (strlen (old_result
) + value_size
+ 2);
1705 strcpy (result
, old_result
);
1706 strcat (result
, value
);
1707 strcat (result
, ";");
1712 /* Remove the trailing ";". */
1714 result
[strlen (result
) - 1] = 0;
1721 __gnat_stat (char *name
, GNAT_STRUCT_STAT
*statbuf
)
1724 WIN32_FILE_ATTRIBUTE_DATA fad
;
1725 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
1730 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
1731 name_len
= _tcslen (wname
);
1733 if (name_len
> GNAT_MAX_PATH_LEN
)
1736 ZeroMemory (statbuf
, sizeof(GNAT_STRUCT_STAT
));
1738 res
= GetFileAttributesEx (wname
, GetFileExInfoStandard
, &fad
);
1741 error
= GetLastError();
1743 /* Check file existence using GetFileAttributes() which does not fail on
1744 special Windows files like con:, aux:, nul: etc... */
1746 if (GetFileAttributes(wname
) != INVALID_FILE_ATTRIBUTES
) {
1747 /* Just pretend that it is a regular and readable file */
1748 statbuf
->st_mode
= S_IFREG
| S_IREAD
| S_IWRITE
;
1753 case ERROR_ACCESS_DENIED
:
1754 case ERROR_SHARING_VIOLATION
:
1755 case ERROR_LOCK_VIOLATION
:
1756 case ERROR_SHARING_BUFFER_EXCEEDED
:
1758 case ERROR_BUFFER_OVERFLOW
:
1759 return ENAMETOOLONG
;
1760 case ERROR_NOT_ENOUGH_MEMORY
:
1767 f2t (&fad
.ftCreationTime
, &statbuf
->st_ctime
);
1768 f2t (&fad
.ftLastWriteTime
, &statbuf
->st_mtime
);
1769 f2t (&fad
.ftLastAccessTime
, &statbuf
->st_atime
);
1771 statbuf
->st_size
= (off_t
)fad
.nFileSizeLow
;
1773 /* We do not have the S_IEXEC attribute, but this is not used on GNAT. */
1774 statbuf
->st_mode
= S_IREAD
;
1776 if (fad
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
1777 statbuf
->st_mode
|= S_IFDIR
;
1779 statbuf
->st_mode
|= S_IFREG
;
1781 if (!(fad
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
))
1782 statbuf
->st_mode
|= S_IWRITE
;
1787 return GNAT_STAT (name
, statbuf
);
1791 /*************************************************************************
1792 ** Check whether a file exists
1793 *************************************************************************/
1796 __gnat_file_exists_attr (char* name
, struct file_attributes
* attr
)
1798 if (attr
->exists
== ATTR_UNSET
) {
1799 __gnat_stat_to_attr (-1, name
, attr
);
1802 return attr
->exists
;
1806 __gnat_file_exists (char *name
)
1808 struct file_attributes attr
;
1809 __gnat_reset_attributes (&attr
);
1810 return __gnat_file_exists_attr (name
, &attr
);
1813 /**********************************************************************
1814 ** Whether name is an absolute path
1815 **********************************************************************/
1818 __gnat_is_absolute_path (char *name
, int length
)
1821 /* On VxWorks systems, an absolute path can be represented (depending on
1822 the host platform) as either /dir/file, or device:/dir/file, or
1823 device:drive_letter:/dir/file. */
1830 for (index
= 0; index
< length
; index
++)
1832 if (name
[index
] == ':' &&
1833 ((name
[index
+ 1] == '/') ||
1834 (isalpha (name
[index
+ 1]) && index
+ 2 <= length
&&
1835 name
[index
+ 2] == '/')))
1838 else if (name
[index
] == '/')
1843 return (length
!= 0) &&
1844 (*name
== '/' || *name
== DIR_SEPARATOR
1846 || (length
> 1 && ISALPHA (name
[0]) && name
[1] == ':')
1853 __gnat_is_regular_file_attr (char* name
, struct file_attributes
* attr
)
1855 if (attr
->regular
== ATTR_UNSET
) {
1856 __gnat_stat_to_attr (-1, name
, attr
);
1859 return attr
->regular
;
1863 __gnat_is_regular_file (char *name
)
1865 struct file_attributes attr
;
1866 __gnat_reset_attributes (&attr
);
1867 return __gnat_is_regular_file_attr (name
, &attr
);
1871 __gnat_is_directory_attr (char* name
, struct file_attributes
* attr
)
1873 if (attr
->directory
== ATTR_UNSET
) {
1874 __gnat_stat_to_attr (-1, name
, attr
);
1877 return attr
->directory
;
1881 __gnat_is_directory (char *name
)
1883 struct file_attributes attr
;
1884 __gnat_reset_attributes (&attr
);
1885 return __gnat_is_directory_attr (name
, &attr
);
1888 #if defined (_WIN32) && !defined (RTX)
1890 /* Returns the same constant as GetDriveType but takes a pathname as
1894 GetDriveTypeFromPath (TCHAR
*wfullpath
)
1896 TCHAR wdrv
[MAX_PATH
];
1897 TCHAR wpath
[MAX_PATH
];
1898 TCHAR wfilename
[MAX_PATH
];
1899 TCHAR wext
[MAX_PATH
];
1901 _tsplitpath (wfullpath
, wdrv
, wpath
, wfilename
, wext
);
1903 if (_tcslen (wdrv
) != 0)
1905 /* we have a drive specified. */
1906 _tcscat (wdrv
, _T("\\"));
1907 return GetDriveType (wdrv
);
1911 /* No drive specified. */
1913 /* Is this a relative path, if so get current drive type. */
1914 if (wpath
[0] != _T('\\') ||
1915 (_tcslen (wpath
) > 2 && wpath
[0] == _T('\\') && wpath
[1] != _T('\\')))
1916 return GetDriveType (NULL
);
1918 UINT result
= GetDriveType (wpath
);
1920 /* Cannot guess the drive type, is this \\.\ ? */
1922 if (result
== DRIVE_NO_ROOT_DIR
&&
1923 _tcslen (wpath
) >= 4 && wpath
[0] == _T('\\') && wpath
[1] == _T('\\')
1924 && wpath
[2] == _T('.') && wpath
[3] == _T('\\'))
1926 if (_tcslen (wpath
) == 4)
1927 _tcscat (wpath
, wfilename
);
1929 LPTSTR p
= &wpath
[4];
1930 LPTSTR b
= _tcschr (p
, _T('\\'));
1933 { /* logical drive \\.\c\dir\file */
1939 _tcscat (p
, _T(":\\"));
1941 return GetDriveType (p
);
1948 /* This MingW section contains code to work with ACL. */
1950 __gnat_check_OWNER_ACL
1952 DWORD CheckAccessDesired
,
1953 GENERIC_MAPPING CheckGenericMapping
)
1955 DWORD dwAccessDesired
, dwAccessAllowed
;
1956 PRIVILEGE_SET PrivilegeSet
;
1957 DWORD dwPrivSetSize
= sizeof (PRIVILEGE_SET
);
1958 BOOL fAccessGranted
= FALSE
;
1959 HANDLE hToken
= NULL
;
1961 SECURITY_DESCRIPTOR
* pSD
= NULL
;
1964 (wname
, OWNER_SECURITY_INFORMATION
|
1965 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
,
1968 if ((pSD
= (PSECURITY_DESCRIPTOR
) HeapAlloc
1969 (GetProcessHeap (), HEAP_ZERO_MEMORY
, nLength
)) == NULL
)
1972 /* Obtain the security descriptor. */
1974 if (!GetFileSecurity
1975 (wname
, OWNER_SECURITY_INFORMATION
|
1976 GROUP_SECURITY_INFORMATION
| DACL_SECURITY_INFORMATION
,
1977 pSD
, nLength
, &nLength
))
1980 if (!ImpersonateSelf (SecurityImpersonation
))
1983 if (!OpenThreadToken
1984 (GetCurrentThread(), TOKEN_DUPLICATE
| TOKEN_QUERY
, FALSE
, &hToken
))
1987 /* Undoes the effect of ImpersonateSelf. */
1991 /* We want to test for write permissions. */
1993 dwAccessDesired
= CheckAccessDesired
;
1995 MapGenericMask (&dwAccessDesired
, &CheckGenericMapping
);
1998 (pSD
, /* security descriptor to check */
1999 hToken
, /* impersonation token */
2000 dwAccessDesired
, /* requested access rights */
2001 &CheckGenericMapping
, /* pointer to GENERIC_MAPPING */
2002 &PrivilegeSet
, /* receives privileges used in check */
2003 &dwPrivSetSize
, /* size of PrivilegeSet buffer */
2004 &dwAccessAllowed
, /* receives mask of allowed access rights */
2008 CloseHandle (hToken
);
2009 HeapFree (GetProcessHeap (), 0, pSD
);
2010 return fAccessGranted
;
2014 CloseHandle (hToken
);
2015 HeapFree (GetProcessHeap (), 0, pSD
);
2020 __gnat_set_OWNER_ACL
2023 DWORD AccessPermissions
)
2025 PACL pOldDACL
= NULL
;
2026 PACL pNewDACL
= NULL
;
2027 PSECURITY_DESCRIPTOR pSD
= NULL
;
2029 TCHAR username
[100];
2032 /* Get current user, he will act as the owner */
2034 if (!GetUserName (username
, &unsize
))
2037 if (GetNamedSecurityInfo
2040 DACL_SECURITY_INFORMATION
,
2041 NULL
, NULL
, &pOldDACL
, NULL
, &pSD
) != ERROR_SUCCESS
)
2044 BuildExplicitAccessWithName
2045 (&ea
, username
, AccessPermissions
, AccessMode
, NO_INHERITANCE
);
2047 if (AccessMode
== SET_ACCESS
)
2049 /* SET_ACCESS, we want to set an explicte set of permissions, do not
2050 merge with current DACL. */
2051 if (SetEntriesInAcl (1, &ea
, NULL
, &pNewDACL
) != ERROR_SUCCESS
)
2055 if (SetEntriesInAcl (1, &ea
, pOldDACL
, &pNewDACL
) != ERROR_SUCCESS
)
2058 if (SetNamedSecurityInfo
2059 (wname
, SE_FILE_OBJECT
,
2060 DACL_SECURITY_INFORMATION
, NULL
, NULL
, pNewDACL
, NULL
) != ERROR_SUCCESS
)
2064 LocalFree (pNewDACL
);
2067 /* Check if it is possible to use ACL for wname, the file must not be on a
2071 __gnat_can_use_acl (TCHAR
*wname
)
2073 return __gnat_use_acl
&& GetDriveTypeFromPath (wname
) != DRIVE_REMOTE
;
2076 #endif /* defined (_WIN32) && !defined (RTX) */
2079 __gnat_is_readable_file_attr (char* name
, struct file_attributes
* attr
)
2081 if (attr
->readable
== ATTR_UNSET
) {
2082 #if defined (_WIN32) && !defined (RTX)
2083 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2084 GENERIC_MAPPING GenericMapping
;
2086 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2088 if (__gnat_can_use_acl (wname
))
2090 ZeroMemory (&GenericMapping
, sizeof (GENERIC_MAPPING
));
2091 GenericMapping
.GenericRead
= GENERIC_READ
;
2093 __gnat_check_OWNER_ACL (wname
, FILE_READ_DATA
, GenericMapping
);
2096 attr
->readable
= GetFileAttributes (wname
) != INVALID_FILE_ATTRIBUTES
;
2098 __gnat_stat_to_attr (-1, name
, attr
);
2102 return attr
->readable
;
2106 __gnat_is_readable_file (char *name
)
2108 struct file_attributes attr
;
2109 __gnat_reset_attributes (&attr
);
2110 return __gnat_is_readable_file_attr (name
, &attr
);
2114 __gnat_is_writable_file_attr (char* name
, struct file_attributes
* attr
)
2116 if (attr
->writable
== ATTR_UNSET
) {
2117 #if defined (_WIN32) && !defined (RTX)
2118 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2119 GENERIC_MAPPING GenericMapping
;
2121 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2123 if (__gnat_can_use_acl (wname
))
2125 ZeroMemory (&GenericMapping
, sizeof (GENERIC_MAPPING
));
2126 GenericMapping
.GenericWrite
= GENERIC_WRITE
;
2128 attr
->writable
= __gnat_check_OWNER_ACL
2129 (wname
, FILE_WRITE_DATA
| FILE_APPEND_DATA
, GenericMapping
)
2130 && !(GetFileAttributes (wname
) & FILE_ATTRIBUTE_READONLY
);
2133 attr
->writable
= !(GetFileAttributes (wname
) & FILE_ATTRIBUTE_READONLY
);
2136 __gnat_stat_to_attr (-1, name
, attr
);
2140 return attr
->writable
;
2144 __gnat_is_writable_file (char *name
)
2146 struct file_attributes attr
;
2147 __gnat_reset_attributes (&attr
);
2148 return __gnat_is_writable_file_attr (name
, &attr
);
2152 __gnat_is_executable_file_attr (char* name
, struct file_attributes
* attr
)
2154 if (attr
->executable
== ATTR_UNSET
) {
2155 #if defined (_WIN32) && !defined (RTX)
2156 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2157 GENERIC_MAPPING GenericMapping
;
2159 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2161 if (__gnat_can_use_acl (wname
))
2163 ZeroMemory (&GenericMapping
, sizeof (GENERIC_MAPPING
));
2164 GenericMapping
.GenericExecute
= GENERIC_EXECUTE
;
2167 __gnat_check_OWNER_ACL (wname
, FILE_EXECUTE
, GenericMapping
);
2171 TCHAR
*l
, *last
= _tcsstr(wname
, _T(".exe"));
2173 /* look for last .exe */
2175 while (l
= _tcsstr(last
+1, _T(".exe"))) last
= l
;
2177 attr
->executable
= GetFileAttributes (wname
) != INVALID_FILE_ATTRIBUTES
2178 && last
- wname
== (int) (_tcslen (wname
) - 4);
2181 __gnat_stat_to_attr (-1, name
, attr
);
2185 return attr
->executable
;
2189 __gnat_is_executable_file (char *name
)
2191 struct file_attributes attr
;
2192 __gnat_reset_attributes (&attr
);
2193 return __gnat_is_executable_file_attr (name
, &attr
);
2197 __gnat_set_writable (char *name
)
2199 #if defined (_WIN32) && !defined (RTX)
2200 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2202 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2204 if (__gnat_can_use_acl (wname
))
2205 __gnat_set_OWNER_ACL (wname
, GRANT_ACCESS
, FILE_GENERIC_WRITE
);
2208 (wname
, GetFileAttributes (wname
) & ~FILE_ATTRIBUTE_READONLY
);
2209 #elif ! (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 6) && \
2210 ! defined(__nucleus__)
2211 GNAT_STRUCT_STAT statbuf
;
2213 if (GNAT_STAT (name
, &statbuf
) == 0)
2215 statbuf
.st_mode
= statbuf
.st_mode
| S_IWUSR
;
2216 chmod (name
, statbuf
.st_mode
);
2222 __gnat_set_executable (char *name
)
2224 #if defined (_WIN32) && !defined (RTX)
2225 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2227 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2229 if (__gnat_can_use_acl (wname
))
2230 __gnat_set_OWNER_ACL (wname
, GRANT_ACCESS
, FILE_GENERIC_EXECUTE
);
2232 #elif ! (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 6) && \
2233 ! defined(__nucleus__)
2234 GNAT_STRUCT_STAT statbuf
;
2236 if (GNAT_STAT (name
, &statbuf
) == 0)
2238 statbuf
.st_mode
= statbuf
.st_mode
| S_IXUSR
;
2239 chmod (name
, statbuf
.st_mode
);
2245 __gnat_set_non_writable (char *name
)
2247 #if defined (_WIN32) && !defined (RTX)
2248 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2250 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2252 if (__gnat_can_use_acl (wname
))
2253 __gnat_set_OWNER_ACL
2254 (wname
, DENY_ACCESS
,
2255 FILE_WRITE_DATA
| FILE_APPEND_DATA
|
2256 FILE_WRITE_EA
| FILE_WRITE_ATTRIBUTES
);
2259 (wname
, GetFileAttributes (wname
) | FILE_ATTRIBUTE_READONLY
);
2260 #elif ! (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 6) && \
2261 ! defined(__nucleus__)
2262 GNAT_STRUCT_STAT statbuf
;
2264 if (GNAT_STAT (name
, &statbuf
) == 0)
2266 statbuf
.st_mode
= statbuf
.st_mode
& 07577;
2267 chmod (name
, statbuf
.st_mode
);
2273 __gnat_set_readable (char *name
)
2275 #if defined (_WIN32) && !defined (RTX)
2276 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2278 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2280 if (__gnat_can_use_acl (wname
))
2281 __gnat_set_OWNER_ACL (wname
, GRANT_ACCESS
, FILE_GENERIC_READ
);
2283 #elif ! (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 6) && \
2284 ! defined(__nucleus__)
2285 GNAT_STRUCT_STAT statbuf
;
2287 if (GNAT_STAT (name
, &statbuf
) == 0)
2289 chmod (name
, statbuf
.st_mode
| S_IREAD
);
2295 __gnat_set_non_readable (char *name
)
2297 #if defined (_WIN32) && !defined (RTX)
2298 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
2300 S2WSC (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
2302 if (__gnat_can_use_acl (wname
))
2303 __gnat_set_OWNER_ACL (wname
, DENY_ACCESS
, FILE_GENERIC_READ
);
2305 #elif ! (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 6) && \
2306 ! defined(__nucleus__)
2307 GNAT_STRUCT_STAT statbuf
;
2309 if (GNAT_STAT (name
, &statbuf
) == 0)
2311 chmod (name
, statbuf
.st_mode
& (~S_IREAD
));
2317 __gnat_is_symbolic_link_attr (char* name ATTRIBUTE_UNUSED
,
2318 struct file_attributes
* attr
)
2320 if (attr
->symbolic_link
== ATTR_UNSET
) {
2321 #if defined (__vxworks) || defined (__nucleus__)
2322 attr
->symbolic_link
= 0;
2324 #elif defined (_AIX) || defined (__APPLE__) || defined (__unix__)
2326 GNAT_STRUCT_STAT statbuf
;
2327 ret
= GNAT_LSTAT (name
, &statbuf
);
2328 attr
->symbolic_link
= (!ret
&& S_ISLNK (statbuf
.st_mode
));
2330 attr
->symbolic_link
= 0;
2333 return attr
->symbolic_link
;
2337 __gnat_is_symbolic_link (char *name ATTRIBUTE_UNUSED
)
2339 struct file_attributes attr
;
2340 __gnat_reset_attributes (&attr
);
2341 return __gnat_is_symbolic_link_attr (name
, &attr
);
2345 #if defined (sun) && defined (__SVR4)
2346 /* Using fork on Solaris will duplicate all the threads. fork1, which
2347 duplicates only the active thread, must be used instead, or spawning
2348 subprocess from a program with tasking will lead into numerous problems. */
2353 __gnat_portable_spawn (char *args
[])
2356 int finished ATTRIBUTE_UNUSED
;
2357 int pid ATTRIBUTE_UNUSED
;
2359 #if defined (__vxworks) || defined(__nucleus__) || defined(RTX)
2362 #elif defined (_WIN32)
2363 /* args[0] must be quotes as it could contain a full pathname with spaces */
2364 char *args_0
= args
[0];
2365 args
[0] = (char *)xmalloc (strlen (args_0
) + 3);
2366 strcpy (args
[0], "\"");
2367 strcat (args
[0], args_0
);
2368 strcat (args
[0], "\"");
2370 status
= spawnvp (P_WAIT
, args_0
, (const char* const*)args
);
2372 /* restore previous value */
2374 args
[0] = (char *)args_0
;
2390 if (execv (args
[0], MAYBE_TO_PTR32 (args
)) != 0)
2392 return -1; /* execv is in parent context on VMS. */
2399 finished
= waitpid (pid
, &status
, 0);
2401 if (finished
!= pid
|| WIFEXITED (status
) == 0)
2404 return WEXITSTATUS (status
);
2410 /* Create a copy of the given file descriptor.
2411 Return -1 if an error occurred. */
2414 __gnat_dup (int oldfd
)
2416 #if defined (__vxworks) && !defined (__RTP__)
2417 /* Not supported on VxWorks 5.x, but supported on VxWorks 6.0 when using
2425 /* Make newfd be the copy of oldfd, closing newfd first if necessary.
2426 Return -1 if an error occurred. */
2429 __gnat_dup2 (int oldfd
, int newfd
)
2431 #if defined (__vxworks) && !defined (__RTP__)
2432 /* Not supported on VxWorks 5.x, but supported on VxWorks 6.0 when using
2436 return dup2 (oldfd
, newfd
);
2441 __gnat_number_of_cpus (void)
2445 #if defined (linux) || defined (sun) || defined (AIX) \
2446 || (defined (__alpha__) && defined (_osf_)) || defined (__APPLE__)
2447 cores
= (int) sysconf (_SC_NPROCESSORS_ONLN
);
2449 #elif (defined (__mips) && defined (__sgi))
2450 cores
= (int) sysconf (_SC_NPROC_ONLN
);
2452 #elif defined (__hpux__)
2453 struct pst_dynamic psd
;
2454 if (pstat_getdynamic (&psd
, sizeof (psd
), 1, 0) != -1)
2455 cores
= (int) psd
.psd_proc_cnt
;
2457 #elif defined (_WIN32)
2458 SYSTEM_INFO sysinfo
;
2459 GetSystemInfo (&sysinfo
);
2460 cores
= (int) sysinfo
.dwNumberOfProcessors
;
2463 int code
= SYI$_ACTIVECPU_CNT
;
2467 status
= LIB$
GETSYI (&code
, &res
);
2468 if ((status
& 1) != 0)
2471 #elif defined (_WRS_CONFIG_SMP)
2472 unsigned int vxCpuConfiguredGet (void);
2474 cores
= vxCpuConfiguredGet ();
2481 /* WIN32 code to implement a wait call that wait for any child process. */
2483 #if defined (_WIN32) && !defined (RTX)
2485 /* Synchronization code, to be thread safe. */
2489 /* For the Cert run times on native Windows we use dummy functions
2490 for locking and unlocking tasks since we do not support multiple
2491 threads on this configuration (Cert run time on native Windows). */
2493 void dummy (void) {}
2495 void (*Lock_Task
) () = &dummy
;
2496 void (*Unlock_Task
) () = &dummy
;
2500 #define Lock_Task system__soft_links__lock_task
2501 extern void (*Lock_Task
) (void);
2503 #define Unlock_Task system__soft_links__unlock_task
2504 extern void (*Unlock_Task
) (void);
2508 static HANDLE
*HANDLES_LIST
= NULL
;
2509 static int *PID_LIST
= NULL
, plist_length
= 0, plist_max_length
= 0;
2512 add_handle (HANDLE h
, int pid
)
2515 /* -------------------- critical section -------------------- */
2518 if (plist_length
== plist_max_length
)
2520 plist_max_length
+= 1000;
2522 xrealloc (HANDLES_LIST
, sizeof (HANDLE
) * plist_max_length
);
2524 xrealloc (PID_LIST
, sizeof (int) * plist_max_length
);
2527 HANDLES_LIST
[plist_length
] = h
;
2528 PID_LIST
[plist_length
] = pid
;
2532 /* -------------------- critical section -------------------- */
2536 __gnat_win32_remove_handle (HANDLE h
, int pid
)
2540 /* -------------------- critical section -------------------- */
2543 for (j
= 0; j
< plist_length
; j
++)
2545 if ((HANDLES_LIST
[j
] == h
) || (PID_LIST
[j
] == pid
))
2549 HANDLES_LIST
[j
] = HANDLES_LIST
[plist_length
];
2550 PID_LIST
[j
] = PID_LIST
[plist_length
];
2556 /* -------------------- critical section -------------------- */
2560 win32_no_block_spawn (char *command
, char *args
[], HANDLE
*h
, int *pid
)
2564 PROCESS_INFORMATION PI
;
2565 SECURITY_ATTRIBUTES SA
;
2570 /* compute the total command line length */
2574 csize
+= strlen (args
[k
]) + 1;
2578 full_command
= (char *) xmalloc (csize
);
2581 SI
.cb
= sizeof (STARTUPINFO
);
2582 SI
.lpReserved
= NULL
;
2583 SI
.lpReserved2
= NULL
;
2584 SI
.lpDesktop
= NULL
;
2588 SI
.wShowWindow
= SW_HIDE
;
2590 /* Security attributes. */
2591 SA
.nLength
= sizeof (SECURITY_ATTRIBUTES
);
2592 SA
.bInheritHandle
= TRUE
;
2593 SA
.lpSecurityDescriptor
= NULL
;
2595 /* Prepare the command string. */
2596 strcpy (full_command
, command
);
2597 strcat (full_command
, " ");
2602 strcat (full_command
, args
[k
]);
2603 strcat (full_command
, " ");
2608 int wsize
= csize
* 2;
2609 TCHAR
*wcommand
= (TCHAR
*) xmalloc (wsize
);
2611 S2WSC (wcommand
, full_command
, wsize
);
2613 free (full_command
);
2615 result
= CreateProcess
2616 (NULL
, wcommand
, &SA
, NULL
, TRUE
,
2617 GetPriorityClass (GetCurrentProcess()), NULL
, NULL
, &SI
, &PI
);
2624 CloseHandle (PI
.hThread
);
2626 *pid
= PI
.dwProcessId
;
2636 win32_wait (int *status
)
2638 DWORD exitcode
, pid
;
2645 if (plist_length
== 0)
2653 /* -------------------- critical section -------------------- */
2656 hl_len
= plist_length
;
2658 hl
= (HANDLE
*) xmalloc (sizeof (HANDLE
) * hl_len
);
2660 memmove (hl
, HANDLES_LIST
, sizeof (HANDLE
) * hl_len
);
2663 /* -------------------- critical section -------------------- */
2665 res
= WaitForMultipleObjects (hl_len
, hl
, FALSE
, INFINITE
);
2666 h
= hl
[res
- WAIT_OBJECT_0
];
2668 GetExitCodeProcess (h
, &exitcode
);
2669 pid
= PID_LIST
[res
- WAIT_OBJECT_0
];
2670 __gnat_win32_remove_handle (h
, -1);
2674 *status
= (int) exitcode
;
2681 __gnat_portable_no_block_spawn (char *args
[])
2684 #if defined (__vxworks) || defined (__nucleus__) || defined (RTX)
2687 #elif defined (_WIN32)
2692 win32_no_block_spawn (args
[0], args
, &h
, &pid
);
2695 add_handle (h
, pid
);
2708 if (execv (args
[0], MAYBE_TO_PTR32 (args
)) != 0)
2710 return -1; /* execv is in parent context on VMS. */
2722 __gnat_portable_wait (int *process_status
)
2727 #if defined (__vxworks) || defined (__nucleus__) || defined (RTX)
2728 /* Not sure what to do here, so do nothing but return zero. */
2730 #elif defined (_WIN32)
2732 pid
= win32_wait (&status
);
2736 pid
= waitpid (-1, &status
, 0);
2737 status
= status
& 0xffff;
2740 *process_status
= status
;
2745 __gnat_os_exit (int status
)
2750 /* Locate file on path, that matches a predicate */
2753 __gnat_locate_file_with_predicate
2754 (char *file_name
, char *path_val
, int (*predicate
)(char*))
2757 char *file_path
= (char *) alloca (strlen (file_name
) + 1);
2760 /* Return immediately if file_name is empty */
2762 if (*file_name
== '\0')
2765 /* Remove quotes around file_name if present */
2771 strcpy (file_path
, ptr
);
2773 ptr
= file_path
+ strlen (file_path
) - 1;
2778 /* Handle absolute pathnames. */
2780 absolute
= __gnat_is_absolute_path (file_path
, strlen (file_name
));
2784 if (predicate (file_path
))
2785 return xstrdup (file_path
);
2790 /* If file_name include directory separator(s), try it first as
2791 a path name relative to the current directory */
2792 for (ptr
= file_name
; *ptr
&& *ptr
!= '/' && *ptr
!= DIR_SEPARATOR
; ptr
++)
2797 if (predicate (file_name
))
2798 return xstrdup (file_name
);
2805 /* The result has to be smaller than path_val + file_name. */
2807 (char *) alloca (strlen (path_val
) + strlen (file_name
) + 2);
2811 /* Skip the starting quote */
2813 if (*path_val
== '"')
2816 for (ptr
= file_path
; *path_val
&& *path_val
!= PATH_SEPARATOR
; )
2817 *ptr
++ = *path_val
++;
2819 /* If directory is empty, it is the current directory*/
2821 if (ptr
== file_path
)
2828 /* Skip the ending quote */
2833 if (*ptr
!= '/' && *ptr
!= DIR_SEPARATOR
)
2834 *++ptr
= DIR_SEPARATOR
;
2836 strcpy (++ptr
, file_name
);
2838 if (predicate (file_path
))
2839 return xstrdup (file_path
);
2844 /* Skip path separator */
2853 /* Locate an executable file, give a Path value. */
2856 __gnat_locate_executable_file (char *file_name
, char *path_val
)
2858 return __gnat_locate_file_with_predicate
2859 (file_name
, path_val
, &__gnat_is_executable_file
);
2862 /* Locate a regular file, give a Path value. */
2865 __gnat_locate_regular_file (char *file_name
, char *path_val
)
2867 return __gnat_locate_file_with_predicate
2868 (file_name
, path_val
, &__gnat_is_regular_file
);
2871 /* Locate an executable given a Path argument. This routine is only used by
2872 gnatbl and should not be used otherwise. Use locate_exec_on_path
2876 __gnat_locate_exec (char *exec_name
, char *path_val
)
2879 if (!strstr (exec_name
, HOST_EXECUTABLE_SUFFIX
))
2881 char *full_exec_name
=
2883 (strlen (exec_name
) + strlen (HOST_EXECUTABLE_SUFFIX
) + 1);
2885 strcpy (full_exec_name
, exec_name
);
2886 strcat (full_exec_name
, HOST_EXECUTABLE_SUFFIX
);
2887 ptr
= __gnat_locate_executable_file (full_exec_name
, path_val
);
2890 return __gnat_locate_executable_file (exec_name
, path_val
);
2894 return __gnat_locate_executable_file (exec_name
, path_val
);
2897 /* Locate an executable using the Systems default PATH. */
2900 __gnat_locate_exec_on_path (char *exec_name
)
2904 #if defined (_WIN32) && !defined (RTX)
2905 TCHAR
*wpath_val
= _tgetenv (_T("PATH"));
2907 /* In Win32 systems we expand the PATH as for XP environment
2908 variables are not automatically expanded. We also prepend the
2909 ".;" to the path to match normal NT path search semantics */
2911 #define EXPAND_BUFFER_SIZE 32767
2913 wapath_val
= alloca (EXPAND_BUFFER_SIZE
);
2915 wapath_val
[0] = '.';
2916 wapath_val
[1] = ';';
2918 DWORD res
= ExpandEnvironmentStrings
2919 (wpath_val
, &wapath_val
[2], EXPAND_BUFFER_SIZE
- 2);
2921 if (!res
) wapath_val
[0] = _T('\0');
2923 apath_val
= alloca (EXPAND_BUFFER_SIZE
);
2925 WS2SC (apath_val
, wapath_val
, EXPAND_BUFFER_SIZE
);
2926 return __gnat_locate_exec (exec_name
, apath_val
);
2931 char *path_val
= "/VAXC$PATH";
2933 char *path_val
= getenv ("PATH");
2935 if (path_val
== NULL
) return NULL
;
2936 apath_val
= (char *) alloca (strlen (path_val
) + 1);
2937 strcpy (apath_val
, path_val
);
2938 return __gnat_locate_exec (exec_name
, apath_val
);
2944 /* These functions are used to translate to and from VMS and Unix syntax
2945 file, directory and path specifications. */
2948 #define MAXNAMES 256
2949 #define NEW_CANONICAL_FILELIST_INCREMENT 64
2951 static char new_canonical_dirspec
[MAXPATH
];
2952 static char new_canonical_filespec
[MAXPATH
];
2953 static char new_canonical_pathspec
[MAXNAMES
*MAXPATH
];
2954 static unsigned new_canonical_filelist_index
;
2955 static unsigned new_canonical_filelist_in_use
;
2956 static unsigned new_canonical_filelist_allocated
;
2957 static char **new_canonical_filelist
;
2958 static char new_host_pathspec
[MAXNAMES
*MAXPATH
];
2959 static char new_host_dirspec
[MAXPATH
];
2960 static char new_host_filespec
[MAXPATH
];
2962 /* Routine is called repeatedly by decc$from_vms via
2963 __gnat_to_canonical_file_list_init until it returns 0 or the expansion
2967 wildcard_translate_unix (char *name
)
2970 char buff
[MAXPATH
];
2972 strncpy (buff
, name
, MAXPATH
);
2973 buff
[MAXPATH
- 1] = (char) 0;
2974 ver
= strrchr (buff
, '.');
2976 /* Chop off the version. */
2980 /* Dynamically extend the allocation by the increment. */
2981 if (new_canonical_filelist_in_use
== new_canonical_filelist_allocated
)
2983 new_canonical_filelist_allocated
+= NEW_CANONICAL_FILELIST_INCREMENT
;
2984 new_canonical_filelist
= (char **) xrealloc
2985 (new_canonical_filelist
,
2986 new_canonical_filelist_allocated
* sizeof (char *));
2989 new_canonical_filelist
[new_canonical_filelist_in_use
++] = xstrdup (buff
);
2994 /* Translate a wildcard VMS file spec into a list of Unix file specs. First do
2995 full translation and copy the results into a list (_init), then return them
2996 one at a time (_next). If onlydirs set, only expand directory files. */
2999 __gnat_to_canonical_file_list_init (char *filespec
, int onlydirs
)
3002 char buff
[MAXPATH
];
3004 len
= strlen (filespec
);
3005 strncpy (buff
, filespec
, MAXPATH
);
3007 /* Only look for directories */
3008 if (onlydirs
&& !strstr (&buff
[len
-5], "*.dir"))
3009 strncat (buff
, "*.dir", MAXPATH
);
3011 buff
[MAXPATH
- 1] = (char) 0;
3013 decc$
from_vms (buff
, wildcard_translate_unix
, 1);
3015 /* Remove the .dir extension. */
3021 for (i
= 0; i
< new_canonical_filelist_in_use
; i
++)
3023 ext
= strstr (new_canonical_filelist
[i
], ".dir");
3029 return new_canonical_filelist_in_use
;
3032 /* Return the next filespec in the list. */
3035 __gnat_to_canonical_file_list_next ()
3037 return new_canonical_filelist
[new_canonical_filelist_index
++];
3040 /* Free storage used in the wildcard expansion. */
3043 __gnat_to_canonical_file_list_free ()
3047 for (i
= 0; i
< new_canonical_filelist_in_use
; i
++)
3048 free (new_canonical_filelist
[i
]);
3050 free (new_canonical_filelist
);
3052 new_canonical_filelist_in_use
= 0;
3053 new_canonical_filelist_allocated
= 0;
3054 new_canonical_filelist_index
= 0;
3055 new_canonical_filelist
= 0;
3058 /* The functional equivalent of decc$translate_vms routine.
3059 Designed to produce the same output, but is protected against
3060 malformed paths (original version ACCVIOs in this case) and
3061 does not require VMS-specific DECC RTL */
3063 #define NAM$C_MAXRSS 1024
3066 __gnat_translate_vms (char *src
)
3068 static char retbuf
[NAM$C_MAXRSS
+1];
3069 char *srcendpos
, *pos1
, *pos2
, *retpos
;
3070 int disp
, path_present
= 0;
3072 if (!src
) return NULL
;
3074 srcendpos
= strchr (src
, '\0');
3077 /* Look for the node and/or device in front of the path */
3079 pos2
= strchr (pos1
, ':');
3081 if (pos2
&& (pos2
< srcendpos
) && (*(pos2
+ 1) == ':')) {
3082 /* There is a node name. "node_name::" becomes "node_name!" */
3084 strncpy (retbuf
, pos1
, disp
);
3085 retpos
[disp
] = '!';
3086 retpos
= retpos
+ disp
+ 1;
3088 pos2
= strchr (pos1
, ':');
3092 /* There is a device name. "dev_name:" becomes "/dev_name/" */
3095 strncpy (retpos
, pos1
, disp
);
3096 retpos
= retpos
+ disp
;
3101 /* No explicit device; we must look ahead and prepend /sys$disk/ if
3102 the path is absolute */
3103 if ((*pos1
== '[' || *pos1
== '<') && (pos1
< srcendpos
)
3104 && !strchr (".-]>", *(pos1
+ 1))) {
3105 strncpy (retpos
, "/sys$disk/", 10);
3109 /* Process the path part */
3110 while (*pos1
== '[' || *pos1
== '<') {
3113 if (*pos1
== ']' || *pos1
== '>') {
3114 /* Special case, [] translates to '.' */
3119 /* '[000000' means root dir. It can be present in the middle of
3120 the path due to expansion of logical devices, in which case
3122 if (!strncmp (pos1
, "000000", 6) && path_present
> 1 &&
3123 (*(pos1
+ 6) == ']' || *(pos1
+ 6) == '>' || *(pos1
+ 6) == '.')) {
3125 if (*pos1
== '.') pos1
++;
3127 else if (*pos1
== '.') {
3132 /* There is a qualified path */
3133 while (*pos1
&& *pos1
!= ']' && *pos1
!= '>') {
3136 /* '.' is used to separate directories. Replace it with '/' but
3137 only if there isn't already '/' just before */
3138 if (*(retpos
- 1) != '/') *(retpos
++) = '/';
3140 if (pos1
+ 1 < srcendpos
&& *pos1
== '.' && *(pos1
+ 1) == '.') {
3141 /* ellipsis refers to entire subtree; replace with '**' */
3142 *(retpos
++) = '*'; *(retpos
++) = '*'; *(retpos
++) = '/';
3147 /* When after '.' '[' '<' is equivalent to Unix ".." but there
3148 may be several in a row */
3149 if (*(pos1
- 1) == '.' || *(pos1
- 1) == '[' ||
3150 *(pos1
- 1) == '<') {
3151 while (*pos1
== '-') {
3153 *(retpos
++) = '.'; *(retpos
++) = '.'; *(retpos
++) = '/';
3158 /* otherwise fall through to default */
3160 *(retpos
++) = *(pos1
++);
3167 if (pos1
< srcendpos
) {
3168 /* Now add the actual file name, until the version suffix if any */
3169 if (path_present
) *(retpos
++) = '/';
3170 pos2
= strchr (pos1
, ';');
3171 disp
= pos2
? (pos2
- pos1
) : (srcendpos
- pos1
);
3172 strncpy (retpos
, pos1
, disp
);
3174 if (pos2
&& pos2
< srcendpos
) {
3175 /* There is a non-empty version suffix. ";<ver>" becomes ".<ver>" */
3177 disp
= srcendpos
- pos2
- 1;
3178 strncpy (retpos
, pos2
+ 1, disp
);
3189 /* Translate a VMS syntax directory specification in to Unix syntax. If
3190 PREFIXFLAG is set, append an underscore "/". If no indicators of VMS syntax
3191 found, return input string. Also translate a dirname that contains no
3192 slashes, in case it's a logical name. */
3195 __gnat_to_canonical_dir_spec (char *dirspec
, int prefixflag
)
3199 strcpy (new_canonical_dirspec
, "");
3200 if (strlen (dirspec
))
3204 if (strchr (dirspec
, ']') || strchr (dirspec
, ':'))
3206 strncpy (new_canonical_dirspec
,
3207 __gnat_translate_vms (dirspec
),
3210 else if (!strchr (dirspec
, '/') && (dirspec1
= getenv (dirspec
)) != 0)
3212 strncpy (new_canonical_dirspec
,
3213 __gnat_translate_vms (dirspec1
),
3218 strncpy (new_canonical_dirspec
, dirspec
, MAXPATH
);
3222 len
= strlen (new_canonical_dirspec
);
3223 if (prefixflag
&& new_canonical_dirspec
[len
-1] != '/')
3224 strncat (new_canonical_dirspec
, "/", MAXPATH
);
3226 new_canonical_dirspec
[MAXPATH
- 1] = (char) 0;
3228 return new_canonical_dirspec
;
3232 /* Translate a VMS syntax file specification into Unix syntax.
3233 If no indicators of VMS syntax found, check if it's an uppercase
3234 alphanumeric_ name and if so try it out as an environment
3235 variable (logical name). If all else fails return the
3239 __gnat_to_canonical_file_spec (char *filespec
)
3243 strncpy (new_canonical_filespec
, "", MAXPATH
);
3245 if (strchr (filespec
, ']') || strchr (filespec
, ':'))
3247 char *tspec
= (char *) __gnat_translate_vms (filespec
);
3249 if (tspec
!= (char *) -1)
3250 strncpy (new_canonical_filespec
, tspec
, MAXPATH
);
3252 else if ((strlen (filespec
) == strspn (filespec
,
3253 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"))
3254 && (filespec1
= getenv (filespec
)))
3256 char *tspec
= (char *) __gnat_translate_vms (filespec1
);
3258 if (tspec
!= (char *) -1)
3259 strncpy (new_canonical_filespec
, tspec
, MAXPATH
);
3263 strncpy (new_canonical_filespec
, filespec
, MAXPATH
);
3266 new_canonical_filespec
[MAXPATH
- 1] = (char) 0;
3268 return new_canonical_filespec
;
3271 /* Translate a VMS syntax path specification into Unix syntax.
3272 If no indicators of VMS syntax found, return input string. */
3275 __gnat_to_canonical_path_spec (char *pathspec
)
3277 char *curr
, *next
, buff
[MAXPATH
];
3282 /* If there are /'s, assume it's a Unix path spec and return. */
3283 if (strchr (pathspec
, '/'))
3286 new_canonical_pathspec
[0] = 0;
3291 next
= strchr (curr
, ',');
3293 next
= strchr (curr
, 0);
3295 strncpy (buff
, curr
, next
- curr
);
3296 buff
[next
- curr
] = 0;
3298 /* Check for wildcards and expand if present. */
3299 if (strchr (buff
, '*') || strchr (buff
, '%') || strstr (buff
, "..."))
3303 dirs
= __gnat_to_canonical_file_list_init (buff
, 1);
3304 for (i
= 0; i
< dirs
; i
++)
3308 next_dir
= __gnat_to_canonical_file_list_next ();
3309 strncat (new_canonical_pathspec
, next_dir
, MAXPATH
);
3311 /* Don't append the separator after the last expansion. */
3313 strncat (new_canonical_pathspec
, ":", MAXPATH
);
3316 __gnat_to_canonical_file_list_free ();
3319 strncat (new_canonical_pathspec
,
3320 __gnat_to_canonical_dir_spec (buff
, 0), MAXPATH
);
3325 strncat (new_canonical_pathspec
, ":", MAXPATH
);
3329 new_canonical_pathspec
[MAXPATH
- 1] = (char) 0;
3331 return new_canonical_pathspec
;
3334 static char filename_buff
[MAXPATH
];
3337 translate_unix (char *name
, int type
)
3339 strncpy (filename_buff
, name
, MAXPATH
);
3340 filename_buff
[MAXPATH
- 1] = (char) 0;
3344 /* Translate a Unix syntax path spec into a VMS style (comma separated list of
3348 to_host_path_spec (char *pathspec
)
3350 char *curr
, *next
, buff
[MAXPATH
];
3355 /* Can't very well test for colons, since that's the Unix separator! */
3356 if (strchr (pathspec
, ']') || strchr (pathspec
, ','))
3359 new_host_pathspec
[0] = 0;
3364 next
= strchr (curr
, ':');
3366 next
= strchr (curr
, 0);
3368 strncpy (buff
, curr
, next
- curr
);
3369 buff
[next
- curr
] = 0;
3371 strncat (new_host_pathspec
, __gnat_to_host_dir_spec (buff
, 0), MAXPATH
);
3374 strncat (new_host_pathspec
, ",", MAXPATH
);
3378 new_host_pathspec
[MAXPATH
- 1] = (char) 0;
3380 return new_host_pathspec
;
3383 /* Translate a Unix syntax directory specification into VMS syntax. The
3384 PREFIXFLAG has no effect, but is kept for symmetry with
3385 to_canonical_dir_spec. If indicators of VMS syntax found, return input
3389 __gnat_to_host_dir_spec (char *dirspec
, int prefixflag ATTRIBUTE_UNUSED
)
3391 int len
= strlen (dirspec
);
3393 strncpy (new_host_dirspec
, dirspec
, MAXPATH
);
3394 new_host_dirspec
[MAXPATH
- 1] = (char) 0;
3396 if (strchr (new_host_dirspec
, ']') || strchr (new_host_dirspec
, ':'))
3397 return new_host_dirspec
;
3399 while (len
> 1 && new_host_dirspec
[len
- 1] == '/')
3401 new_host_dirspec
[len
- 1] = 0;
3405 decc$
to_vms (new_host_dirspec
, translate_unix
, 1, 2);
3406 strncpy (new_host_dirspec
, filename_buff
, MAXPATH
);
3407 new_host_dirspec
[MAXPATH
- 1] = (char) 0;
3409 return new_host_dirspec
;
3412 /* Translate a Unix syntax file specification into VMS syntax.
3413 If indicators of VMS syntax found, return input string. */
3416 __gnat_to_host_file_spec (char *filespec
)
3418 strncpy (new_host_filespec
, "", MAXPATH
);
3419 if (strchr (filespec
, ']') || strchr (filespec
, ':'))
3421 strncpy (new_host_filespec
, filespec
, MAXPATH
);
3425 decc$
to_vms (filespec
, translate_unix
, 1, 1);
3426 strncpy (new_host_filespec
, filename_buff
, MAXPATH
);
3429 new_host_filespec
[MAXPATH
- 1] = (char) 0;
3431 return new_host_filespec
;
3435 __gnat_adjust_os_resource_limits ()
3437 SYS$
ADJWSL (131072, 0);
3442 /* Dummy functions for Osint import for non-VMS systems. */
3445 __gnat_to_canonical_file_list_init
3446 (char *dirspec ATTRIBUTE_UNUSED
, int onlydirs ATTRIBUTE_UNUSED
)
3452 __gnat_to_canonical_file_list_next (void)
3454 static char empty
[] = "";
3459 __gnat_to_canonical_file_list_free (void)
3464 __gnat_to_canonical_dir_spec (char *dirspec
, int prefixflag ATTRIBUTE_UNUSED
)
3470 __gnat_to_canonical_file_spec (char *filespec
)
3476 __gnat_to_canonical_path_spec (char *pathspec
)
3482 __gnat_to_host_dir_spec (char *dirspec
, int prefixflag ATTRIBUTE_UNUSED
)
3488 __gnat_to_host_file_spec (char *filespec
)
3494 __gnat_adjust_os_resource_limits (void)
3500 #if defined (__mips_vxworks)
3504 CACHE_USER_FLUSH (0, ENTIRE_CACHE
);
3508 #if defined (IS_CROSS) \
3509 || (! ((defined (sparc) || defined (i386)) && defined (sun) \
3510 && defined (__SVR4)) \
3511 && ! (defined (linux) && (defined (i386) || defined (__x86_64__))) \
3512 && ! (defined (linux) && defined (__ia64__)) \
3513 && ! (defined (linux) && defined (powerpc)) \
3514 && ! defined (__FreeBSD__) \
3515 && ! defined (__Lynx__) \
3516 && ! defined (__hpux__) \
3517 && ! defined (__APPLE__) \
3518 && ! defined (_AIX) \
3519 && ! (defined (__alpha__) && defined (__osf__)) \
3520 && ! defined (VMS) \
3521 && ! defined (__MINGW32__) \
3522 && ! (defined (__mips) && defined (__sgi)))
3524 /* Dummy function to satisfy g-trasym.o. See the preprocessor conditional
3525 just above for a list of native platforms that provide a non-dummy
3526 version of this procedure in libaddr2line.a. */
3529 convert_addresses (const char *file_name ATTRIBUTE_UNUSED
,
3530 void *addrs ATTRIBUTE_UNUSED
,
3531 int n_addr ATTRIBUTE_UNUSED
,
3532 void *buf ATTRIBUTE_UNUSED
,
3533 int *len ATTRIBUTE_UNUSED
)
3539 #if defined (_WIN32)
3540 int __gnat_argument_needs_quote
= 1;
3542 int __gnat_argument_needs_quote
= 0;
3545 /* This option is used to enable/disable object files handling from the
3546 binder file by the GNAT Project module. For example, this is disabled on
3547 Windows (prior to GCC 3.4) as it is already done by the mdll module.
3548 Stating with GCC 3.4 the shared libraries are not based on mdll
3549 anymore as it uses the GCC's -shared option */
3550 #if defined (_WIN32) \
3551 && ((__GNUC__ < 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ < 4)))
3552 int __gnat_prj_add_obj_files
= 0;
3554 int __gnat_prj_add_obj_files
= 1;
3557 /* char used as prefix/suffix for environment variables */
3558 #if defined (_WIN32)
3559 char __gnat_environment_char
= '%';
3561 char __gnat_environment_char
= '$';
3564 /* This functions copy the file attributes from a source file to a
3567 mode = 0 : In this mode copy only the file time stamps (last access and
3568 last modification time stamps).
3570 mode = 1 : In this mode, time stamps and read/write/execute attributes are
3573 Returns 0 if operation was successful and -1 in case of error. */
3576 __gnat_copy_attribs (char *from
, char *to
, int mode
)
3578 #if defined (VMS) || (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 6) || \
3579 defined (__nucleus__)
3582 #elif defined (_WIN32) && !defined (RTX)
3583 TCHAR wfrom
[GNAT_MAX_PATH_LEN
+ 2];
3584 TCHAR wto
[GNAT_MAX_PATH_LEN
+ 2];
3586 FILETIME fct
, flat
, flwt
;
3589 S2WSC (wfrom
, from
, GNAT_MAX_PATH_LEN
+ 2);
3590 S2WSC (wto
, to
, GNAT_MAX_PATH_LEN
+ 2);
3592 /* retrieve from times */
3595 (wfrom
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3597 if (hfrom
== INVALID_HANDLE_VALUE
)
3600 res
= GetFileTime (hfrom
, &fct
, &flat
, &flwt
);
3602 CloseHandle (hfrom
);
3607 /* retrieve from times */
3610 (wto
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3612 if (hto
== INVALID_HANDLE_VALUE
)
3615 res
= SetFileTime (hto
, NULL
, &flat
, &flwt
);
3622 /* Set file attributes in full mode. */
3626 DWORD attribs
= GetFileAttributes (wfrom
);
3628 if (attribs
== INVALID_FILE_ATTRIBUTES
)
3631 res
= SetFileAttributes (wto
, attribs
);
3639 GNAT_STRUCT_STAT fbuf
;
3640 struct utimbuf tbuf
;
3642 if (GNAT_STAT (from
, &fbuf
) == -1)
3647 tbuf
.actime
= fbuf
.st_atime
;
3648 tbuf
.modtime
= fbuf
.st_mtime
;
3650 if (utime (to
, &tbuf
) == -1)
3657 if (chmod (to
, fbuf
.st_mode
) == -1)
3668 __gnat_lseek (int fd
, long offset
, int whence
)
3670 return (int) lseek (fd
, offset
, whence
);
3673 /* This function returns the major version number of GCC being used. */
3675 get_gcc_version (void)
3680 return (int) (version_string
[0] - '0');
3685 __gnat_set_close_on_exec (int fd ATTRIBUTE_UNUSED
,
3686 int close_on_exec_p ATTRIBUTE_UNUSED
)
3688 #if defined (F_GETFD) && defined (FD_CLOEXEC) && ! defined (__vxworks)
3689 int flags
= fcntl (fd
, F_GETFD
, 0);
3692 if (close_on_exec_p
)
3693 flags
|= FD_CLOEXEC
;
3695 flags
&= ~FD_CLOEXEC
;
3696 return fcntl (fd
, F_SETFD
, flags
| FD_CLOEXEC
);
3697 #elif defined(_WIN32)
3698 HANDLE h
= (HANDLE
) _get_osfhandle (fd
);
3699 if (h
== (HANDLE
) -1)
3701 if (close_on_exec_p
)
3702 return ! SetHandleInformation (h
, HANDLE_FLAG_INHERIT
, 0);
3703 return ! SetHandleInformation (h
, HANDLE_FLAG_INHERIT
,
3704 HANDLE_FLAG_INHERIT
);
3706 /* TODO: Unimplemented. */
3711 /* Indicates if platforms supports automatic initialization through the
3712 constructor mechanism */
3714 __gnat_binder_supports_auto_init (void)
3723 /* Indicates that Stand-Alone Libraries are automatically initialized through
3724 the constructor mechanism */
3726 __gnat_sals_init_using_constructors (void)
3728 #if defined (__vxworks) || defined (__Lynx__) || defined (VMS)
3737 /* In RTX mode, the procedure to get the time (as file time) is different
3738 in RTSS mode and Win32 mode. In order to avoid duplicating an Ada file,
3739 we introduce an intermediate procedure to link against the corresponding
3740 one in each situation. */
3742 extern void GetTimeAsFileTime(LPFILETIME pTime
);
3744 void GetTimeAsFileTime(LPFILETIME pTime
)
3747 RtGetRtssTimeAsFileTime (pTime
); /* RTSS interface */
3749 GetSystemTimeAsFileTime (pTime
); /* w32 interface */
3754 /* Add symbol that is required to link. It would otherwise be taken from
3755 libgcc.a and it would try to use the gcc constructors that are not
3756 supported by Microsoft linker. */
3758 extern void __main (void);
3760 void __main (void) {}
3765 /* There is no function in the glibc to retrieve the LWP of the current
3766 thread. We need to do a system call in order to retrieve this
3768 #include <sys/syscall.h>
3769 void *__gnat_lwp_self (void)
3771 return (void *) syscall (__NR_gettid
);
3776 void __gnat_cpu_zero (cpu_set_t
*set
)
3781 void __gnat_cpu_set (int cpu
, cpu_set_t
*set
)
3783 /* Ada handles CPU numbers starting from 1, while C identifies the first
3784 CPU by a 0, so we need to adjust. */
3785 CPU_SET (cpu
- 1, set
);