mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-19 11:10:25 +02:00
Win32: add replacement for mkdtemp
* libguile/posix-w32.c (mkdtemp): new win32 replacement procedure * libguile/posix-w32.h: add declaration for mkdtemp (HAVE_MKDTEMP): new define * libguile/filesys.c: include posix-w32.h
This commit is contained in:
parent
c08debbd39
commit
0b70769247
3 changed files with 181 additions and 85 deletions
|
@ -89,6 +89,9 @@
|
||||||
#include "pairs.h"
|
#include "pairs.h"
|
||||||
#include "ports-internal.h"
|
#include "ports-internal.h"
|
||||||
#include "ports.h"
|
#include "ports.h"
|
||||||
|
#ifdef __MINGW32__
|
||||||
|
#include "posix-w32.h"
|
||||||
|
#endif
|
||||||
#include "posix.h"
|
#include "posix.h"
|
||||||
#if __MINGW32__
|
#if __MINGW32__
|
||||||
#include "posix-w32.h"
|
#include "posix-w32.h"
|
||||||
|
|
|
@ -18,10 +18,11 @@
|
||||||
<https://www.gnu.org/licenses/>. */
|
<https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
# include <config.h>
|
#include <config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#define _CRT_RAND_S
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <c-strcase.h>
|
#include <c-strcase.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
@ -34,9 +35,14 @@
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
#include "gc.h" /* for scm_*alloc, scm_strdup */
|
#include "gc.h" /* for scm_*alloc, scm_strdup */
|
||||||
#include "filename.h"
|
#include "filename.h"
|
||||||
#include "threads.h" /* for scm_i_scm_pthread_mutex_lock */
|
#include "threads.h" /* for scm_i_scm_pthread_mutex_lock */
|
||||||
|
=======
|
||||||
|
#include "gc.h" /* for scm_*alloc, scm_strdup */
|
||||||
|
#include "threads.h" /* for scm_i_scm_pthread_mutex_lock */
|
||||||
|
>>>>>>> bbd90294d (Win32: add replacement for mkdtemp)
|
||||||
|
|
||||||
#include "posix-w32.h"
|
#include "posix-w32.h"
|
||||||
|
|
||||||
|
@ -46,7 +52,8 @@
|
||||||
int
|
int
|
||||||
uname (struct utsname *uts)
|
uname (struct utsname *uts)
|
||||||
{
|
{
|
||||||
enum { WinNT, Win95, Win98, WinUnknown };
|
enum
|
||||||
|
{ WinNT, Win95, Win98, WinUnknown };
|
||||||
OSVERSIONINFO osver;
|
OSVERSIONINFO osver;
|
||||||
SYSTEM_INFO sysinfo;
|
SYSTEM_INFO sysinfo;
|
||||||
DWORD sLength;
|
DWORD sLength;
|
||||||
|
@ -60,55 +67,55 @@ uname (struct utsname *uts)
|
||||||
|
|
||||||
switch (osver.dwPlatformId)
|
switch (osver.dwPlatformId)
|
||||||
{
|
{
|
||||||
case VER_PLATFORM_WIN32_NT: /* NT, Windows 2000 or Windows XP */
|
case VER_PLATFORM_WIN32_NT: /* NT, Windows 2000 or Windows XP */
|
||||||
if (osver.dwMajorVersion == 4)
|
if (osver.dwMajorVersion == 4)
|
||||||
strcpy (uts->sysname, "Windows NT4x"); /* NT4x */
|
strcpy (uts->sysname, "Windows NT4x"); /* NT4x */
|
||||||
else if (osver.dwMajorVersion <= 3)
|
else if (osver.dwMajorVersion <= 3)
|
||||||
strcpy (uts->sysname, "Windows NT3x"); /* NT3x */
|
strcpy (uts->sysname, "Windows NT3x"); /* NT3x */
|
||||||
else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion < 1)
|
else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion < 1)
|
||||||
strcpy (uts->sysname, "Windows 2000"); /* 2k */
|
strcpy (uts->sysname, "Windows 2000"); /* 2k */
|
||||||
else if (osver.dwMajorVersion < 6)
|
else if (osver.dwMajorVersion < 6)
|
||||||
strcpy (uts->sysname, "Windows XP"); /* XP */
|
strcpy (uts->sysname, "Windows XP"); /* XP */
|
||||||
else if (osver.dwMajorVersion == 6)
|
else if (osver.dwMajorVersion == 6)
|
||||||
{
|
{
|
||||||
if (osver.dwMinorVersion < 1)
|
if (osver.dwMinorVersion < 1)
|
||||||
strcpy (uts->sysname, "Windows Vista"); /* Vista */
|
strcpy (uts->sysname, "Windows Vista"); /* Vista */
|
||||||
else if (osver.dwMinorVersion < 2)
|
else if (osver.dwMinorVersion < 2)
|
||||||
strcpy (uts->sysname, "Windows 7"); /* Windows 7 */
|
strcpy (uts->sysname, "Windows 7"); /* Windows 7 */
|
||||||
else if (osver.dwMinorVersion < 3)
|
else if (osver.dwMinorVersion < 3)
|
||||||
strcpy (uts->sysname, "Windows 8"); /* Windows 8 */
|
strcpy (uts->sysname, "Windows 8"); /* Windows 8 */
|
||||||
else if (osver.dwMinorVersion < 4)
|
else if (osver.dwMinorVersion < 4)
|
||||||
strcpy (uts->sysname, "Windows 8.1"); /* Windows 8.1 */
|
strcpy (uts->sysname, "Windows 8.1"); /* Windows 8.1 */
|
||||||
}
|
}
|
||||||
else if (osver.dwMajorVersion >= 10)
|
else if (osver.dwMajorVersion >= 10)
|
||||||
strcpy (uts->sysname, "Windows 10 or later"); /* Windows 10 and later */
|
strcpy (uts->sysname, "Windows 10 or later"); /* Windows 10 and later */
|
||||||
os = WinNT;
|
os = WinNT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VER_PLATFORM_WIN32_WINDOWS: /* Win95, Win98 or WinME */
|
case VER_PLATFORM_WIN32_WINDOWS: /* Win95, Win98 or WinME */
|
||||||
if ((osver.dwMajorVersion > 4) ||
|
if ((osver.dwMajorVersion > 4) ||
|
||||||
((osver.dwMajorVersion == 4) && (osver.dwMinorVersion > 0)))
|
((osver.dwMajorVersion == 4) && (osver.dwMinorVersion > 0)))
|
||||||
{
|
{
|
||||||
if (osver.dwMinorVersion >= 90)
|
if (osver.dwMinorVersion >= 90)
|
||||||
strcpy (uts->sysname, "Windows ME"); /* ME */
|
strcpy (uts->sysname, "Windows ME"); /* ME */
|
||||||
else
|
else
|
||||||
strcpy (uts->sysname, "Windows 98"); /* 98 */
|
strcpy (uts->sysname, "Windows 98"); /* 98 */
|
||||||
os = Win98;
|
os = Win98;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
strcpy (uts->sysname, "Windows 95"); /* 95 */
|
strcpy (uts->sysname, "Windows 95"); /* 95 */
|
||||||
os = Win95;
|
os = Win95;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VER_PLATFORM_WIN32s: /* Windows 3.x */
|
case VER_PLATFORM_WIN32s: /* Windows 3.x */
|
||||||
strcpy (uts->sysname, "Windows");
|
strcpy (uts->sysname, "Windows");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf (uts->version, "%ld.%02ld",
|
sprintf (uts->version, "%ld.%02ld",
|
||||||
osver.dwMajorVersion, osver.dwMinorVersion);
|
osver.dwMajorVersion, osver.dwMinorVersion);
|
||||||
|
|
||||||
if (osver.szCSDVersion[0] != '\0' &&
|
if (osver.szCSDVersion[0] != '\0' &&
|
||||||
(strlen (osver.szCSDVersion) + strlen (uts->version) + 1) <
|
(strlen (osver.szCSDVersion) + strlen (uts->version) + 1) <
|
||||||
|
@ -140,28 +147,28 @@ uname (struct utsname *uts)
|
||||||
* wProcessorLevel is only valid in WinNT
|
* wProcessorLevel is only valid in WinNT
|
||||||
*/
|
*/
|
||||||
switch (os)
|
switch (os)
|
||||||
{
|
{
|
||||||
case Win95:
|
case Win95:
|
||||||
case Win98:
|
case Win98:
|
||||||
switch (sysinfo.dwProcessorType)
|
switch (sysinfo.dwProcessorType)
|
||||||
{
|
{
|
||||||
case PROCESSOR_INTEL_386:
|
case PROCESSOR_INTEL_386:
|
||||||
case PROCESSOR_INTEL_486:
|
case PROCESSOR_INTEL_486:
|
||||||
case PROCESSOR_INTEL_PENTIUM:
|
case PROCESSOR_INTEL_PENTIUM:
|
||||||
sprintf (uts->machine, "i%ld", sysinfo.dwProcessorType);
|
sprintf (uts->machine, "i%ld", sysinfo.dwProcessorType);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
strcpy (uts->machine, "i386");
|
strcpy (uts->machine, "i386");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WinNT:
|
case WinNT:
|
||||||
sprintf (uts->machine, "i%d86", sysinfo.wProcessorLevel);
|
sprintf (uts->machine, "i%d86", sysinfo.wProcessorLevel);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
strcpy (uts->machine, "unknown");
|
strcpy (uts->machine, "unknown");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PROCESSOR_ARCHITECTURE_AMD64:
|
case PROCESSOR_ARCHITECTURE_AMD64:
|
||||||
strcpy (uts->machine, "x86_64");
|
strcpy (uts->machine, "x86_64");
|
||||||
|
@ -169,42 +176,43 @@ uname (struct utsname *uts)
|
||||||
default:
|
default:
|
||||||
strcpy (uts->machine, "unknown");
|
strcpy (uts->machine, "unknown");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
sLength = sizeof (uts->nodename) - 1;
|
sLength = sizeof (uts->nodename) - 1;
|
||||||
GetComputerName (uts->nodename, &sLength);
|
GetComputerName (uts->nodename, &sLength);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Translate abnormal exit status of Windows programs into the signal
|
/* Translate abnormal exit status of Windows programs into the signal
|
||||||
that terminated the program. This is required to support scm_kill
|
that terminated the program. This is required to support scm_kill
|
||||||
and WTERMSIG. */
|
and WTERMSIG. */
|
||||||
|
|
||||||
struct signal_and_status {
|
struct signal_and_status
|
||||||
|
{
|
||||||
int sig;
|
int sig;
|
||||||
DWORD status;
|
DWORD status;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct signal_and_status sigtbl[] = {
|
static const struct signal_and_status sigtbl[] = {
|
||||||
{SIGSEGV, 0xC0000005}, /* access to invalid address */
|
{SIGSEGV, 0xC0000005}, /* access to invalid address */
|
||||||
{SIGSEGV, 0xC0000008}, /* invalid handle */
|
{SIGSEGV, 0xC0000008}, /* invalid handle */
|
||||||
{SIGILL, 0xC000001D}, /* illegal instruction */
|
{SIGILL, 0xC000001D}, /* illegal instruction */
|
||||||
{SIGILL, 0xC0000025}, /* non-continuable instruction */
|
{SIGILL, 0xC0000025}, /* non-continuable instruction */
|
||||||
{SIGSEGV, 0xC000008C}, /* array bounds exceeded */
|
{SIGSEGV, 0xC000008C}, /* array bounds exceeded */
|
||||||
{SIGFPE, 0xC000008D}, /* float denormal */
|
{SIGFPE, 0xC000008D}, /* float denormal */
|
||||||
{SIGFPE, 0xC000008E}, /* float divide by zero */
|
{SIGFPE, 0xC000008E}, /* float divide by zero */
|
||||||
{SIGFPE, 0xC000008F}, /* float inexact */
|
{SIGFPE, 0xC000008F}, /* float inexact */
|
||||||
{SIGFPE, 0xC0000090}, /* float invalid operation */
|
{SIGFPE, 0xC0000090}, /* float invalid operation */
|
||||||
{SIGFPE, 0xC0000091}, /* float overflow */
|
{SIGFPE, 0xC0000091}, /* float overflow */
|
||||||
{SIGFPE, 0xC0000092}, /* float stack check */
|
{SIGFPE, 0xC0000092}, /* float stack check */
|
||||||
{SIGFPE, 0xC0000093}, /* float underflow */
|
{SIGFPE, 0xC0000093}, /* float underflow */
|
||||||
{SIGFPE, 0xC0000094}, /* integer divide by zero */
|
{SIGFPE, 0xC0000094}, /* integer divide by zero */
|
||||||
{SIGFPE, 0xC0000095}, /* integer overflow */
|
{SIGFPE, 0xC0000095}, /* integer overflow */
|
||||||
{SIGILL, 0xC0000096}, /* privileged instruction */
|
{SIGILL, 0xC0000096}, /* privileged instruction */
|
||||||
{SIGSEGV, 0xC00000FD}, /* stack overflow */
|
{SIGSEGV, 0xC00000FD}, /* stack overflow */
|
||||||
{SIGTERM, 0xC000013A}, /* Ctrl-C exit */
|
{SIGTERM, 0xC000013A}, /* Ctrl-C exit */
|
||||||
{SIGINT, 0xC000013A}
|
{SIGINT, 0xC000013A}
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -216,7 +224,7 @@ w32_signal_to_status (int sig)
|
||||||
if (sig == sigtbl[i].sig)
|
if (sig == sigtbl[i].sig)
|
||||||
return sigtbl[i].status;
|
return sigtbl[i].status;
|
||||||
|
|
||||||
return (int)0xC000013A;
|
return (int) 0xC000013A;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -320,17 +328,17 @@ console_has_return_keyevent_w32 (int fdes)
|
||||||
{
|
{
|
||||||
bRet = PeekConsoleInput (h, irbuffer, NBUFFER, &avail);
|
bRet = PeekConsoleInput (h, irbuffer, NBUFFER, &avail);
|
||||||
if (!bRet || avail == 0)
|
if (!bRet || avail == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
for (i = 0; i < avail; i++)
|
for (i = 0; i < avail; i++)
|
||||||
if (irbuffer[i].EventType == KEY_EVENT)
|
if (irbuffer[i].EventType == KEY_EVENT)
|
||||||
{
|
{
|
||||||
n_chars ++;
|
n_chars++;
|
||||||
if (irbuffer[i].Event.KeyEvent.uChar.AsciiChar == 13)
|
if (irbuffer[i].Event.KeyEvent.uChar.AsciiChar == 13)
|
||||||
n_returns ++;
|
n_returns++;
|
||||||
}
|
}
|
||||||
if (avail < NBUFFER)
|
if (avail < NBUFFER)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n_chars == 1 && n_returns == 1)
|
if (n_chars == 1 && n_returns == 1)
|
||||||
|
@ -382,3 +390,86 @@ canonicalize_file_name_mingw (const char *name)
|
||||||
slashify_file_name (canon);
|
slashify_file_name (canon);
|
||||||
return canon;
|
return canon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate a random string of specified length using character set safe
|
||||||
|
// for filenames
|
||||||
|
static void
|
||||||
|
generate_random_string (char *str, size_t len)
|
||||||
|
{
|
||||||
|
const char charset[] = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
const size_t charset_size = sizeof (charset) - 1;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
unsigned int r;
|
||||||
|
if (rand_s (&r) != 0)
|
||||||
|
{
|
||||||
|
// Handle rand_s failure (rare, but possible)
|
||||||
|
str[i] = charset[0]; // Fallback to first character
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
str[i] = charset[r % charset_size];
|
||||||
|
}
|
||||||
|
str[len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
mkdtemp (char *template)
|
||||||
|
{
|
||||||
|
const int MAX_TRIES = 20;
|
||||||
|
|
||||||
|
if (template == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if template ends with "XXXXXX"
|
||||||
|
size_t len = strlen (template);
|
||||||
|
if (len < 6 || strcmp (template + len - 6, "XXXXXX") != 0)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *working_template = _strdup (template);
|
||||||
|
if (working_template == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locate the position of "XXXXXX" in the working copy
|
||||||
|
char *pattern_pos = working_template + len - 6;
|
||||||
|
|
||||||
|
// Try up to MAX_TRIES times to create a unique directory
|
||||||
|
for (int try = 0; try < MAX_TRIES; try++)
|
||||||
|
{
|
||||||
|
// Replace "XXXXXX" with a random 6-character string
|
||||||
|
generate_random_string (pattern_pos, 6);
|
||||||
|
|
||||||
|
if (CreateDirectoryA (working_template, NULL))
|
||||||
|
{
|
||||||
|
// Success: copy the modified name back to the original template
|
||||||
|
strcpy (template, working_template);
|
||||||
|
free (working_template);
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DWORD error = GetLastError ();
|
||||||
|
if (error == ERROR_ALREADY_EXISTS)
|
||||||
|
{
|
||||||
|
// Name is taken, try again with a new random string
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Other error (e.g., invalid path, permission denied), give up
|
||||||
|
free (working_template);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Failed to find a unique name after MAX_TRIES
|
||||||
|
free (working_template);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
|
@ -76,9 +76,11 @@ SCM_INTERNAL int dlclose_w32 (void *handle);
|
||||||
SCM_INTERNAL char *dlerror_w32 (void);
|
SCM_INTERNAL char *dlerror_w32 (void);
|
||||||
SCM_INTERNAL int console_has_return_keyevent_w32 (int fdes);
|
SCM_INTERNAL int console_has_return_keyevent_w32 (int fdes);
|
||||||
SCM_INTERNAL int getpagesize_w32 (void);
|
SCM_INTERNAL int getpagesize_w32 (void);
|
||||||
|
SCM_INTERNAL char* mkdtemp (char* template);
|
||||||
|
|
||||||
#define HAVE_UNAME 1
|
#define HAVE_UNAME 1
|
||||||
#define HAVE_WAITPID 1
|
#define HAVE_WAITPID 1
|
||||||
|
#define HAVE_MKDTEMP 1
|
||||||
|
|
||||||
#define RTLD_NOW 1
|
#define RTLD_NOW 1
|
||||||
#define RTLD_LAZY 2
|
#define RTLD_LAZY 2
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue