mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-12-23 10:34:07 +00:00
cb5af79249
* configure.ac [mingw32]: Don't add -Wpointer-sign, and add -Wno-pointer-sign, to keep the noise level down. * nt/mingw-cfg.site (gl_cv_warn_c__Wredundant_decls): Disable -Wredundant-decls, as that produces a lot of noise due to redeclaration of time-related functions by gnulib. * nt/runemacs.c (set_user_model_id): Fix argument type of 'SetCurrentProcessExplicitAppUserModelID'. * src/image.c (x_create_bitmap_from_file) [HAVE_NTGUI]: Don't declare 'dpyinfo', as it is unused. (xpm_load): Fix warnings about pointer signedness. * src/w32proc.c (IsValidLocale, init_winsock): Remove redundant prototypes. (sys_spawnve): Avoid warnings about discarding 'const' qualifier. (sys_select): Provide prototype. (g_b_init_compare_string_w): Move declaration to file scope. * src/w32heap.c (dumped_data_commit): Now static. (FREEABLE_P): Avoid warnings about pointer comparison with integer. (mmap_realloc): Cast to 'char *' for arithmetics on void pointers. * src/w32console.c (ctrl_c_handler, sys_tputs, sys_tgetstr) (evalcost, cmputc, cmcheckmagic, cmcostinit, cmgoto, Wcm_clear): Provide prototypes. * src/w32.c (globals_of_w32, conv_sockaddr_to_lisp): Remove redundant prototypes. (w32_get_internal_run_time, map_w32_filename): Provide prototype. (init_environment, sys_ctime): Avoid warnings about discarding 'const' qualifier. Include utimens.h. (sys_ctime, sys_chdir, sys_creat, sys_fopen, sys_mkdir) (sys_open, sys_rename, sys_rmdir, is_slow_fs, term_winsock) (sys_close, sys_dup2, sys_read, sys_write, sys_localtime): Provide prototypes. (sys_rename_replace): Use %d to avoid compiler warnings. (_wsa_errlist): Make the message text 'const char *', to avoid compilation warnings. (dynlib_reset_last_error): Move prototype to file scope. (w32_get_resource): First argument is now 'const char *'. * src/w32uniscribe.c (syms_of_w32uniscribe): Provide prototype. (otf_features): Second argument is no 'const char *'. * src/w32term.c (free_frame_menubar, x_wm_set_size_hint) (x_set_window_size): Remove redundant prototypes. (XChangeGC, XGetGCValues, w32_draw_underwave) (w32_draw_rectangle, w32_shift_glyphs_for_insert, x_mouse_leave) (x_calc_absolute_position, x_destroy_window): Now static. (menubar_selection_callback): Move prototype to file scope. * src/w32font.c (g_b_init_get_glyph_outline_w): Remove redundant declaration. (w32_to_x_charset): Fix warnings about discarding 'const' qualifier. (w32font_full_name): Fix warnings about implicit conversion of 'float' to 'double'. * src/w32reg.c (w32_get_rdb_resource): Fix warnings about discarding 'const' qualifier. * src/w32menu.c (syms_of_w32menu, globals_of_w32menu) (set_frame_menubar): Remove redundant prototypes. (menubar_selection_callback, w32_menu_display_help): Provide prototypes. (simple_dialog_show): Avoid warnings about discarding 'const' qualifier. * src/w32fns.c (syms_of_w32fns, globals_of_w32fns) (free_frame_menubar, w32_strerror, x_set_menu_bar_lines) (x_set_tool_bar_lines, x_set_internal_border_width): Remove redundant prototypes. (current_popup_menu): Remove redundant declaration. (colormap_t): Member 'name' is now 'const char *'. (add_system_logical_colors_to_map): Fix signed/unsigned warnings. (x_decode_color, x_set_border_pixel) (x_clear_under_internal_border, x_set_name, hook_w32_key) (reset_w32_kbdhook_state, deliver_wm_chars, w32_backtrace): Now static. (w32_load_cursor, w32_key_to_modifier, map_keypad_keys) (w32_msg_worker, w32_last_error): Provide prototypes. (funhook, lookup_vk_code): Avoid warnings about missing parentheses. (x_default_font_parameter, Fw32_notification_notify): Avoid warnings about discarding 'const' qualifier. (Fx_create_frame): Avoid warnings about empty body of 'else'. (x_screen_planes): Ifdef away unused function. (Fx_show_tip): Remove unused variables. (Fw32_battery_status): Avoid warnings about implicit promotion from float to double. (Fw32_notification_notify): Initialize 'timeout'. * src/profiler.c (profiler_cpu_running) [HAVE_ITIMERSPEC]: Only define the TIMER_SETTIME_RUNNING value if it will be used. * src/w32notify.c (send_notifications): Ifdef away an empty if clause. Remove unused variable. (watch_end, watch_completion): Provide prototypes. * src/sound.c (sound_warning) [WINDOWSNT]: Don't define: unused. * src/callproc.c (child_setup, getenv_internal_1) [WINDOWSNT]: Fix warning with pointer signedness. * src/gnutls.c (gnutls_x509_crt_get_signature) (gnutls_alert_send_appropriate) [WINDOWSNT]: Don't define, and don't load them from the GnuTLS library, as they are no longer used. * src/process.c (DATAGRAM_CHAN_P) [!DATAGRAM_SOCKETS]: Don't define, as it's unused. * src/unexw32.c (open_input_file, open_output_file) (close_file_data): Remove redundant prototypes. (_start): provide prototype. (mainCRTStartup): Move prototype to file level. (find_section): Use type-cast to shut up compiler warnings. (offset_to_section, relocate_offset): Now static. (find_section): First argument is now a 'const char *'. (offset_to_section): Ifdef away, as it's unused. * src/w32heap.h (find_section): Adjust prototype. * src/dynlib.c (dynlib_reset_last_error): Provide prototype. * src/dired.c (directory_files_internal_w32_unwind): Avoid warnings about missing prototypes. (is_slow_fs) [WINDOWSNT]: Provide prototype at file level. (directory_files_internal) [WINDOWSNT]: Fix warnings about pointer signedness. * src/fileio.c (Ffile_writable_p, Ffile_regular_p) [WINDOWSNT]: Fix warnings about pointer signedness. * src/filelock.c (WTMP_FILE) [WINDOWSNT]: Don't define, it's unused. * src/sysdep.c (_getpid): Remove redundant prototype. (sys_subshell) [DOS_NT]: Don't define 'status', it's unused. [!MSDOS]: Don't define 'st', it's unused. (init_sys_modes) [DOS_NT]: Don't define 'terminal', it's unused. (str_collate) [WINDOWSNT]: Avoid warnings about pointer signedness. * src/keyboard.c (tty_read_avail_input) [WINDOWSNT]: Don't define n_to_read, as it is not used. (MAX_ENCODED_BYTES) [WINDOWSNT]: Don't define, as it's unused. * src/w32font.h (syms_of_w32font): Remove redundant prototype. * src/xfaces.c (x_display_info) [HAVE_NTGUI]: Remove unused macro. * src/term.c (init_tty) [DOS_NT]: Ifdef away variables that are not used by DOS_NT builds, to avoid compiler warnings. * src/menu.c (current_popup_menu) [HAVE_NTGUI]: Remove redundant declaration. * src/dispnew.c (init_display) [WINDOWSNT]: Use type-cast to shut up compiler warnings. * src/w32term.h (x_set_window_size, x_get_focus_frame) (x_make_frame_visible, x_make_frame_invisible, x_iconify_frame) (x_set_frame_alpha, x_activate_menubar, x_bitmap_icon) (x_free_frame_resources, x_real_positions) (display_x_get_resource): Remove redundant prototypes. * lib-src/ntlib.c (sys_ctime, sys_fopen, sys_chdir, mkostemp) (sys_rename, gettimeofday): Provide prototypes. * lib-src/ntlib.h (getuid, geteuid, mkostemp): Remove redundant declarations. * lib-src/emacsclient.c (w32_getenv): Argument is now 'const char *'. (xstrdup, w32_get_resource, w32_window_app, w32_execvp, ttyname) (close_winsock, initialize_sockets, w32_set_user_model_id) (w32_find_emacs_process, w32_give_focus) [WINDOWSNT]: Add prototypes. (w32_get_resource) [WINDOWSNT]: Fix a warning about signedness difference. (w32_set_user_model_id): Update prototype of SetCurrentProcessExplicitAppUserModelID to avoid compiler warnings. (start_daemon_and_retry_set_socket) [WINDOWSNT]: Use type-cast to shut up compiler warnings. * lib-src/etags.c (MAXPATHLEN) [WINDOWSNT]: Remove unused macro.
502 lines
11 KiB
C
502 lines
11 KiB
C
/* Utility and Unix shadow routines for GNU Emacs support programs on NT.
|
|
|
|
Copyright (C) 1994, 2001-2016 Free Software Foundation, Inc.
|
|
|
|
Author: Geoff Voelker (voelker@cs.washington.edu)
|
|
Created: 10-8-94
|
|
|
|
This file is part of GNU Emacs.
|
|
|
|
GNU Emacs is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or (at
|
|
your option) any later version.
|
|
|
|
GNU Emacs is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
#include <windows.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <time.h>
|
|
#include <direct.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <errno.h>
|
|
#include <ctype.h>
|
|
#include <sys/timeb.h>
|
|
#include <mbstring.h>
|
|
|
|
#include "ntlib.h"
|
|
|
|
char *sys_ctime (const time_t *);
|
|
FILE *sys_fopen (const char *, const char *);
|
|
int sys_chdir (const char *);
|
|
int mkostemp (char *, int);
|
|
int sys_rename (const char *, const char *);
|
|
|
|
/* MinGW64 defines _TIMEZONE_DEFINED and defines 'struct timespec' in
|
|
its system headers. */
|
|
#ifndef _TIMEZONE_DEFINED
|
|
struct timezone
|
|
{
|
|
int tz_minuteswest; /* minutes west of Greenwich */
|
|
int tz_dsttime; /* type of dst correction */
|
|
};
|
|
#endif
|
|
|
|
void gettimeofday (struct timeval *, struct timezone *);
|
|
|
|
#define MAXPATHLEN _MAX_PATH
|
|
|
|
/* Emulate sleep...we could have done this with a define, but that
|
|
would necessitate including windows.h in the files that used it.
|
|
This is much easier. */
|
|
unsigned
|
|
sleep (unsigned seconds)
|
|
{
|
|
Sleep (seconds * 1000);
|
|
return 0;
|
|
}
|
|
|
|
/* Get the current working directory. */
|
|
char *
|
|
getwd (char *dir)
|
|
{
|
|
if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
|
|
return dir;
|
|
return NULL;
|
|
}
|
|
|
|
static HANDLE getppid_parent;
|
|
static int getppid_ppid;
|
|
|
|
int
|
|
getppid (void)
|
|
{
|
|
char *ppid;
|
|
DWORD result;
|
|
|
|
ppid = getenv ("EM_PARENT_PROCESS_ID");
|
|
if (!ppid)
|
|
{
|
|
printf ("no pid.\n");
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
getppid_ppid = atoi (ppid);
|
|
}
|
|
|
|
if (!getppid_parent)
|
|
{
|
|
getppid_parent = OpenProcess (SYNCHRONIZE, FALSE, atoi (ppid));
|
|
if (!getppid_parent)
|
|
{
|
|
printf ("Failed to open handle to parent process: %d\n",
|
|
GetLastError ());
|
|
exit (1);
|
|
}
|
|
}
|
|
|
|
result = WaitForSingleObject (getppid_parent, 0);
|
|
switch (result)
|
|
{
|
|
case WAIT_TIMEOUT:
|
|
/* The parent is still alive. */
|
|
return getppid_ppid;
|
|
case WAIT_OBJECT_0:
|
|
/* The parent is gone. Return the pid of Unix init (1). */
|
|
return 1;
|
|
case WAIT_FAILED:
|
|
default:
|
|
printf ("Checking parent status failed: %d\n", GetLastError ());
|
|
exit (1);
|
|
}
|
|
}
|
|
|
|
char *
|
|
getlogin (void)
|
|
{
|
|
static char user_name[256];
|
|
DWORD length = sizeof (user_name);
|
|
|
|
if (GetUserName (user_name, &length))
|
|
return user_name;
|
|
return NULL;
|
|
}
|
|
|
|
char *
|
|
cuserid (char * s)
|
|
{
|
|
char * name = getlogin ();
|
|
if (s)
|
|
return strcpy (s, name ? name : "");
|
|
return name;
|
|
}
|
|
|
|
unsigned
|
|
getuid (void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
unsigned
|
|
geteuid (void)
|
|
{
|
|
return getuid ();
|
|
}
|
|
|
|
unsigned
|
|
getgid (void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
unsigned
|
|
getegid (void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
setuid (unsigned uid)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
setregid (unsigned rgid, unsigned gid)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
struct passwd *
|
|
getpwuid (unsigned uid)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
char *
|
|
getpass (const char * prompt)
|
|
{
|
|
static char input[256];
|
|
HANDLE in;
|
|
HANDLE err;
|
|
DWORD count;
|
|
|
|
in = GetStdHandle (STD_INPUT_HANDLE);
|
|
err = GetStdHandle (STD_ERROR_HANDLE);
|
|
|
|
if (in == INVALID_HANDLE_VALUE || err == INVALID_HANDLE_VALUE)
|
|
return NULL;
|
|
|
|
if (WriteFile (err, prompt, strlen (prompt), &count, NULL))
|
|
{
|
|
int istty = (GetFileType (in) == FILE_TYPE_CHAR);
|
|
DWORD old_flags;
|
|
int rc;
|
|
|
|
if (istty)
|
|
{
|
|
if (GetConsoleMode (in, &old_flags))
|
|
SetConsoleMode (in, ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT);
|
|
else
|
|
istty = 0;
|
|
}
|
|
rc = ReadFile (in, input, sizeof (input), &count, NULL);
|
|
if (count >= 2 && input[count - 2] == '\r')
|
|
input[count - 2] = '\0';
|
|
else
|
|
{
|
|
char buf[256];
|
|
while (ReadFile (in, buf, sizeof (buf), &count, NULL) > 0)
|
|
if (count >= 2 && buf[count - 2] == '\r')
|
|
break;
|
|
}
|
|
WriteFile (err, "\r\n", 2, &count, NULL);
|
|
if (istty)
|
|
SetConsoleMode (in, old_flags);
|
|
if (rc)
|
|
return input;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* This is needed because lib/gettime.c calls gettimeofday, which MSVC
|
|
doesn't have. Copied from w32.c. */
|
|
void
|
|
gettimeofday (struct timeval *tv, struct timezone *tz)
|
|
{
|
|
struct _timeb tb;
|
|
_ftime (&tb);
|
|
|
|
tv->tv_sec = tb.time;
|
|
tv->tv_usec = tb.millitm * 1000L;
|
|
/* Implementation note: _ftime sometimes doesn't update the dstflag
|
|
according to the new timezone when the system timezone is
|
|
changed. We could fix that by using GetSystemTime and
|
|
GetTimeZoneInformation, but that doesn't seem necessary, since
|
|
Emacs always calls gettimeofday with the 2nd argument NULL (see
|
|
current_emacs_time). */
|
|
if (tz)
|
|
{
|
|
tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */
|
|
tz->tz_dsttime = tb.dstflag; /* type of dst correction */
|
|
}
|
|
}
|
|
|
|
int
|
|
fchown (int fd, unsigned uid, unsigned gid)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/* Place a wrapper around the MSVC version of ctime. It returns NULL
|
|
on network directories, so we handle that case here.
|
|
(Ulrich Leodolter, 1/11/95). */
|
|
char *
|
|
sys_ctime (const time_t *t)
|
|
{
|
|
char *str = (char *) ctime (t);
|
|
return (str ? str : "Sun Jan 01 00:00:00 1970");
|
|
}
|
|
|
|
FILE *
|
|
sys_fopen (const char * path, const char * mode)
|
|
{
|
|
return fopen (path, mode);
|
|
}
|
|
|
|
int
|
|
sys_chdir (const char * path)
|
|
{
|
|
return _chdir (path);
|
|
}
|
|
|
|
static FILETIME utc_base_ft;
|
|
static long double utc_base;
|
|
static int init = 0;
|
|
|
|
static time_t
|
|
convert_time (FILETIME ft)
|
|
{
|
|
long double ret;
|
|
|
|
if (CompareFileTime (&ft, &utc_base_ft) < 0)
|
|
return 0;
|
|
|
|
ret = (long double) ft.dwHighDateTime
|
|
* 4096.0L * 1024.0L * 1024.0L + ft.dwLowDateTime;
|
|
ret -= utc_base;
|
|
return (time_t) (ret * 1e-7L);
|
|
}
|
|
|
|
static int
|
|
is_exec (const char * name)
|
|
{
|
|
char * p = strrchr (name, '.');
|
|
return
|
|
(p != NULL
|
|
&& (stricmp (p, ".exe") == 0 ||
|
|
stricmp (p, ".com") == 0 ||
|
|
stricmp (p, ".bat") == 0 ||
|
|
stricmp (p, ".cmd") == 0));
|
|
}
|
|
|
|
/* FIXME? This is in configure.ac now - is this still needed? */
|
|
#define IS_DIRECTORY_SEP(x) ((x) == '/' || (x) == '\\')
|
|
|
|
/* We need this because nt/inc/sys/stat.h defines struct stat that is
|
|
incompatible with the MS run-time libraries. */
|
|
int
|
|
stat (const char * path, struct stat * buf)
|
|
{
|
|
WIN32_FIND_DATA wfd;
|
|
HANDLE fh;
|
|
int permission;
|
|
int len;
|
|
int rootdir = FALSE;
|
|
char *name = alloca (FILENAME_MAX);
|
|
|
|
if (!init)
|
|
{
|
|
/* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
|
|
SYSTEMTIME st;
|
|
|
|
st.wYear = 1970;
|
|
st.wMonth = 1;
|
|
st.wDay = 1;
|
|
st.wHour = 0;
|
|
st.wMinute = 0;
|
|
st.wSecond = 0;
|
|
st.wMilliseconds = 0;
|
|
|
|
SystemTimeToFileTime (&st, &utc_base_ft);
|
|
utc_base = (long double) utc_base_ft.dwHighDateTime
|
|
* 4096.0L * 1024.0L * 1024.0L + utc_base_ft.dwLowDateTime;
|
|
init = 1;
|
|
}
|
|
|
|
if (path == NULL || buf == NULL || *path == '\0')
|
|
{
|
|
errno = EFAULT;
|
|
return -1;
|
|
}
|
|
if (_mbspbrk (path, "*?|<>\""))
|
|
{
|
|
errno = ENOENT;
|
|
return -1;
|
|
}
|
|
|
|
strcpy (name, path);
|
|
/* Remove trailing directory separator, unless name is the root
|
|
directory of a drive in which case ensure there is a trailing
|
|
separator. */
|
|
len = strlen (name);
|
|
rootdir = IS_DIRECTORY_SEP (name[0])
|
|
|| (len == 3 && name[1] == ':' && IS_DIRECTORY_SEP (name[2]));
|
|
if (rootdir)
|
|
{
|
|
if (GetDriveType (name) < 2)
|
|
{
|
|
errno = ENOENT;
|
|
return -1;
|
|
}
|
|
memset (&wfd, 0, sizeof (wfd));
|
|
wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
|
|
wfd.ftCreationTime = utc_base_ft;
|
|
wfd.ftLastAccessTime = utc_base_ft;
|
|
wfd.ftLastWriteTime = utc_base_ft;
|
|
strcpy (wfd.cFileName, name);
|
|
}
|
|
else
|
|
{
|
|
if (IS_DIRECTORY_SEP (name[len-1]))
|
|
name[len - 1] = 0;
|
|
|
|
fh = FindFirstFile (name, &wfd);
|
|
if (fh == INVALID_HANDLE_VALUE)
|
|
{
|
|
errno = ENOENT;
|
|
return -1;
|
|
}
|
|
FindClose (fh);
|
|
}
|
|
buf->st_mode = (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
|
|
S_IFDIR : S_IFREG;
|
|
buf->st_nlink = 1;
|
|
buf->st_ino = 0;
|
|
|
|
if (name[0] && name[1] == ':')
|
|
buf->st_dev = tolower (name[0]) - 'a' + 1;
|
|
else
|
|
buf->st_dev = _getdrive ();
|
|
buf->st_rdev = buf->st_dev;
|
|
|
|
buf->st_size = wfd.nFileSizeLow;
|
|
|
|
/* Convert timestamps to Unix format. */
|
|
buf->st_mtime = convert_time (wfd.ftLastWriteTime);
|
|
buf->st_atime = convert_time (wfd.ftLastAccessTime);
|
|
if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
|
|
buf->st_ctime = convert_time (wfd.ftCreationTime);
|
|
if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
|
|
|
|
/* determine rwx permissions */
|
|
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
|
|
permission = S_IREAD;
|
|
else
|
|
permission = S_IREAD | S_IWRITE;
|
|
|
|
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
permission |= S_IEXEC;
|
|
else if (is_exec (name))
|
|
permission |= S_IEXEC;
|
|
|
|
buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
lstat (const char * path, struct stat * buf)
|
|
{
|
|
return stat (path, buf);
|
|
}
|
|
|
|
/* Implementation of mkostemp for MS-Windows, to avoid race conditions
|
|
when using mktemp. Copied from w32.c.
|
|
|
|
This is used only in update-game-score.c. It is overkill for that
|
|
use case, since update-game-score renames the temporary file into
|
|
the game score file, which isn't atomic on MS-Windows anyway, when
|
|
the game score already existed before running the program, which it
|
|
almost always does. But using a simpler implementation just to
|
|
make a point is uneconomical... */
|
|
|
|
int
|
|
mkostemp (char * template, int flags)
|
|
{
|
|
char * p;
|
|
int i, fd = -1;
|
|
unsigned uid = GetCurrentThreadId ();
|
|
int save_errno = errno;
|
|
static char first_char[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
|
|
|
|
errno = EINVAL;
|
|
if (template == NULL)
|
|
return -1;
|
|
|
|
p = template + strlen (template);
|
|
i = 5;
|
|
/* replace up to the last 5 X's with uid in decimal */
|
|
while (--p >= template && p[0] == 'X' && --i >= 0)
|
|
{
|
|
p[0] = '0' + uid % 10;
|
|
uid /= 10;
|
|
}
|
|
|
|
if (i < 0 && p[0] == 'X')
|
|
{
|
|
i = 0;
|
|
do
|
|
{
|
|
p[0] = first_char[i];
|
|
if ((fd = open (template,
|
|
flags | _O_CREAT | _O_EXCL | _O_RDWR,
|
|
S_IRUSR | S_IWUSR)) >= 0
|
|
|| errno != EEXIST)
|
|
{
|
|
if (fd >= 0)
|
|
errno = save_errno;
|
|
return fd;
|
|
}
|
|
}
|
|
while (++i < sizeof (first_char));
|
|
}
|
|
|
|
/* Template is badly formed or else we can't generate a unique name. */
|
|
return -1;
|
|
}
|
|
|
|
/* On Windows, you cannot rename into an existing file. */
|
|
int
|
|
sys_rename (const char *from, const char *to)
|
|
{
|
|
int retval = rename (from, to);
|
|
|
|
if (retval < 0 && errno == EEXIST)
|
|
{
|
|
if (unlink (to) == 0)
|
|
retval = rename (from, to);
|
|
}
|
|
return retval;
|
|
}
|