#include <config.h>
#include "lisp.h"
-#include <limits.h>
#include "buffer.h"
#include "events.h"
#endif /* HPUX_PRE_8_0 */
#endif /* HPUX */
-#ifdef WINDOWSNT
-#define NOMINMAX 1
-#include <direct.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#endif /* not WINDOWSNT */
-
-#ifdef WINDOWSNT
-#define CORRECT_DIR_SEPS(s) \
- do { if ('/' == DIRECTORY_SEP) dostounix_filename (s); \
- else unixtodos_filename (s); \
- } while (0)
+#ifdef WIN32_NATIVE
#define IS_DRIVE(x) isalpha (x)
/* Need to lower-case the drive letter, or else expanded
filenames will sometimes compare inequal, because
`expand-file-name' doesn't always down-case the drive letter. */
#define DRIVE_LETTER(x) tolower (x)
-#endif /* WINDOWSNT */
+#endif /* WIN32_NATIVE */
int lisp_to_time (Lisp_Object, time_t *);
Lisp_Object time_to_lisp (time_t);
p = beg + XSTRING_LENGTH (file);
while (p != beg && !IS_ANY_SEP (p[-1])
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
/* only recognize drive specifier at beginning */
&& !(p[-1] == ':' && p == beg + 2)
#endif
if (p == beg)
return Qnil;
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
/* Expansion of "c:" to drive and default directory. */
/* (NT does the right thing.) */
if (p == beg + 2 && beg[1] == ':')
{
/* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir. */
Bufbyte *res = (Bufbyte*) alloca (MAXPATHLEN + 1);
- if (getdefdir (toupper (*beg) - 'A' + 1, (char *)res))
+ if (_getdcwd (toupper (*beg) - 'A' + 1, (char *)res, MAXPATHLEN))
{
char *c=((char *) res) + strlen ((char *) res);
if (!IS_DIRECTORY_SEP (*c))
p = beg + strlen ((char *) beg);
}
}
-#endif /* WINDOWSNT */
+#endif /* WIN32_NATIVE */
return make_string (beg, p - beg);
}
end = p = beg + XSTRING_LENGTH (file);
while (p != beg && !IS_ANY_SEP (p[-1])
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
/* only recognize drive specifier at beginning */
&& !(p[-1] == ':' && p == beg + 2)
#endif
strcpy (dst, src);
if (slen > 1
&& IS_DIRECTORY_SEP (dst[slen - 1])
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
&& !IS_ANY_SEP (dst[slen - 2])
-#endif /* WINDOWSNT */
+#endif /* WIN32_NATIVE */
)
dst[slen - 1] = 0;
return 1;
This implementation is better than what one usually finds in libc.
--hniksic */
+static unsigned int temp_name_rand;
+
DEFUN ("make-temp-name", Fmake_temp_name, 1, 1, 0, /*
-Generate temporary file name starting with PREFIX.
+Generate a temporary file name starting with PREFIX.
The Emacs process number forms part of the result, so there is no
danger of generating a name being used by another process.
*/
(prefix))
{
- static char tbl[64] = {
+ static const char tbl[64] =
+ {
'A','B','C','D','E','F','G','H',
'I','J','K','L','M','N','O','P',
'Q','R','S','T','U','V','W','X',
'g','h','i','j','k','l','m','n',
'o','p','q','r','s','t','u','v',
'w','x','y','z','0','1','2','3',
- '4','5','6','7','8','9','-','_' };
- static unsigned count, count_initialized_p;
+ '4','5','6','7','8','9','-','_'
+ };
Lisp_Object val;
Bytecount len;
Bufbyte *p, *data;
- unsigned pid;
CHECK_STRING (prefix);
/* VAL is created by adding 6 characters to PREFIX. The first three
are the PID of this process, in base 64, and the second three are
- incremented if the file already exists. This ensures 262144
- unique file names per PID per PREFIX. */
+ a pseudo-random number seeded from process startup time. This
+ ensures 262144 unique file names per PID per PREFIX per machine. */
- pid = (unsigned)getpid ();
- *p++ = tbl[pid & 63], pid >>= 6;
- *p++ = tbl[pid & 63], pid >>= 6;
- *p++ = tbl[pid & 63], pid >>= 6;
+ {
+ unsigned int pid = (unsigned int) getpid ();
+ *p++ = tbl[(pid >> 0) & 63];
+ *p++ = tbl[(pid >> 6) & 63];
+ *p++ = tbl[(pid >> 12) & 63];
+ }
/* Here we try to minimize useless stat'ing when this function is
invoked many times successively with the same PREFIX. We achieve
- this by initializing count to a random value, and incrementing it
- afterwards. */
- if (!count_initialized_p)
- {
- count = (unsigned)time (NULL);
- /* Dumping temacs with a non-zero count_initialized_p wouldn't
- make much sense. */
- if (NILP (Frunning_temacs_p ()))
- count_initialized_p = 1;
- }
+ this by using a very pseudo-random number generator to generate
+ file names unique to this process, with a very long cycle. */
while (1)
{
struct stat ignored;
- unsigned num = count;
- p[0] = tbl[num & 63], num >>= 6;
- p[1] = tbl[num & 63], num >>= 6;
- p[2] = tbl[num & 63], num >>= 6;
+ p[0] = tbl[(temp_name_rand >> 0) & 63];
+ p[1] = tbl[(temp_name_rand >> 6) & 63];
+ p[2] = tbl[(temp_name_rand >> 12) & 63];
/* Poor man's congruential RN generator. Replace with ++count
for debugging. */
- count += 25229;
- count %= 225307;
+ temp_name_rand += 25229;
+ temp_name_rand %= 225307;
QUIT;
Bufbyte *newdir, *p, *o;
int tlen;
Bufbyte *target;
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
int drive = 0;
int collapse_newdir = 1;
#else
struct passwd *pw;
-#endif /* WINDOWSNT */
+#endif /* WIN32_NATIVE */
int length;
Lisp_Object handler;
-#ifdef __CYGWIN32__
+#ifdef CYGWIN
char *user;
#endif
/* Save time in some common cases - as long as default_directory
is not relative, it can be canonicalized with name below (if it
is needed at all) without requiring it to be expanded now. */
-#ifdef WINDOWSNT
- /* Detect MSDOS file names with drive specifiers. */
+#ifdef WIN32_NATIVE
+ /* Detect Windows file names with drive specifiers. */
&& ! (IS_DRIVE (o[0]) && (IS_DEVICE_SEP (o[1]) && IS_DIRECTORY_SEP (o[2])))
/* Detect Windows file names in UNC format. */
&& ! (IS_DIRECTORY_SEP (o[0]) && IS_DIRECTORY_SEP (o[1]))
-#else /* not WINDOWSNT */
+#else /* not WIN32_NATIVE */
/* Detect Unix absolute file names (/... alone is not absolute on
- DOS or Windows). */
+ Windows). */
&& ! (IS_DIRECTORY_SEP (o[0]))
-#endif /* not WINDOWSNT */
+#endif /* not WIN32_NATIVE */
)
{
struct gcpro gcpro1;
into name should be safe during all of this, though. */
nm = XSTRING_DATA (name);
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
/* We will force directory separators to be either all \ or /, so make
a local copy to modify, even if there ends up being no change. */
nm = strcpy ((char *)alloca (strlen ((char *)nm) + 1), (char *)nm);
"//somedir". */
if (drive && IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1]))
nm++;
-#endif /* WINDOWSNT */
+#endif /* WIN32_NATIVE */
/* If nm is absolute, look for /./ or /../ sequences; if none are
found, we can probably return right away. We will avoid allocating
a new string if name is already fully expanded. */
if (
IS_DIRECTORY_SEP (nm[0])
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
&& (drive || IS_DIRECTORY_SEP (nm[1]))
#endif
)
}
if (!lose)
{
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
/* Make sure directories are all separated with / or \ as
desired, but avoid allocation of a new string when not
required. */
XSTRING_DATA (name)[1] = ':';
}
return name;
-#else /* not WINDOWSNT */
+#else /* not WIN32_NATIVE */
if (nm == XSTRING_DATA (name))
return name;
return build_string ((char *) nm);
-#endif /* not WINDOWSNT */
+#endif /* not WIN32_NATIVE */
}
}
Qfile_name);
nm++;
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
collapse_newdir = 0;
#endif
}
multiple user profiles users defined, each with its HOME.
Therefore, the following should be reworked to handle
this case. */
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
/* Now if the file given is "~foo/file" and HOME="c:/", then
we want the file to be named "c:/file" ("~foo" becomes
"c:/"). The variable o has "~foo", so we can use the
newdir = (Bufbyte *) get_home_directory();
dostounix_filename (newdir);
nm += strlen(o) + 1;
-#else /* not WINDOWSNT */
-#ifdef __CYGWIN32__
+#else /* not WIN32_NATIVE */
+#ifdef CYGWIN
if ((user = user_login_name (NULL)) != NULL)
{
/* Does the user login name match the ~name? */
}
if (! newdir)
{
-#endif /* __CYGWIN32__ */
+#endif /* CYGWIN */
/* Jamie reports that getpwnam() can get wedged by SIGIO/SIGALARM
occurring in it. (It can call select()). */
slow_down_interrupts ();
newdir = (Bufbyte *) pw -> pw_dir;
nm = p;
}
-#ifdef __CYGWIN32__
+#ifdef CYGWIN
}
#endif
-#endif /* not WINDOWSNT */
+#endif /* not WIN32_NATIVE */
/* If we don't find a user of that name, leave the name
unchanged; don't move nm forward to p. */
}
}
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
/* On DOS and Windows, nm is absolute if a drive name was specified;
use the drive's current directory as the prefix if needed. */
if (!newdir && drive)
if (!IS_DIRECTORY_SEP (nm[0]))
{
newdir = alloca (MAXPATHLEN + 1);
- if (!getdefdir (toupper (drive) - 'A' + 1, newdir))
+ if (!_getdcwd (toupper (drive) - 'A' + 1, newdir, MAXPATHLEN))
newdir = NULL;
}
if (!newdir)
newdir[3] = 0;
}
}
-#endif /* WINDOWSNT */
+#endif /* WIN32_NATIVE */
/* Finally, if no prefix has been specified and nm is not absolute,
then it must be expanded relative to default_directory. */
if (1
-#ifndef WINDOWSNT
+#ifndef WIN32_NATIVE
/* /... alone is not absolute on DOS and Windows. */
&& !IS_DIRECTORY_SEP (nm[0])
#else
newdir = XSTRING_DATA (default_directory);
}
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
if (newdir)
{
/* First ensure newdir is an absolute name. */
if (
- /* Detect MSDOS file names with drive specifiers. */
+ /* Detect Windows file names with drive specifiers. */
! (IS_DRIVE (newdir[0])
&& IS_DEVICE_SEP (newdir[1]) && IS_DIRECTORY_SEP (newdir[2]))
/* Detect Windows file names in UNC format. */
newdir = alloca (MAXPATHLEN + 1);
if (drive)
{
- if (!getdefdir (toupper (drive) - 'A' + 1, newdir))
+ if (!_getdcwd (toupper (drive) - 'A' + 1, newdir, MAXPATHLEN))
newdir = "/";
}
else
newdir = "";
}
}
-#endif /* WINDOWSNT */
+#endif /* WIN32_NATIVE */
if (newdir)
{
just // (an incomplete UNC name). */
length = strlen ((char *) newdir);
if (length > 1 && IS_DIRECTORY_SEP (newdir[length - 1])
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
&& !(length == 2 && IS_DIRECTORY_SEP (newdir[0]))
#endif
)
/* Now concatenate the directory and name to new space in the stack frame */
tlen += strlen ((char *) nm) + 1;
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
/* Add reserved space for drive name. (The Microsoft x86 compiler
produces incorrect code if the following two lines are combined.) */
target = (Bufbyte *) alloca (tlen + 2);
target += 2;
-#else /* not WINDOWSNT */
+#else /* not WIN32_NATIVE */
target = (Bufbyte *) alloca (tlen);
-#endif /* not WINDOWSNT */
+#endif /* not WIN32_NATIVE */
*target = 0;
if (newdir)
++o;
p += 3;
}
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
/* if drive is set, we're not dealing with an UNC, so
multiple dir-seps are redundant (and reportedly cause trouble
under win95) */
}
}
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
/* At last, set drive name, except for network file name. */
if (drive)
{
assert (IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1]));
}
CORRECT_DIR_SEPS (target);
-#endif /* WINDOWSNT */
+#endif /* WIN32_NATIVE */
return make_string (target, o - target);
}
for (p = nm; p != endp; p++)
{
if ((p[0] == '~'
-#if defined (WINDOWSNT) || defined (__CYGWIN32__)
+#if defined (WIN32_NATIVE) || defined (CYGWIN)
/* // at start of file name is meaningful in WindowsNT systems */
|| (IS_DIRECTORY_SEP (p[0]) && p - 1 != nm)
-#else /* not (WINDOWSNT || __CYGWIN32__) */
+#else /* not (WIN32_NATIVE || CYGWIN) */
|| IS_DIRECTORY_SEP (p[0])
-#endif /* not (WINDOWSNT || __CYGWIN32__) */
+#endif /* not (WIN32_NATIVE || CYGWIN) */
)
&& p != nm
&& (IS_DIRECTORY_SEP (p[-1])))
nm = p;
substituted = 1;
}
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
/* see comment in expand-file-name about drive specifiers */
else if (IS_DRIVE (p[0]) && p[1] == ':'
&& p > nm && IS_DIRECTORY_SEP (p[-1]))
nm = p;
substituted = 1;
}
-#endif /* WINDOWSNT */
+#endif /* WIN32_NATIVE */
}
/* See if any variables are substituted into the string
target = (Bufbyte *) alloca (s - o + 1);
strncpy ((char *) target, (char *) o, s - o);
target[s - o] = 0;
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
strupr (target); /* $home == $HOME etc. */
-#endif /* WINDOWSNT */
+#endif /* WIN32_NATIVE */
/* Get variable value */
o = (Bufbyte *) egetenv ((char *) target);
target = (Bufbyte *) alloca (s - o + 1);
strncpy ((char *) target, (char *) o, s - o);
target[s - o] = 0;
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
strupr (target); /* $home == $HOME etc. */
-#endif /* WINDOWSNT */
+#endif /* WIN32_NATIVE */
/* Get variable value */
o = (Bufbyte *) egetenv ((char *) target);
for (p = xnm; p != x; p++)
if ((p[0] == '~'
-#if defined (WINDOWSNT)
+#if defined (WIN32_NATIVE)
|| (IS_DIRECTORY_SEP (p[0]) && p - 1 != xnm)
-#else /* not WINDOWSNT */
+#else /* not WIN32_NATIVE */
|| IS_DIRECTORY_SEP (p[0])
-#endif /* not WINDOWSNT */
+#endif /* not WIN32_NATIVE */
)
/* don't do p[-1] if that would go off the beginning --jwz */
&& p != nm && p > xnm && IS_DIRECTORY_SEP (p[-1]))
xnm = p;
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
else if (IS_DRIVE (p[0]) && p[1] == ':'
&& p > nm && IS_DIRECTORY_SEP (p[-1]))
xnm = p;
copyable by us. */
input_file_statable_p = (fstat (ifd, &st) >= 0);
-#ifndef WINDOWSNT
+#ifndef WIN32_NATIVE
if (out_st.st_mode != 0
&& st.st_dev == out_st.st_dev && st.st_ino == out_st.st_ino)
{
{
return Fsignal (Qfile_error,
list3 (build_translated_string ("Creating directory"),
- build_translated_string ("pathame too long"),
+ build_translated_string ("pathname too long"),
dirname_));
}
strncpy (dir, (char *) XSTRING_DATA (dirname_),
INTP (ok_if_already_exists), 0);
/* Syncing with FSF 19.34.6 note: FSF does not have conditional code for
- WINDOWSNT here; I've removed it. --marcpa */
+ WIN32_NATIVE here; I've removed it. --marcpa */
- /* FSFmacs only calls rename() here under BSD 4.1, and calls
- link() and unlink() otherwise, but that's bogus. Sometimes
- rename() succeeds where link()/unlink() fail, and we have
- configure check for rename() and emulate using link()/unlink()
- if necessary. */
+ /* We have configure check for rename() and emulate using
+ link()/unlink() if necessary. */
if (0 > rename ((char *) XSTRING_DATA (filename),
(char *) XSTRING_DATA (newname)))
{
/* But FSF #defines link as sys_link which is supplied in nt.c. We can't do
that because sysfile.h defines sys_link depending on ENCAPSULATE_LINK.
Reverted to previous behavior pending a working fix. (jhar) */
-#if defined(WINDOWSNT)
+#if defined(WIN32_NATIVE)
/* Windows does not support this operation. */
report_file_error ("Adding new name", Flist (2, &filename));
-#else /* not defined(WINDOWSNT) */
+#else /* not defined(WIN32_NATIVE) */
unlink ((char *) XSTRING_DATA (newname));
if (0 > link ((char *) XSTRING_DATA (filename),
report_file_error ("Adding new name",
list2 (filename, newname));
}
-#endif /* defined(WINDOWSNT) */
+#endif /* defined(WIN32_NATIVE) */
UNGCPRO;
return Qnil;
}
-#ifdef S_IFLNK
DEFUN ("make-symbolic-link", Fmake_symbolic_link, 2, 3,
"FMake symbolic link to file: \nFMake symbolic link to file %s: \np", /*
Make a symbolic link to FILENAME, named LINKNAME. Both args strings.
(filename, linkname, ok_if_already_exists))
{
/* This function can GC. GC checked 1997.06.04. */
+ /* XEmacs change: run handlers even if local machine doesn't have symlinks */
Lisp_Object handler;
struct gcpro gcpro1, gcpro2;
RETURN_UNGCPRO (call4 (handler, Qmake_symbolic_link, filename,
linkname, ok_if_already_exists));
+#ifdef S_IFLNK
if (NILP (ok_if_already_exists)
|| INTP (ok_if_already_exists))
barf_or_query_if_file_exists (linkname, "make it a link",
report_file_error ("Making symbolic link",
list2 (filename, linkname));
}
+#endif /* S_IFLNK */
+
UNGCPRO;
return Qnil;
}
-#endif /* S_IFLNK */
#ifdef HPUX_NET
CHECK_STRING (filename);
ptr = XSTRING_DATA (filename);
return (IS_DIRECTORY_SEP (*ptr) || *ptr == '~'
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
|| (IS_DRIVE (*ptr) && ptr[1] == ':' && IS_DIRECTORY_SEP (ptr[2]))
#endif
) ? Qt : Qnil;
static int
check_executable (char *filename)
{
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
struct stat st;
if (stat (filename, &st) < 0)
return 0;
return ((st.st_mode & S_IEXEC) != 0);
-#else /* not WINDOWSNT */
+#else /* not WIN32_NATIVE */
#ifdef HAVE_EACCESS
return eaccess (filename, 1) >= 0;
#else
But Unix doesn't give us a right way to do it. */
return access (filename, 1) >= 0;
#endif /* HAVE_EACCESS */
-#endif /* not WINDOWSNT */
+#endif /* not WIN32_NATIVE */
}
/* Return nonzero if file FILENAME exists and can be written. */
if (!NILP (handler))
RETURN_UNGCPRO (call2 (handler, Qfile_readable_p, abspath));
-#if defined(WINDOWSNT) || defined(__CYGWIN32__)
+#if defined(WIN32_NATIVE) || defined(CYGWIN)
/* Under MS-DOS and Windows, open does not work for directories. */
UNGCPRO;
if (access (XSTRING_DATA (abspath), 0) == 0)
return Qt;
else
return Qnil;
-#else /* not WINDOWSNT */
+#else /* not WIN32_NATIVE */
{
int desc = interruptible_open ((char *) XSTRING_DATA (abspath), O_RDONLY | OPEN_BINARY, 0);
UNGCPRO;
close (desc);
return Qt;
}
-#endif /* not WINDOWSNT */
+#endif /* not WIN32_NATIVE */
}
/* Having this before file-symlink-p mysteriously caused it to be forgotten
(filename))
{
/* This function can GC. GC checked 1997.04.10. */
+ /* XEmacs change: run handlers even if local machine doesn't have symlinks */
#ifdef S_IFLNK
char *buf;
int bufsize;
int valsize;
Lisp_Object val;
+#endif
Lisp_Object handler;
struct gcpro gcpro1;
if (!NILP (handler))
return call2 (handler, Qfile_symlink_p, filename);
+#ifdef S_IFLNK
bufsize = 100;
while (1)
{
return call2 (handler, Qfile_accessible_directory_p,
filename);
-#if !defined(WINDOWSNT)
+#if !defined(WIN32_NATIVE)
if (NILP (Ffile_directory_p (filename)))
return (Qnil);
else
UNGCPRO;
return tem ? Qnil : Qt;
}
-#endif /* !defined(WINDOWSNT) */
+#endif /* !defined(WIN32_NATIVE) */
}
DEFUN ("file-regular-p", Ffile_regular_p, 1, 1, 0, /*
return Qnil;
/* Syncing with FSF 19.34.6 note: not in FSF, #if 0'ed out here. */
#if 0
-#ifdef DOS_NT
+#ifdef WIN32_NATIVE
if (check_executable (XSTRING_DATA (abspath)))
st.st_mode |= S_IEXEC;
-#endif /* DOS_NT */
+#endif /* WIN32_NATIVE */
#endif /* 0 */
return make_int (st.st_mode & 07777);
*/
())
{
-#ifndef WINDOWSNT
+#ifndef WIN32_NATIVE
sync ();
#endif
return Qnil;
DEFSUBR (Fdelete_file);
DEFSUBR (Frename_file);
DEFSUBR (Fadd_name_to_file);
-#ifdef S_IFLNK
DEFSUBR (Fmake_symbolic_link);
-#endif /* S_IFLNK */
#ifdef HPUX_NET
DEFSUBR (Fsysnetunam);
#endif /* HPUX_NET */
on other platforms, it is initialized so that Lisp code can find out
what the normal separator is.
*/ );
-#ifdef WINDOWSNT
+#ifdef WIN32_NATIVE
Vdirectory_sep_char = make_char ('\\');
#else
- Vdirectory_sep_char = make_char ('/');
+ Vdirectory_sep_char = make_char ('/');
#endif
+
+ reinit_vars_of_fileio ();
+}
+
+void
+reinit_vars_of_fileio (void)
+{
+ /* We want temp_name_rand to be initialized to a value likely to be
+ unique to the process, not to the executable. The danger is that
+ two different XEmacs processes using the same binary on different
+ machines creating temp files in the same directory will be
+ unlucky enough to have the same pid. If we randomize using
+ process startup time, then in practice they will be unlikely to
+ collide. We use the microseconds field so that scripts that start
+ simultaneous XEmacs processes on multiple machines will have less
+ chance of collision. */
+ {
+ EMACS_TIME thyme;
+
+ EMACS_GET_TIME (thyme);
+ temp_name_rand = (unsigned int) (EMACS_SECS (thyme) ^ EMACS_USECS (thyme));
+ }
}