#endif
#if defined (_WIN32)
+
#include <dir.h>
#include <windows.h>
#include <accctrl.h>
#endif
+/* Used for Ada bindings */
+const int __gnat_size_of_file_attributes = sizeof (struct file_attributes);
+
+/* Reset the file attributes as if no system call had been performed */
+void __gnat_stat_to_attr (int fd, char* name, struct file_attributes* attr);
+
/* The __gnat_max_path_len variable is used to export the maximum
length of a path name to Ada code. max_path_len is also provided
for compatibility with older GNAT versions, please do not use
#define MAYBE_TO_PTR32(argv) argv
#endif
+const char ATTR_UNSET = 127;
+
+void
+__gnat_reset_attributes
+ (struct file_attributes* attr)
+{
+ attr->exists = ATTR_UNSET;
+
+ attr->writable = ATTR_UNSET;
+ attr->readable = ATTR_UNSET;
+ attr->executable = ATTR_UNSET;
+
+ attr->regular = ATTR_UNSET;
+ attr->symbolic_link = ATTR_UNSET;
+ attr->directory = ATTR_UNSET;
+
+ attr->timestamp = (OS_Time)-2;
+ attr->file_length = -1;
+}
+
OS_Time
__gnat_current_time
(void)
{
char full_path[256];
char temp_file[256];
- STRUCT_STAT stat_result;
+ GNAT_STRUCT_STAT stat_result;
int fd;
sprintf (full_path, "%s%c%s", dir, DIR_SEPARATOR, file);
char *encoding ATTRIBUTE_UNUSED, int *e_length)
{
#if defined (_WIN32) && ! defined (__vxworks) && ! defined (IS_CROSS)
- WS2SC (os_name, (TCHAR *)w_filename, (DWORD)o_length);
+ WS2SC (os_name, (TCHAR *)w_filename, (DWORD)*o_length);
*o_length = strlen (os_name);
strcpy (encoding, "encoding=utf8");
*e_length = strlen (encoding);
#elif defined (VMS)
return decc$fopen (path, mode);
#else
- return FOPEN (path, mode);
+ return GNAT_FOPEN (path, mode);
#endif
}
}
int
+__gnat_create_output_file_new (char *path)
+{
+ int fd;
+#if defined (VMS)
+ fd = open (path, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT | O_EXCL, PERM,
+ "rfm=stmlf", "ctx=rec", "rat=none", "rop=nlk",
+ "shr=del,get,put,upd");
+#elif defined (__MINGW32__)
+ {
+ TCHAR wpath[GNAT_MAX_PATH_LEN];
+
+ S2WSC (wpath, path, GNAT_MAX_PATH_LEN);
+ fd = _topen (wpath, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT | O_EXCL, PERM);
+ }
+#else
+ fd = open (path, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT | O_EXCL, PERM);
+#endif
+
+ return fd < 0 ? -1 : fd;
+}
+
+int
__gnat_open_append (char *path, int fmode)
{
int fd;
return fd < 0 ? -1 : fd;
}
-/* Return the number of bytes in the specified file. */
+/****************************************************************
+ ** Perform a call to GNAT_STAT or GNAT_FSTAT, and extract as much information
+ ** as possible from it, storing the result in a cache for later reuse
+ ****************************************************************/
-long
-__gnat_file_length (int fd)
+void
+__gnat_stat_to_attr (int fd, char* name, struct file_attributes* attr)
{
+ GNAT_STRUCT_STAT statbuf;
int ret;
- STRUCT_STAT statbuf;
- ret = FSTAT (fd, &statbuf);
- if (ret || !S_ISREG (statbuf.st_mode))
- return 0;
+ if (fd != -1)
+ ret = GNAT_FSTAT (fd, &statbuf);
+ else
+ ret = __gnat_stat (name, &statbuf);
+
+ attr->regular = (!ret && S_ISREG (statbuf.st_mode));
+ attr->directory = (!ret && S_ISDIR (statbuf.st_mode));
- /* st_size may be 32 bits, or 64 bits which is converted to long. We
- don't return a useful value for files larger than 2 gigabytes in
- either case. */
+ if (!attr->regular)
+ attr->file_length = 0;
+ else
+ /* st_size may be 32 bits, or 64 bits which is converted to long. We
+ don't return a useful value for files larger than 2 gigabytes in
+ either case. */
+ attr->file_length = statbuf.st_size; /* all systems */
+
+#ifndef __MINGW32__
+ /* on Windows requires extra system call, see comment in __gnat_file_exists_attr */
+ attr->exists = !ret;
+#endif
+
+#if !defined (_WIN32) || defined (RTX)
+ /* on Windows requires extra system call, see __gnat_is_readable_file_attr */
+ attr->readable = (!ret && (statbuf.st_mode & S_IRUSR));
+ attr->writable = (!ret && (statbuf.st_mode & S_IWUSR));
+ attr->executable = (!ret && (statbuf.st_mode & S_IXUSR));
+#endif
+
+#if !defined (__EMX__) && !defined (MSDOS) && (!defined (_WIN32) || defined (RTX))
+ /* on Windows requires extra system call, see __gnat_file_time_name_attr */
+ if (ret != 0) {
+ attr->timestamp = (OS_Time)-1;
+ } else {
+#ifdef VMS
+ /* VMS has file versioning. */
+ attr->timestamp = (OS_Time)statbuf.st_ctime;
+#else
+ attr->timestamp = (OS_Time)statbuf.st_mtime;
+#endif
+ }
+#endif
- return (statbuf.st_size);
}
-/* Return the number of bytes in the specified named file. */
+/****************************************************************
+ ** Return the number of bytes in the specified file
+ ****************************************************************/
long
-__gnat_named_file_length (char *name)
+__gnat_file_length_attr (int fd, char* name, struct file_attributes* attr)
{
- int ret;
- STRUCT_STAT statbuf;
+ if (attr->file_length == -1) {
+ __gnat_stat_to_attr (fd, name, attr);
+ }
- ret = __gnat_stat (name, &statbuf);
- if (ret || !S_ISREG (statbuf.st_mode))
- return 0;
+ return attr->file_length;
+}
- /* st_size may be 32 bits, or 64 bits which is converted to long. We
- don't return a useful value for files larger than 2 gigabytes in
- either case. */
+long
+__gnat_file_length (int fd)
+{
+ struct file_attributes attr;
+ __gnat_reset_attributes (&attr);
+ return __gnat_file_length_attr (fd, NULL, &attr);
+}
- return (statbuf.st_size);
+long
+__gnat_named_file_length (char *name)
+{
+ struct file_attributes attr;
+ __gnat_reset_attributes (&attr);
+ return __gnat_file_length_attr (-1, name, &attr);
}
/* Create a temporary filename and put it in string pointed to by
/* Return a GNAT time stamp given a file name. */
OS_Time
-__gnat_file_time_name (char *name)
+__gnat_file_time_name_attr (char* name, struct file_attributes* attr)
{
-
+ if (attr->timestamp == (OS_Time)-2) {
#if defined (__EMX__) || defined (MSDOS)
- int fd = open (name, O_RDONLY | O_BINARY);
- time_t ret = __gnat_file_time_fd (fd);
- close (fd);
- return (OS_Time)ret;
+ int fd = open (name, O_RDONLY | O_BINARY);
+ time_t ret = __gnat_file_time_fd (fd);
+ close (fd);
+ attr->timestamp = (OS_Time)ret;
#elif defined (_WIN32) && !defined (RTX)
- time_t ret = -1;
- TCHAR wname[GNAT_MAX_PATH_LEN];
-
- S2WSC (wname, name, GNAT_MAX_PATH_LEN);
+ time_t ret = -1;
+ TCHAR wname[GNAT_MAX_PATH_LEN];
+ S2WSC (wname, name, GNAT_MAX_PATH_LEN);
- HANDLE h = CreateFile
- (wname, GENERIC_READ, FILE_SHARE_READ, 0,
- OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
+ HANDLE h = CreateFile
+ (wname, GENERIC_READ, FILE_SHARE_READ, 0,
+ OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
- if (h != INVALID_HANDLE_VALUE)
- {
- ret = win32_filetime (h);
- CloseHandle (h);
- }
- return (OS_Time) ret;
-#else
- STRUCT_STAT statbuf;
- if (__gnat_stat (name, &statbuf) != 0) {
- return (OS_Time)-1;
- } else {
-#ifdef VMS
- /* VMS has file versioning. */
- return (OS_Time)statbuf.st_ctime;
+ if (h != INVALID_HANDLE_VALUE) {
+ ret = win32_filetime (h);
+ CloseHandle (h);
+ }
+ attr->timestamp = (OS_Time) ret;
#else
- return (OS_Time)statbuf.st_mtime;
+ __gnat_stat_to_attr (-1, name, attr);
#endif
}
-#endif
+ return attr->timestamp;
+}
+
+OS_Time
+__gnat_file_time_name (char *name)
+{
+ struct file_attributes attr;
+ __gnat_reset_attributes (&attr);
+ return __gnat_file_time_name_attr (name, &attr);
}
/* Return a GNAT time stamp given a file descriptor. */
OS_Time
-__gnat_file_time_fd (int fd)
+__gnat_file_time_fd_attr (int fd, struct file_attributes* attr)
{
- /* The following workaround code is due to the fact that under EMX and
- DJGPP fstat attempts to convert time values to GMT rather than keep the
- actual OS timestamp of the file. By using the OS2/DOS functions directly
- the GNAT timestamp are independent of this behavior, which is desired to
- facilitate the distribution of GNAT compiled libraries. */
+ if (attr->timestamp == (OS_Time)-2) {
+ /* The following workaround code is due to the fact that under EMX and
+ DJGPP fstat attempts to convert time values to GMT rather than keep the
+ actual OS timestamp of the file. By using the OS2/DOS functions directly
+ the GNAT timestamp are independent of this behavior, which is desired to
+ facilitate the distribution of GNAT compiled libraries. */
#if defined (__EMX__) || defined (MSDOS)
#ifdef __EMX__
- FILESTATUS fs;
- int ret = DosQueryFileInfo (fd, 1, (unsigned char *) &fs,
- sizeof (FILESTATUS));
+ FILESTATUS fs;
+ int ret = DosQueryFileInfo (fd, 1, (unsigned char *) &fs,
+ sizeof (FILESTATUS));
- unsigned file_year = fs.fdateLastWrite.year;
- unsigned file_month = fs.fdateLastWrite.month;
- unsigned file_day = fs.fdateLastWrite.day;
- unsigned file_hour = fs.ftimeLastWrite.hours;
- unsigned file_min = fs.ftimeLastWrite.minutes;
- unsigned file_tsec = fs.ftimeLastWrite.twosecs;
+ unsigned file_year = fs.fdateLastWrite.year;
+ unsigned file_month = fs.fdateLastWrite.month;
+ unsigned file_day = fs.fdateLastWrite.day;
+ unsigned file_hour = fs.ftimeLastWrite.hours;
+ unsigned file_min = fs.ftimeLastWrite.minutes;
+ unsigned file_tsec = fs.ftimeLastWrite.twosecs;
#else
- struct ftime fs;
- int ret = getftime (fd, &fs);
+ struct ftime fs;
+ int ret = getftime (fd, &fs);
- unsigned file_year = fs.ft_year;
- unsigned file_month = fs.ft_month;
- unsigned file_day = fs.ft_day;
- unsigned file_hour = fs.ft_hour;
- unsigned file_min = fs.ft_min;
- unsigned file_tsec = fs.ft_tsec;
+ unsigned file_year = fs.ft_year;
+ unsigned file_month = fs.ft_month;
+ unsigned file_day = fs.ft_day;
+ unsigned file_hour = fs.ft_hour;
+ unsigned file_min = fs.ft_min;
+ unsigned file_tsec = fs.ft_tsec;
#endif
- /* Calculate the seconds since epoch from the time components. First count
- the whole days passed. The value for years returned by the DOS and OS2
- functions count years from 1980, so to compensate for the UNIX epoch which
- begins in 1970 start with 10 years worth of days and add days for each
- four year period since then. */
+ /* Calculate the seconds since epoch from the time components. First count
+ the whole days passed. The value for years returned by the DOS and OS2
+ functions count years from 1980, so to compensate for the UNIX epoch which
+ begins in 1970 start with 10 years worth of days and add days for each
+ four year period since then. */
- time_t tot_secs;
- int cum_days[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
- int days_passed = 3652 + (file_year / 4) * 1461;
- int years_since_leap = file_year % 4;
+ time_t tot_secs;
+ int cum_days[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
+ int days_passed = 3652 + (file_year / 4) * 1461;
+ int years_since_leap = file_year % 4;
- if (years_since_leap == 1)
- days_passed += 366;
- else if (years_since_leap == 2)
- days_passed += 731;
- else if (years_since_leap == 3)
- days_passed += 1096;
+ if (years_since_leap == 1)
+ days_passed += 366;
+ else if (years_since_leap == 2)
+ days_passed += 731;
+ else if (years_since_leap == 3)
+ days_passed += 1096;
- if (file_year > 20)
- days_passed -= 1;
+ if (file_year > 20)
+ days_passed -= 1;
- days_passed += cum_days[file_month - 1];
- if (years_since_leap == 0 && file_year != 20 && file_month > 2)
- days_passed++;
+ days_passed += cum_days[file_month - 1];
+ if (years_since_leap == 0 && file_year != 20 && file_month > 2)
+ days_passed++;
- days_passed += file_day - 1;
+ days_passed += file_day - 1;
- /* OK - have whole days. Multiply -- then add in other parts. */
+ /* OK - have whole days. Multiply -- then add in other parts. */
- tot_secs = days_passed * 86400;
- tot_secs += file_hour * 3600;
- tot_secs += file_min * 60;
- tot_secs += file_tsec * 2;
- return (OS_Time) tot_secs;
+ tot_secs = days_passed * 86400;
+ tot_secs += file_hour * 3600;
+ tot_secs += file_min * 60;
+ tot_secs += file_tsec * 2;
+ attr->timestamp = (OS_Time) tot_secs;
#elif defined (_WIN32) && !defined (RTX)
- HANDLE h = (HANDLE) _get_osfhandle (fd);
- time_t ret = win32_filetime (h);
- return (OS_Time) ret;
+ HANDLE h = (HANDLE) _get_osfhandle (fd);
+ time_t ret = win32_filetime (h);
+ attr->timestamp = (OS_Time) ret;
#else
- STRUCT_STAT statbuf;
-
- if (FSTAT (fd, &statbuf) != 0) {
- return (OS_Time) -1;
- } else {
-#ifdef VMS
- /* VMS has file versioning. */
- return (OS_Time) statbuf.st_ctime;
-#else
- return (OS_Time) statbuf.st_mtime;
-#endif
- }
+ __gnat_stat_to_attr (fd, NULL, attr);
#endif
+ }
+
+ return attr->timestamp;
+}
+
+OS_Time
+__gnat_file_time_fd (int fd)
+{
+ struct file_attributes attr;
+ __gnat_reset_attributes (&attr);
+ return __gnat_file_time_fd_attr (fd, &attr);
}
/* Set the file time stamp. */
}
int
-__gnat_stat (char *name, STRUCT_STAT *statbuf)
+__gnat_stat (char *name, GNAT_STRUCT_STAT *statbuf)
{
#ifdef __MINGW32__
/* Under Windows the directory name for the stat function must not be
- terminated by a directory separator except if just after a drive name. */
+ terminated by a directory separator except if just after a drive name
+ or with UNC path without directory (only the name of the shared
+ resource), for example: \\computer\share\ */
+
TCHAR wname [GNAT_MAX_PATH_LEN + 2];
- int name_len;
+ int name_len, k;
TCHAR last_char;
+ int dirsep_count = 0;
S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
name_len = _tcslen (wname);
last_char = wname[name_len - 1];
}
+ /* Count back-slashes. */
+
+ for (k=0; k<name_len; k++)
+ if (wname[k] == _T('\\') || wname[k] == _T('/'))
+ dirsep_count++;
+
/* Only a drive letter followed by ':', we must add a directory separator
for the stat routine to work properly. */
- if (name_len == 2 && wname[1] == _T(':'))
+ if ((name_len == 2 && wname[1] == _T(':'))
+ || (name_len > 3 && wname[0] == _T('\\') && wname[1] == _T('\\')
+ && dirsep_count == 3))
_tcscat (wname, _T("\\"));
return _tstat (wname, (struct _stat *)statbuf);
#else
- return STAT (name, statbuf);
+ return GNAT_STAT (name, statbuf);
#endif
}
+/*************************************************************************
+ ** Check whether a file exists
+ *************************************************************************/
+
int
-__gnat_file_exists (char *name)
+__gnat_file_exists_attr (char* name, struct file_attributes* attr)
{
+ if (attr->exists == ATTR_UNSET) {
#ifdef __MINGW32__
- /* On Windows do not use __gnat_stat() because a bug in Microsoft
- _stat() routine. When the system time-zone is set with a negative
- offset the _stat() routine fails on specific files like CON: */
- TCHAR wname [GNAT_MAX_PATH_LEN + 2];
-
- S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
- return GetFileAttributes (wname) != INVALID_FILE_ATTRIBUTES;
+ /* On Windows do not use __gnat_stat() because of a bug in Microsoft
+ _stat() routine. When the system time-zone is set with a negative
+ offset the _stat() routine fails on specific files like CON: */
+ TCHAR wname [GNAT_MAX_PATH_LEN + 2];
+ S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
+ attr->exists = GetFileAttributes (wname) != INVALID_FILE_ATTRIBUTES;
#else
- STRUCT_STAT statbuf;
-
- return !__gnat_stat (name, &statbuf);
+ __gnat_stat_to_attr (-1, name, attr);
#endif
+ }
+
+ return attr->exists;
}
int
+__gnat_file_exists (char *name)
+{
+ struct file_attributes attr;
+ __gnat_reset_attributes (&attr);
+ return __gnat_file_exists_attr (name, &attr);
+}
+
+/**********************************************************************
+ ** Whether name is an absolute path
+ **********************************************************************/
+
+int
__gnat_is_absolute_path (char *name, int length)
{
#ifdef __vxworks
}
int
+__gnat_is_regular_file_attr (char* name, struct file_attributes* attr)
+{
+ if (attr->regular == ATTR_UNSET) {
+ __gnat_stat_to_attr (-1, name, attr);
+ }
+
+ return attr->regular;
+}
+
+int
__gnat_is_regular_file (char *name)
{
- int ret;
- STRUCT_STAT statbuf;
+ struct file_attributes attr;
+ __gnat_reset_attributes (&attr);
+ return __gnat_is_regular_file_attr (name, &attr);
+}
- ret = __gnat_stat (name, &statbuf);
- return (!ret && S_ISREG (statbuf.st_mode));
+int
+__gnat_is_directory_attr (char* name, struct file_attributes* attr)
+{
+ if (attr->directory == ATTR_UNSET) {
+ __gnat_stat_to_attr (-1, name, attr);
+ }
+
+ return attr->directory;
}
int
__gnat_is_directory (char *name)
{
- int ret;
- STRUCT_STAT statbuf;
-
- ret = __gnat_stat (name, &statbuf);
- return (!ret && S_ISDIR (statbuf.st_mode));
+ struct file_attributes attr;
+ __gnat_reset_attributes (&attr);
+ return __gnat_is_directory_attr (name, &attr);
}
#if defined (_WIN32) && !defined (RTX)
DWORD AccessMode,
DWORD AccessPermissions)
{
- ACL* pOldDACL = NULL;
- ACL* pNewDACL = NULL;
- SECURITY_DESCRIPTOR* pSD = NULL;
+ PACL pOldDACL = NULL;
+ PACL pNewDACL = NULL;
+ PSECURITY_DESCRIPTOR pSD = NULL;
EXPLICIT_ACCESS ea;
TCHAR username [100];
DWORD unsize = 100;
#endif /* defined (_WIN32) && !defined (RTX) */
int
-__gnat_is_readable_file (char *name)
+__gnat_is_readable_file_attr (char* name, struct file_attributes* attr)
{
+ if (attr->readable == ATTR_UNSET) {
#if defined (_WIN32) && !defined (RTX)
- TCHAR wname [GNAT_MAX_PATH_LEN + 2];
- GENERIC_MAPPING GenericMapping;
-
- S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
+ TCHAR wname [GNAT_MAX_PATH_LEN + 2];
+ GENERIC_MAPPING GenericMapping;
- if (__gnat_can_use_acl (wname))
- {
- ZeroMemory (&GenericMapping, sizeof (GENERIC_MAPPING));
- GenericMapping.GenericRead = GENERIC_READ;
-
- return __gnat_check_OWNER_ACL (wname, FILE_READ_DATA, GenericMapping);
- }
- else
- return GetFileAttributes (wname) != INVALID_FILE_ATTRIBUTES;
+ S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
+ if (__gnat_can_use_acl (wname))
+ {
+ ZeroMemory (&GenericMapping, sizeof (GENERIC_MAPPING));
+ GenericMapping.GenericRead = GENERIC_READ;
+ attr->readable = __gnat_check_OWNER_ACL (wname, FILE_READ_DATA, GenericMapping);
+ }
+ else
+ attr->readable = GetFileAttributes (wname) != INVALID_FILE_ATTRIBUTES;
#else
- int ret;
- int mode;
- STRUCT_STAT statbuf;
-
- ret = STAT (name, &statbuf);
- mode = statbuf.st_mode & S_IRUSR;
- return (!ret && mode);
+ __gnat_stat_to_attr (-1, name, attr);
#endif
+ }
+
+ return attr->readable;
}
int
-__gnat_is_writable_file (char *name)
+__gnat_is_readable_file (char *name)
{
+ struct file_attributes attr;
+ __gnat_reset_attributes (&attr);
+ return __gnat_is_readable_file_attr (name, &attr);
+}
+
+int
+__gnat_is_writable_file_attr (char* name, struct file_attributes* attr)
+{
+ if (attr->writable == ATTR_UNSET) {
#if defined (_WIN32) && !defined (RTX)
- TCHAR wname [GNAT_MAX_PATH_LEN + 2];
- GENERIC_MAPPING GenericMapping;
+ TCHAR wname [GNAT_MAX_PATH_LEN + 2];
+ GENERIC_MAPPING GenericMapping;
- S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
+ S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
- if (__gnat_can_use_acl (wname))
- {
- ZeroMemory (&GenericMapping, sizeof (GENERIC_MAPPING));
- GenericMapping.GenericWrite = GENERIC_WRITE;
+ if (__gnat_can_use_acl (wname))
+ {
+ ZeroMemory (&GenericMapping, sizeof (GENERIC_MAPPING));
+ GenericMapping.GenericWrite = GENERIC_WRITE;
- return __gnat_check_OWNER_ACL
- (wname, FILE_WRITE_DATA | FILE_APPEND_DATA, GenericMapping)
- && !(GetFileAttributes (wname) & FILE_ATTRIBUTE_READONLY);
- }
- else
- return !(GetFileAttributes (wname) & FILE_ATTRIBUTE_READONLY);
+ attr->writable = __gnat_check_OWNER_ACL
+ (wname, FILE_WRITE_DATA | FILE_APPEND_DATA, GenericMapping)
+ && !(GetFileAttributes (wname) & FILE_ATTRIBUTE_READONLY);
+ }
+ else
+ attr->writable = !(GetFileAttributes (wname) & FILE_ATTRIBUTE_READONLY);
#else
- int ret;
- int mode;
- STRUCT_STAT statbuf;
-
- ret = STAT (name, &statbuf);
- mode = statbuf.st_mode & S_IWUSR;
- return (!ret && mode);
+ __gnat_stat_to_attr (-1, name, attr);
#endif
+ }
+
+ return attr->writable;
}
int
-__gnat_is_executable_file (char *name)
+__gnat_is_writable_file (char *name)
{
+ struct file_attributes attr;
+ __gnat_reset_attributes (&attr);
+ return __gnat_is_writable_file_attr (name, &attr);
+}
+
+int
+__gnat_is_executable_file_attr (char* name, struct file_attributes* attr)
+{
+ if (attr->executable == ATTR_UNSET) {
#if defined (_WIN32) && !defined (RTX)
- TCHAR wname [GNAT_MAX_PATH_LEN + 2];
- GENERIC_MAPPING GenericMapping;
+ TCHAR wname [GNAT_MAX_PATH_LEN + 2];
+ GENERIC_MAPPING GenericMapping;
- S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
+ S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
- if (__gnat_can_use_acl (wname))
- {
- ZeroMemory (&GenericMapping, sizeof (GENERIC_MAPPING));
- GenericMapping.GenericExecute = GENERIC_EXECUTE;
+ if (__gnat_can_use_acl (wname))
+ {
+ ZeroMemory (&GenericMapping, sizeof (GENERIC_MAPPING));
+ GenericMapping.GenericExecute = GENERIC_EXECUTE;
- return __gnat_check_OWNER_ACL (wname, FILE_EXECUTE, GenericMapping);
- }
- else
- return GetFileAttributes (wname) != INVALID_FILE_ATTRIBUTES
- && _tcsstr (wname, _T(".exe")) - wname == (int) (_tcslen (wname) - 4);
+ attr->executable = __gnat_check_OWNER_ACL (wname, FILE_EXECUTE, GenericMapping);
+ }
+ else
+ attr->executable = GetFileAttributes (wname) != INVALID_FILE_ATTRIBUTES
+ && _tcsstr (wname, _T(".exe")) - wname == (int) (_tcslen (wname) - 4);
#else
- int ret;
- int mode;
- STRUCT_STAT statbuf;
-
- ret = STAT (name, &statbuf);
- mode = statbuf.st_mode & S_IXUSR;
- return (!ret && mode);
+ __gnat_stat_to_attr (-1, name, attr);
#endif
+ }
+
+ return attr->executable;
+}
+
+int
+__gnat_is_executable_file (char *name)
+{
+ struct file_attributes attr;
+ __gnat_reset_attributes (&attr);
+ return __gnat_is_executable_file_attr (name, &attr);
}
void
SetFileAttributes
(wname, GetFileAttributes (wname) & ~FILE_ATTRIBUTE_READONLY);
#elif ! defined (__vxworks) && ! defined(__nucleus__)
- STRUCT_STAT statbuf;
+ GNAT_STRUCT_STAT statbuf;
- if (STAT (name, &statbuf) == 0)
+ if (GNAT_STAT (name, &statbuf) == 0)
{
statbuf.st_mode = statbuf.st_mode | S_IWUSR;
chmod (name, statbuf.st_mode);
__gnat_set_OWNER_ACL (wname, GRANT_ACCESS, FILE_GENERIC_EXECUTE);
#elif ! defined (__vxworks) && ! defined(__nucleus__)
- STRUCT_STAT statbuf;
+ GNAT_STRUCT_STAT statbuf;
- if (STAT (name, &statbuf) == 0)
+ if (GNAT_STAT (name, &statbuf) == 0)
{
statbuf.st_mode = statbuf.st_mode | S_IXUSR;
chmod (name, statbuf.st_mode);
SetFileAttributes
(wname, GetFileAttributes (wname) | FILE_ATTRIBUTE_READONLY);
#elif ! defined (__vxworks) && ! defined(__nucleus__)
- STRUCT_STAT statbuf;
+ GNAT_STRUCT_STAT statbuf;
- if (STAT (name, &statbuf) == 0)
+ if (GNAT_STAT (name, &statbuf) == 0)
{
statbuf.st_mode = statbuf.st_mode & 07577;
chmod (name, statbuf.st_mode);
__gnat_set_OWNER_ACL (wname, GRANT_ACCESS, FILE_GENERIC_READ);
#elif ! defined (__vxworks) && ! defined(__nucleus__)
- STRUCT_STAT statbuf;
+ GNAT_STRUCT_STAT statbuf;
- if (STAT (name, &statbuf) == 0)
+ if (GNAT_STAT (name, &statbuf) == 0)
{
chmod (name, statbuf.st_mode | S_IREAD);
}
__gnat_set_OWNER_ACL (wname, DENY_ACCESS, FILE_GENERIC_READ);
#elif ! defined (__vxworks) && ! defined(__nucleus__)
- STRUCT_STAT statbuf;
+ GNAT_STRUCT_STAT statbuf;
- if (STAT (name, &statbuf) == 0)
+ if (GNAT_STAT (name, &statbuf) == 0)
{
chmod (name, statbuf.st_mode & (~S_IREAD));
}
}
int
-__gnat_is_symbolic_link (char *name ATTRIBUTE_UNUSED)
+__gnat_is_symbolic_link_attr (char* name, struct file_attributes* attr)
{
+ if (attr->symbolic_link == ATTR_UNSET) {
#if defined (__vxworks) || defined (__nucleus__)
- return 0;
+ attr->symbolic_link = 0;
#elif defined (_AIX) || defined (__APPLE__) || defined (__unix__)
- int ret;
- STRUCT_STAT statbuf;
-
- ret = LSTAT (name, &statbuf);
- return (!ret && S_ISLNK (statbuf.st_mode));
-
+ int ret;
+ GNAT_STRUCT_STAT statbuf;
+ ret = GNAT_LSTAT (name, &statbuf);
+ attr->symbolic_link = (!ret && S_ISLNK (statbuf.st_mode));
#else
- return 0;
+ attr->symbolic_link = 0;
#endif
+ }
+ return attr->symbolic_link;
+}
+
+int
+__gnat_is_symbolic_link (char *name ATTRIBUTE_UNUSED)
+{
+ struct file_attributes attr;
+ __gnat_reset_attributes (&attr);
+ return __gnat_is_symbolic_link_attr (name, &attr);
+
}
#if defined (sun) && defined (__SVR4)
#endif
-typedef struct _process_list
-{
- HANDLE h;
- struct _process_list *next;
-} Process_List;
-
-static Process_List *PLIST = NULL;
-
-static int plist_length = 0;
+static HANDLE *HANDLES_LIST = NULL;
+static int *PID_LIST = NULL, plist_length = 0, plist_max_length = 0;
static void
add_handle (HANDLE h)
{
- Process_List *pl;
-
- pl = (Process_List *) xmalloc (sizeof (Process_List));
/* -------------------- critical section -------------------- */
(*Lock_Task) ();
- pl->h = h;
- pl->next = PLIST;
- PLIST = pl;
+ if (plist_length == plist_max_length)
+ {
+ plist_max_length += 1000;
+ HANDLES_LIST =
+ xrealloc (HANDLES_LIST, sizeof (HANDLE) * plist_max_length);
+ PID_LIST =
+ xrealloc (PID_LIST, sizeof (int) * plist_max_length);
+ }
+
+ HANDLES_LIST[plist_length] = h;
+ PID_LIST[plist_length] = GetProcessId (h);
++plist_length;
(*Unlock_Task) ();
/* -------------------- critical section -------------------- */
}
-static void
-remove_handle (HANDLE h)
+void
+__gnat_win32_remove_handle (HANDLE h, int pid)
{
- Process_List *pl;
- Process_List *prev = NULL;
+ int j;
/* -------------------- critical section -------------------- */
(*Lock_Task) ();
- pl = PLIST;
- while (pl)
+ for (j = 0; j < plist_length; j++)
{
- if (pl->h == h)
+ if ((HANDLES_LIST[j] == h) || (PID_LIST[j] == pid))
{
- if (pl == PLIST)
- PLIST = pl->next;
- else
- prev->next = pl->next;
- free (pl);
+ CloseHandle (h);
+ --plist_length;
+ HANDLES_LIST[j] = HANDLES_LIST[plist_length];
+ PID_LIST[j] = PID_LIST[plist_length];
break;
}
- else
- {
- prev = pl;
- pl = pl->next;
- }
}
- --plist_length;
-
(*Unlock_Task) ();
/* -------------------- critical section -------------------- */
}
-static int
+static HANDLE
win32_no_block_spawn (char *command, char *args[])
{
BOOL result;
if (result == TRUE)
{
- add_handle (PI.hProcess);
CloseHandle (PI.hThread);
- return (int) PI.hProcess;
+ return PI.hProcess;
}
else
- return -1;
+ return NULL;
}
static int
win32_wait (int *status)
{
- DWORD exitcode;
+ DWORD exitcode, pid;
HANDLE *hl;
HANDLE h;
DWORD res;
int k;
- Process_List *pl;
int hl_len;
if (plist_length == 0)
hl = (HANDLE *) xmalloc (sizeof (HANDLE) * hl_len);
- pl = PLIST;
- while (pl)
- {
- hl[k++] = pl->h;
- pl = pl->next;
- }
+ memmove (hl, HANDLES_LIST, sizeof (HANDLE) * hl_len);
(*Unlock_Task) ();
/* -------------------- critical section -------------------- */
res = WaitForMultipleObjects (hl_len, hl, FALSE, INFINITE);
h = hl[res - WAIT_OBJECT_0];
- free (hl);
-
- remove_handle (h);
GetExitCodeProcess (h, &exitcode);
- CloseHandle (h);
+ pid = GetProcessId (h);
+ __gnat_win32_remove_handle (h, -1);
+
+ free (hl);
*status = (int) exitcode;
- return (int) h;
+ return (int) pid;
}
#endif
int
__gnat_portable_no_block_spawn (char *args[])
{
- int pid = 0;
#if defined (__vxworks) || defined (__nucleus__) || defined (RTX)
return -1;
#elif defined (_WIN32)
- pid = win32_no_block_spawn (args[0], args);
- return pid;
+ HANDLE h = NULL;
+
+ h = win32_no_block_spawn (args[0], args);
+ if (h != NULL)
+ {
+ add_handle (h);
+ return GetProcessId (h);
+ }
+ else
+ return -1;
#else
- pid = fork ();
+
+ int pid = fork ();
if (pid == 0)
{
#endif
}
-#endif
-
return pid;
+
+ #endif
}
int
char *
__gnat_to_canonical_file_list_next (void)
{
- return (char *) "";
+ static char *empty = "";
+ return empty;
}
void
return 0;
#else
- STRUCT_STAT fbuf;
+ GNAT_STRUCT_STAT fbuf;
struct utimbuf tbuf;
- if (STAT (from, &fbuf) == -1)
+ if (GNAT_STAT (from, &fbuf) == -1)
{
return -1;
}
return -1;
if (close_on_exec_p)
return ! SetHandleInformation (h, HANDLE_FLAG_INHERIT, 0);
- return ! SetHandleInformation (h, HANDLE_FLAG_INHERIT,
+ return ! SetHandleInformation (h, HANDLE_FLAG_INHERIT,
HANDLE_FLAG_INHERIT);
#else
/* TODO: Unimplemented. */
/* Indicates if platforms supports automatic initialization through the
constructor mechanism */
int
-__gnat_binder_supports_auto_init ()
+__gnat_binder_supports_auto_init (void)
{
#ifdef VMS
return 0;
/* Indicates that Stand-Alone Libraries are automatically initialized through
the constructor mechanism */
int
-__gnat_sals_init_using_constructors ()
+__gnat_sals_init_using_constructors (void)
{
#if defined (__vxworks) || defined (__Lynx__) || defined (VMS)
return 0;