Commit 480b0c5b authored by Geoff Voelker's avatar Geoff Voelker
Browse files

(nt_stat, nt_ctime): Functions deleted.

Undefine macros of CRT functions.
parent 2fd5e802
......@@ -22,55 +22,37 @@ Boston, MA 02111-1307, USA.
*/
/* Define stat before including config.h. */
#include <string.h>
#include <sys/stat.h>
#include <malloc.h>
static int is_toplevel_share_name (char *);
static int stat_toplevel_share (char *, void *);
int
nt_stat (char *filename, struct stat *statbuf)
{
int l = strlen (filename);
char *str = NULL;
/* stat has a bug when passed a name of a directory with a trailing
backslash (but a trailing forward slash works fine). */
if (filename[l - 1] == '\\')
{
str = (char *) alloca (l + 1);
strcpy (str, filename);
str[l - 1] = '/';
return stat (str, statbuf);
}
if (stat (filename, statbuf) == 0)
return 0;
else if (is_toplevel_share_name (filename))
return stat_toplevel_share (filename, statbuf);
else
return -1;
}
/* Place a wrapper around the NT version of ctime. It returns NULL
on network directories, so we handle that case here.
Define it before including config.h. (Ulrich Leodolter, 1/11/95). */
char *
nt_ctime (const time_t *t)
{
char *str = (char *) ctime (t);
return (str ? str : "Sun Jan 01 00:00:00 1970");
}
#include <config.h>
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <errno.h>
#include <fcntl.h>
#include <ctype.h>
#include <signal.h>
#include <sys/time.h>
/* must include CRT headers *before* config.h */
#include "config.h"
#undef access
#undef chdir
#undef chmod
#undef creat
#undef ctime
#undef fopen
#undef link
#undef mkdir
#undef mktemp
#undef open
#undef rename
#undef rmdir
#undef unlink
#undef close
#undef dup
#undef dup2
#undef pipe
#undef read
#undef write
#define getwd _getwd
#include "lisp.h"
......@@ -78,114 +60,35 @@ nt_ctime (const time_t *t)
#include <pwd.h>
#include "ndir.h"
#include "ntheap.h"
extern int report_file_error (char *, Lisp_Object);
/* Routines for extending stat above. */
static int
get_unassigned_drive_letter ()
{
int i;
unsigned int mask;
mask = GetLogicalDrives ();
for (i = 0; i < 26; i++)
{
if (mask & (1 << i))
continue;
break;
}
return (i == 26 ? -1 : 'A' + i);
}
void dostounix_filename (char *);
/* Return nonzero if NAME is of the form \\host\share (forward slashes
also valid), otherwise return 0. */
static int
is_toplevel_share_name (char *filename)
{
int len;
char *name;
char *host;
char *share;
char *suffix;
len = strlen (filename);
name = alloca (len + 1);
strcpy (name, filename);
dostounix_filename (name);
if (name[0] != '/' || name[1] != '/')
return 0;
host = strtok (&name[2], "/");
share = strtok (NULL, "/");
suffix = strtok (NULL, "/");
if (!host || !share || suffix)
return 0;
return 1;
}
/* FILENAME is of the form \\host\share, and stat can't handle names
of this form. But stat can handle \\host\share if it's been
assigned a drive letter. So we create a network connection to this
share, assign it a drive letter, stat the drive letter, and
disconnect from the share. Hassle... */
static int
stat_toplevel_share (char *filename, void *statbuf)
{
NETRESOURCE net;
int drive_letter;
char drive[4];
int result;
drive_letter = get_unassigned_drive_letter ();
if (drive_letter < 0)
return -1;
drive[0] = drive_letter;
drive[1] = ':';
drive[2] = '\0';
net.dwType = RESOURCETYPE_DISK;
net.lpLocalName = drive;
net.lpRemoteName = filename;
net.lpProvider = NULL;
switch (WNetAddConnection2 (&net, NULL, NULL, 0))
{
case NO_ERROR:
break;
case ERROR_ALREADY_ASSIGNED:
default:
return -1;
}
/* Name the toplevel directory on the drive letter. */
drive[2] = '/';
drive[3] = '\0';
result = stat (drive, (void *) statbuf);
/* Strip the slash so we can disconnect. */
drive[2] = '\0';
if (WNetCancelConnection2 (drive, 0, TRUE) != NO_ERROR)
result = -1;
#include <windows.h>
return result;
}
#ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
#include <sys/socket.h>
#undef socket
#undef bind
#undef connect
#undef htons
#undef ntohs
#undef inet_addr
#undef gethostname
#undef gethostbyname
#undef getservbyname
#endif
#include "nt.h"
#include "ndir.h"
#include "ntheap.h"
/* Get the current working directory. */
int
char *
getwd (char *dir)
{
return GetCurrentDirectory (MAXPATHLEN, dir);
if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
return dir;
return NULL;
}
#ifndef HAVE_SOCKETS
/* Emulate gethostname. */
int
gethostname (char *buffer, int size)
......@@ -194,6 +97,7 @@ gethostname (char *buffer, int size)
certainly large enough. */
return !GetComputerName (buffer, &size);
}
#endif /* HAVE_SOCKETS */
/* Emulate getloadavg. */
int
......@@ -209,124 +113,14 @@ getloadavg (double loadavg[], int nelem)
return i;
}
/* 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. */
void
nt_sleep (int seconds)
{
Sleep (seconds * 1000);
}
/* Emulate rename. */
#ifndef ENOENT
#define ENOENT 2
#endif
#ifndef EXDEV
#define EXDEV 18
#endif
#ifndef EINVAL
#define EINVAL 22
#endif
int
rename (const char *oldname, const char *newname)
{
#ifdef WINDOWS95
int i, len, len0, len1;
char *dirs[2], *names[2], *ptr;
/* A bug in MoveFile under Windows 95 incorrectly renames files in
some cases. If the old name is of the form FILENAME or
FILENAME.SUF, and the new name is of the form FILENAME~ or
FILENAME.SUF~, and both the source and target are in the same
directory, then MoveFile renames the long form of the filename to
FILENAME~ (FILENAME.SUF~) but leaves the DOS short form as
FILENAME (FILENAME.SUF). The result is that the two different
filenames refer to the same file. In this case, rename the
source to a temporary name that can then successfully be renamed
to the target. */
dirs[0] = names[0] = oldname;
dirs[1] = names[1] = newname;
for (i = 0; i < 2; i++)
{
/* Canonicalize and remove prefix. */
len = strlen (names[i]);
for (ptr = names[i] + len - 1; ptr > names[i]; ptr--)
{
if (IS_ANY_SEP (ptr[0]) && ptr[1] != '\0')
{
names[i] = ptr + 1;
break;
}
}
}
len0 = strlen (names[0]);
len1 = strlen (names[1]);
/* The predicate is whether the file is being renamed to a filename
with ~ appended. This is conservative, but should be correct. */
if ((len0 == len1 - 1)
&& (names[1][len0] == '~')
&& (!strnicmp (names[0], names[1], len0)))
{
/* Rename the source to a temporary name that can succesfully be
renamed to the target. The temporary name is in the directory
of the target. */
char *tmp, *fulltmp;
tmp = "eXXXXXX";
fulltmp = alloca (strlen (dirs[1]) + strlen (tmp) + 1);
fulltmp[0] = '\0';
if (dirs[1] != names[1])
{
len = names[1] - dirs[1];
strncpy (fulltmp, dirs[1], len);
fulltmp[len] = '\0';
}
strcat (fulltmp, tmp);
mktemp (fulltmp);
if (rename (oldname, fulltmp) < 0)
return -1;
oldname = fulltmp;
}
#endif
if (!MoveFile (oldname, newname))
{
switch (GetLastError ())
{
case ERROR_FILE_NOT_FOUND:
errno = ENOENT;
break;
case ERROR_ACCESS_DENIED:
/* This gets returned when going across devices. */
errno = EXDEV;
break;
case ERROR_FILE_EXISTS:
case ERROR_ALREADY_EXISTS:
default:
errno = EINVAL;
break;
}
return -1;
}
errno = 0;
return 0;
}
/* Emulate the Unix directory procedures opendir, closedir,
and readdir. We can't use the procedures supplied in sysdep.c,
so we provide them here. */
struct direct dir_static; /* simulated directory contents */
static int dir_finding;
static HANDLE dir_find_handle;
static HANDLE dir_find_handle = INVALID_HANDLE_VALUE;
static int dir_is_fat;
static char dir_pathname[MAXPATHLEN+1];
DIR *
opendir (char *filename)
......@@ -334,22 +128,21 @@ opendir (char *filename)
DIR *dirp;
/* Opening is done by FindFirstFile. However, a read is inherent to
this operation, so we have a flag to handle the open at read
time. This flag essentially means "there is a find-handle open and
it needs to be closed." */
this operation, so we defer the open until read time. */
if (!(dirp = (DIR *) malloc (sizeof (DIR))))
{
return 0;
}
if (!(dirp = (DIR *) malloc (sizeof (DIR))))
return NULL;
if (dir_find_handle != INVALID_HANDLE_VALUE)
return NULL;
dirp->dd_fd = 0;
dirp->dd_loc = 0;
dirp->dd_size = 0;
/* This is tacky, but we need the directory name for our
implementation of readdir. */
strncpy (dirp->dd_buf, filename, DIRBLKSIZ);
strncpy (dir_pathname, filename, MAXPATHLEN);
dir_pathname[MAXPATHLEN] = '\0';
dir_is_fat = is_fat_volume (filename, NULL);
return dirp;
}
......@@ -357,10 +150,10 @@ void
closedir (DIR *dirp)
{
/* If we have a find-handle open, close it. */
if (dir_finding)
if (dir_find_handle != INVALID_HANDLE_VALUE)
{
FindClose (dir_find_handle);
dir_finding = 0;
dir_find_handle = INVALID_HANDLE_VALUE;
}
xfree ((char *) dirp);
}
......@@ -371,46 +164,44 @@ readdir (DIR *dirp)
WIN32_FIND_DATA find_data;
/* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
if (!dir_finding)
if (dir_find_handle == INVALID_HANDLE_VALUE)
{
char filename[MAXNAMLEN + 3];
int ln;
strncpy (filename, dirp->dd_buf, MAXNAMLEN);
ln = strlen (filename)-1;
if (!IS_ANY_SEP (filename[ln]))
strcpy (filename, dir_pathname);
ln = strlen (filename) - 1;
if (!IS_DIRECTORY_SEP (filename[ln]))
strcat (filename, "\\");
strcat (filename, "*.*");
strcat (filename, "*");
dir_find_handle = FindFirstFile (filename, &find_data);
if (dir_find_handle == INVALID_HANDLE_VALUE)
if (dir_find_handle == INVALID_HANDLE_VALUE)
return NULL;
dir_finding = 1;
}
else
}
else
{
if (!FindNextFile (dir_find_handle, &find_data))
return NULL;
}
/* NT's unique ID for a file is 64 bits, so we have to fake it here.
This should work as long as we never use 0. */
/* Emacs never uses this value, so don't bother making it match
value returned by stat(). */
dir_static.d_ino = 1;
dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 +
dir_static.d_namlen - dir_static.d_namlen % 4;
dir_static.d_namlen = strlen (find_data.cFileName);
strncpy (dir_static.d_name, find_data.cFileName, MAXNAMLEN);
strcpy (dir_static.d_name, find_data.cFileName);
if (dir_is_fat)
_strlwr (dir_static.d_name);
return &dir_static;
}
/* Emulate getpwuid and getpwnam. */
int getuid (); /* forward declaration */
/* Emulate getpwuid, getpwnam and others. */
#define PASSWD_FIELD_SIZE 256
......@@ -432,22 +223,39 @@ static struct passwd the_passwd =
the_passwd_shell,
};
int
getuid ()
{
return the_passwd.pw_uid;
}
int
geteuid ()
{
/* I could imagine arguing for checking to see whether the user is
in the Administrators group and returning a UID of 0 for that
case, but I don't know how wise that would be in the long run. */
return getuid ();
}
int
getgid ()
{
return the_passwd.pw_gid;
}
int
getegid ()
{
return getgid ();
}
struct passwd *
getpwuid (int uid)
{
int size = PASSWD_FIELD_SIZE;
if (!GetUserName (the_passwd.pw_name, &size))
return NULL;
the_passwd.pw_passwd[0] = '\0';
the_passwd.pw_uid = 0;
the_passwd.pw_gid = 0;
strcpy (the_passwd.pw_gecos, the_passwd.pw_name);
the_passwd.pw_dir[0] = '\0';
the_passwd.pw_shell[0] = '\0';
return &the_passwd;
if (uid == the_passwd.pw_uid)
return &the_passwd;
return NULL;
}
struct passwd *
......@@ -459,336 +267,174 @@ getpwnam (char *name)
if (!pw)
return pw;
if (strcmp (name, pw->pw_name))
if (stricmp (name, pw->pw_name))
return NULL;
return pw;
}
/* We don't have scripts to automatically determine the system configuration
for Emacs before it's compiled, and we don't want to have to make the
user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
routine. */
static char configuration_buffer[32];
char *
get_emacs_configuration (void)
void
init_user_info ()
{
char *arch, *oem, *os;
/* Determine the processor type. */
switch (get_processor_type ())
/* Find the user's real name by opening the process token and
looking up the name associated with the user-sid in that token.
Use the relative portion of the identifier authority value from
the user-sid as the user id value (same for group id using the
primary group sid from the process token). */
char user_sid[256], name[256], domain[256];
DWORD length = sizeof (name), dlength = sizeof (domain), trash;
HANDLE token = NULL;
SID_NAME_USE user_type;
if (OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token)
&& GetTokenInformation (token, TokenUser,
(PVOID) user_sid, sizeof (user_sid), &trash)
&& LookupAccountSid (NULL, *((PSID *) user_sid), name, &length,
domain, &dlength, &user_type))
{
#ifdef PROCESSOR_INTEL_386
case PROCESSOR_INTEL_386:
case PROCESSOR_INTEL_486:
case PROCESSOR_INTEL_PENTIUM:
arch = "i386";
break;
#endif
#ifdef PROCESSOR_INTEL_860
case PROCESSOR_INTEL_860:
arch = "i860";
break;
#endif
#ifdef PROCESSOR_MIPS_R2000
case PROCESSOR_MIPS_R2000:
case PROCESSOR_MIPS_R3000:
case PROCESSOR_MIPS_R4000:
arch = "mips";
break;
#endif
#ifdef PROCESSOR_ALPHA_21064
case PROCESSOR_ALPHA_21064:
arch = "alpha";
break;
#endif
default:
arch = "unknown";
break;
strcpy (the_passwd.pw_name, name);
/* Determine a reasonable uid value. */
if (stricmp ("administrator", name) == 0)
{
the_passwd.pw_uid = 0;
the_passwd.pw_gid = 0;
}
else
{
SID_IDENTIFIER_AUTHORITY * pSIA;
pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid));
/* I believe the relative portion is the last 4 bytes (of 6)
with msb first. */
the_passwd.pw_uid = ((pSIA->Value[2] << 24) +
(pSIA->Value[3] << 16) +
(pSIA->Value[4] << 8) +
(pSIA->Value[5] << 0));
/* restrict to conventional uid range for normal users */
the_passwd.pw_uid = the_passwd.pw_uid % 60001;
/* Get group id */
if (GetTokenInformation (token, TokenPrimaryGroup,
(PVOID) user_sid, sizeof (user_sid), &trash))
{
SID_IDENTIFIER_AUTHORITY * pSIA;
pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid));
the_passwd.pw_gid = ((pSIA->Value[2] << 24) +
(pSIA->Value[3] << 16) +
(pSIA->Value[4] << 8) +
(pSIA->Value[5] << 0));
/* I don't know if this is necessary, but for safety... */
the_passwd.pw_gid = the_passwd.pw_gid % 60001;
}
else
the_passwd.pw_gid = the_passwd.pw_uid;
}
}
/* If security calls are not supported (presumably because we
are running under Windows 95), fallback to this. */
else if (GetUserName (name, &length))
{
strcpy (the_passwd.pw_name, name);
if (stricmp ("administrator", name) == 0)
the_passwd.pw_uid = 0;
else
the_passwd.pw_uid = 123;
the_passwd.pw_gid = the_passwd.pw_uid;
}
else
{
strcpy (the_passwd.pw_name, "unknown");
the_passwd.pw_uid = 123;
the_passwd.pw_gid = 123;
}
/* Let oem be "*" until we figure out how to decode the OEM field. */
oem = "*";
/* Ensure HOME and SHELL are defined. */
if (getenv ("HOME") == NULL)
putenv ("HOME=c:/");
if (getenv ("SHELL") == NULL)
putenv ((GetVersion () & 0x80000000) ? "SHELL=command" : "SHELL=cmd");
#ifdef WINDOWS95
os = "win";
#else
os = "nt";
#endif
/* Set dir and shell from environment variables. */
strcpy (the_passwd.pw_dir, getenv ("HOME"));
strcpy (the_passwd.pw_shell, getenv ("SHELL"));
sprintf (configuration_buffer, "%s-%s-%s%d.%d", arch, oem, os,
get_nt_major_version (), get_nt_minor_version ());
return configuration_buffer;
if (token)
CloseHandle (token);