* *
* C Implementation File *
* *
- * Copyright (C) 1992-2015, Free Software Foundation, Inc. *
+ * Copyright (C) 1992-2019, Free Software Foundation, Inc. *
* *
* GNAT is free software; you can redistribute it and/or modify it under *
* terms of the GNU General Public License as published by the Free Soft- *
#define _THREAD_SAFE
/* Use 64 bit Large File API */
-#ifndef _LARGEFILE_SOURCE
+#if defined (__QNX__)
+#define _LARGEFILE64_SOURCE 1
+#elif !defined(_LARGEFILE_SOURCE)
#define _LARGEFILE_SOURCE
#endif
#define _FILE_OFFSET_BITS 64
#define __BSD_VISIBLE 1
#endif
+#ifdef __QNX__
+#include <sys/syspage.h>
+#endif
+
#ifdef IN_RTS
+
+#ifdef STANDALONE
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* for CPU_SET/CPU_ZERO */
+#define _GNU_SOURCE
+#define __USE_GNU
+
+#include "runtime.h"
+
+#else
#include "tconfig.h"
#include "tsystem.h"
+#endif
+
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
extern "C" {
#endif
-#if defined (__MINGW32__) || defined (__CYGWIN__)
+#if defined (__DJGPP__)
+
+/* For isalpha-like tests in the compiler, we're expected to resort to
+ safe-ctype.h/ISALPHA. This isn't available for the runtime library
+ build, so we fallback on ctype.h/isalpha there. */
+
+#ifdef IN_RTS
+#include <ctype.h>
+#define ISALPHA isalpha
+#endif
+
+#elif defined (__MINGW32__) || defined (__CYGWIN__)
#include "mingw32.h"
/* Current code page and CCS encoding to use, set in initialize.c. */
-UINT CurrentCodePage;
-UINT CurrentCCSEncoding;
+UINT __gnat_current_codepage;
+UINT __gnat_current_ccs_encoding;
#include <sys/utime.h>
#include <sys/wait.h>
#endif
-#if defined (_WIN32)
-
+#if defined (__DJGPP__)
#include <process.h>
#include <signal.h>
#include <dir.h>
+#include <utime.h>
+#undef DIR_SEPARATOR
+#define DIR_SEPARATOR '\\'
+
+#elif defined (_WIN32)
+
#include <windows.h>
#include <accctrl.h>
#include <aclapi.h>
#include <tlhelp32.h>
+#include <signal.h>
#undef DIR_SEPARATOR
#define DIR_SEPARATOR '\\'
system provides the routine readdir_r.
... but we never define it anywhere??? */
#undef HAVE_READDIR_R
-\f
+
#define MAYBE_TO_PTR32(argv) argv
static const char ATTR_UNSET = 127;
struct tm *res;
time_t time = (time_t) *p_time;
-#ifdef _WIN32
- /* On Windows systems, the time is sometimes rounded up to the nearest
- even second, so if the number of seconds is odd, increment it. */
- if (time & 1)
- time++;
-#endif
-
res = gmtime (&time);
if (res)
{
{
/* By default, we suppose filesystems aren't case sensitive on
Windows and Darwin (but they are on arm-darwin). */
-#if defined (WINNT) \
+#if defined (WINNT) || defined (__DJGPP__) \
|| (defined (__APPLE__) && !(defined (__arm__) || defined (__arm64__)))
file_names_case_sensitive_cache = 0;
#else
int
__gnat_get_env_vars_case_sensitive (void)
{
-#if defined (WINNT)
+#if defined (WINNT) || defined (__DJGPP__)
return 0;
#else
return 1;
WS2SC (dir, wdir, GNAT_MAX_PATH_LEN);
#else
- getcwd (dir, *length);
+ char* result = getcwd (dir, *length);
+ /* If the current directory does not exist, set length = 0
+ to indicate error. That can't happen on windows, where
+ you can't delete a directory if it is the current
+ directory of some process. */
+ if (!result)
+ {
+ *length = 0;
+ return;
+ }
#endif
*length = strlen (dir);
__gnat_get_executable_suffix_ptr (int *len, const char **value)
{
*value = HOST_EXECUTABLE_SUFFIX;
+
if (!*value)
*len = 0;
else
}
#if defined (_WIN32) || defined (__linux__) || defined (__sun__) \
- || defined (__FreeBSD__) || defined(__DragonFly__)
+ || defined (__FreeBSD__) || defined(__DragonFly__) || defined (__QNX__)
#define HAS_TARGET_WCHAR_T
#endif
#if (defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) \
|| defined (__linux__) || defined (__GLIBC__) || defined (__ANDROID__) \
- || defined (__DragonFly__)) && !defined (__vxworks)
+ || defined (__DragonFly__) || defined (__QNX__)) && !defined (__vxworks)
return mkstemp (path);
#elif defined (__Lynx__)
mktemp (path);
#elif defined (__linux__) || defined (__FreeBSD__) || defined (__NetBSD__) \
|| defined (__OpenBSD__) || defined (__GLIBC__) || defined (__ANDROID__) \
- || defined (__DragonFly__)
+ || defined (__DragonFly__) || defined (__QNX__)
#define MAX_SAFE_PATH 1000
char *tmpdir = getenv ("TMPDIR");
/* Fill up the name buffer from the last position. */
seed++;
- for (t = seed; 0 <= --index; t >>= 3)
+ for (t = seed; --index >= 0; t >>= 3)
*--pos = '0' + (t & 07);
/* Check to see if its unique, if not bump the seed and try again. */
utimbuf.modtime = time_stamp;
/* Set access time to now in local time. */
- t = time ((time_t) 0);
+ t = time (NULL);
utimbuf.actime = mktime (localtime (&t));
utime (name, &utimbuf);
#else
return (length != 0) &&
(*name == '/' || *name == DIR_SEPARATOR
-#if defined (WINNT)
+#if defined (WINNT) || defined(__DJGPP__)
|| (length > 1 && ISALPHA (name[0]) && name[1] == ':')
#endif
);
S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
- return !_access (wname, 4);
+ return !_waccess (wname, 4);
+
+#elif defined (__vxworks)
+ int fd;
+
+ if ((fd = open (name, O_RDONLY, 0)) < 0)
+ return 0;
+ close (fd);
+ return 1;
+
#else
return !access (name, R_OK);
#endif
S2WSC (wname, name, GNAT_MAX_PATH_LEN + 2);
- return !_access (wname, 2);
+ return !_waccess (wname, 2);
+
+#elif defined (__vxworks)
+ int fd;
+
+ if ((fd = open (name, O_WRONLY, 0)) < 0)
+ return 0;
+ close (fd);
+ return 1;
+
#else
return !access (name, W_OK);
#endif
#if defined (__vxworks) || defined(__PikeOS__)
return -1;
-#elif defined (_WIN32)
+#elif defined (__DJGPP__) || defined (_WIN32)
/* args[0] must be quotes as it could contain a full pathname with spaces */
char *args_0 = args[0];
args[0] = (char *)xmalloc (strlen (args_0) + 3);
RTPs. */
return -1;
#elif defined (__PikeOS__)
- /* Not supported. */
+ /* Not supported. */
return -1;
#elif defined (_WIN32)
/* Special case when oldfd and newfd are identical and are the standard
|| defined (__DragonFly__) || defined (__NetBSD__)
cores = (int) sysconf (_SC_NPROCESSORS_ONLN);
+#elif defined (__QNX__)
+ cores = (int) _syspage_ptr->num_cpu;
+
#elif defined (__hpux__)
struct pst_dynamic psd;
if (pstat_getdynamic (&psd, sizeof (psd), 1, 0) != -1)
DWORD res;
int hl_len;
int found;
+ int pos;
START_WAIT:
/* -------------------- critical section -------------------- */
EnterCS();
+ /* ??? We can't wait for more than MAXIMUM_WAIT_OBJECTS due to a Win32
+ limitation */
+ if (plist_length < MAXIMUM_WAIT_OBJECTS)
hl_len = plist_length;
+ else
+ {
+ errno = EINVAL;
+ return -1;
+ }
#ifdef CERT
hl = (HANDLE *) xmalloc (sizeof (HANDLE) * hl_len);
#else
/* Note that index 0 contains the event handle that is signaled when the
process list has changed */
- hl = (HANDLE *) xmalloc (sizeof (HANDLE) * hl_len + 1);
+ hl = (HANDLE *) xmalloc (sizeof (HANDLE) * (hl_len + 1));
hl[0] = ProcListEvt;
memmove (&hl[1], HANDLES_LIST, sizeof (HANDLE) * hl_len);
- pidl = (int *) xmalloc (sizeof (int) * hl_len + 1);
+ pidl = (int *) xmalloc (sizeof (int) * (hl_len + 1));
memmove (&pidl[1], PID_LIST, sizeof (int) * hl_len);
hl_len++;
#endif
res = WaitForMultipleObjects (hl_len, hl, FALSE, INFINITE);
+ /* If there was an error, exit now */
+ if (res == WAIT_FAILED)
+ {
+ free (hl);
+ free (pidl);
+ errno = EINVAL;
+ return -1;
+ }
+
/* if the ProcListEvt has been signaled then the list of processes has been
updated to add or remove a handle, just loop over */
goto START_WAIT;
}
- h = hl[res - WAIT_OBJECT_0];
+ /* Handle two distinct groups of return codes: finished waits and abandoned
+ waits */
+
+ if (res < WAIT_ABANDONED_0)
+ pos = res - WAIT_OBJECT_0;
+ else
+ pos = res - WAIT_ABANDONED_0;
+
+ h = hl[pos];
GetExitCodeProcess (h, &exitcode);
- pid = pidl [res - WAIT_OBJECT_0];
+ pid = pidl [pos];
found = __gnat_win32_remove_handle (h, -1);
/* Not supported. */
return -1;
+#elif defined(__DJGPP__)
+ if (spawnvp (P_WAIT, args[0], args) != 0)
+ return -1;
+ else
+ return 0;
+
#elif defined (_WIN32)
HANDLE h = NULL;
pid = win32_wait (&status);
+#elif defined (__DJGPP__)
+ /* Child process has already ended in case of DJGPP.
+ No need to do anything. Just return success. */
#else
pid = waitpid (-1, &status, 0);
return pid;
}
+int
+__gnat_portable_no_block_wait (int *process_status)
+{
+ int status = 0;
+ int pid = 0;
+
+#if defined (__vxworks) || defined (__PikeOS__) || defined (_WIN32)
+ /* Not supported. */
+ status = -1;
+
+#else
+
+ pid = waitpid (-1, &status, WNOHANG);
+ status = status & 0xffff;
+#endif
+
+ *process_status = status;
+ return pid;
+}
+
void
__gnat_os_exit (int status)
{
char *
__gnat_locate_exec (char *exec_name, char *path_val)
{
+ const unsigned int len = strlen (HOST_EXECUTABLE_SUFFIX);
char *ptr;
- if (!strstr (exec_name, HOST_EXECUTABLE_SUFFIX))
+
+ if (len > 0 && !strstr (exec_name, HOST_EXECUTABLE_SUFFIX))
{
- char *full_exec_name =
- (char *) alloca
- (strlen (exec_name) + strlen (HOST_EXECUTABLE_SUFFIX) + 1);
+ char *full_exec_name = (char *) alloca (strlen (exec_name) + len + 1);
strcpy (full_exec_name, exec_name);
strcat (full_exec_name, HOST_EXECUTABLE_SUFFIX);
#endif
#if defined (__APPLE__)
-#include <mach/thread_info.h>
-#include <mach/mach_init.h>
-#include <mach/thread_act.h>
+# if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060
+# include <mach/thread_info.h>
+# include <mach/mach_init.h>
+# include <mach/thread_act.h>
+# else
+# include <pthread.h>
+# endif
/* System-wide thread identifier. Note it could be truncated on 32 bit
hosts.
void *
__gnat_lwp_self (void)
{
+#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060
thread_identifier_info_data_t data;
mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT;
kern_return_t kret;
return (void *)(uintptr_t)data.thread_id;
else
return 0;
+#else
+ return (void *)pthread_mach_thread_np (pthread_self ());
+#endif
}
#endif
void __gnat_killprocesstree (int pid, int sig_num)
{
#if defined(_WIN32)
- HANDLE hWnd;
PROCESSENTRY32 pe;
memset(&pe, 0, sizeof(PROCESSENTRY32));
while (bContinue)
{
- if (pe.th32ParentProcessID == (int)pid)
+ if (pe.th32ParentProcessID == (DWORD)pid)
__gnat_killprocesstree (pe.th32ProcessID, sig_num);
bContinue = Process32Next (hSnap, &pe);
{
if ((d->d_type & DT_DIR) == DT_DIR)
{
- char statfile[64] = { 0 };
+ char statfile[64];
int _pid, _ppid;
/* read /proc/<PID>/stat */
- strncpy (statfile, "/proc/", sizeof(statfile));
- strncat (statfile, d->d_name, sizeof(statfile));
- strncat (statfile, "/stat", sizeof(statfile));
+ if (strlen (d->d_name) >= sizeof (statfile) - strlen ("/proc//stat"))
+ continue;
+ strcpy (statfile, "/proc/");
+ strcat (statfile, d->d_name);
+ strcat (statfile, "/stat");
FILE *fd = fopen (statfile, "r");