/* Utility and Unix shadow routines for GNU Emacs on the Microsoft W32 API.
- Copyright (C) 1994-1995, 2000-2011 Free Software Foundation, Inc.
+ Copyright (C) 1994-1995, 2000-2012 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <tlhelp32.h>
#include <psapi.h>
+#ifndef _MSC_VER
#include <w32api.h>
-#if !defined(__MINGW32__) || __W32API_MAJOR_VERSION < 3 || (__W32API_MAJOR_VERSION == 3 && __W32API_MINOR_VERSION < 15)
+#endif
+#if !defined (__MINGW32__) || __W32API_MAJOR_VERSION < 3 || (__W32API_MAJOR_VERSION == 3 && __W32API_MINOR_VERSION < 15)
/* This either is not in psapi.h or guarded by higher value of
_WIN32_WINNT than what we use. w32api supplied with MinGW 3.15
defines it in psapi.h */
return s_b_ret;
}
+static Lisp_Object ltime (ULONGLONG);
+
/* Get total user and system times for get-internal-run-time.
- Returns a list of three integers if the times are provided by the OS
+ Returns a list of integers if the times are provided by the OS
(NT derivatives), otherwise it returns the result of current-time. */
Lisp_Object
w32_get_internal_run_time (void)
if ((*get_process_times_fn) (proc, &create, &exit, &kernel, &user))
{
LARGE_INTEGER user_int, kernel_int, total;
- int microseconds;
user_int.LowPart = user.dwLowDateTime;
user_int.HighPart = user.dwHighDateTime;
kernel_int.LowPart = kernel.dwLowDateTime;
kernel_int.HighPart = kernel.dwHighDateTime;
total.QuadPart = user_int.QuadPart + kernel_int.QuadPart;
- /* FILETIME is 100 nanosecond increments, Emacs only wants
- microsecond resolution. */
- total.QuadPart /= 10;
- microseconds = total.QuadPart % 1000000;
- total.QuadPart /= 1000000;
-
- /* Sanity check to make sure we can represent the result. */
- if (total.HighPart == 0)
- {
- int secs = total.LowPart;
-
- return list3 (make_number ((secs >> 16) & 0xffff),
- make_number (secs & 0xffff),
- make_number (microseconds));
- }
+ return ltime (total.QuadPart);
}
}
return dir;
return NULL;
#else
- /* Emacs doesn't actually change directory itself, and we want to
- force our real wd to be where emacs.exe is to avoid unnecessary
- conflicts when trying to rename or delete directories. */
+ /* Emacs doesn't actually change directory itself, it stays in the
+ same directory where it was started. */
strcpy (dir, startup_dir);
return dir;
#endif
read-only filesystem, like CD-ROM or a write-protected floppy.
The only way to be really sure is to actually create a file and
see if it succeeds. But I think that's too much to ask. */
- if (tmp && _access (tmp, D_OK) == 0)
+ if (tmp && sys_access (tmp, D_OK) == 0)
{
char * var = alloca (strlen (tmp) + 8);
sprintf (var, "TMPDIR=%s", tmp);
}
}
+ /* When Emacs is invoked with --no-site-lisp, we must remove the
+ site-lisp directories from the default value of EMACSLOADPATH.
+ This assumes that the site-lisp entries are at the front, and
+ that additional entries do exist. */
+ if (no_site_lisp)
+ {
+ for (i = 0; i < N_ENV_VARS; i++)
+ {
+ if (strcmp (env_vars[i].name, "EMACSLOADPATH") == 0)
+ {
+ char *site;
+ while ((site = strstr (env_vars[i].def_value, "site-lisp")))
+ env_vars[i].def_value = strchr (site, ';') + 1;
+ break;
+ }
+ }
+ }
+
#define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
/* Treat emacs_dir specially: set it unconditionally based on our
memcpy (*envp, "COMSPEC=", 8);
}
- /* Remember the initial working directory for getwd, then make the
- real wd be the location of emacs.exe to avoid conflicts when
- renaming or deleting directories. (We also don't call chdir when
- running subprocesses for the same reason.) */
+ /* Remember the initial working directory for getwd. */
if (!GetCurrentDirectory (MAXPATHLEN, startup_dir))
abort ();
{
- char *p;
static char modname[MAX_PATH];
if (!GetModuleFileName (NULL, modname, MAX_PATH))
abort ();
- if ((p = strrchr (modname, '\\')) == NULL)
- abort ();
- *p = 0;
-
- SetCurrentDirectory (modname);
-
- /* Ensure argv[0] has the full path to Emacs. */
- *p = '\\';
argv[0] = modname;
}
cv, /* To be filled later. */
#ifdef EMACSDEBUG
" --no-opt",
+#endif
+#ifdef ENABLE_CHECKING
+ " --enable-checking",
#endif
/* configure.bat already sets USER_CFLAGS and USER_LDFLAGS
with a starting space to save work here. */
}
}
+/* Emulate fdutimens. */
+
+/* Set the access and modification time stamps of FD (a.k.a. FILE) to be
+ TIMESPEC[0] and TIMESPEC[1], respectively.
+ FD must be either negative -- in which case it is ignored --
+ or a file descriptor that is open on FILE.
+ If FD is nonnegative, then FILE can be NULL, which means
+ use just futimes instead of utimes.
+ If TIMESPEC is null, FAIL.
+ Return 0 on success, -1 (setting errno) on failure. */
+
+int
+fdutimens (int fd, char const *file, struct timespec const timespec[2])
+{
+ struct _utimbuf ut;
+
+ if (!timespec)
+ {
+ errno = ENOSYS;
+ return -1;
+ }
+ if (fd < 0 && !file)
+ {
+ errno = EBADF;
+ return -1;
+ }
+ ut.actime = timespec[0].tv_sec;
+ ut.modtime = timespec[1].tv_sec;
+ if (fd >= 0)
+ return _futime (fd, &ut);
+ else
+ return _utime (file, &ut);
+}
+
+
/* ------------------------------------------------------------------------- */
/* IO support and wrapper functions for W32 API. */
/* ------------------------------------------------------------------------- */
{
DWORD attributes;
- /* MSVC implementation doesn't recognize D_OK. */
+ /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its
+ newer versions blow up when passed D_OK. */
path = map_w32_filename (path, NULL);
if (is_unc_volume (path))
{
}
else if ((attributes = GetFileAttributes (path)) == -1)
{
- /* Should try mapping GetLastError to errno; for now just indicate
- that path doesn't exist. */
- errno = EACCES;
+ DWORD w32err = GetLastError ();
+
+ switch (w32err)
+ {
+ case ERROR_FILE_NOT_FOUND:
+ errno = ENOENT;
+ break;
+ default:
+ errno = EACCES;
+ break;
+ }
return -1;
}
if ((mode & X_OK) != 0 && !is_exec (path))
{
BOOL result;
char temp[MAX_PATH];
+ int newname_dev;
+ int oldname_dev;
/* MoveFile on Windows 95 doesn't correctly change the short file name
alias in a number of circumstances (it is not easy to predict when
strcpy (temp, map_w32_filename (oldname, NULL));
+ /* volume_info is set indirectly by map_w32_filename. */
+ oldname_dev = volume_info.serialnum;
+
if (os_subtype == OS_WIN95)
{
char * o;
int i = 0;
oldname = map_w32_filename (oldname, NULL);
- if (o = strrchr (oldname, '\\'))
+ if ((o = strrchr (oldname, '\\')))
o++;
else
o = (char *) oldname;
- if (p = strrchr (temp, '\\'))
+ if ((p = strrchr (temp, '\\')))
p++;
else
p = temp;
all the permutations of shared or subst'd drives, etc.) */
newname = map_w32_filename (newname, NULL);
+
+ /* volume_info is set indirectly by map_w32_filename. */
+ newname_dev = volume_info.serialnum;
+
result = rename (temp, newname);
- if (result < 0
- && errno == EEXIST
- && _chmod (newname, 0666) == 0
- && _unlink (newname) == 0)
- result = rename (temp, newname);
+ if (result < 0)
+ {
+
+ if (errno == EACCES
+ && newname_dev != oldname_dev)
+ {
+ /* The implementation of `rename' on Windows does not return
+ errno = EXDEV when you are moving a directory to a
+ different storage device (ex. logical disk). It returns
+ EACCES instead. So here we handle such situations and
+ return EXDEV. */
+ DWORD attributes;
+
+ if ((attributes = GetFileAttributes (temp)) != -1
+ && attributes & FILE_ATTRIBUTE_DIRECTORY)
+ errno = EXDEV;
+ }
+ else if (errno == EEXIST)
+ {
+ if (_chmod (newname, 0666) != 0)
+ return result;
+ if (_unlink (newname) != 0)
+ return result;
+ result = rename (temp, newname);
+ }
+ }
return result;
}
unsigned hash;
/* Get the truly canonical filename, if it exists. (Note: this
- doesn't resolve aliasing due to subst commands, or recognise hard
+ doesn't resolve aliasing due to subst commands, or recognize hard
links. */
if (!w32_get_long_filename ((char *)name, fullname, MAX_PATH))
abort ();
FILE_FLAG_BACKUP_SEMANTICS, NULL))
!= INVALID_HANDLE_VALUE)
{
- /* This is more accurate in terms of gettting the correct number
+ /* This is more accurate in terms of getting the correct number
of links, but is quite slow (it is noticeable when Emacs is
making a list of file name completions). */
BY_HANDLE_FILE_INFORMATION info;
}
static Lisp_Object
-ltime (long time_sec, long time_usec)
+ltime (ULONGLONG time_100ns)
{
- return list3 (make_number ((time_sec >> 16) & 0xffff),
+ ULONGLONG time_sec = time_100ns / 10000000;
+ int subsec = time_100ns % 10000000;
+ return list4 (make_number (time_sec >> 16),
make_number (time_sec & 0xffff),
- make_number (time_usec));
+ make_number (subsec / 10),
+ make_number (subsec % 10 * 100000));
}
-#define U64_TO_LISP_TIME(time) ltime ((time) / 1000000L, (time) % 1000000L)
+#define U64_TO_LISP_TIME(time) ltime (time)
static int
process_times (HANDLE h_proc, Lisp_Object *ctime, Lisp_Object *etime,
GetSystemTimeAsFileTime (&ft_current);
FILETIME_TO_U64 (tem1, ft_kernel);
- tem1 /= 10L;
*stime = U64_TO_LISP_TIME (tem1);
FILETIME_TO_U64 (tem2, ft_user);
- tem2 /= 10L;
*utime = U64_TO_LISP_TIME (tem2);
tem3 = tem1 + tem2;
FILETIME_TO_U64 (tem, ft_creation);
/* Process no 4 (System) returns zero creation time. */
if (tem)
- tem = (tem - utc_base) / 10L;
+ tem -= utc_base;
*ctime = U64_TO_LISP_TIME (tem);
if (tem)
{
FILETIME_TO_U64 (tem3, ft_current);
- tem = (tem3 - utc_base) / 10L - tem;
+ tem = (tem3 - utc_base) - tem;
}
*etime = U64_TO_LISP_TIME (tem);
for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls))
{
CHECK_STRING_CAR (dlls);
- if (library_dll = LoadLibrary (SDATA (XCAR (dlls))))
+ if ((library_dll = LoadLibrary (SDATA (XCAR (dlls)))))
{
- found = XCAR (dlls);
+ char name[MAX_PATH];
+ DWORD len;
+
+ len = GetModuleFileNameA (library_dll, name, sizeof (name));
+ found = Fcons (XCAR (dlls),
+ (len > 0)
+ /* Possibly truncated */
+ ? make_specified_string (name, -1, len, 1)
+ : Qnil);
break;
}
}
it cannot find the Windows installation file. If this file does
not exist in the expected place, tell the user. */
- if (!noninteractive && !inhibit_window_system)
+ if (!noninteractive && !inhibit_window_system
+ /* Vload_path is not yet initialized when we are loading
+ loadup.el. */
+ && NILP (Vpurify_flag))
{
Lisp_Object objs[2];
Lisp_Object full_load_path;
void
init_ntproc (void)
{
- /* Initialise the socket interface now if available and requested by
+ /* Initialize the socket interface now if available and requested by
the user by defining PRELOAD_WINSOCK; otherwise loading will be
delayed until open-network-stream is called (w32-has-winsock can
also be used to dynamically load or reload winsock).
{
int n, sc, err;
SELECT_TYPE fdset;
- EMACS_TIME timeout;
+ struct timeval timeout;
struct Lisp_Process *process = (struct Lisp_Process *)p;
int fd = process->infd;
for (;;)
{
- n = sys_read(fd, (char*)buf, sz);
+ n = sys_read (fd, (char*)buf, sz);
if (n >= 0)
return n;
if (err == EWOULDBLOCK)
{
/* Set a small timeout. */
- EMACS_SET_SECS_USECS(timeout, 1, 0);
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
FD_ZERO (&fdset);
FD_SET ((int)fd, &fdset);
/* Use select with the timeout to poll the selector. */
sc = select (fd + 1, &fdset, (SELECT_TYPE *)0, (SELECT_TYPE *)0,
- &timeout);
+ &timeout, NULL);
if (sc > 0)
continue; /* Try again. */
{
struct Lisp_Process *process = (struct Lisp_Process *)p;
int fd = process->outfd;
- ssize_t n = sys_write(fd, buf, sz);
+ ssize_t n = sys_write (fd, buf, sz);
/* 0 or more bytes written means everything went fine. */
if (n >= 0)