OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [ada/] [adaint.c] - Blame information for rev 747

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 706 jeremybenn
/****************************************************************************
2
 *                                                                          *
3
 *                         GNAT COMPILER COMPONENTS                         *
4
 *                                                                          *
5
 *                               A D A I N T                                *
6
 *                                                                          *
7
 *                          C Implementation File                           *
8
 *                                                                          *
9
 *          Copyright (C) 1992-2011, Free Software Foundation, Inc.         *
10
 *                                                                          *
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.                                     *
17
 *                                                                          *
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.               *
21
 *                                                                          *
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/>.                                          *
26
 *                                                                          *
27
 * GNAT was originally developed  by the GNAT team at  New York University. *
28
 * Extensive contributions were provided by Ada Core Technologies Inc.      *
29
 *                                                                          *
30
 ****************************************************************************/
31
 
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.  */
36
 
37
#ifdef __cplusplus
38
extern "C" {
39
#endif
40
 
41
#ifdef __vxworks
42
 
43
/* No need to redefine exit here.  */
44
#undef exit
45
 
46
/* We want to use the POSIX variants of include files.  */
47
#define POSIX
48
#include "vxWorks.h"
49
 
50
#if defined (__mips_vxworks)
51
#include "cacheLib.h"
52
#endif /* __mips_vxworks */
53
 
54
/* If SMP, access vxCpuConfiguredGet */
55
#ifdef _WRS_CONFIG_SMP
56
#include <vxCpuLib.h>
57
#endif /* _WRS_CONFIG_SMP */
58
 
59
/* We need to know the VxWorks version because some file operations
60
   (such as chmod) are only available on VxWorks 6.  */
61
#include "version.h"
62
 
63
#endif /* VxWorks */
64
 
65
#if (defined (__mips) && defined (__sgi)) || defined (__APPLE__)
66
#include <unistd.h>
67
#endif
68
 
69
#if defined (__hpux__)
70
#include <sys/param.h>
71
#include <sys/pstat.h>
72
#endif
73
 
74
#ifdef VMS
75
#define _POSIX_EXIT 1
76
#define HOST_EXECUTABLE_SUFFIX ".exe"
77
#define HOST_OBJECT_SUFFIX ".obj"
78
#endif
79
 
80
#ifdef IN_RTS
81
#include "tconfig.h"
82
#include "tsystem.h"
83
 
84
#include <sys/stat.h>
85
#include <fcntl.h>
86
#include <time.h>
87
#ifdef VMS
88
#include <unixio.h>
89
#endif
90
 
91
#ifdef __vxworks
92
/* S_IREAD and S_IWRITE are not defined in VxWorks */
93
#ifndef S_IREAD
94
#define S_IREAD  (S_IRUSR | S_IRGRP | S_IROTH)
95
#endif
96
 
97
#ifndef S_IWRITE
98
#define S_IWRITE (S_IWUSR)
99
#endif
100
#endif
101
 
102
/* We don't have libiberty, so use malloc.  */
103
#define xmalloc(S) malloc (S)
104
#define xrealloc(V,S) realloc (V,S)
105
#else
106
#include "config.h"
107
#include "system.h"
108
#include "version.h"
109
#endif
110
 
111
#if defined (__MINGW32__)
112
 
113
#if defined (RTX)
114
#include <windows.h>
115
#include <Rtapi.h>
116
#else
117
#include "mingw32.h"
118
 
119
/* Current code page to use, set in initialize.c.  */
120
UINT CurrentCodePage;
121
#endif
122
 
123
#include <sys/utime.h>
124
 
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.  */
128
 
129
#ifdef IN_RTS
130
#include <ctype.h>
131
#define ISALPHA isalpha
132
#endif
133
 
134
#elif defined (__Lynx__)
135
 
136
/* Lynx utime.h only defines the entities of interest to us if
137
   defined (VMOS_DEV), so ... */
138
#define VMOS_DEV
139
#include <utime.h>
140
#undef VMOS_DEV
141
 
142
#elif !defined (VMS)
143
#include <utime.h>
144
#endif
145
 
146
/* wait.h processing */
147
#ifdef __MINGW32__
148
#if OLD_MINGW
149
#include <sys/wait.h>
150
#endif
151
#elif defined (__vxworks) && defined (__RTP__)
152
#include <wait.h>
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 */
163
#else
164
/* Default case */
165
#include <sys/wait.h>
166
#endif
167
 
168
#if defined (_WIN32)
169
#elif defined (VMS)
170
 
171
/* Header files and definitions for __gnat_set_file_time_name.  */
172
 
173
#define __NEW_STARLET 1
174
#include <vms/rms.h>
175
#include <vms/atrdef.h>
176
#include <vms/fibdef.h>
177
#include <vms/stsdef.h>
178
#include <vms/iodef.h>
179
#include <errno.h>
180
#include <vms/descrip.h>
181
#include <string.h>
182
#include <unixlib.h>
183
 
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; }
190
 
191
/* descrip.h doesn't have everything ... */
192
typedef struct fibdef* __fibdef_ptr32 __attribute__ (( mode (SI) ));
193
struct dsc$descriptor_fib
194
{
195
  unsigned int fib$l_len;
196
  __fibdef_ptr32 fib$l_addr;
197
};
198
 
199
/* I/O Status Block.  */
200
struct IOSB
201
{
202
  unsigned short status, count;
203
  unsigned int devdep;
204
};
205
 
206
static char *tryfile;
207
 
208
/* Variable length string.  */
209
struct vstring
210
{
211
  short length;
212
  char string[NAM$C_MAXRSS+1];
213
};
214
 
215
#define SYI$_ACTIVECPU_CNT 0x111e
216
extern int LIB$GETSYI (int *, unsigned int *);
217
 
218
#else
219
#include <utime.h>
220
#endif
221
 
222
#if defined (_WIN32)
223
#include <process.h>
224
#endif
225
 
226
#if defined (_WIN32)
227
 
228
#include <dir.h>
229
#include <windows.h>
230
#include <accctrl.h>
231
#include <aclapi.h>
232
#undef DIR_SEPARATOR
233
#define DIR_SEPARATOR '\\'
234
#endif
235
 
236
#include "adaint.h"
237
 
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.  */
243
 
244
#ifndef O_BINARY
245
#define O_BINARY 0
246
#endif
247
 
248
#ifndef O_TEXT
249
#define O_TEXT 0
250
#endif
251
 
252
#ifndef HOST_EXECUTABLE_SUFFIX
253
#define HOST_EXECUTABLE_SUFFIX ""
254
#endif
255
 
256
#ifndef HOST_OBJECT_SUFFIX
257
#define HOST_OBJECT_SUFFIX ".o"
258
#endif
259
 
260
#ifndef PATH_SEPARATOR
261
#define PATH_SEPARATOR ':'
262
#endif
263
 
264
#ifndef DIR_SEPARATOR
265
#define DIR_SEPARATOR '/'
266
#endif
267
 
268
/* Check for cross-compilation */
269
#if defined (CROSS_COMPILE) || defined (CROSS_DIRECTORY_STRUCTURE)
270
#define IS_CROSS 1
271
int __gnat_is_cross_compiler = 1;
272
#else
273
#undef IS_CROSS
274
int __gnat_is_cross_compiler = 0;
275
#endif
276
 
277
char __gnat_dir_separator = DIR_SEPARATOR;
278
 
279
char __gnat_path_separator = PATH_SEPARATOR;
280
 
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
285
 
286
     library_template ::= { pattern ; } pattern NUL
287
     pattern          ::= [ prefix ] * [ postfix ]
288
 
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
292
   to be up-to-date:
293
 
294
     * if they are needed but not present, the link
295
       will fail,
296
 
297
     * otherwise they are libraries in the system paths and so
298
       they are considered part of the system and not checked
299
       for that reason.
300
 
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.  */
304
 
305
#ifndef GNAT_LIBRARY_TEMPLATE
306
#if defined (VMS)
307
#define GNAT_LIBRARY_TEMPLATE "*.olb"
308
#else
309
#define GNAT_LIBRARY_TEMPLATE "lib*.a"
310
#endif
311
#endif
312
 
313
const char *__gnat_library_template = GNAT_LIBRARY_TEMPLATE;
314
 
315
/* This variable is used in hostparm.ads to say whether the host is a VMS
316
   system.  */
317
#ifdef VMS
318
int __gnat_vmsp = 1;
319
#else
320
int __gnat_vmsp = 0;
321
#endif
322
 
323
#if defined (VMS)
324
#define GNAT_MAX_PATH_LEN 256 /* PATH_MAX */
325
 
326
#elif defined (__vxworks) || defined (__OPENNT) || defined(__nucleus__)
327
#define GNAT_MAX_PATH_LEN PATH_MAX
328
 
329
#else
330
 
331
#if defined (__MINGW32__)
332
#include "mingw32.h"
333
 
334
#if OLD_MINGW
335
#include <sys/param.h>
336
#endif
337
 
338
#else
339
#include <sys/param.h>
340
#endif
341
 
342
#ifdef MAXPATHLEN
343
#define GNAT_MAX_PATH_LEN MAXPATHLEN
344
#else
345
#define GNAT_MAX_PATH_LEN 256
346
#endif
347
 
348
#endif
349
 
350
/* Used for Ada bindings */
351
int __gnat_size_of_file_attributes = sizeof (struct file_attributes);
352
 
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);
355
 
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
359
   it. */
360
 
361
int __gnat_max_path_len = GNAT_MAX_PATH_LEN;
362
int max_path_len = GNAT_MAX_PATH_LEN;
363
 
364
/* Control whether we can use ACL on Windows.  */
365
 
366
int __gnat_use_acl = 1;
367
 
368
/* The following macro HAVE_READDIR_R should be defined if the
369
   system provides the routine readdir_r.  */
370
#undef HAVE_READDIR_R
371
 
372
#if defined(VMS) && defined (__LONG_POINTERS)
373
 
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 */
376
 
377
typedef __char_ptr32 *__char_ptr_char_ptr32 __attribute__ ((mode (SI)));
378
 
379
static __char_ptr_char_ptr32
380
to_ptr32 (char **ptr64)
381
{
382
  int argc;
383
  __char_ptr_char_ptr32 short_argv;
384
 
385
  for (argc=0; ptr64[argc]; argc++);
386
 
387
  /* Reallocate argv with 32 bit pointers. */
388
  short_argv = (__char_ptr_char_ptr32) decc$malloc
389
    (sizeof (__char_ptr32) * (argc + 1));
390
 
391
  for (argc=0; ptr64[argc]; argc++)
392
    short_argv[argc] = (__char_ptr32) decc$strdup (ptr64[argc]);
393
 
394
  short_argv[argc] = (__char_ptr32) 0;
395
  return short_argv;
396
 
397
}
398
#define MAYBE_TO_PTR32(argv) to_ptr32 (argv)
399
#else
400
#define MAYBE_TO_PTR32(argv) argv
401
#endif
402
 
403
static const char ATTR_UNSET = 127;
404
 
405
void
406
__gnat_reset_attributes
407
  (struct file_attributes* attr)
408
{
409
  attr->exists     = ATTR_UNSET;
410
 
411
  attr->writable   = ATTR_UNSET;
412
  attr->readable   = ATTR_UNSET;
413
  attr->executable = ATTR_UNSET;
414
 
415
  attr->regular    = ATTR_UNSET;
416
  attr->symbolic_link = ATTR_UNSET;
417
  attr->directory = ATTR_UNSET;
418
 
419
  attr->timestamp = (OS_Time)-2;
420
  attr->file_length = -1;
421
}
422
 
423
OS_Time
424
__gnat_current_time
425
  (void)
426
{
427
  time_t res = time (NULL);
428
  return (OS_Time) res;
429
}
430
 
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
433
   long. */
434
 
435
void
436
__gnat_current_time_string
437
  (char *result)
438
{
439
  const char *format = "%Y-%m-%d %H:%M:%S";
440
  /* Format string necessary to describe the ISO 8601 format */
441
 
442
  const time_t t_val = time (NULL);
443
 
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. */
447
 
448
  result [19] = '.';
449
  result [20] = '0';
450
  result [21] = '0';
451
  /* The sub-seconds are manually set to zero since type time_t lacks the
452
     precision necessary for nanoseconds. */
453
}
454
 
455
void
456
__gnat_to_gm_time
457
  (OS_Time *p_time,
458
   int *p_year,
459
   int *p_month,
460
   int *p_day,
461
   int *p_hours,
462
   int *p_mins,
463
   int *p_secs)
464
{
465
  struct tm *res;
466
  time_t time = (time_t) *p_time;
467
 
468
#ifdef _WIN32
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.  */
471
  if (time & 1)
472
    time++;
473
#endif
474
 
475
#ifdef VMS
476
  res = localtime (&time);
477
#else
478
  res = gmtime (&time);
479
#endif
480
 
481
  if (res)
482
    {
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;
489
    }
490
  else
491
    *p_year = *p_month = *p_day = *p_hours = *p_mins = *p_secs = 0;
492
}
493
 
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.  */
498
 
499
int
500
__gnat_readlink (char *path ATTRIBUTE_UNUSED,
501
                 char *buf ATTRIBUTE_UNUSED,
502
                 size_t bufsiz ATTRIBUTE_UNUSED)
503
{
504
#if defined (_WIN32) || defined (VMS) \
505
    || defined(__vxworks) || defined (__nucleus__)
506
  return -1;
507
#else
508
  return readlink (path, buf, bufsiz);
509
#endif
510
}
511
 
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.  */
515
 
516
int
517
__gnat_symlink (char *oldpath ATTRIBUTE_UNUSED,
518
                char *newpath ATTRIBUTE_UNUSED)
519
{
520
#if defined (_WIN32) || defined (VMS) \
521
    || defined(__vxworks) || defined (__nucleus__)
522
  return -1;
523
#else
524
  return symlink (oldpath, newpath);
525
#endif
526
}
527
 
528
/* Try to lock a file, return 1 if success.  */
529
 
530
#if defined (__vxworks) || defined (__nucleus__) \
531
  || defined (_WIN32) || defined (VMS)
532
 
533
/* Version that does not use link. */
534
 
535
int
536
__gnat_try_lock (char *dir, char *file)
537
{
538
  int fd;
539
#ifdef __MINGW32__
540
  TCHAR wfull_path[GNAT_MAX_PATH_LEN];
541
  TCHAR wfile[GNAT_MAX_PATH_LEN];
542
  TCHAR wdir[GNAT_MAX_PATH_LEN];
543
 
544
  S2WSC (wdir, dir, GNAT_MAX_PATH_LEN);
545
  S2WSC (wfile, file, GNAT_MAX_PATH_LEN);
546
 
547
  _stprintf (wfull_path, _T("%s%c%s"), wdir, _T(DIR_SEPARATOR), wfile);
548
  fd = _topen (wfull_path, O_CREAT | O_EXCL, 0600);
549
#else
550
  char full_path[256];
551
 
552
  sprintf (full_path, "%s%c%s", dir, DIR_SEPARATOR, file);
553
  fd = open (full_path, O_CREAT | O_EXCL, 0600);
554
#endif
555
 
556
  if (fd < 0)
557
    return 0;
558
 
559
  close (fd);
560
  return 1;
561
}
562
 
563
#else
564
 
565
/* Version using link(), more secure over NFS.  */
566
/* See TN 6913-016 for discussion ??? */
567
 
568
int
569
__gnat_try_lock (char *dir, char *file)
570
{
571
  char full_path[256];
572
  char temp_file[256];
573
  GNAT_STRUCT_STAT stat_result;
574
  int fd;
575
 
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 ());
579
 
580
  /* Create the temporary file and write the process number.  */
581
  fd = open (temp_file, O_CREAT | O_WRONLY, 0600);
582
  if (fd < 0)
583
    return 0;
584
 
585
  close (fd);
586
 
587
  /* Link it with the new file.  */
588
  link (temp_file, full_path);
589
 
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);
593
  unlink (temp_file);
594
  return stat_result.st_nlink == 2;
595
}
596
#endif
597
 
598
/* Return the maximum file name length.  */
599
 
600
int
601
__gnat_get_maximum_file_name_length (void)
602
{
603
#if defined (VMS)
604
  if (getenv ("GNAT$EXTENDED_FILE_SPECIFICATIONS"))
605
    return -1;
606
  else
607
    return 39;
608
#else
609
  return -1;
610
#endif
611
}
612
 
