mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-01 10:12:27 +00:00
Make improvements
- You can now run `make -j8 toolchain` on Windows - You can now run `make -j` on MacOS ARM64 and BSD OSes - You can now use our Emacs dev environment on MacOS/Windows - Fix bug where the x16 register was being corrupted by --ftrace - The programs under build/bootstrap/ are updated as fat binaries - The Makefile now explains how to download cosmocc-0.0.12 toolchain - The build scripts under bin/ now support "cosmo" branded toolchains - stat() now goes faster on Windows (shaves 100ms off `make` latency) - Code cleanup and added review on the Windows signal checking code - posix_spawnattr_setrlimit() now works around MacOS ARM64 bugs - Landlock Make now favors posix_spawn() on non-Linux/OpenBSD - posix_spawn() now has better --strace logging on Windows - fstatat() can now avoid EACCES in more cases on Windows - fchmod() can now change the readonly bit on Windows
This commit is contained in:
parent
06c6baaf50
commit
c9fecf3a55
109 changed files with 1188 additions and 454 deletions
217
third_party/make/findprog-in.c
vendored
217
third_party/make/findprog-in.c
vendored
|
@ -20,6 +20,9 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "third_party/make/filename.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
#include "third_party/make/config.h"
|
||||
|
||||
/* Specification. */
|
||||
|
@ -58,8 +61,8 @@ static const char * const suffixes[] =
|
|||
/* Note: The cmd.exe program does a different lookup: It searches according
|
||||
to the PATHEXT environment variable.
|
||||
See <https://stackoverflow.com/questions/7839150/>.
|
||||
Also, it executes files ending .bat and .cmd directly without letting the
|
||||
kernel interpret the program file. */
|
||||
Also, it executes files ending in .bat and .cmd directly without letting
|
||||
the kernel interpret the program file. */
|
||||
#elif defined __CYGWIN__
|
||||
"", ".exe", ".com"
|
||||
#elif defined __EMX__
|
||||
|
@ -73,7 +76,7 @@ static const char * const suffixes[] =
|
|||
|
||||
const char *
|
||||
find_in_given_path (const char *progname, const char *path,
|
||||
bool optimize_for_exec)
|
||||
const char *directory, bool optimize_for_exec)
|
||||
{
|
||||
{
|
||||
bool has_slash = false;
|
||||
|
@ -101,6 +104,12 @@ find_in_given_path (const char *progname, const char *path,
|
|||
with such a suffix is actually executable. */
|
||||
int failure_errno;
|
||||
size_t i;
|
||||
|
||||
const char *directory_as_prefix =
|
||||
(directory != NULL && IS_RELATIVE_FILE_NAME (progname)
|
||||
? directory
|
||||
: "");
|
||||
|
||||
#if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */
|
||||
const char *progbasename;
|
||||
|
||||
|
@ -112,6 +121,8 @@ find_in_given_path (const char *progname, const char *path,
|
|||
if (ISSLASH (*p))
|
||||
progbasename = p + 1;
|
||||
}
|
||||
|
||||
bool progbasename_has_dot = (strchr (progbasename, '.') != NULL);
|
||||
#endif
|
||||
|
||||
/* Try all platform-dependent suffixes. */
|
||||
|
@ -123,12 +134,16 @@ find_in_given_path (const char *progname, const char *path,
|
|||
#if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */
|
||||
/* File names without a '.' are not considered executable, and
|
||||
for file names with a '.' no additional suffix is tried. */
|
||||
if ((*suffix != '\0') != (strchr (progbasename, '.') != NULL))
|
||||
if ((*suffix != '\0') != progbasename_has_dot)
|
||||
#endif
|
||||
{
|
||||
/* Concatenate progname and suffix. */
|
||||
/* Concatenate directory_as_prefix, progname, suffix. */
|
||||
char *progpathname =
|
||||
xconcatenated_filename ("", progname, suffix);
|
||||
concatenated_filename (directory_as_prefix, progname,
|
||||
suffix);
|
||||
|
||||
if (progpathname == NULL)
|
||||
return NULL; /* errno is set here */
|
||||
|
||||
/* On systems which have the eaccess() system call, let's
|
||||
use it. On other systems, let's hope that this program
|
||||
|
@ -136,14 +151,26 @@ find_in_given_path (const char *progname, const char *path,
|
|||
call access() despite its design flaw. */
|
||||
if (eaccess (progpathname, X_OK) == 0)
|
||||
{
|
||||
/* Found! */
|
||||
if (strcmp (progpathname, progname) == 0)
|
||||
/* Check that the progpathname does not point to a
|
||||
directory. */
|
||||
struct stat statbuf;
|
||||
|
||||
if (stat (progpathname, &statbuf) >= 0)
|
||||
{
|
||||
free (progpathname);
|
||||
return progname;
|
||||
if (! S_ISDIR (statbuf.st_mode))
|
||||
{
|
||||
/* Found! */
|
||||
if (strcmp (progpathname, progname) == 0)
|
||||
{
|
||||
free (progpathname);
|
||||
return progname;
|
||||
}
|
||||
else
|
||||
return progpathname;
|
||||
}
|
||||
|
||||
errno = EACCES;
|
||||
}
|
||||
else
|
||||
return progpathname;
|
||||
}
|
||||
|
||||
if (errno != ENOENT)
|
||||
|
@ -152,6 +179,36 @@ find_in_given_path (const char *progname, const char *path,
|
|||
free (progpathname);
|
||||
}
|
||||
}
|
||||
#if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */
|
||||
if (failure_errno == ENOENT && !progbasename_has_dot)
|
||||
{
|
||||
/* In the loop above, we skipped suffix = "". Do this loop
|
||||
round now, merely to provide a better errno than ENOENT. */
|
||||
|
||||
char *progpathname =
|
||||
concatenated_filename (directory_as_prefix, progname, "");
|
||||
|
||||
if (progpathname == NULL)
|
||||
return NULL; /* errno is set here */
|
||||
|
||||
if (eaccess (progpathname, X_OK) == 0)
|
||||
{
|
||||
struct stat statbuf;
|
||||
|
||||
if (stat (progpathname, &statbuf) >= 0)
|
||||
{
|
||||
if (! S_ISDIR (statbuf.st_mode))
|
||||
errno = ENOEXEC;
|
||||
else
|
||||
errno = EACCES;
|
||||
}
|
||||
}
|
||||
|
||||
failure_errno = errno;
|
||||
|
||||
free (progpathname);
|
||||
}
|
||||
#endif
|
||||
|
||||
errno = failure_errno;
|
||||
return NULL;
|
||||
|
@ -165,17 +222,26 @@ find_in_given_path (const char *progname, const char *path,
|
|||
path = "";
|
||||
|
||||
{
|
||||
int failure_errno;
|
||||
/* Make a copy, to prepare for destructive modifications. */
|
||||
char *path_copy = xstrdup (path);
|
||||
char *path_copy = strdup (path);
|
||||
if (path_copy == NULL)
|
||||
return NULL; /* errno is set here */
|
||||
|
||||
int failure_errno;
|
||||
char *path_rest;
|
||||
char *cp;
|
||||
|
||||
#if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */
|
||||
bool progname_has_dot = (strchr (progname, '.') != NULL);
|
||||
#endif
|
||||
|
||||
failure_errno = ENOENT;
|
||||
for (path_rest = path_copy; ; path_rest = cp + 1)
|
||||
{
|
||||
const char *dir;
|
||||
bool last;
|
||||
char *dir_as_prefix_to_free;
|
||||
const char *dir_as_prefix;
|
||||
size_t i;
|
||||
|
||||
/* Extract next directory in PATH. */
|
||||
|
@ -189,6 +255,25 @@ find_in_given_path (const char *progname, const char *path,
|
|||
if (dir == cp)
|
||||
dir = ".";
|
||||
|
||||
/* Concatenate directory and dir. */
|
||||
if (directory != NULL && IS_RELATIVE_FILE_NAME (dir))
|
||||
{
|
||||
dir_as_prefix_to_free =
|
||||
concatenated_filename (directory, dir, NULL);
|
||||
if (dir_as_prefix_to_free == NULL)
|
||||
{
|
||||
/* errno is set here. */
|
||||
failure_errno = errno;
|
||||
goto failed;
|
||||
}
|
||||
dir_as_prefix = dir_as_prefix_to_free;
|
||||
}
|
||||
else
|
||||
{
|
||||
dir_as_prefix_to_free = NULL;
|
||||
dir_as_prefix = dir;
|
||||
}
|
||||
|
||||
/* Try all platform-dependent suffixes. */
|
||||
for (i = 0; i < sizeof (suffixes) / sizeof (suffixes[0]); i++)
|
||||
{
|
||||
|
@ -197,12 +282,20 @@ find_in_given_path (const char *progname, const char *path,
|
|||
#if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */
|
||||
/* File names without a '.' are not considered executable, and
|
||||
for file names with a '.' no additional suffix is tried. */
|
||||
if ((*suffix != '\0') != (strchr (progname, '.') != NULL))
|
||||
if ((*suffix != '\0') != progname_has_dot)
|
||||
#endif
|
||||
{
|
||||
/* Concatenate dir, progname, and suffix. */
|
||||
/* Concatenate dir_as_prefix, progname, and suffix. */
|
||||
char *progpathname =
|
||||
xconcatenated_filename (dir, progname, suffix);
|
||||
concatenated_filename (dir_as_prefix, progname, suffix);
|
||||
|
||||
if (progpathname == NULL)
|
||||
{
|
||||
/* errno is set here. */
|
||||
failure_errno = errno;
|
||||
free (dir_as_prefix_to_free);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* On systems which have the eaccess() system call, let's
|
||||
use it. On other systems, let's hope that this program
|
||||
|
@ -210,25 +303,45 @@ find_in_given_path (const char *progname, const char *path,
|
|||
call access() despite its design flaw. */
|
||||
if (eaccess (progpathname, X_OK) == 0)
|
||||
{
|
||||
/* Found! */
|
||||
if (strcmp (progpathname, progname) == 0)
|
||||
/* Check that the progpathname does not point to a
|
||||
directory. */
|
||||
struct stat statbuf;
|
||||
|
||||
if (stat (progpathname, &statbuf) >= 0)
|
||||
{
|
||||
free (progpathname);
|
||||
if (! S_ISDIR (statbuf.st_mode))
|
||||
{
|
||||
/* Found! */
|
||||
if (strcmp (progpathname, progname) == 0)
|
||||
{
|
||||
free (progpathname);
|
||||
|
||||
/* Add the "./" prefix for real, that
|
||||
xconcatenated_filename() optimized away. This
|
||||
avoids a second PATH search when the caller uses
|
||||
execl/execv/execlp/execvp. */
|
||||
progpathname =
|
||||
XNMALLOC (2 + strlen (progname) + 1, char);
|
||||
progpathname[0] = '.';
|
||||
progpathname[1] = NATIVE_SLASH;
|
||||
memcpy (progpathname + 2, progname,
|
||||
strlen (progname) + 1);
|
||||
/* Add the "./" prefix for real, that
|
||||
concatenated_filename() optimized away.
|
||||
This avoids a second PATH search when the
|
||||
caller uses execl/execv/execlp/execvp. */
|
||||
progpathname =
|
||||
(char *) malloc (2 + strlen (progname) + 1);
|
||||
if (progpathname == NULL)
|
||||
{
|
||||
/* errno is set here. */
|
||||
failure_errno = errno;
|
||||
free (dir_as_prefix_to_free);
|
||||
goto failed;
|
||||
}
|
||||
progpathname[0] = '.';
|
||||
progpathname[1] = NATIVE_SLASH;
|
||||
memcpy (progpathname + 2, progname,
|
||||
strlen (progname) + 1);
|
||||
}
|
||||
|
||||
free (dir_as_prefix_to_free);
|
||||
free (path_copy);
|
||||
return progpathname;
|
||||
}
|
||||
|
||||
errno = EACCES;
|
||||
}
|
||||
|
||||
free (path_copy);
|
||||
return progpathname;
|
||||
}
|
||||
|
||||
if (errno != ENOENT)
|
||||
|
@ -237,11 +350,49 @@ find_in_given_path (const char *progname, const char *path,
|
|||
free (progpathname);
|
||||
}
|
||||
}
|
||||
#if defined _WIN32 && !defined __CYGWIN__ /* Native Windows */
|
||||
if (failure_errno == ENOENT && !progname_has_dot)
|
||||
{
|
||||
/* In the loop above, we skipped suffix = "". Do this loop
|
||||
round now, merely to provide a better errno than ENOENT. */
|
||||
|
||||
char *progpathname =
|
||||
concatenated_filename (dir_as_prefix, progname, "");
|
||||
|
||||
if (progpathname == NULL)
|
||||
{
|
||||
/* errno is set here. */
|
||||
failure_errno = errno;
|
||||
free (dir_as_prefix_to_free);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (eaccess (progpathname, X_OK) == 0)
|
||||
{
|
||||
struct stat statbuf;
|
||||
|
||||
if (stat (progpathname, &statbuf) >= 0)
|
||||
{
|
||||
if (! S_ISDIR (statbuf.st_mode))
|
||||
errno = ENOEXEC;
|
||||
else
|
||||
errno = EACCES;
|
||||
}
|
||||
}
|
||||
|
||||
failure_errno = errno;
|
||||
|
||||
free (progpathname);
|
||||
}
|
||||
#endif
|
||||
|
||||
free (dir_as_prefix_to_free);
|
||||
|
||||
if (last)
|
||||
break;
|
||||
}
|
||||
|
||||
failed:
|
||||
/* Not found in PATH. */
|
||||
free (path_copy);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue