mirror of
https://github.com/mirror/make.git
synced 2025-02-25 03:10:31 +08:00
Fix tmpfile on MS-Windows.
w32/compat/posixfcn.c (tmpfile): New function, a replacement for the Windows libc version.
This commit is contained in:
parent
f8786092ad
commit
98197303b1
@ -1,5 +1,8 @@
|
|||||||
2013-10-02 Eli Zaretskii <eliz@gnu.org>
|
2013-10-02 Eli Zaretskii <eliz@gnu.org>
|
||||||
|
|
||||||
|
* w32/compat/posixfcn.c (tmpfile): New function, a replacement for
|
||||||
|
the Windows libc version.
|
||||||
|
|
||||||
Fix $abspath on Cygwin when HAVE_DOS_PATHS is in effect.
|
Fix $abspath on Cygwin when HAVE_DOS_PATHS is in effect.
|
||||||
* function.c (IS_ABSOLUTE) [__CYGWIN__]: Special definition for
|
* function.c (IS_ABSOLUTE) [__CYGWIN__]: Special definition for
|
||||||
Cygwin.
|
Cygwin.
|
||||||
|
@ -257,6 +257,106 @@ same_stream (FILE *f1, FILE *f2)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* A replacement for tmpfile, since the MSVCRT implementation creates
|
||||||
|
the file in the root directory of the current drive, which might
|
||||||
|
not be writable by our user. Most of the code borrowed from
|
||||||
|
create_batch_file, see job.c. */
|
||||||
|
FILE *
|
||||||
|
tmpfile (void)
|
||||||
|
{
|
||||||
|
char temp_path[MAXPATHLEN];
|
||||||
|
unsigned path_size = GetTempPath (sizeof temp_path, temp_path);
|
||||||
|
int path_is_dot = 0;
|
||||||
|
/* The following variable is static so we won't try to reuse a name
|
||||||
|
that was generated a little while ago, because that file might
|
||||||
|
not be on disk yet, since we use FILE_ATTRIBUTE_TEMPORARY below,
|
||||||
|
which tells the OS it doesn't need to flush the cache to disk.
|
||||||
|
If the file is not yet on disk, we might think the name is
|
||||||
|
available, while it really isn't. This happens in parallel
|
||||||
|
builds, where Make doesn't wait for one job to finish before it
|
||||||
|
launches the next one. */
|
||||||
|
static unsigned uniq = 0;
|
||||||
|
static int second_loop = 0;
|
||||||
|
const char base[] = "gmake_tmpf";
|
||||||
|
const unsigned sizemax = sizeof base - 1 + 4 + 10 + 10;
|
||||||
|
unsigned pid = GetCurrentProcessId ();
|
||||||
|
|
||||||
|
if (path_size == 0)
|
||||||
|
{
|
||||||
|
path_size = GetCurrentDirectory (sizeof temp_path, temp_path);
|
||||||
|
path_is_dot = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
++uniq;
|
||||||
|
if (uniq >= 0x10000 && !second_loop)
|
||||||
|
{
|
||||||
|
/* If we already had 64K batch files in this
|
||||||
|
process, make a second loop through the numbers,
|
||||||
|
looking for free slots, i.e. files that were
|
||||||
|
deleted in the meantime. */
|
||||||
|
second_loop = 1;
|
||||||
|
uniq = 1;
|
||||||
|
}
|
||||||
|
while (path_size > 0 &&
|
||||||
|
path_size + sizemax < sizeof temp_path &&
|
||||||
|
!(uniq >= 0x10000 && second_loop))
|
||||||
|
{
|
||||||
|
sprintf (temp_path + path_size,
|
||||||
|
"%s%s%u-%x.tmp",
|
||||||
|
temp_path[path_size - 1] == '\\' ? "" : "\\",
|
||||||
|
base, pid, uniq);
|
||||||
|
HANDLE h = CreateFile (temp_path, /* file name */
|
||||||
|
GENERIC_READ | GENERIC_WRITE | DELETE, /* desired access */
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE, /* share mode */
|
||||||
|
NULL, /* default security attributes */
|
||||||
|
CREATE_NEW, /* creation disposition */
|
||||||
|
FILE_ATTRIBUTE_NORMAL | /* flags and attributes */
|
||||||
|
FILE_ATTRIBUTE_TEMPORARY |
|
||||||
|
FILE_FLAG_DELETE_ON_CLOSE,
|
||||||
|
NULL); /* no template file */
|
||||||
|
|
||||||
|
if (h == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
const DWORD er = GetLastError ();
|
||||||
|
|
||||||
|
if (er == ERROR_FILE_EXISTS || er == ERROR_ALREADY_EXISTS)
|
||||||
|
{
|
||||||
|
++uniq;
|
||||||
|
if (uniq == 0x10000 && !second_loop)
|
||||||
|
{
|
||||||
|
second_loop = 1;
|
||||||
|
uniq = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The temporary path is not guaranteed to exist, or might
|
||||||
|
not be writable by user. Use the current directory as
|
||||||
|
fallback. */
|
||||||
|
else if (path_is_dot == 0)
|
||||||
|
{
|
||||||
|
path_size = GetCurrentDirectory (sizeof temp_path, temp_path);
|
||||||
|
path_is_dot = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errno = EACCES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int fd = _open_osfhandle ((intptr_t)h, 0);
|
||||||
|
|
||||||
|
return _fdopen (fd, "w+b");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uniq >= 0x10000)
|
||||||
|
errno = EEXIST;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* !NO_OUTPUT_SYNC */
|
#endif /* !NO_OUTPUT_SYNC */
|
||||||
|
|
||||||
#if MAKE_LOAD
|
#if MAKE_LOAD
|
||||||
|
Loading…
Reference in New Issue
Block a user