613
/* Return nonzero if file names are case sensitive.  */
614
 
615
static int file_names_case_sensitive_cache = -1;
616
 
617
int
618
__gnat_get_file_names_case_sensitive (void)
619
{
620
  if (file_names_case_sensitive_cache == -1)
621
    {
622
      const char *sensitive = getenv ("GNAT_FILE_NAME_CASE_SENSITIVE");
623
 
624
      if (sensitive != NULL
625
          && (sensitive[0] == '0' || sensitive[0] == '1')
626
          && sensitive[1] == '\0')
627
        file_names_case_sensitive_cache = sensitive[0] - '0';
628
      else
629
#if defined (VMS) || defined (WINNT) || defined (__APPLE__)
630
        file_names_case_sensitive_cache = 0;
631
#else
632
        file_names_case_sensitive_cache = 1;
633
#endif
634
    }
635
  return file_names_case_sensitive_cache;
636
}
637
 
638
/* Return nonzero if environment variables are case sensitive.  */
639
 
640
int
641
__gnat_get_env_vars_case_sensitive (void)
642
{
643
#if defined (VMS) || defined (WINNT)
644
 return 0;
645
#else
646
 return 1;
647
#endif
648
}
649
 
650
char
651
__gnat_get_default_identifier_character_set (void)
652
{
653
  return '1';
654
}
655
 
656
/* Return the current working directory.  */
657
 
658
void
659
__gnat_get_current_dir (char *dir, int *length)
660
{
661
#if defined (__MINGW32__)
662
  TCHAR wdir[GNAT_MAX_PATH_LEN];
663
 
664
  _tgetcwd (wdir, *length);
665
 
666
  WS2SC (dir, wdir, GNAT_MAX_PATH_LEN);
667
 
668
#elif defined (VMS)
669
   /* Force Unix style, which is what GNAT uses internally.  */
670
   getcwd (dir, *length, 0);
671
#else
672
   getcwd (dir, *length);
673
#endif
674
 
675
   *length = strlen (dir);
676
 
677
   if (dir [*length - 1] != DIR_SEPARATOR)
678
     {
679
       dir [*length] = DIR_SEPARATOR;
680
       ++(*length);
681
     }
682
   dir[*length] = '\0';
683
}
684
 
685
/* Return the suffix for object files.  */
686
 
687
void
688
__gnat_get_object_suffix_ptr (int *len, const char **value)
689
{
690
  *value = HOST_OBJECT_SUFFIX;
691
 
692
  if (*value == 0)
693
    *len = 0;
694
  else
695
    *len = strlen (*value);
696
 
697
  return;
698
}
699
 
700
/* Return the suffix for executable files.  */
701
 
702
void
703
__gnat_get_executable_suffix_ptr (int *len, const char **value)
704
{
705
  *value = HOST_EXECUTABLE_SUFFIX;
706
  if (!*value)
707
    *len = 0;
708
  else
709
    *len = strlen (*value);
710
 
711
  return;
712
}
713
 
714
/* Return the suffix for debuggable files. Usually this is the same as the
715
   executable extension.  */
716
 
717
void
718
__gnat_get_debuggable_suffix_ptr (int *len, const char **value)
719
{
720
  *value = HOST_EXECUTABLE_SUFFIX;
721
 
722
  if (*value == 0)
723
    *len = 0;
724
  else
725
    *len = strlen (*value);
726
 
727
  return;
728
}
729
 
730
/* Returns the OS filename and corresponding encoding.  */
731
 
732
void
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)
737
{
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);
743
#else
744
  strcpy (os_name, filename);
745
  *o_length = strlen (filename);
746
  *e_length = 0;
747
#endif
748
}
749
 
750
/* Delete a file.  */
751
 
752
int
753
__gnat_unlink (char *path)
754
{
755
#if defined (__MINGW32__) && ! defined (__vxworks) && ! defined (IS_CROSS)
756
  {
757
    TCHAR wpath[GNAT_MAX_PATH_LEN];
758
 
759
    S2WSC (wpath, path, GNAT_MAX_PATH_LEN);
760
    return _tunlink (wpath);
761
  }
762
#else
763
  return unlink (path);
764
#endif
765
}
766
 
767
/* Rename a file.  */
768
 
769
int
770
__gnat_rename (char *from, char *to)
771
{
772
#if defined (__MINGW32__) && ! defined (__vxworks) && ! defined (IS_CROSS)
773
  {
774
    TCHAR wfrom[GNAT_MAX_PATH_LEN], wto[GNAT_MAX_PATH_LEN];
775
 
776
    S2WSC (wfrom, from, GNAT_MAX_PATH_LEN);
777
    S2WSC (wto, to, GNAT_MAX_PATH_LEN);
778
    return _trename (wfrom, wto);
779
  }
780
#else
781
  return rename (from, to);
782
#endif
783
}
784
 
785
/* Changing directory.  */
786
 
787
int
788
__gnat_chdir (char *path)
789
{
790
#if defined (__MINGW32__) && ! defined (__vxworks) && ! defined (IS_CROSS)
791
  {
792
    TCHAR wpath[GNAT_MAX_PATH_LEN];
793
 
794
    S2WSC (wpath, path, GNAT_MAX_PATH_LEN);
795
    return _tchdir (wpath);
796
  }
797
#else
798
  return chdir (path);
799
#endif
800
}
801
 
802
/* Removing a directory.  */
803
 
804
int
805
__gnat_rmdir (char *path)
806
{
807
#if defined (__MINGW32__) && ! defined (__vxworks) && ! defined (IS_CROSS)
808
  {
809
    TCHAR wpath[GNAT_MAX_PATH_LEN];
810
 
811
    S2WSC (wpath, path, GNAT_MAX_PATH_LEN);
812
    return _trmdir (wpath);
813
  }
814
#elif defined (VTHREADS)
815
  /* rmdir not available */
816
  return -1;
817
#else
818
  return rmdir (path);
819
#endif
820
}
821
 
822
FILE *
823
__gnat_fopen (char *path, char *mode, int encoding ATTRIBUTE_UNUSED)
824
{
825
#if defined (_WIN32) && ! defined (__vxworks) && ! defined (IS_CROSS)
826
  TCHAR wpath[GNAT_MAX_PATH_LEN];
827
  TCHAR wmode[10];
828
 
829
  S2WS (wmode, mode, 10);
830
 
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);
835
  else
836
    S2WS (wpath, path, GNAT_MAX_PATH_LEN);
837
 
838
  return _tfopen (wpath, wmode);
839
#elif defined (VMS)
840
  return decc$fopen (path, mode);
841
#else
842
  return GNAT_FOPEN (path, mode);
843
#endif
844
}
845
 
846
FILE *
847
__gnat_freopen (char *path,
848
                char *mode,
849
                FILE *stream,
850
                int encoding ATTRIBUTE_UNUSED)
851
{
852
#if defined (_WIN32) && ! defined (__vxworks) && ! defined (IS_CROSS)
853
  TCHAR wpath[GNAT_MAX_PATH_LEN];
854
  TCHAR wmode[10];
855
 
856
  S2WS (wmode, mode, 10);
857
 
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);
862
  else
863
    S2WS (wpath, path, GNAT_MAX_PATH_LEN);
864
 
865
  return _tfreopen (wpath, wmode, stream);
866
#elif defined (VMS)
867
  return decc$freopen (path, mode, stream);
868
#else
869
  return freopen (path, mode, stream);
870
#endif
871
}
872
 
873
int
874
__gnat_open_read (char *path, int fmode)
875
{
876
  int fd;
877
  int o_fmode = O_BINARY;
878
 
879
  if (fmode)
880
    o_fmode = O_TEXT;
881
 
882
#if defined (VMS)
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__)
889
 {
890
   TCHAR wpath[GNAT_MAX_PATH_LEN];
891
 
892
   S2WSC (wpath, path, GNAT_MAX_PATH_LEN);
893
   fd = _topen (wpath, O_RDONLY | o_fmode, 0444);
894
 }
895
#else
896
  fd = open (path, O_RDONLY | o_fmode);
897
#endif
898
 
899
  return fd < 0 ? -1 : fd;
900
}
901
 
902
#if defined (__MINGW32__)
903
#define PERM (S_IREAD | S_IWRITE)
904
#elif defined (VMS)
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
911
   files, and so on. */
912
#define PERM 0777
913
#else
914
#define PERM (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
915
#endif
916
 
917
int
918
__gnat_open_rw (char *path, int fmode)
919
{
920
  int fd;
921
  int o_fmode = O_BINARY;
922
 
923
  if (fmode)
924
    o_fmode = O_TEXT;
925
 
926
#if defined (VMS)
927
  fd = open (path, O_RDWR | o_fmode, PERM,
928
             "mbc=16", "deq=64", "fop=tef");
929
#elif defined (__MINGW32__)
930
  {
931
    TCHAR wpath[GNAT_MAX_PATH_LEN];
932
 
933
    S2WSC (wpath, path, GNAT_MAX_PATH_LEN);
934
    fd = _topen (wpath, O_RDWR | o_fmode, PERM);
935
  }
936
#else
937
  fd = open (path, O_RDWR | o_fmode, PERM);
938
#endif
939
 
940
  return fd < 0 ? -1 : fd;
941
}
942
 
943
int
944
__gnat_open_create (char *path, int fmode)
945
{
946
  int fd;
947
  int o_fmode = O_BINARY;
948
 
949
  if (fmode)
950
    o_fmode = O_TEXT;
951
 
952
#if defined (VMS)
953
  fd = open (path, O_WRONLY | O_CREAT | O_TRUNC | o_fmode, PERM,
954
             "mbc=16", "deq=64", "fop=tef");
955
#elif defined (__MINGW32__)
956
  {
957
    TCHAR wpath[GNAT_MAX_PATH_LEN];
958
 
959
    S2WSC (wpath, path, GNAT_MAX_PATH_LEN);
960
    fd = _topen (wpath, O_WRONLY | O_CREAT | O_TRUNC | o_fmode, PERM);
961
  }
962
#else
963
  fd = open (path, O_WRONLY | O_CREAT | O_TRUNC | o_fmode, PERM);
964
#endif
965
 
966
  return fd < 0 ? -1 : fd;
967
}
968
 
969
int
970
__gnat_create_output_file (char *path)
971
{
972
  int fd;
973
#if defined (VMS)
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__)
978
  {
979
    TCHAR wpath[GNAT_MAX_PATH_LEN];
980
 
981
    S2WSC (wpath, path, GNAT_MAX_PATH_LEN);
982
    fd = _topen (wpath, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, PERM);
983
  }
984
#else
985
  fd = open (path, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, PERM);
986
#endif
987
 
988
  return fd < 0 ? -1 : fd;
989
}
990
 
991
int
992
__gnat_create_output_file_new (char *path)
993
{
994
  int fd;
995
#if defined (VMS)
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__)
1000
  {
1001
    TCHAR wpath[GNAT_MAX_PATH_LEN];
1002
 
1003
    S2WSC (wpath, path, GNAT_MAX_PATH_LEN);
1004
    fd = _topen (wpath, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT | O_EXCL, PERM);
1005
  }
1006
#else
1007
  fd = open (path, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT | O_EXCL, PERM);
1008
#endif
1009
 
1010
  return fd < 0 ? -1 : fd;
1011
}
1012
 
1013
int
1014
__gnat_open_append (char *path, int fmode)
1015
{
1016
  int fd;
1017
  int o_fmode = O_BINARY;
1018
 
1019
  if (fmode)
1020
    o_fmode = O_TEXT;
1021
 
1022
#if defined (VMS)
1023
  fd = open (path, O_WRONLY | O_CREAT | O_APPEND | o_fmode, PERM,
1024
             "mbc=16", "deq=64", "fop=tef");
1025
#elif defined (__MINGW32__)
1026
  {
1027
    TCHAR wpath[GNAT_MAX_PATH_LEN];
1028
 
1029
    S2WSC (wpath, path, GNAT_MAX_PATH_LEN);
1030
    fd = _topen (wpath, O_WRONLY | O_CREAT | O_APPEND | o_fmode, PERM);
1031
  }
1032
#else
1033
  fd = open (path, O_WRONLY | O_CREAT | O_APPEND | o_fmode, PERM);
1034
#endif
1035
 
1036
  return fd < 0 ? -1 : fd;
1037
}
1038
 
1039
/*  Open a new file.  Return error (-1) if the file already exists.  */
1040
 
1041
int
1042
__gnat_open_new (char *path, int fmode)
1043
{
1044
  int fd;
1045
  int o_fmode = O_BINARY;
1046
 
1047
  if (fmode)
1048
    o_fmode = O_TEXT;
1049
 
1050
#if defined (VMS)
1051
  fd = open (path, O_WRONLY | O_CREAT | O_EXCL | o_fmode, PERM,
1052
             "mbc=16", "deq=64", "fop=tef");
1053
#elif defined (__MINGW32__)
1054
  {
1055
    TCHAR wpath[GNAT_MAX_PATH_LEN];
1056
 
1057
    S2WSC (wpath, path, GNAT_MAX_PATH_LEN);
1058
    fd = _topen (wpath, O_WRONLY | O_CREAT | O_EXCL | o_fmode, PERM);
1059
  }
1060
#else
1061
  fd = open (path, O_WRONLY | O_CREAT | O_EXCL | o_fmode, PERM);
1062
#endif
1063
 
1064
  return fd < 0 ? -1 : fd;
1065
}
1066
 
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.  */
1070
 
1071
int
1072
__gnat_open_new_temp (char *path, int fmode)
1073
{
1074
  int fd;
1075
  int o_fmode = O_BINARY;
1076
 
1077
  strcpy (path, "GNAT-XXXXXX");
1078
 
1079
#if (defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) \
1080
  || defined (linux) || defined(__GLIBC__)) && !defined (__vxworks)
1081
  return mkstemp (path);
1082
#elif defined (__Lynx__)
1083
  mktemp (path);
1084
#elif defined (__nucleus__)
1085
  return -1;
1086
#else
1087
  if (mktemp (path) == NULL)
1088
    return -1;
1089
#endif
1090
 
1091
  if (fmode)
1092
    o_fmode = O_TEXT;
1093
 
1094
#if defined (VMS)
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");
1098
#else
1099
  fd = open (path, O_WRONLY | O_CREAT | O_EXCL | o_fmode, PERM);
1100
#endif
1101
 
1102
  return fd < 0 ? -1 : fd;
1103
}
1104
 
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
 ****************************************************************/
1109
 
1110
void
1111
__gnat_stat_to_attr (int fd, char* name, struct file_attributes* attr)
1112
{
1113
  GNAT_STRUCT_STAT statbuf;
1114
  int ret;
1115
 
1116
  if (fd != -1)
1117
    ret = GNAT_FSTAT (fd, &statbuf);
1118
  else
1119
    ret = __gnat_stat (name, &statbuf);
1120
 
1121
  attr->regular   = (!ret && S_ISREG (statbuf.st_mode));
1122
  attr->directory = (!ret && S_ISDIR (statbuf.st_mode));
1123
 
1124
  if (!attr->regular)
1125
    attr->file_length = 0;
1126
  else
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
1129
       either case. */
1130
    attr->file_length = statbuf.st_size;  /* all systems */
1131
 
1132
  attr->exists = !ret;
1133
 
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));
1139
#endif
1140
 
1141
  if (ret != 0) {
1142
     attr->timestamp = (OS_Time)-1;
1143
  } else {
1144
#ifdef VMS
1145
     /* VMS has file versioning.  */
1146
     attr->timestamp = (OS_Time)statbuf.st_ctime;
1147
#else
1148
     attr->timestamp = (OS_Time)statbuf.st_mtime;
1149
#endif
1150
  }
1151
}
1152
 
1153
/****************************************************************
1154
 ** Return the number of bytes in the specified file
1155
 ****************************************************************/
1156
 
1157
long
1158
__gnat_file_length_attr (int fd, char* name, struct file_attributes* attr)
1159
{
1160
  if (attr->file_length == -1) {
1161
    __gnat_stat_to_attr (fd, name, attr);
1162
  }
1163
 
1164
  return attr->file_length;
1165
}
1166
 
1167
long
1168
__gnat_file_length (int fd)
1169
{
1170
  struct file_attributes attr;
1171
  __gnat_reset_attributes (&attr);
1172
  return __gnat_file_length_attr (fd, NULL, &attr);
1173
}
1174
 
1175
long
1176
__gnat_named_file_length (char *name)
1177
{
1178
  struct file_attributes attr;
1179
  __gnat_reset_attributes (&attr);
1180
  return __gnat_file_length_attr (-1, name, &attr);
1181
}
1182
 
1183
/* Create a temporary filename and put it in string pointed to by
1184
   TMP_FILENAME.  */
1185
 
1186
void
1187
__gnat_tmp_name (char *tmp_filename)
1188
{
1189
#ifdef RTX
1190
  /* Variable used to create a series of unique names */
1191
  static int counter = 0;
1192
 
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++);
1196
 
1197
#elif defined (__MINGW32__)
1198
  {
1199
    char *pname;
1200
    char prefix[25];
1201
 
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-".  */
1206
 
1207
    sprintf (prefix, "gnat-%d-", (int)getpid());
1208
    pname = (char *) _tempnam ("c:\\temp", prefix);
1209
 
1210
    /* if pname is NULL, the file was not created properly, the disk is full
1211
       or there is no more free temporary files */
1212
 
1213
    if (pname == NULL)
1214
      *tmp_filename = '\0';
1215
 
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.  */
1218
 
1219
    else if (pname[0] == '\\')
1220
      {
1221
        strcpy (tmp_filename, ".\\");
1222
        strcat (tmp_filename, pname+1);
1223
      }
1224
    else
1225
      strcpy (tmp_filename, pname);
1226
 
1227
    free (pname);
1228
  }
1229
 
1230
#elif defined (linux) || defined (__FreeBSD__) || defined (__NetBSD__) \
1231
  || defined (__OpenBSD__) || defined(__GLIBC__)
1232
#define MAX_SAFE_PATH 1000
1233
  char *tmpdir = getenv ("TMPDIR");
1234
 
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");
1239
  else
1240
    sprintf (tmp_filename, "%s/gnat-XXXXXX", tmpdir);
1241
 
1242
  close (mkstemp(tmp_filename));
1243
#elif defined (__vxworks) && !(defined (__RTP__) || defined (VTHREADS))
1244
  int             index;
1245
  char *          pos;
1246
  ushort_t        t;
1247
  static ushort_t seed = 0; /* used to generate unique name */
1248
 
1249
  /* generate unique name */
1250
  strcpy (tmp_filename, "tmp");
1251
 
1252
  /* fill up the name buffer from the last position */
1253
  index = 5;
1254
  pos = tmp_filename + strlen (tmp_filename) + index;
1255
  *pos = '\0';
1256
 
1257
  seed++;
1258
  for (t = seed; 0 <= --index; t >>= 3)
1259
      *--pos = '0' + (t & 07);
1260
#else
1261
  tmpnam (tmp_filename);
1262
#endif
1263
}
1264
 
1265
/*  Open directory and returns a DIR pointer.  */
1266
 
1267
DIR* __gnat_opendir (char *name)
1268
{
1269
#if defined (RTX)
1270
  /* Not supported in RTX */
1271
 
1272
  return NULL;
1273
 
1274
#elif defined (__MINGW32__)
1275
  TCHAR wname[GNAT_MAX_PATH_LEN];
1276
 
1277
  S2WSC (wname, name, GNAT_MAX_PATH_LEN);
1278
  return (DIR*)_topendir (wname);
1279
 
1280
#else
1281
  return opendir (name);
1282
#endif
1283
}
1284
 
1285
/* Read the next entry in a directory.  The returned string points somewhere
1286
   in the buffer.  */
1287
 
1288
char *
1289
__gnat_readdir (DIR *dirp, char *buffer, int *len)
1290
{
1291
#if defined (RTX)
1292
  /* Not supported in RTX */
1293
 
1294
  return NULL;
1295
 
1296
#elif defined (__MINGW32__)
1297
  struct _tdirent *dirent = _treaddir ((_TDIR*)dirp);
1298
 
1299
  if (dirent != NULL)
1300
    {
1301
      WS2SC (buffer, dirent->d_name, GNAT_MAX_PATH_LEN);
1302
      *len = strlen (buffer);
1303
 
1304
      return buffer;
1305
    }
1306
  else
1307
    return NULL;
1308
 
1309
#elif defined (HAVE_READDIR_R)
1310
  /* If possible, try to use the thread-safe version.  */
1311
  if (readdir_r (dirp, buffer) != NULL)
1312
    {
1313
      *len = strlen (((struct dirent*) buffer)->d_name);
1314
      return ((struct dirent*) buffer)->d_name;
1315
    }
1316
  else
1317
    return NULL;
1318
 
1319
#else
1320
  struct dirent *dirent = (struct dirent *) readdir (dirp);
1321
 
1322
  if (dirent != NULL)
1323
    {
1324
      strcpy (buffer, dirent->d_name);
1325
      *len = strlen (buffer);
1326
      return buffer;
1327
    }
1328
  else
1329
    return NULL;
1330
 
1331
#endif
1332
}
1333
 
1334
/* Close a directory entry.  */
1335
 
1336
int __gnat_closedir (DIR *dirp)
1337
{
1338
#if defined (RTX)
1339
  /* Not supported in RTX */
1340
 
1341
  return 0;
1342
 
1343
#elif defined (__MINGW32__)
1344
  return _tclosedir ((_TDIR*)dirp);
1345
 
1346
#else
1347
  return closedir (dirp);
1348
#endif
1349
}
1350
 
1351
/* Returns 1 if readdir is thread safe, 0 otherwise.  */
1352
 
1353
int
1354
__gnat_readdir_is_thread_safe (void)
1355
{
1356
#ifdef HAVE_READDIR_R
1357
  return 1;
1358
#else
1359
  return 0;
1360
#endif
1361
}
1362
 
1363
#if defined (_WIN32) && !defined (RTX)
1364
/* Number of seconds between <Jan 1st 1601> and <Jan 1st 1970>.  */
1365
static const unsigned long long w32_epoch_offset = 11644473600ULL;
1366
 
1367
/* Returns the file modification timestamp using Win32 routines which are
1368
   immune against daylight saving time change. It is in fact not possible to
1369
   use fstat for this purpose as the DST modify the st_mtime field of the
1370
   stat structure.  */
1371
 
1372
static time_t
1373
win32_filetime (HANDLE h)
1374
{
1375
  union
1376
  {
1377
    FILETIME ft_time;
1378
    unsigned long long ull_time;
1379
  } t_write;
1380
 
1381
  /* GetFileTime returns FILETIME data which are the number of 100 nanosecs
1382
     since <Jan 1st 1601>. This function must return the number of seconds
1383
     since <Jan 1st 1970>.  */
1384
 
1385
  if (GetFileTime (h, NULL, NULL, &t_write.ft_time))
1386
    return (time_t) (t_write.ull_time / 10000000ULL - w32_epoch_offset);
1387
  return (time_t) 0;
1388
}
1389
 
1390
/* As above but starting from a FILETIME.  */
1391
static void
1392
f2t (const FILETIME *ft, time_t *t)
1393
{
1394
  union
1395
  {
1396
    FILETIME ft_time;
1397
    unsigned long long ull_time;
1398
  } t_write;
1399
 
1400
  t_write.ft_time = *ft;
1401
  *t = (time_t) (t_write.ull_time / 10000000ULL - w32_epoch_offset);
1402
}
1403
#endif
1404
 
1405
/* Return a GNAT time stamp given a file name.  */
1406
 
1407
OS_Time
1408
__gnat_file_time_name_attr (char* name, struct file_attributes* attr)
1409
{
1410
   if (attr->timestamp == (OS_Time)-2) {
1411
#if defined (_WIN32) && !defined (RTX)
1412
      BOOL res;
1413
      WIN32_FILE_ATTRIBUTE_DATA fad;
1414
      time_t ret = -1;
1415
      TCHAR wname[GNAT_MAX_PATH_LEN];
1416
      S2WSC (wname, name, GNAT_MAX_PATH_LEN);
1417
 
1418
      if ((res = GetFileAttributesEx (wname, GetFileExInfoStandard, &fad)))
1419
        f2t (&fad.ftLastWriteTime, &ret);
1420
      attr->timestamp = (OS_Time) ret;
1421
#else
1422
      __gnat_stat_to_attr (-1, name, attr);
1423
#endif
1424
  }
1425
  return attr->timestamp;
1426
}
1427
 
1428
OS_Time
1429
__gnat_file_time_name (char *name)
1430
{
1431
   struct file_attributes attr;
1432
   __gnat_reset_attributes (&attr);
1433
   return __gnat_file_time_name_attr (name, &attr);
1434
}
1435
 
1436
/* Return a GNAT time stamp given a file descriptor.  */
1437
 
1438
OS_Time
1439
__gnat_file_time_fd_attr (int fd, struct file_attributes* attr)
1440
{
1441
   if (attr->timestamp == (OS_Time)-2) {
1442
#if defined (_WIN32) && !defined (RTX)
1443
     HANDLE h = (HANDLE) _get_osfhandle (fd);
1444
     time_t ret = win32_filetime (h);
1445
     attr->timestamp = (OS_Time) ret;
1446
 
1447
#else
1448
     __gnat_stat_to_attr (fd, NULL, attr);
1449
#endif
1450
   }
1451
 
1452
   return attr->timestamp;
1453
}
1454
 
1455
OS_Time
1456
__gnat_file_time_fd (int fd)
1457
{
1458
   struct file_attributes attr;
1459
   __gnat_reset_attributes (&attr);
1460
   return __gnat_file_time_fd_attr (fd, &attr);
1461
}
1462
 
1463
/* Set the file time stamp.  */
1464
 
1465
void
1466
__gnat_set_file_time_name (char *name, time_t time_stamp)
1467
{
1468
#if defined (__vxworks)
1469
 
1470
/* Code to implement __gnat_set_file_time_name for these systems.  */
1471
 
1472
#elif defined (_WIN32) && !defined (RTX)
1473
  union
1474
  {
1475
    FILETIME ft_time;
1476
    unsigned long long ull_time;
1477
  } t_write;
1478
  TCHAR wname[GNAT_MAX_PATH_LEN];
1479
 
1480
  S2WSC (wname, name, GNAT_MAX_PATH_LEN);
1481
 
1482
  HANDLE h  = CreateFile
1483
    (wname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
1484
     OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
1485
     NULL);
1486
  if (h == INVALID_HANDLE_VALUE)
1487
    return;
1488
  /* Add number of seconds between <Jan 1st 1601> and <Jan 1st 1970> */
1489
  t_write.ull_time = ((unsigned long long)time_stamp + w32_epoch_offset);
1490
  /*  Convert to 100 nanosecond units  */
1491
  t_write.ull_time *= 10000000ULL;
1492
 
1493
  SetFileTime(h, NULL, NULL, &t_write.ft_time);
1494
  CloseHandle (h);
1495
  return;
1496
 
1497
#elif defined (VMS)
1498
  struct FAB fab;
1499
  struct NAM nam;
1500
 
1501
  struct
1502
    {
1503
      unsigned long long backup, create, expire, revise;
1504
      unsigned int uic;
1505
      union
1506
        {
1507
          unsigned short value;
1508
          struct
1509
            {
1510
              unsigned system : 4;
1511
              unsigned owner  : 4;
1512
              unsigned group  : 4;
1513
              unsigned world  : 4;
1514
            } bits;
1515
        } prot;
1516
    } Fat = { 0, 0, 0, 0, 0, { 0 }};
1517
 
1518
  ATRDEF atrlst[]
1519
    = {
1520
      { ATR$S_CREDATE,  ATR$C_CREDATE,  &Fat.create },
1521
      { ATR$S_REVDATE,  ATR$C_REVDATE,  &Fat.revise },
1522
      { ATR$S_EXPDATE,  ATR$C_EXPDATE,  &Fat.expire },
1523
      { ATR$S_BAKDATE,  ATR$C_BAKDATE,  &Fat.backup },
1524
      { ATR$S_FPRO,     ATR$C_FPRO,     &Fat.prot },
1525
      { ATR$S_UIC,      ATR$C_UIC,      &Fat.uic },
1526
      { 0, 0, 0}
1527
    };
1528
 
1529
  FIBDEF fib;
1530
  struct dsc$descriptor_fib fibdsc = {sizeof (fib), (void *) &fib};
1531
 
1532
  struct IOSB iosb;
1533
 
1534
  unsigned long long newtime;
1535
  unsigned long long revtime;
1536
  long status;
1537
  short chan;
1538
 
1539
  struct vstring file;
1540
  struct dsc$descriptor_s filedsc
1541
    = {NAM$C_MAXRSS, DSC$K_DTYPE_T, DSC$K_CLASS_S, (void *) file.string};
1542
  struct vstring device;
1543
  struct dsc$descriptor_s devicedsc
1544
    = {NAM$C_MAXRSS, DSC$K_DTYPE_T, DSC$K_CLASS_S, (void *) device.string};
1545
  struct vstring timev;
1546
  struct dsc$descriptor_s timedsc
1547
    = {NAM$C_MAXRSS, DSC$K_DTYPE_T, DSC$K_CLASS_S, (void *) timev.string};
1548
  struct vstring result;
1549
  struct dsc$descriptor_s resultdsc
1550
    = {NAM$C_MAXRSS, DSC$K_DTYPE_VT, DSC$K_CLASS_VS, (void *) result.string};
1551
 
1552
  /* Convert parameter name (a file spec) to host file form. Note that this
1553
     is needed on VMS to prepare for subsequent calls to VMS RMS library
1554
     routines. Note that it would not work to call __gnat_to_host_dir_spec
1555
     as was done in a previous version, since this fails silently unless
1556
     the feature logical DECC$EFS_CHARSET is enabled, in which case a DNF
1557
     (directory not found) condition is signalled.  */
1558
  tryfile = (char *) __gnat_to_host_file_spec (name);
1559
 
1560
  /* Allocate and initialize a FAB and NAM structures.  */
1561
  fab = cc$rms_fab;
1562
  nam = cc$rms_nam;
1563
 
1564
  nam.nam$l_esa = file.string;
1565
  nam.nam$b_ess = NAM$C_MAXRSS;
1566
  nam.nam$l_rsa = result.string;
1567
  nam.nam$b_rss = NAM$C_MAXRSS;
1568
  fab.fab$l_fna = tryfile;
1569
  fab.fab$b_fns = strlen (tryfile);
1570
  fab.fab$l_nam = &nam;
1571
 
1572
  /* Validate filespec syntax and device existence.  */
1573
  status = SYS$PARSE (&fab, 0, 0);
1574
  if ((status & 1) != 1)
1575
    LIB$SIGNAL (status);
1576
 
1577
  file.string[nam.nam$b_esl] = 0;
1578
 
1579
  /* Find matching filespec.  */
1580
  status = SYS$SEARCH (&fab, 0, 0);
1581
  if ((status & 1) != 1)
1582
    LIB$SIGNAL (status);
1583
 
1584
  file.string[nam.nam$b_esl] = 0;
1585
  result.string[result.length=nam.nam$b_rsl] = 0;
1586
 
1587
  /* Get the device name and assign an IO channel.  */
1588
  strncpy (device.string, nam.nam$l_dev, nam.nam$b_dev);
1589
  devicedsc.dsc$w_length  = nam.nam$b_dev;
1590
  chan = 0;
1591
  status = SYS$ASSIGN (&devicedsc, &chan, 0, 0, 0);
1592
  if ((status & 1) != 1)
1593
    LIB$SIGNAL (status);
1594
 
1595
  /* Initialize the FIB and fill in the directory id field.  */
1596
  memset (&fib, 0, sizeof (fib));
1597
  fib.fib$w_did[0]  = nam.nam$w_did[0];
1598
  fib.fib$w_did[1]  = nam.nam$w_did[1];
1599
  fib.fib$w_did[2]  = nam.nam$w_did[2];
1600
  fib.fib$l_acctl = 0;
1601
  fib.fib$l_wcc = 0;
1602
  strcpy (file.string, (strrchr (result.string, ']') + 1));
1603
  filedsc.dsc$w_length = strlen (file.string);
1604
  result.string[result.length = 0] = 0;
1605
 
1606
  /* Open and close the file to fill in the attributes.  */
1607
  status
1608
    = SYS$QIOW (0, chan, IO$_ACCESS|IO$M_ACCESS, &iosb, 0, 0,
1609
                &fibdsc, &filedsc, &result.length, &resultdsc, &atrlst, 0);
1610
  if ((status & 1) != 1)
1611
    LIB$SIGNAL (status);
1612
  if ((iosb.status & 1) != 1)
1613
    LIB$SIGNAL (iosb.status);
1614
 
1615
  result.string[result.length] = 0;
1616
  status = SYS$QIOW (0, chan, IO$_DEACCESS, &iosb, 0, 0, &fibdsc, 0, 0, 0,
1617
                     &atrlst, 0);
1618
  if ((status & 1) != 1)
1619
    LIB$SIGNAL (status);
1620
  if ((iosb.status & 1) != 1)
1621
    LIB$SIGNAL (iosb.status);
1622
 
1623
  {
1624
    time_t t;
1625
 
1626
    /* Set creation time to requested time.  */
1627
    unix_time_to_vms (time_stamp, newtime);
1628
 
1629
    t = time ((time_t) 0);
1630
 
1631
    /* Set revision time to now in local time.  */
1632
    unix_time_to_vms (t, revtime);
1633
  }
1634
 
1635
  /* Reopen the file, modify the times and then close.  */
1636
  fib.fib$l_acctl = FIB$M_WRITE;
1637
  status
1638
    = SYS$QIOW (0, chan, IO$_ACCESS|IO$M_ACCESS, &iosb, 0, 0,
1639
                &fibdsc, &filedsc, &result.length, &resultdsc, &atrlst, 0);
1640
  if ((status & 1) != 1)
1641
    LIB$SIGNAL (status);
1642
  if ((iosb.status & 1) != 1)
1643
    LIB$SIGNAL (iosb.status);
1644
 
1645
  Fat.create = newtime;
1646
  Fat.revise = revtime;
1647
 
1648
  status = SYS$QIOW (0, chan, IO$_DEACCESS, &iosb, 0, 0,
1649
                     &fibdsc, 0, 0, 0, &atrlst, 0);
1650
  if ((status & 1) != 1)
1651
    LIB$SIGNAL (status);
1652
  if ((iosb.status & 1) != 1)
1653
    LIB$SIGNAL (iosb.status);
1654
 
1655
  /* Deassign the channel and exit.  */
1656
  status = SYS$DASSGN (chan);
1657
  if ((status & 1) != 1)
1658
    LIB$SIGNAL (status);
1659
#else
1660
  struct utimbuf utimbuf;
1661
  time_t t;
1662
 
1663
  /* Set modification time to requested time.  */
1664
  utimbuf.modtime = time_stamp;
1665
 
1666
  /* Set access time to now in local time.  */
1667
  t = time ((time_t) 0);
1668
  utimbuf.actime = mktime (localtime (&t));
1669
 
1670
  utime (name, &utimbuf);
1671
#endif
1672
}
1673
 
1674
/* Get the list of installed standard libraries from the
1675
   HKEY_LOCAL_MACHINE\SOFTWARE\Ada Core Technologies\GNAT\Standard Libraries
1676
   key.  */
1677
 
1678
char *
1679
__gnat_get_libraries_from_registry (void)
1680
{
1681
  char *result = (char *) xmalloc (1);
1682
 
1683
  result[0] = '\0';
1684
 
1685
#if defined (_WIN32) && ! defined (__vxworks) && ! defined (IS_CROSS) \
1686
  && ! defined (RTX)
1687
 
1688
  HKEY reg_key;
1689
  DWORD name_size, value_size;
1690
  char name[256];
1691
  char value[256];
1692
  DWORD type;
1693
  DWORD index;
1694
  LONG res;
1695
 
1696
  /* First open the key.  */
1697
  res = RegOpenKeyExA (HKEY_LOCAL_MACHINE, "SOFTWARE", 0, KEY_READ, &reg_key);
1698
 
1699
  if (res == ERROR_SUCCESS)
1700
    res = RegOpenKeyExA (reg_key, "Ada Core Technologies", 0,
1701
                         KEY_READ, &reg_key);
1702
 
1703
  if (res == ERROR_SUCCESS)
1704
    res = RegOpenKeyExA (reg_key, "GNAT", 0, KEY_READ, &reg_key);
1705
 
1706
  if (res == ERROR_SUCCESS)
1707
    res = RegOpenKeyExA (reg_key, "Standard Libraries", 0, KEY_READ, &reg_key);
1708
 
1709
  /* If the key exists, read out all the values in it and concatenate them
1710
     into a path.  */
1711
  for (index = 0; res == ERROR_SUCCESS; index++)
1712
    {
1713
      value_size = name_size = 256;
1714
      res = RegEnumValueA (reg_key, index, name, &name_size, 0,
1715
                           &type, (LPBYTE)value, &value_size);
1716
 
1717
      if (res == ERROR_SUCCESS && type == REG_SZ)
1718
        {
1719
          char *old_result = result;
1720
 
1721
          result = (char *) xmalloc (strlen (old_result) + value_size + 2);
1722
          strcpy (result, old_result);
1723
          strcat (result, value);
1724
          strcat (result, ";");
1725
          free (old_result);
1726
        }
1727
    }
1728
 
1729
  /* Remove the trailing ";".  */
1730
  if (result[0] != 0)
1731
    result[strlen (result) - 1] = 0;
1732
 
1733
#endif
1734
  return result;
1735
}
1736
 
1737
int
1738
__gnat_stat (char *name, GNAT_STRUCT_STAT *statbuf)
1739
{
1740
#ifdef __MINGW32__
1741
  WIN32_FILE_ATTRIBUTE_DATA fad;
1742
  TCHAR wname [GNAT_MAX_PATH_LEN + 2];
1743
  int name_len;
1744
  BOOL res;
1745
  DWORD error;
1746
 
1747
  S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
1748
  name_len = _tcslen (wname);
1749
 
1750
  if (name_len > GNAT_MAX_PATH_LEN)
1751
    return -1;
1752
 
1753
  ZeroMemory (statbuf, sizeof(GNAT_STRUCT_STAT));
1754
 
1755
  res = GetFileAttributesEx (wname, GetFileExInfoStandard, &fad);
1756
 
1757
  if (res == FALSE) {
1758
    error = GetLastError();
1759
 
1760
    /* Check file existence using GetFileAttributes() which does not fail on
1761
       special Windows files like con:, aux:, nul: etc...  */
1762
 
1763
    if (GetFileAttributes(wname) != INVALID_FILE_ATTRIBUTES) {
1764
      /* Just pretend that it is a regular and readable file  */
1765
      statbuf->st_mode = S_IFREG | S_IREAD | S_IWRITE;
1766
      return 0;
1767
    }
1768
 
1769
    switch (error) {
1770
      case ERROR_ACCESS_DENIED:
1771
      case ERROR_SHARING_VIOLATION:
1772
      case ERROR_LOCK_VIOLATION:
1773
      case ERROR_SHARING_BUFFER_EXCEEDED:
1774
        return EACCES;
1775
      case ERROR_BUFFER_OVERFLOW:
1776
        return ENAMETOOLONG;
1777
      case ERROR_NOT_ENOUGH_MEMORY:
1778
        return ENOMEM;
1779
      default:
1780
        return ENOENT;
1781
    }
1782
  }
1783
 
1784
  f2t (&fad.ftCreationTime, &statbuf->st_ctime);
1785
  f2t (&fad.ftLastWriteTime, &statbuf->st_mtime);
1786
  f2t (&fad.ftLastAccessTime, &statbuf->st_atime);
1787
 
1788
  statbuf->st_size = (off_t)fad.nFileSizeLow;
1789
 
1790
  /* We do not have the S_IEXEC attribute, but this is not used on GNAT.  */
1791
  statbuf->st_mode = S_IREAD;
1792
 
1793
  if (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1794
    statbuf->st_mode |= S_IFDIR;
1795
  else
1796
    statbuf->st_mode |= S_IFREG;
1797
 
1798
  if (!(fad.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
1799
    statbuf->st_mode |= S_IWRITE;
1800
 
1801
  return 0;
1802
 
1803
#else
1804
  return GNAT_STAT (name, statbuf);
1805
#endif
1806
}
1807
 
1808
/*************************************************************************
1809
 ** Check whether a file exists
1810
 *************************************************************************/
1811
 
1812
int
1813
__gnat_file_exists_attr (char* name, struct file_attributes* attr)
1814
{
1815
   if (attr->exists == ATTR_UNSET) {
1816
      __gnat_stat_to_attr (-1, name, attr);
1817
   }
1818
 
1819
   return attr->exists;
1820
}
1821
 
1822
int
1823
__gnat_file_exists (char *name)
1824
{
1825
   struct file_attributes attr;
1826
   __gnat_reset_attributes (&attr);
1827
   return __gnat_file_exists_attr (name, &attr);
1828
}
1829
 
1830
/**********************************************************************
1831
 ** Whether name is an absolute path
1832
 **********************************************************************/
1833
 
1834
int
1835
__gnat_is_absolute_path (char *name, int length)
1836
{
1837
#ifdef __vxworks
1838
  /* On VxWorks systems, an absolute path can be represented (depending on
1839
     the host platform) as either /dir/file, or device:/dir/file, or
1840
     device:drive_letter:/dir/file. */
1841
 
1842
  int index;
1843
 
1844
  if (name[0] == '/')
1845
    return 1;
1846
 
1847
  for (index = 0; index < length; index++)
1848
    {
1849
      if (name[index] == ':' &&
1850
          ((name[index + 1] == '/') ||
1851
           (isalpha (name[index + 1]) && index + 2 <= length &&
1852
            name[index + 2] == '/')))
1853
        return 1;
1854
 
1855
      else if (name[index] == '/')
1856
        return 0;
1857
    }
1858
  return 0;
1859
#else
1860
  return (length != 0) &&
1861
     (*name == '/' || *name == DIR_SEPARATOR
1862
#if defined (WINNT)
1863
      || (length > 1 && ISALPHA (name[0]) && name[1] == ':')
1864
#endif
1865
          );
1866
#endif
1867
}
1868
 
1869
int
1870
__gnat_is_regular_file_attr (char* name, struct file_attributes* attr)
1871
{
1872
   if (attr->regular == ATTR_UNSET) {
1873
      __gnat_stat_to_attr (-1, name, attr);
1874
   }
1875
 
1876
   return attr->regular;
1877
}
1878
 
1879
int
1880
__gnat_is_regular_file (char *name)
1881
{
1882
   struct file_attributes attr;
1883
   __gnat_reset_attributes (&attr);
1884
   return __gnat_is_regular_file_attr (name, &attr);
1885
}
1886
 
1887
int
1888
__gnat_is_directory_attr (char* name, struct file_attributes* attr)
1889
{
1890
   if (attr->directory == ATTR_UNSET) {
1891
      __gnat_stat_to_attr (-1, name, attr);
1892
   }
1893
 
1894
   return attr->directory;
1895
}
1896
 
1897
int
1898
__gnat_is_directory (char *name)
1899
{
1900
   struct file_attributes attr;
1901
   __gnat_reset_attributes (&attr);
1902
   return __gnat_is_directory_attr (name, &attr);
1903
}
1904
 
1905
#if defined (_WIN32) && !defined (RTX)
1906
 
1907
/* Returns the same constant as GetDriveType but takes a pathname as
1908
   argument. */
1909
 
1910
static UINT
1911
GetDriveTypeFromPath (TCHAR *wfullpath)
1912
{
1913
  TCHAR wdrv[MAX_PATH];
1914
  TCHAR wpath[MAX_PATH];
1915
  TCHAR wfilename[MAX_PATH];
1916
  TCHAR wext[MAX_PATH];
1917
 
1918
  _tsplitpath (wfullpath, wdrv, wpath, wfilename, wext);
1919
 
1920
  if (_tcslen (wdrv) != 0)
1921
    {
1922
      /* we have a drive specified. */
1923
      _tcscat (wdrv, _T("\\"));
1924
      return GetDriveType (wdrv);
1925
    }
1926
  else
1927
    {
1928
      /* No drive specified. */
1929
 
1930
      /* Is this a relative path, if so get current drive type. */
1931
      if (wpath[0] != _T('\\') ||
1932
          (_tcslen (wpath) > 2 && wpath[0] == _T('\\') && wpath[1] != _T('\\')))
1933
        return GetDriveType (NULL);
1934
 
1935
      UINT result = GetDriveType (wpath);
1936
 
1937
      /* Cannot guess the drive type, is this \\.\ ? */
1938
 
1939
      if (result == DRIVE_NO_ROOT_DIR &&
1940
         _tcslen (wpath) >= 4 && wpath[0] == _T('\\') && wpath[1] == _T('\\')
1941
          && wpath[2] == _T('.') && wpath[3] == _T('\\'))
1942
        {
1943
          if (_tcslen (wpath) == 4)
1944
            _tcscat (wpath, wfilename);
1945
 
1946
          LPTSTR p = &wpath[4];
1947
          LPTSTR b = _tcschr (p, _T('\\'));
1948
 
1949
          if (b != NULL)
1950
            { /* logical drive \\.\c\dir\file */
1951
              *b++ = _T(':');
1952
              *b++ = _T('\\');
1953
              *b = _T('\0');
1954
            }
1955
          else
1956
            _tcscat (p, _T(":\\"));
1957
 
1958
          return GetDriveType (p);
1959
        }
1960
 
1961
      return result;
1962
    }
1963
}
1964
 
1965
/*  This MingW section contains code to work with ACL. */
1966
static int
1967
__gnat_check_OWNER_ACL
1968
(TCHAR *wname,
1969
 DWORD CheckAccessDesired,
1970
 GENERIC_MAPPING CheckGenericMapping)
1971
{
1972
  DWORD dwAccessDesired, dwAccessAllowed;
1973
  PRIVILEGE_SET PrivilegeSet;
1974
  DWORD dwPrivSetSize = sizeof (PRIVILEGE_SET);
1975
  BOOL fAccessGranted = FALSE;
1976
  HANDLE hToken = NULL;
1977
  DWORD nLength = 0;
1978
  SECURITY_DESCRIPTOR* pSD = NULL;
1979
 
1980
  GetFileSecurity
1981
    (wname, OWNER_SECURITY_INFORMATION |
1982
     GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
1983
     NULL, 0, &nLength);
1984
 
1985
  if ((pSD = (PSECURITY_DESCRIPTOR) HeapAlloc
1986
       (GetProcessHeap (), HEAP_ZERO_MEMORY, nLength)) == NULL)
1987
    return 0;
1988
 
1989
  /* Obtain the security descriptor. */
1990
 
1991
  if (!GetFileSecurity
1992
      (wname, OWNER_SECURITY_INFORMATION |
1993
       GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
1994
       pSD, nLength, &nLength))
1995
    goto error;
1996
 
1997
  if (!ImpersonateSelf (SecurityImpersonation))
1998
    goto error;
1999
 
2000
  if (!OpenThreadToken
2001
      (GetCurrentThread(), TOKEN_DUPLICATE | TOKEN_QUERY, FALSE, &hToken))
2002
    goto error;
2003
 
2004
  /*  Undoes the effect of ImpersonateSelf. */
2005
 
2006
  RevertToSelf ();
2007
 
2008
  /*  We want to test for write permissions. */
2009
 
2010
  dwAccessDesired = CheckAccessDesired;
2011
 
2012
  MapGenericMask (&dwAccessDesired, &CheckGenericMapping);
2013
 
2014
  if (!AccessCheck
2015
      (pSD ,                 /* security descriptor to check */
2016
       hToken,               /* impersonation token */
2017
       dwAccessDesired,      /* requested access rights */
2018
       &CheckGenericMapping, /* pointer to GENERIC_MAPPING */
2019
       &PrivilegeSet,        /* receives privileges used in check */
2020
       &dwPrivSetSize,       /* size of PrivilegeSet buffer */
2021
       &dwAccessAllowed,     /* receives mask of allowed access rights */
2022
       &fAccessGranted))
2023
    goto error;
2024
 
2025
  CloseHandle (hToken);
2026
  HeapFree (GetProcessHeap (), 0, pSD);
2027
  return fAccessGranted;
2028
 
2029
 error:
2030
  if (hToken)
2031
    CloseHandle (hToken);
2032
  HeapFree (GetProcessHeap (), 0, pSD);
2033
  return 0;
2034
}
2035
 
2036
static void
2037
__gnat_set_OWNER_ACL
2038
(TCHAR *wname,
2039
 DWORD AccessMode,
2040
 DWORD AccessPermissions)
2041
{
2042
  PACL pOldDACL = NULL;
2043
  PACL pNewDACL = NULL;
2044
  PSECURITY_DESCRIPTOR pSD = NULL;
2045
  EXPLICIT_ACCESS ea;
2046
  TCHAR username [100];
2047
  DWORD unsize = 100;
2048
 
2049
  /*  Get current user, he will act as the owner */
2050
 
2051
  if (!GetUserName (username, &unsize))
2052
    return;
2053
 
2054
  if (GetNamedSecurityInfo
2055
      (wname,
2056
       SE_FILE_OBJECT,
2057
       DACL_SECURITY_INFORMATION,
2058
       NULL, NULL, &pOldDACL, NULL, &pSD) != ERROR_SUCCESS)
2059
    return;
2060
 
2061
  BuildExplicitAccessWithName
2062
    (&ea, username, AccessPermissions, AccessMode, NO_INHERITANCE);
2063
 
2064
  if (AccessMode == SET_ACCESS)
2065
    {
2066
      /*  SET_ACCESS, we want to set an explicte set of permissions, do not
2067
          merge with current DACL.  */
2068
      if (SetEntriesInAcl (1, &ea, NULL, &pNewDACL) != ERROR_SUCCESS)
2069
        return;
2070
    }
2071
  else
2072
    if (SetEntriesInAcl (1, &ea, pOldDACL, &pNewDACL) != ERROR_SUCCESS)
2073
      return;
2074
 
2075
  if (SetNamedSecurityInfo
2076
      (wname, SE_FILE_OBJECT,
2077
       DACL_SECURITY_INFORMATION, NULL, NULL, pNewDACL, NULL) != ERROR_SUCCESS)
2078
    return;
2079
 
2080
  LocalFree (pSD);
2081
  LocalFree (pNewDACL);
2082
}
2083
 
2084
/* Check if it is possible to use ACL for wname, the file must not be on a
2085
   network drive. */
2086
 
2087
static int
2088
__gnat_can_use_acl (TCHAR *wname)
2089
{
2090
  return __gnat_use_acl && GetDriveTypeFromPath (wname) != DRIVE_REMOTE;
2091
}
2092
 
2093
#endif /* defined (_WIN32) && !defined (RTX) */
2094
 
2095
int
2096
__gnat_is_readable_file_attr (char* name, struct file_attributes* attr)
2097
{
2098
   if (attr->readable == ATTR_UNSET) {
2099
#if defined (_WIN32) && !defined (RTX)
2100
     TCHAR wname [GNAT_MAX_PATH_LEN + 2];
2101
     GENERIC_MAPPING GenericMapping;
2102
 
2103
     S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
2104
 
2105
     if (__gnat_can_use_acl (wname))
2106
     {
2107
        ZeroMemory (&GenericMapping, sizeof (GENERIC_MAPPING));
2108
        GenericMapping.GenericRead = GENERIC_READ;
2109
        attr->readable =
2110
          __gnat_check_OWNER_ACL (wname, FILE_READ_DATA, GenericMapping);
2111
     }
2112
     else
2113
        attr->readable = GetFileAttributes (wname) != INVALID_FILE_ATTRIBUTES;
2114
#else
2115
     __gnat_stat_to_attr (-1, name, attr);
2116
#endif
2117
   }
2118
 
2119
   return attr->readable;
2120
}
2121
 
2122
int
2123
__gnat_is_readable_file (char *name)
2124
{
2125
   struct file_attributes attr;
2126
   __gnat_reset_attributes (&attr);
2127
   return __gnat_is_readable_file_attr (name, &attr);
2128
}
2129
 
2130
int
2131
__gnat_is_writable_file_attr (char* name, struct file_attributes* attr)
2132
{
2133
   if (attr->writable == ATTR_UNSET) {
2134
#if defined (_WIN32) && !defined (RTX)
2135
     TCHAR wname [GNAT_MAX_PATH_LEN + 2];
2136
     GENERIC_MAPPING GenericMapping;
2137
 
2138
     S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
2139
 
2140
     if (__gnat_can_use_acl (wname))
2141
       {
2142
         ZeroMemory (&GenericMapping, sizeof (GENERIC_MAPPING));
2143
         GenericMapping.GenericWrite = GENERIC_WRITE;
2144
 
2145
         attr->writable = __gnat_check_OWNER_ACL
2146
             (wname, FILE_WRITE_DATA | FILE_APPEND_DATA, GenericMapping)
2147
             && !(GetFileAttributes (wname) & FILE_ATTRIBUTE_READONLY);
2148
       }
2149
     else
2150
       attr->writable = !(GetFileAttributes (wname) & FILE_ATTRIBUTE_READONLY);
2151
 
2152
#else
2153
     __gnat_stat_to_attr (-1, name, attr);
2154
#endif
2155
   }
2156
 
2157
   return attr->writable;
2158
}
2159
 
2160
int
2161
__gnat_is_writable_file (char *name)
2162
{
2163
   struct file_attributes attr;
2164
   __gnat_reset_attributes (&attr);
2165
   return __gnat_is_writable_file_attr (name, &attr);
2166
}
2167
 
2168
int
2169
__gnat_is_executable_file_attr (char* name, struct file_attributes* attr)
2170
{
2171
   if (attr->executable == ATTR_UNSET) {
2172
#if defined (_WIN32) && !defined (RTX)
2173
     TCHAR wname [GNAT_MAX_PATH_LEN + 2];
2174
     GENERIC_MAPPING GenericMapping;
2175
 
2176
     S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
2177
 
2178
     if (__gnat_can_use_acl (wname))
2179
       {
2180
         ZeroMemory (&GenericMapping, sizeof (GENERIC_MAPPING));
2181
         GenericMapping.GenericExecute = GENERIC_EXECUTE;
2182
 
2183
         attr->executable =
2184
           __gnat_check_OWNER_ACL (wname, FILE_EXECUTE, GenericMapping);
2185
       }
2186
     else
2187
       {
2188
         TCHAR *l, *last = _tcsstr(wname, _T(".exe"));
2189
 
2190
         /* look for last .exe */
2191
         if (last)
2192
           while ((l = _tcsstr(last+1, _T(".exe")))) last = l;
2193
 
2194
         attr->executable = GetFileAttributes (wname) != INVALID_FILE_ATTRIBUTES
2195
           && (last - wname) == (int) (_tcslen (wname) - 4);
2196
       }
2197
#else
2198
     __gnat_stat_to_attr (-1, name, attr);
2199
#endif
2200
   }
2201
 
2202
   return attr->executable;
2203
}
2204
 
2205
int
2206
__gnat_is_executable_file (char *name)
2207
{
2208
   struct file_attributes attr;
2209
   __gnat_reset_attributes (&attr);
2210
   return __gnat_is_executable_file_attr (name, &attr);
2211
}
2212
 
2213
void
2214
__gnat_set_writable (char *name)
2215
{
2216
#if defined (_WIN32) && !defined (RTX)
2217
  TCHAR wname [GNAT_MAX_PATH_LEN + 2];
2218
 
2219
  S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
2220
 
2221
  if (__gnat_can_use_acl (wname))
2222
    __gnat_set_OWNER_ACL (wname, GRANT_ACCESS, FILE_GENERIC_WRITE);
2223
 
2224
  SetFileAttributes
2225
    (wname, GetFileAttributes (wname) & ~FILE_ATTRIBUTE_READONLY);
2226
#elif ! (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 6) && \
2227
  ! defined(__nucleus__)
2228
  GNAT_STRUCT_STAT statbuf;
2229
 
2230
  if (GNAT_STAT (name, &statbuf) == 0)
2231
    {
2232
      statbuf.st_mode = statbuf.st_mode | S_IWUSR;
2233
      chmod (name, statbuf.st_mode);
2234
    }
2235
#endif
2236
}
2237
 
2238
void
2239
__gnat_set_executable (char *name)
2240
{
2241
#if defined (_WIN32) && !defined (RTX)
2242
  TCHAR wname [GNAT_MAX_PATH_LEN + 2];
2243
 
2244
  S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
2245
 
2246
  if (__gnat_can_use_acl (wname))
2247
    __gnat_set_OWNER_ACL (wname, GRANT_ACCESS, FILE_GENERIC_EXECUTE);
2248
 
2249
#elif ! (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 6) && \
2250
  ! defined(__nucleus__)
2251
  GNAT_STRUCT_STAT statbuf;
2252
 
2253
  if (GNAT_STAT (name, &statbuf) == 0)
2254
    {
2255
      statbuf.st_mode = statbuf.st_mode | S_IXUSR;
2256
      chmod (name, statbuf.st_mode);
2257
    }
2258
#endif
2259
}
2260
 
2261
void
2262
__gnat_set_non_writable (char *name)
2263
{
2264
#if defined (_WIN32) && !defined (RTX)
2265
  TCHAR wname [GNAT_MAX_PATH_LEN + 2];
2266
 
2267
  S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
2268
 
2269
  if (__gnat_can_use_acl (wname))
2270
    __gnat_set_OWNER_ACL
2271
      (wname, DENY_ACCESS,
2272
       FILE_WRITE_DATA | FILE_APPEND_DATA |
2273
       FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES);
2274
 
2275
  SetFileAttributes
2276
    (wname, GetFileAttributes (wname) | FILE_ATTRIBUTE_READONLY);
2277
#elif ! (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 6) && \
2278
  ! defined(__nucleus__)
2279
  GNAT_STRUCT_STAT statbuf;
2280
 
2281
  if (GNAT_STAT (name, &statbuf) == 0)
2282
    {
2283
      statbuf.st_mode = statbuf.st_mode & 07577;
2284
      chmod (name, statbuf.st_mode);
2285
    }
2286
#endif
2287
}
2288
 
2289
void
2290
__gnat_set_readable (char *name)
2291
{
2292
#if defined (_WIN32) && !defined (RTX)
2293
  TCHAR wname [GNAT_MAX_PATH_LEN + 2];
2294
 
2295
  S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
2296
 
2297
  if (__gnat_can_use_acl (wname))
2298
    __gnat_set_OWNER_ACL (wname, GRANT_ACCESS, FILE_GENERIC_READ);
2299
 
2300
#elif ! (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 6) && \
2301
  ! defined(__nucleus__)
2302
  GNAT_STRUCT_STAT statbuf;
2303
 
2304
  if (GNAT_STAT (name, &statbuf) == 0)
2305
    {
2306
      chmod (name, statbuf.st_mode | S_IREAD);
2307
    }
2308
#endif
2309
}
2310
 
2311
void
2312
__gnat_set_non_readable (char *name)
2313
{
2314
#if defined (_WIN32) && !defined (RTX)
2315
  TCHAR wname [GNAT_MAX_PATH_LEN + 2];
2316
 
2317
  S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
2318
 
2319
  if (__gnat_can_use_acl (wname))
2320
    __gnat_set_OWNER_ACL (wname, DENY_ACCESS, FILE_GENERIC_READ);
2321
 
2322
#elif ! (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 6) && \
2323
  ! defined(__nucleus__)
2324
  GNAT_STRUCT_STAT statbuf;
2325
 
2326
  if (GNAT_STAT (name, &statbuf) == 0)
2327
    {
2328
      chmod (name, statbuf.st_mode & (~S_IREAD));
2329
    }
2330
#endif
2331
}
2332
 
2333
int
2334
__gnat_is_symbolic_link_attr (char* name ATTRIBUTE_UNUSED,
2335
                              struct file_attributes* attr)
2336
{
2337
   if (attr->symbolic_link == ATTR_UNSET) {
2338
#if defined (__vxworks) || defined (__nucleus__)
2339
      attr->symbolic_link = 0;
2340
 
2341
#elif defined (_AIX) || defined (__APPLE__) || defined (__unix__)
2342
      int ret;
2343
      GNAT_STRUCT_STAT statbuf;
2344
      ret = GNAT_LSTAT (name, &statbuf);
2345
      attr->symbolic_link = (!ret && S_ISLNK (statbuf.st_mode));
2346
#else
2347
      attr->symbolic_link = 0;
2348
#endif
2349
   }
2350
   return attr->symbolic_link;
2351
}
2352
 
2353
int
2354
__gnat_is_symbolic_link (char *name ATTRIBUTE_UNUSED)
2355
{
2356
   struct file_attributes attr;
2357
   __gnat_reset_attributes (&attr);
2358
   return __gnat_is_symbolic_link_attr (name, &attr);
2359
 
2360
}
2361
 
2362
#if defined (sun) && defined (__SVR4)
2363
/* Using fork on Solaris will duplicate all the threads. fork1, which
2364
   duplicates only the active thread, must be used instead, or spawning
2365
   subprocess from a program with tasking will lead into numerous problems.  */
2366
#define fork fork1
2367
#endif
2368
 
2369
int
2370
__gnat_portable_spawn (char *args[])
2371
{
2372
  int status = 0;
2373
  int finished ATTRIBUTE_UNUSED;
2374
  int pid ATTRIBUTE_UNUSED;
2375
 
2376
#if defined (__vxworks) || defined(__nucleus__) || defined(RTX)
2377
  return -1;
2378
 
2379
#elif defined (_WIN32)
2380
  /* args[0] must be quotes as it could contain a full pathname with spaces */
2381
  char *args_0 = args[0];
2382
  args[0] = (char *)xmalloc (strlen (args_0) + 3);
2383
  strcpy (args[0], "\"");
2384
  strcat (args[0], args_0);
2385
  strcat (args[0], "\"");
2386
 
2387
  status = spawnvp (P_WAIT, args_0, (const char* const*)args);
2388
 
2389
  /* restore previous value */
2390
  free (args[0]);
2391
  args[0] = (char *)args_0;
2392
 
2393
  if (status < 0)
2394
    return -1;
2395
  else
2396
    return status;
2397
 
2398
#else
2399
 
2400
  pid = fork ();
2401
  if (pid < 0)
2402
    return -1;
2403
 
2404
  if (pid == 0)
2405
    {
2406
      /* The child. */
2407
      if (execv (args[0], MAYBE_TO_PTR32 (args)) != 0)
2408
#if defined (VMS)
2409
        return -1; /* execv is in parent context on VMS.  */
2410
#else
2411
        _exit (1);
2412
#endif
2413
    }
2414
 
2415
  /* The parent.  */
2416
  finished = waitpid (pid, &status, 0);
2417
 
2418
  if (finished != pid || WIFEXITED (status) == 0)
2419
    return -1;
2420
 
2421
  return WEXITSTATUS (status);
2422
#endif
2423
 
2424
  return 0;
2425
}
2426
 
2427
/* Create a copy of the given file descriptor.
2428
   Return -1 if an error occurred.  */
2429
 
2430
int
2431
__gnat_dup (int oldfd)
2432
{
2433
#if defined (__vxworks) && !defined (__RTP__)
2434
  /* Not supported on VxWorks 5.x, but supported on VxWorks 6.0 when using
2435
     RTPs. */
2436
  return -1;
2437
#else
2438
  return dup (oldfd);
2439
#endif
2440
}
2441
 
2442
/* Make newfd be the copy of oldfd, closing newfd first if necessary.
2443
   Return -1 if an error occurred.  */
2444
 
2445
int
2446
__gnat_dup2 (int oldfd, int newfd)
2447
{
2448
#if defined (__vxworks) && !defined (__RTP__)
2449
  /* Not supported on VxWorks 5.x, but supported on VxWorks 6.0 when using
2450
     RTPs.  */
2451
  return -1;
2452
#elif defined (_WIN32)
2453
  /* Special case when oldfd and newfd are identical and are the standard
2454
     input, output or error as this makes Windows XP hangs. Note that we
2455
     do that only for standard file descriptors that are known to be valid. */
2456
  if (oldfd == newfd && newfd >= 0 && newfd <= 2)
2457
    return newfd;
2458
  else
2459
    return dup2 (oldfd, newfd);
2460
#else
2461
  return dup2 (oldfd, newfd);
2462
#endif
2463
}
2464
 
2465
int
2466
__gnat_number_of_cpus (void)
2467
{
2468
  int cores = 1;
2469
 
2470
#if defined (linux) || defined (sun) || defined (AIX) \
2471
    || (defined (__alpha__)  && defined (_osf_)) || defined (__APPLE__)
2472
  cores = (int) sysconf (_SC_NPROCESSORS_ONLN);
2473
 
2474
#elif (defined (__mips) && defined (__sgi))
2475
  cores = (int) sysconf (_SC_NPROC_ONLN);
2476
 
2477
#elif defined (__hpux__)
2478
  struct pst_dynamic psd;
2479
  if (pstat_getdynamic (&psd, sizeof (psd), 1, 0) != -1)
2480
    cores = (int) psd.psd_proc_cnt;
2481
 
2482
#elif defined (_WIN32)
2483
  SYSTEM_INFO sysinfo;
2484
  GetSystemInfo (&sysinfo);
2485
  cores = (int) sysinfo.dwNumberOfProcessors;
2486
 
2487
#elif defined (VMS)
2488
  int code = SYI$_ACTIVECPU_CNT;
2489
  unsigned int res;
2490
  int status;
2491
 
2492
  status = LIB$GETSYI (&code, &res);
2493
  if ((status & 1) != 0)
2494
    cores = res;
2495
 
2496
#elif defined (_WRS_CONFIG_SMP)
2497
  unsigned int vxCpuConfiguredGet (void);
2498
 
2499
  cores = vxCpuConfiguredGet ();
2500
 
2501
#endif
2502
 
2503
  return cores;
2504
}
2505
 
2506
/* WIN32 code to implement a wait call that wait for any child process.  */
2507
 
2508
#if defined (_WIN32) && !defined (RTX)
2509
 
2510
/* Synchronization code, to be thread safe.  */
2511
 
2512
#ifdef CERT
2513
 
2514
/* For the Cert run times on native Windows we use dummy functions
2515
   for locking and unlocking tasks since we do not support multiple
2516
   threads on this configuration (Cert run time on native Windows). */
2517
 
2518
void dummy (void) {}
2519
 
2520
void (*Lock_Task) ()   = &dummy;
2521
void (*Unlock_Task) () = &dummy;
2522
 
2523
#else
2524
 
2525
#define Lock_Task system__soft_links__lock_task
2526
extern void (*Lock_Task) (void);
2527
 
2528
#define Unlock_Task system__soft_links__unlock_task
2529
extern void (*Unlock_Task) (void);
2530
 
2531
#endif
2532
 
2533
static HANDLE *HANDLES_LIST = NULL;
2534
static int *PID_LIST = NULL, plist_length = 0, plist_max_length = 0;
2535
 
2536
static void
2537
add_handle (HANDLE h, int pid)
2538
{
2539
 
2540
  /* -------------------- critical section -------------------- */
2541
  (*Lock_Task) ();
2542
 
2543
  if (plist_length == plist_max_length)
2544
    {
2545
      plist_max_length += 1000;
2546
      HANDLES_LIST =
2547
        xrealloc (HANDLES_LIST, sizeof (HANDLE) * plist_max_length);
2548
      PID_LIST =
2549
        xrealloc (PID_LIST, sizeof (int) * plist_max_length);
2550
    }
2551
 
2552
  HANDLES_LIST[plist_length] = h;
2553
  PID_LIST[plist_length] = pid;
2554
  ++plist_length;
2555
 
2556
  (*Unlock_Task) ();
2557
  /* -------------------- critical section -------------------- */
2558
}
2559
 
2560
void
2561
__gnat_win32_remove_handle (HANDLE h, int pid)
2562
{
2563
  int j;
2564
 
2565
  /* -------------------- critical section -------------------- */
2566
  (*Lock_Task) ();
2567
 
2568
  for (j = 0; j < plist_length; j++)
2569
    {
2570
      if ((HANDLES_LIST[j] == h) || (PID_LIST[j] == pid))
2571
        {
2572
          CloseHandle (h);
2573
          --plist_length;
2574
          HANDLES_LIST[j] = HANDLES_LIST[plist_length];
2575
          PID_LIST[j] = PID_LIST[plist_length];
2576
          break;
2577
        }
2578
    }
2579
 
2580
  (*Unlock_Task) ();
2581
  /* -------------------- critical section -------------------- */
2582
}
2583
 
2584
static void
2585
win32_no_block_spawn (char *command, char *args[], HANDLE *h, int *pid)
2586
{
2587
  BOOL result;
2588
  STARTUPINFO SI;
2589
  PROCESS_INFORMATION PI;
2590
  SECURITY_ATTRIBUTES SA;
2591
  int csize = 1;
2592
  char *full_command;
2593
  int k;
2594
 
2595
  /* compute the total command line length */
2596
  k = 0;
2597
  while (args[k])
2598
    {
2599
      csize += strlen (args[k]) + 1;
2600
      k++;
2601
    }
2602
 
2603
  full_command = (char *) xmalloc (csize);
2604
 
2605
  /* Startup info. */
2606
  SI.cb          = sizeof (STARTUPINFO);
2607
  SI.lpReserved  = NULL;
2608
  SI.lpReserved2 = NULL;
2609
  SI.lpDesktop   = NULL;
2610
  SI.cbReserved2 = 0;
2611
  SI.lpTitle     = NULL;
2612
  SI.dwFlags     = 0;
2613
  SI.wShowWindow = SW_HIDE;
2614
 
2615
  /* Security attributes. */
2616
  SA.nLength = sizeof (SECURITY_ATTRIBUTES);
2617
  SA.bInheritHandle = TRUE;
2618
  SA.lpSecurityDescriptor = NULL;
2619
 
2620
  /* Prepare the command string. */
2621
  strcpy (full_command, command);
2622
  strcat (full_command, " ");
2623
 
2624
  k = 1;
2625
  while (args[k])
2626
    {
2627
      strcat (full_command, args[k]);
2628
      strcat (full_command, " ");
2629
      k++;
2630
    }
2631
 
2632
  {
2633
    int wsize = csize * 2;
2634
    TCHAR *wcommand = (TCHAR *) xmalloc (wsize);
2635
 
2636
    S2WSC (wcommand, full_command, wsize);
2637
 
2638
    free (full_command);
2639
 
2640
    result = CreateProcess
2641
      (NULL, wcommand, &SA, NULL, TRUE,
2642
       GetPriorityClass (GetCurrentProcess()), NULL, NULL, &SI, &PI);
2643
 
2644
    free (wcommand);
2645
  }
2646
 
2647
  if (result == TRUE)
2648
    {
2649
      CloseHandle (PI.hThread);
2650
      *h = PI.hProcess;
2651
      *pid = PI.dwProcessId;
2652
    }
2653
  else
2654
    {
2655
      *h = NULL;
2656
      *pid = 0;
2657
    }
2658
}
2659
 
2660
static int
2661
win32_wait (int *status)
2662
{
2663
  DWORD exitcode, pid;
2664
  HANDLE *hl;
2665
  HANDLE h;
2666
  DWORD res;
2667
  int k;
2668
  int hl_len;
2669
 
2670
  if (plist_length == 0)
2671
    {
2672
      errno = ECHILD;
2673
      return -1;
2674
    }
2675
 
2676
  k = 0;
2677
 
2678
  /* -------------------- critical section -------------------- */
2679
  (*Lock_Task) ();
2680
 
2681
  hl_len = plist_length;
2682
 
2683
  hl = (HANDLE *) xmalloc (sizeof (HANDLE) * hl_len);
2684
 
2685
  memmove (hl, HANDLES_LIST, sizeof (HANDLE) * hl_len);
2686
 
2687
  (*Unlock_Task) ();
2688
  /* -------------------- critical section -------------------- */
2689
 
2690
  res = WaitForMultipleObjects (hl_len, hl, FALSE, INFINITE);
2691
  h = hl[res - WAIT_OBJECT_0];
2692
 
2693
  GetExitCodeProcess (h, &exitcode);
2694
  pid = PID_LIST [res - WAIT_OBJECT_0];
2695
  __gnat_win32_remove_handle (h, -1);
2696
 
2697
  free (hl);
2698
 
2699
  *status = (int) exitcode;
2700
  return (int) pid;
2701
}
2702
 
2703
#endif
2704
 
2705
int
2706
__gnat_portable_no_block_spawn (char *args[])
2707
{
2708
 
2709
#if defined (__vxworks) || defined (__nucleus__) || defined (RTX)
2710
  return -1;
2711
 
2712
#elif defined (_WIN32)
2713
 
2714
  HANDLE h = NULL;
2715
  int pid;
2716
 
2717
  win32_no_block_spawn (args[0], args, &h, &pid);
2718
  if (h != NULL)
2719
    {
2720
      add_handle (h, pid);
2721
      return pid;
2722
    }
2723
  else
2724
    return -1;
2725
 
2726
#else
2727
 
2728
  int pid = fork ();
2729
 
2730
  if (pid == 0)
2731
    {
2732
      /* The child.  */
2733
      if (execv (args[0], MAYBE_TO_PTR32 (args)) != 0)
2734
#if defined (VMS)
2735
        return -1; /* execv is in parent context on VMS. */
2736
#else
2737
        _exit (1);
2738
#endif
2739
    }
2740
 
2741
  return pid;
2742
 
2743
  #endif
2744
}
2745
 
2746
int
2747
__gnat_portable_wait (int *process_status)
2748
{
2749
  int status = 0;
2750
  int pid = 0;
2751
 
2752
#if defined (__vxworks) || defined (__nucleus__) || defined (RTX)
2753
  /* Not sure what to do here, so do nothing but return zero.  */
2754
 
2755
#elif defined (_WIN32)
2756
 
2757
  pid = win32_wait (&status);
2758
 
2759
#else
2760
 
2761
  pid = waitpid (-1, &status, 0);
2762
  status = status & 0xffff;
2763
#endif
2764
 
2765
  *process_status = status;
2766
  return pid;
2767
}
2768
 
2769
void
2770
__gnat_os_exit (int status)
2771
{
2772
  exit (status);
2773
}
2774
 
2775
/* Locate file on path, that matches a predicate */
2776
 
2777
char *
2778
__gnat_locate_file_with_predicate
2779
   (char *file_name, char *path_val, int (*predicate)(char*))
2780
{
2781
  char *ptr;
2782
  char *file_path = (char *) alloca (strlen (file_name) + 1);
2783
  int absolute;
2784
 
2785
  /* Return immediately if file_name is empty */
2786
 
2787
  if (*file_name == '\0')
2788
    return 0;
2789
 
2790
  /* Remove quotes around file_name if present */
2791
 
2792
  ptr = file_name;
2793
  if (*ptr == '"')
2794
    ptr++;
2795
 
2796
  strcpy (file_path, ptr);
2797
 
2798
  ptr = file_path + strlen (file_path) - 1;
2799
 
2800
  if (*ptr == '"')
2801
    *ptr = '\0';
2802
 
2803
  /* Handle absolute pathnames.  */
2804
 
2805
  absolute = __gnat_is_absolute_path (file_path, strlen (file_name));
2806
 
2807
  if (absolute)
2808
    {
2809
     if (predicate (file_path))
2810
       return xstrdup (file_path);
2811
 
2812
      return 0;
2813
    }
2814
 
2815
  /* If file_name include directory separator(s), try it first as
2816
     a path name relative to the current directory */
2817
  for (ptr = file_name; *ptr && *ptr != '/' && *ptr != DIR_SEPARATOR; ptr++)
2818
    ;
2819
 
2820
  if (*ptr != 0)
2821
    {
2822
      if (predicate (file_name))
2823
        return xstrdup (file_name);
2824
    }
2825
 
2826
  if (path_val == 0)
2827
    return 0;
2828
 
2829
  {
2830
    /* The result has to be smaller than path_val + file_name.  */
2831
    char *file_path =
2832
      (char *) alloca (strlen (path_val) + strlen (file_name) + 2);
2833
 
2834
    for (;;)
2835
      {
2836
      /* Skip the starting quote */
2837
 
2838
      if (*path_val == '"')
2839
        path_val++;
2840
 
2841
      for (ptr = file_path; *path_val && *path_val != PATH_SEPARATOR; )
2842
        *ptr++ = *path_val++;
2843
 
2844
      /* If directory is empty, it is the current directory*/
2845
 
2846
      if (ptr == file_path)
2847
        {
2848
         *ptr = '.';
2849
        }
2850
      else
2851
        ptr--;
2852
 
2853
      /* Skip the ending quote */
2854
 
2855
      if (*ptr == '"')
2856
        ptr--;
2857
 
2858
      if (*ptr != '/' && *ptr != DIR_SEPARATOR)
2859
        *++ptr = DIR_SEPARATOR;
2860
 
2861
      strcpy (++ptr, file_name);
2862
 
2863
      if (predicate (file_path))
2864
        return xstrdup (file_path);
2865
 
2866
      if (*path_val == 0)
2867
        return 0;
2868
 
2869
      /* Skip path separator */
2870
 
2871
      path_val++;
2872
      }
2873
  }
2874
 
2875
  return 0;
2876
}
2877
 
2878
/* Locate an executable file, give a Path value.  */
2879
 
2880
char *
2881
__gnat_locate_executable_file (char *file_name, char *path_val)
2882
{
2883
   return __gnat_locate_file_with_predicate
2884
      (file_name, path_val, &__gnat_is_executable_file);
2885
}
2886
 
2887
/* Locate a regular file, give a Path value.  */
2888
 
2889
char *
2890
__gnat_locate_regular_file (char *file_name, char *path_val)
2891
{
2892
   return __gnat_locate_file_with_predicate
2893
      (file_name, path_val, &__gnat_is_regular_file);
2894
}
2895
 
2896
/* Locate an executable given a Path argument. This routine is only used by
2897
   gnatbl and should not be used otherwise.  Use locate_exec_on_path
2898
   instead.  */
2899
 
2900
char *
2901
__gnat_locate_exec (char *exec_name, char *path_val)
2902
{
2903
  char *ptr;
2904
  if (!strstr (exec_name, HOST_EXECUTABLE_SUFFIX))
2905
    {
2906
      char *full_exec_name =
2907
        (char *) alloca
2908
          (strlen (exec_name) + strlen (HOST_EXECUTABLE_SUFFIX) + 1);
2909
 
2910
      strcpy (full_exec_name, exec_name);
2911
      strcat (full_exec_name, HOST_EXECUTABLE_SUFFIX);
2912
      ptr = __gnat_locate_executable_file (full_exec_name, path_val);
2913
 
2914
      if (ptr == 0)
2915
         return __gnat_locate_executable_file (exec_name, path_val);
2916
      return ptr;
2917
    }
2918
  else
2919
    return __gnat_locate_executable_file (exec_name, path_val);
2920
}
2921
 
2922
/* Locate an executable using the Systems default PATH.  */
2923
 
2924
char *
2925
__gnat_locate_exec_on_path (char *exec_name)
2926
{
2927
  char *apath_val;
2928
 
2929
#if defined (_WIN32) && !defined (RTX)
2930
  TCHAR *wpath_val = _tgetenv (_T("PATH"));
2931
  TCHAR *wapath_val;
2932
  /* In Win32 systems we expand the PATH as for XP environment
2933
     variables are not automatically expanded. We also prepend the
2934
     ".;" to the path to match normal NT path search semantics */
2935
 
2936
  #define EXPAND_BUFFER_SIZE 32767
2937
 
2938
  wapath_val = alloca (EXPAND_BUFFER_SIZE);
2939
 
2940
  wapath_val [0] = '.';
2941
  wapath_val [1] = ';';
2942
 
2943
  DWORD res = ExpandEnvironmentStrings
2944
    (wpath_val, &wapath_val[2], EXPAND_BUFFER_SIZE - 2);
2945
 
2946
  if (!res) wapath_val [0] = _T('\0');
2947
 
2948
  apath_val = alloca (EXPAND_BUFFER_SIZE);
2949
 
2950
  WS2SC (apath_val, wapath_val, EXPAND_BUFFER_SIZE);
2951
  return __gnat_locate_exec (exec_name, apath_val);
2952
 
2953
#else
2954
 
2955
#ifdef VMS
2956
  char *path_val = "/VAXC$PATH";
2957
#else
2958
  char *path_val = getenv ("PATH");
2959
#endif
2960
  if (path_val == NULL) return NULL;
2961
  apath_val = (char *) alloca (strlen (path_val) + 1);
2962
  strcpy (apath_val, path_val);
2963
  return __gnat_locate_exec (exec_name, apath_val);
2964
#endif
2965
}
2966
 
2967
#ifdef VMS
2968
 
2969
/* These functions are used to translate to and from VMS and Unix syntax
2970
   file, directory and path specifications.  */
2971
 
2972
#define MAXPATH  256
2973
#define MAXNAMES 256
2974
#define NEW_CANONICAL_FILELIST_INCREMENT 64
2975
 
2976
static char new_canonical_dirspec [MAXPATH];
2977
static char new_canonical_filespec [MAXPATH];
2978
static char new_canonical_pathspec [MAXNAMES*MAXPATH];
2979
static unsigned new_canonical_filelist_index;
2980
static unsigned new_canonical_filelist_in_use;
2981
static unsigned new_canonical_filelist_allocated;
2982
static char **new_canonical_filelist;
2983
static char new_host_pathspec [MAXNAMES*MAXPATH];
2984
static char new_host_dirspec [MAXPATH];
2985
static char new_host_filespec [MAXPATH];
2986
 
2987
/* Routine is called repeatedly by decc$from_vms via
2988
   __gnat_to_canonical_file_list_init until it returns 0 or the expansion
2989
   runs out. */
2990
 
2991
static int
2992
wildcard_translate_unix (char *name)
2993
{
2994
  char *ver;
2995
  char buff [MAXPATH];
2996
 
2997
  strncpy (buff, name, MAXPATH);
2998
  buff [MAXPATH - 1] = (char) 0;
2999
  ver = strrchr (buff, '.');
3000
 
3001
  /* Chop off the version.  */
3002
  if (ver)
3003
    *ver = 0;
3004
 
3005
  /* Dynamically extend the allocation by the increment.  */
3006
  if (new_canonical_filelist_in_use == new_canonical_filelist_allocated)
3007
    {
3008
      new_canonical_filelist_allocated += NEW_CANONICAL_FILELIST_INCREMENT;
3009
      new_canonical_filelist = (char **) xrealloc
3010
        (new_canonical_filelist,
3011
         new_canonical_filelist_allocated * sizeof (char *));
3012
    }
3013
 
3014
  new_canonical_filelist[new_canonical_filelist_in_use++] = xstrdup (buff);
3015
 
3016
  return 1;
3017
}
3018
 
3019
/* Translate a wildcard VMS file spec into a list of Unix file specs. First do
3020
   full translation and copy the results into a list (_init), then return them
3021
   one at a time (_next). If onlydirs set, only expand directory files.  */
3022
 
3023
int
3024
__gnat_to_canonical_file_list_init (char *filespec, int onlydirs)
3025
{
3026
  int len;
3027
  char buff [MAXPATH];
3028
 
3029
  len = strlen (filespec);
3030
  strncpy (buff, filespec, MAXPATH);
3031
 
3032
  /* Only look for directories */
3033
  if (onlydirs && !strstr (&buff [len-5], "*.dir"))
3034
    strncat (buff, "*.dir", MAXPATH);
3035
 
3036
  buff [MAXPATH - 1] = (char) 0;
3037
 
3038
  decc$from_vms (buff, wildcard_translate_unix, 1);
3039
 
3040
  /* Remove the .dir extension.  */
3041
  if (onlydirs)
3042
    {
3043
      int i;
3044
      char *ext;
3045
 
3046
      for (i = 0; i < new_canonical_filelist_in_use; i++)
3047
        {
3048
          ext = strstr (new_canonical_filelist[i], ".dir");
3049
          if (ext)
3050
            *ext = 0;
3051
        }
3052
    }
3053
 
3054
  return new_canonical_filelist_in_use;
3055
}
3056
 
3057
/* Return the next filespec in the list.  */
3058
 
3059
char *
3060
__gnat_to_canonical_file_list_next ()
3061
{
3062
  return new_canonical_filelist[new_canonical_filelist_index++];
3063
}
3064
 
3065
/* Free storage used in the wildcard expansion.  */
3066
 
3067
void
3068
__gnat_to_canonical_file_list_free ()
3069
{
3070
  int i;
3071
 
3072
   for (i = 0; i < new_canonical_filelist_in_use; i++)
3073
     free (new_canonical_filelist[i]);
3074
 
3075
  free (new_canonical_filelist);
3076
 
3077
  new_canonical_filelist_in_use = 0;
3078
  new_canonical_filelist_allocated = 0;
3079
  new_canonical_filelist_index = 0;
3080
  new_canonical_filelist = 0;
3081
}
3082
 
3083
/* The functional equivalent of decc$translate_vms routine.
3084
   Designed to produce the same output, but is protected against
3085
   malformed paths (original version ACCVIOs in this case) and
3086
   does not require VMS-specific DECC RTL */
3087
 
3088
#define NAM$C_MAXRSS 1024
3089
 
3090
char *
3091
__gnat_translate_vms (char *src)
3092
{
3093
  static char retbuf [NAM$C_MAXRSS+1];
3094
  char *srcendpos, *pos1, *pos2, *retpos;
3095
  int disp, path_present = 0;
3096
 
3097
  if (!src) return NULL;
3098
 
3099
  srcendpos = strchr (src, '\0');
3100
  retpos = retbuf;
3101
 
3102
  /* Look for the node and/or device in front of the path */
3103
  pos1 = src;
3104
  pos2 = strchr (pos1, ':');
3105
 
3106
  if (pos2 && (pos2 < srcendpos) && (*(pos2 + 1) == ':')) {
3107
    /* There is a node name. "node_name::" becomes "node_name!" */
3108
    disp = pos2 - pos1;
3109
    strncpy (retbuf, pos1, disp);
3110
    retpos [disp] = '!';
3111
    retpos = retpos + disp + 1;
3112
    pos1 = pos2 + 2;
3113
    pos2 = strchr (pos1, ':');
3114
  }
3115
 
3116
  if (pos2) {
3117
    /* There is a device name. "dev_name:" becomes "/dev_name/" */
3118
    *(retpos++) = '/';
3119
    disp = pos2 - pos1;
3120
    strncpy (retpos, pos1, disp);
3121
    retpos = retpos + disp;
3122
    pos1 = pos2 + 1;
3123
    *(retpos++) = '/';
3124
  }
3125
  else
3126
    /* No explicit device; we must look ahead and prepend /sys$disk/ if
3127
       the path is absolute */
3128
    if ((*pos1 == '[' || *pos1 == '<') && (pos1 < srcendpos)
3129
        && !strchr (".-]>", *(pos1 + 1))) {
3130
      strncpy (retpos, "/sys$disk/", 10);
3131
      retpos += 10;
3132
    }
3133
 
3134
  /* Process the path part */
3135
  while (*pos1 == '[' || *pos1 == '<') {
3136
    path_present++;
3137
    pos1++;
3138
    if (*pos1 == ']' || *pos1 == '>') {
3139
      /* Special case, [] translates to '.' */
3140
      *(retpos++) = '.';
3141
      pos1++;
3142
    }
3143
    else {
3144
      /* '[000000' means root dir. It can be present in the middle of
3145
         the path due to expansion of logical devices, in which case
3146
         we skip it */
3147
      if (!strncmp (pos1, "000000", 6) && path_present > 1 &&
3148
         (*(pos1 + 6) == ']' || *(pos1 + 6) == '>' || *(pos1 + 6) == '.')) {
3149
          pos1 += 6;
3150
          if (*pos1 == '.') pos1++;
3151
        }
3152
      else if (*pos1 == '.') {
3153
        /* Relative path */
3154
        *(retpos++) = '.';
3155
      }
3156
 
3157
      /* There is a qualified path */
3158
      while (*pos1 && *pos1 != ']' && *pos1 != '>') {
3159
        switch (*pos1) {
3160
          case '.':
3161
            /* '.' is used to separate directories. Replace it with '/' but
3162
               only if there isn't already '/' just before */
3163
            if (*(retpos - 1) != '/') *(retpos++) = '/';
3164
            pos1++;
3165
            if (pos1 + 1 < srcendpos && *pos1 == '.' && *(pos1 + 1) == '.') {
3166
              /* ellipsis refers to entire subtree; replace with '**' */
3167
              *(retpos++) = '*'; *(retpos++) = '*'; *(retpos++) = '/';
3168
              pos1 += 2;
3169
            }
3170
            break;
3171
          case '-' :
3172
            /* When after '.' '[' '<' is equivalent to Unix ".." but there
3173
            may be several in a row */
3174
            if (*(pos1 - 1) == '.' || *(pos1 - 1) == '[' ||
3175
                *(pos1 - 1) == '<') {
3176
              while (*pos1 == '-') {
3177
                pos1++;
3178
                *(retpos++) = '.'; *(retpos++) = '.'; *(retpos++) = '/';
3179
              }
3180
              retpos--;
3181
              break;
3182
            }
3183
            /* otherwise fall through to default */
3184
          default:
3185
            *(retpos++) = *(pos1++);
3186
        }
3187
      }
3188
      pos1++;
3189
    }
3190
  }
3191
 
3192
  if (pos1 < srcendpos) {
3193
    /* Now add the actual file name, until the version suffix if any */
3194
    if (path_present) *(retpos++) = '/';
3195
    pos2 = strchr (pos1, ';');
3196
    disp = pos2? (pos2 - pos1) : (srcendpos - pos1);
3197
    strncpy (retpos, pos1, disp);
3198
    retpos += disp;
3199
    if (pos2 && pos2 < srcendpos) {
3200
      /* There is a non-empty version suffix. ";<ver>" becomes ".<ver>" */
3201
      *retpos++ = '.';
3202
      disp = srcendpos - pos2 - 1;
3203
      strncpy (retpos, pos2 + 1, disp);
3204
      retpos += disp;
3205
    }
3206
  }
3207
 
3208
  *retpos = '\0';
3209
 
3210
  return retbuf;
3211
 
3212
}
3213
 
3214
/* Translate a VMS syntax directory specification in to Unix syntax.  If
3215
   PREFIXFLAG is set, append an underscore "/". If no indicators of VMS syntax
3216
   found, return input string. Also translate a dirname that contains no
3217
   slashes, in case it's a logical name.  */
3218
 
3219
char *
3220
__gnat_to_canonical_dir_spec (char *dirspec, int prefixflag)
3221
{
3222
  int len;
3223
 
3224
  strcpy (new_canonical_dirspec, "");
3225
  if (strlen (dirspec))
3226
    {
3227
      char *dirspec1;
3228
 
3229
      if (strchr (dirspec, ']') || strchr (dirspec, ':'))
3230
        {
3231
          strncpy (new_canonical_dirspec,
3232
                   __gnat_translate_vms (dirspec),
3233
                   MAXPATH);
3234
        }
3235
      else if (!strchr (dirspec, '/') && (dirspec1 = getenv (dirspec)) != 0)
3236
        {
3237
          strncpy (new_canonical_dirspec,
3238
                  __gnat_translate_vms (dirspec1),
3239
                  MAXPATH);
3240
        }
3241
      else
3242
        {
3243
          strncpy (new_canonical_dirspec, dirspec, MAXPATH);
3244
        }
3245
    }
3246
 
3247
  len = strlen (new_canonical_dirspec);
3248
  if (prefixflag && new_canonical_dirspec [len-1] != '/')
3249
    strncat (new_canonical_dirspec, "/", MAXPATH);
3250
 
3251
  new_canonical_dirspec [MAXPATH - 1] = (char) 0;
3252
 
3253
  return new_canonical_dirspec;
3254
 
3255
}
3256
 
3257
/* Translate a VMS syntax file specification into Unix syntax.
3258
   If no indicators of VMS syntax found, check if it's an uppercase
3259
   alphanumeric_ name and if so try it out as an environment
3260
   variable (logical name). If all else fails return the
3261
   input string.  */
3262
 
3263
char *
3264
__gnat_to_canonical_file_spec (char *filespec)
3265
{
3266
  char *filespec1;
3267
 
3268
  strncpy (new_canonical_filespec, "", MAXPATH);
3269
 
3270
  if (strchr (filespec, ']') || strchr (filespec, ':'))
3271
    {
3272
      char *tspec = (char *) __gnat_translate_vms (filespec);
3273
 
3274
      if (tspec != (char *) -1)
3275
        strncpy (new_canonical_filespec, tspec, MAXPATH);
3276
    }
3277
  else if ((strlen (filespec) == strspn (filespec,
3278
            "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"))
3279
        && (filespec1 = getenv (filespec)))
3280
    {
3281
      char *tspec = (char *) __gnat_translate_vms (filespec1);
3282
 
3283
      if (tspec != (char *) -1)
3284
        strncpy (new_canonical_filespec, tspec, MAXPATH);
3285
    }
3286
  else
3287
    {
3288
      strncpy (new_canonical_filespec, filespec, MAXPATH);
3289
    }
3290
 
3291
  new_canonical_filespec [MAXPATH - 1] = (char) 0;
3292
 
3293
  return new_canonical_filespec;
3294
}
3295
 
3296
/* Translate a VMS syntax path specification into Unix syntax.
3297
   If no indicators of VMS syntax found, return input string.  */
3298
 
3299
char *
3300
__gnat_to_canonical_path_spec (char *pathspec)
3301
{
3302
  char *curr, *next, buff [MAXPATH];
3303
 
3304
  if (pathspec == 0)
3305
    return pathspec;
3306
 
3307
  /* If there are /'s, assume it's a Unix path spec and return.  */
3308
  if (strchr (pathspec, '/'))
3309
    return pathspec;
3310
 
3311
  new_canonical_pathspec[0] = 0;
3312
  curr = pathspec;
3313
 
3314
  for (;;)
3315
    {
3316
      next = strchr (curr, ',');
3317
      if (next == 0)
3318
        next = strchr (curr, 0);
3319
 
3320
      strncpy (buff, curr, next - curr);
3321
      buff[next - curr] = 0;
3322
 
3323
      /* Check for wildcards and expand if present.  */
3324
      if (strchr (buff, '*') || strchr (buff, '%') || strstr (buff, "..."))
3325
        {
3326
          int i, dirs;
3327
 
3328
          dirs = __gnat_to_canonical_file_list_init (buff, 1);
3329
          for (i = 0; i < dirs; i++)
3330
            {
3331
              char *next_dir;
3332
 
3333
              next_dir = __gnat_to_canonical_file_list_next ();
3334
              strncat (new_canonical_pathspec, next_dir, MAXPATH);
3335
 
3336
              /* Don't append the separator after the last expansion.  */
3337
              if (i+1 < dirs)
3338
                strncat (new_canonical_pathspec, ":", MAXPATH);
3339
            }
3340
 
3341
          __gnat_to_canonical_file_list_free ();
3342
        }
3343
      else
3344
        strncat (new_canonical_pathspec,
3345
                __gnat_to_canonical_dir_spec (buff, 0), MAXPATH);
3346
 
3347
      if (*next == 0)
3348
        break;
3349
 
3350
      strncat (new_canonical_pathspec, ":", MAXPATH);
3351
      curr = next + 1;
3352
    }
3353
 
3354
  new_canonical_pathspec [MAXPATH - 1] = (char) 0;
3355
 
3356
  return new_canonical_pathspec;
3357
}
3358
 
3359
static char filename_buff [MAXPATH];
3360
 
3361
static int
3362
translate_unix (char *name, int type)
3363
{
3364
  strncpy (filename_buff, name, MAXPATH);
3365
  filename_buff [MAXPATH - 1] = (char) 0;
3366
  return 0;
3367
}
3368
 
3369
/* Translate a Unix syntax path spec into a VMS style (comma separated list of
3370
   directories.  */
3371
 
3372
static char *
3373
to_host_path_spec (char *pathspec)
3374
{
3375
  char *curr, *next, buff [MAXPATH];
3376
 
3377
  if (pathspec == 0)
3378
    return pathspec;
3379
 
3380
  /* Can't very well test for colons, since that's the Unix separator!  */
3381
  if (strchr (pathspec, ']') || strchr (pathspec, ','))
3382
    return pathspec;
3383
 
3384
  new_host_pathspec[0] = 0;
3385
  curr = pathspec;
3386
 
3387
  for (;;)
3388
    {
3389
      next = strchr (curr, ':');
3390
      if (next == 0)
3391
        next = strchr (curr, 0);
3392
 
3393
      strncpy (buff, curr, next - curr);
3394
      buff[next - curr] = 0;
3395
 
3396
      strncat (new_host_pathspec, __gnat_to_host_dir_spec (buff, 0), MAXPATH);
3397
      if (*next == 0)
3398
        break;
3399
      strncat (new_host_pathspec, ",", MAXPATH);
3400
      curr = next + 1;
3401
    }
3402
 
3403
  new_host_pathspec [MAXPATH - 1] = (char) 0;
3404
 
3405
  return new_host_pathspec;
3406
}
3407
 
3408
/* Translate a Unix syntax directory specification into VMS syntax.  The
3409
   PREFIXFLAG has no effect, but is kept for symmetry with
3410
   to_canonical_dir_spec.  If indicators of VMS syntax found, return input
3411
   string. */
3412
 
3413
char *
3414
__gnat_to_host_dir_spec (char *dirspec, int prefixflag ATTRIBUTE_UNUSED)
3415
{
3416
  int len = strlen (dirspec);
3417
 
3418
  strncpy (new_host_dirspec, dirspec, MAXPATH);
3419
  new_host_dirspec [MAXPATH - 1] = (char) 0;
3420
 
3421
  if (strchr (new_host_dirspec, ']') || strchr (new_host_dirspec, ':'))
3422
    return new_host_dirspec;
3423
 
3424
  while (len > 1 && new_host_dirspec[len - 1] == '/')
3425
    {
3426
      new_host_dirspec[len - 1] = 0;
3427
      len--;
3428
    }
3429
 
3430
  decc$to_vms (new_host_dirspec, translate_unix, 1, 2);
3431
  strncpy (new_host_dirspec, filename_buff, MAXPATH);
3432
  new_host_dirspec [MAXPATH - 1] = (char) 0;
3433
 
3434
  return new_host_dirspec;
3435
}
3436
 
3437
/* Translate a Unix syntax file specification into VMS syntax.
3438
   If indicators of VMS syntax found, return input string.  */
3439
 
3440
char *
3441
__gnat_to_host_file_spec (char *filespec)
3442
{
3443
  strncpy (new_host_filespec, "", MAXPATH);
3444
  if (strchr (filespec, ']') || strchr (filespec, ':'))
3445
    {
3446
      strncpy (new_host_filespec, filespec, MAXPATH);
3447
    }
3448
  else
3449
    {
3450
      decc$to_vms (filespec, translate_unix, 1, 1);
3451
      strncpy (new_host_filespec, filename_buff, MAXPATH);
3452
    }
3453
 
3454
  new_host_filespec [MAXPATH - 1] = (char) 0;
3455
 
3456
  return new_host_filespec;
3457
}
3458
 
3459
void
3460
__gnat_adjust_os_resource_limits ()
3461
{
3462
  SYS$ADJWSL (131072, 0);
3463
}
3464
 
3465
#else /* VMS */
3466
 
3467
/* Dummy functions for Osint import for non-VMS systems.  */
3468
 
3469
int
3470
__gnat_to_canonical_file_list_init
3471
  (char *dirspec ATTRIBUTE_UNUSED, int onlydirs ATTRIBUTE_UNUSED)
3472
{
3473
  return 0;
3474
}
3475
 
3476
char *
3477
__gnat_to_canonical_file_list_next (void)
3478
{
3479
  static char empty[] = "";
3480
  return empty;
3481
}
3482
 
3483
void
3484
__gnat_to_canonical_file_list_free (void)
3485
{
3486
}
3487
 
3488
char *
3489
__gnat_to_canonical_dir_spec (char *dirspec, int prefixflag ATTRIBUTE_UNUSED)
3490
{
3491
  return dirspec;
3492
}
3493
 
3494
char *
3495
__gnat_to_canonical_file_spec (char *filespec)
3496
{
3497
  return filespec;
3498
}
3499
 
3500
char *
3501
__gnat_to_canonical_path_spec (char *pathspec)
3502
{
3503
  return pathspec;
3504
}
3505
 
3506
char *
3507
__gnat_to_host_dir_spec (char *dirspec, int prefixflag ATTRIBUTE_UNUSED)
3508
{
3509
  return dirspec;
3510
}
3511
 
3512
char *
3513
__gnat_to_host_file_spec (char *filespec)
3514
{
3515
  return filespec;
3516
}
3517
 
3518
void
3519
__gnat_adjust_os_resource_limits (void)
3520
{
3521
}
3522
 
3523
#endif
3524
 
3525
#if defined (__mips_vxworks)
3526
int
3527
_flush_cache()
3528
{
3529
   CACHE_USER_FLUSH (0, ENTIRE_CACHE);
3530
}
3531
#endif
3532
 
3533
#if defined (IS_CROSS)  \
3534
  || (! ((defined (sparc) || defined (i386)) && defined (sun) \
3535
      && defined (__SVR4)) \
3536
      && ! (defined (linux) && (defined (i386) || defined (__x86_64__))) \
3537
      && ! (defined (linux) && defined (__ia64__)) \
3538
      && ! (defined (linux) && defined (powerpc)) \
3539
      && ! defined (__FreeBSD__) \
3540
      && ! defined (__Lynx__) \
3541
      && ! defined (__hpux__) \
3542
      && ! defined (__APPLE__) \
3543
      && ! defined (_AIX) \
3544
      && ! (defined (__alpha__)  && defined (__osf__)) \
3545
      && ! defined (VMS) \
3546
      && ! defined (__MINGW32__) \
3547
      && ! (defined (__mips) && defined (__sgi)))
3548
 
3549
/* Dummy function to satisfy g-trasym.o. See the preprocessor conditional
3550
   just above for a list of native platforms that provide a non-dummy
3551
   version of this procedure in libaddr2line.a.  */
3552
 
3553
void
3554
convert_addresses (const char *file_name ATTRIBUTE_UNUSED,
3555
                   void *addrs ATTRIBUTE_UNUSED,
3556
                   int n_addr ATTRIBUTE_UNUSED,
3557
                   void *buf ATTRIBUTE_UNUSED,
3558
                   int *len ATTRIBUTE_UNUSED)
3559
{
3560
  *len = 0;
3561
}
3562
#endif
3563
 
3564
#if defined (_WIN32)
3565
int __gnat_argument_needs_quote = 1;
3566
#else
3567
int __gnat_argument_needs_quote = 0;
3568
#endif
3569
 
3570
/* This option is used to enable/disable object files handling from the
3571
   binder file by the GNAT Project module. For example, this is disabled on
3572
   Windows (prior to GCC 3.4) as it is already done by the mdll module.
3573
   Stating with GCC 3.4 the shared libraries are not based on mdll
3574
   anymore as it uses the GCC's -shared option  */
3575
#if defined (_WIN32) \
3576
    && ((__GNUC__ < 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ < 4)))
3577
int __gnat_prj_add_obj_files = 0;
3578
#else
3579
int __gnat_prj_add_obj_files = 1;
3580
#endif
3581
 
3582
/* char used as prefix/suffix for environment variables */
3583
#if defined (_WIN32)
3584
char __gnat_environment_char = '%';
3585
#else
3586
char __gnat_environment_char = '$';
3587
#endif
3588
 
3589
/* This functions copy the file attributes from a source file to a
3590
   destination file.
3591
 
3592
   mode = 0  : In this mode copy only the file time stamps (last access and
3593
               last modification time stamps).
3594
 
3595
   mode = 1  : In this mode, time stamps and read/write/execute attributes are
3596
               copied.
3597
 
3598
   Returns 0 if operation was successful and -1 in case of error. */
3599
 
3600
int
3601
__gnat_copy_attribs (char *from, char *to, int mode)
3602
{
3603
#if defined (VMS) || (defined (__vxworks) && _WRS_VXWORKS_MAJOR < 6) || \
3604
  defined (__nucleus__)
3605
  return -1;
3606
 
3607
#elif defined (_WIN32) && !defined (RTX)
3608
  TCHAR wfrom [GNAT_MAX_PATH_LEN + 2];
3609
  TCHAR wto [GNAT_MAX_PATH_LEN + 2];
3610
  BOOL res;
3611
  FILETIME fct, flat, flwt;
3612
  HANDLE hfrom, hto;
3613
 
3614
  S2WSC (wfrom, from, GNAT_MAX_PATH_LEN + 2);
3615
  S2WSC (wto, to, GNAT_MAX_PATH_LEN + 2);
3616
 
3617
  /* retrieve from times */
3618
 
3619
  hfrom = CreateFile
3620
    (wfrom, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3621
 
3622
  if (hfrom == INVALID_HANDLE_VALUE)
3623
    return -1;
3624
 
3625
  res = GetFileTime (hfrom, &fct, &flat, &flwt);
3626
 
3627
  CloseHandle (hfrom);
3628
 
3629
  if (res == 0)
3630
    return -1;
3631
 
3632
  /* retrieve from times */
3633
 
3634
  hto = CreateFile
3635
    (wto, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3636
 
3637
  if (hto == INVALID_HANDLE_VALUE)
3638
    return -1;
3639
 
3640
  res = SetFileTime (hto, NULL, &flat, &flwt);
3641
 
3642
  CloseHandle (hto);
3643
 
3644
  if (res == 0)
3645
    return -1;
3646
 
3647
  /* Set file attributes in full mode. */
3648
 
3649
  if (mode == 1)
3650
    {
3651
      DWORD attribs = GetFileAttributes (wfrom);
3652
 
3653
      if (attribs == INVALID_FILE_ATTRIBUTES)
3654
        return -1;
3655
 
3656
      res = SetFileAttributes (wto, attribs);
3657
      if (res == 0)
3658
        return -1;
3659
    }
3660
 
3661
  return 0;
3662
 
3663
#else
3664
  GNAT_STRUCT_STAT fbuf;
3665
  struct utimbuf tbuf;
3666
 
3667
  if (GNAT_STAT (from, &fbuf) == -1)
3668
    {
3669
      return -1;
3670
    }
3671
 
3672
  tbuf.actime = fbuf.st_atime;
3673
  tbuf.modtime = fbuf.st_mtime;
3674
 
3675
  if (utime (to, &tbuf) == -1)
3676
    {
3677
      return -1;
3678
    }
3679
 
3680
  if (mode == 1)
3681
    {
3682
      if (chmod (to, fbuf.st_mode) == -1)
3683
        {
3684
          return -1;
3685
        }
3686
    }
3687
 
3688
  return 0;
3689
#endif
3690
}
3691
 
3692
int
3693
__gnat_lseek (int fd, long offset, int whence)
3694
{
3695
  return (int) lseek (fd, offset, whence);
3696
}
3697
 
3698
/* This function returns the major version number of GCC being used.  */
3699
int
3700
get_gcc_version (void)
3701
{
3702
#ifdef IN_RTS
3703
  return __GNUC__;
3704
#else
3705
  return (int) (version_string[0] - '0');
3706
#endif
3707
}
3708
 
3709
int
3710
__gnat_set_close_on_exec (int fd ATTRIBUTE_UNUSED,
3711
                          int close_on_exec_p ATTRIBUTE_UNUSED)
3712
{
3713
#if defined (F_GETFD) && defined (FD_CLOEXEC) && ! defined (__vxworks)
3714
  int flags = fcntl (fd, F_GETFD, 0);
3715
  if (flags < 0)
3716
    return flags;
3717
  if (close_on_exec_p)
3718
    flags |= FD_CLOEXEC;
3719
  else
3720
    flags &= ~FD_CLOEXEC;
3721
  return fcntl (fd, F_SETFD, flags | FD_CLOEXEC);
3722
#elif defined(_WIN32)
3723
  HANDLE h = (HANDLE) _get_osfhandle (fd);
3724
  if (h == (HANDLE) -1)
3725
    return -1;
3726
  if (close_on_exec_p)
3727
    return ! SetHandleInformation (h, HANDLE_FLAG_INHERIT, 0);
3728
  return ! SetHandleInformation (h, HANDLE_FLAG_INHERIT,
3729
    HANDLE_FLAG_INHERIT);
3730
#else
3731
  /* TODO: Unimplemented. */
3732
  return -1;
3733
#endif
3734
}
3735
 
3736
/* Indicates if platforms supports automatic initialization through the
3737
   constructor mechanism */
3738
int
3739
__gnat_binder_supports_auto_init (void)
3740
{
3741
#ifdef VMS
3742
   return 0;
3743
#else
3744
   return 1;
3745
#endif
3746
}
3747
 
3748
/* Indicates that Stand-Alone Libraries are automatically initialized through
3749
   the constructor mechanism */
3750
int
3751
__gnat_sals_init_using_constructors (void)
3752
{
3753
#if defined (__vxworks) || defined (__Lynx__) || defined (VMS)
3754
   return 0;
3755
#else
3756
   return 1;
3757
#endif
3758
}
3759
 
3760
#ifdef RTX
3761
 
3762
/* In RTX mode, the procedure to get the time (as file time) is different
3763
   in RTSS mode and Win32 mode. In order to avoid duplicating an Ada file,
3764
   we introduce an intermediate procedure to link against the corresponding
3765
   one in each situation. */
3766
 
3767
extern void GetTimeAsFileTime(LPFILETIME pTime);
3768
 
3769
void GetTimeAsFileTime(LPFILETIME pTime)
3770
{
3771
#ifdef RTSS
3772
  RtGetRtssTimeAsFileTime (pTime); /* RTSS interface */
3773
#else
3774
  GetSystemTimeAsFileTime (pTime); /* w32 interface */
3775
#endif
3776
}
3777
 
3778
#ifdef RTSS
3779
/* Add symbol that is required to link. It would otherwise be taken from
3780
   libgcc.a and it would try to use the gcc constructors that are not
3781
   supported by Microsoft linker. */
3782
 
3783
extern void __main (void);
3784
 
3785
void __main (void) {}
3786
#endif
3787
#endif
3788
 
3789
#if defined (linux)
3790
/* There is no function in the glibc to retrieve the LWP of the current
3791
   thread. We need to do a system call in order to retrieve this
3792
   information. */
3793
#include <sys/syscall.h>
3794
void *__gnat_lwp_self (void)
3795
{
3796
   return (void *) syscall (__NR_gettid);
3797
}
3798
 
3799
#include <sched.h>
3800
 
3801
/* glibc versions earlier than 2.7 do not define the routines to handle
3802
   dynamically allocated CPU sets. For these targets, we use the static
3803
   versions. */
3804
 
3805
#ifdef CPU_ALLOC
3806
 
3807
/* Dynamic cpu sets */
3808
 
3809
cpu_set_t *__gnat_cpu_alloc (size_t count)
3810
{
3811
  return CPU_ALLOC (count);
3812
}
3813
 
3814
size_t __gnat_cpu_alloc_size (size_t count)
3815
{
3816
  return CPU_ALLOC_SIZE (count);
3817
}
3818
 
3819
void __gnat_cpu_free (cpu_set_t *set)
3820
{
3821
  CPU_FREE (set);
3822
}
3823
 
3824
void __gnat_cpu_zero (size_t count, cpu_set_t *set)
3825
{
3826
  CPU_ZERO_S (count, set);
3827
}
3828
 
3829
void __gnat_cpu_set (int cpu, size_t count, cpu_set_t *set)
3830
{
3831
  /* Ada handles CPU numbers starting from 1, while C identifies the first
3832
     CPU by a 0, so we need to adjust. */
3833
  CPU_SET_S (cpu - 1, count, set);
3834
}
3835
 
3836
#else
3837
 
3838
/* Static cpu sets */
3839
 
3840
cpu_set_t *__gnat_cpu_alloc (size_t count ATTRIBUTE_UNUSED)
3841
{
3842
  return (cpu_set_t *) xmalloc (sizeof (cpu_set_t));
3843
}
3844
 
3845
size_t __gnat_cpu_alloc_size (size_t count ATTRIBUTE_UNUSED)
3846
{
3847
  return sizeof (cpu_set_t);
3848
}
3849
 
3850
void __gnat_cpu_free (cpu_set_t *set)
3851
{
3852
  free (set);
3853
}
3854
 
3855
void __gnat_cpu_zero (size_t count ATTRIBUTE_UNUSED, cpu_set_t *set)
3856
{
3857
  CPU_ZERO (set);
3858
}
3859
 
3860
void __gnat_cpu_set (int cpu, size_t count ATTRIBUTE_UNUSED, cpu_set_t *set)
3861
{
3862
  /* Ada handles CPU numbers starting from 1, while C identifies the first
3863
     CPU by a 0, so we need to adjust. */
3864
  CPU_SET (cpu - 1, set);
3865
}
3866
#endif
3867
#endif
3868
 
3869
#ifdef __cplusplus
3870
}
3871
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.