summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/cvs/windows-NT/filesubr.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/usr.bin/cvs/windows-NT/filesubr.c')
-rw-r--r--gnu/usr.bin/cvs/windows-NT/filesubr.c147
1 files changed, 132 insertions, 15 deletions
diff --git a/gnu/usr.bin/cvs/windows-NT/filesubr.c b/gnu/usr.bin/cvs/windows-NT/filesubr.c
index e3cb9c398df..926e06799d5 100644
--- a/gnu/usr.bin/cvs/windows-NT/filesubr.c
+++ b/gnu/usr.bin/cvs/windows-NT/filesubr.c
@@ -26,14 +26,6 @@
#include "cvs.h"
-/*
- * I don't know of a convenient way to test this at configure time, or else
- * I'd certainly do it there.
- */
-#if defined(NeXT)
-#define LOSING_TMPNAM_FUNCTION
-#endif
-
static int deep_remove_dir PROTO((const char *path));
/*
@@ -62,7 +54,8 @@ copy_file (from, to)
error (1, errno, "cannot open %s for copying", from);
if (fstat (fdin, &sb) < 0)
error (1, errno, "cannot fstat %s", from);
- if ((fdout = creat (to, (int) sb.st_mode & 07777)) < 0)
+ if ((fdout = open (to, O_CREAT | O_TRUNC | O_RDWR | O_BINARY,
+ (int) sb.st_mode & 07777)) < 0)
error (1, errno, "cannot create %s for copying", to);
if (sb.st_size > 0)
{
@@ -307,6 +300,33 @@ make_directories (name)
(void) mkdir (name);
}
+/* Create directory NAME if it does not already exist; fatal error for
+ other errors. Returns 0 if directory was created; 1 if it already
+ existed. */
+int
+mkdir_if_needed (name)
+ char *name;
+{
+ if (mkdir (name) < 0)
+ {
+ if (errno != EEXIST
+#ifdef EACCESS
+ /* This was copied over from the OS/2 code; I would guess it
+ isn't needed here but that has not been verified. */
+ && errno != EACCESS
+#endif
+#ifdef EACCES
+ /* This is said to be needed by NT on Alpha or PowerPC
+ (not sure what version) --August, 1996. */
+ && errno != EACCES
+#endif
+ )
+ error (1, errno, "cannot make directory %s", name);
+ return 1;
+ }
+ return 0;
+}
+
/*
* Change the mode of a file, either adding write permissions, or removing
* all write permissions. Adding write permissions honors the current umask
@@ -461,8 +481,8 @@ unlink_file_dir (f)
if (unlink (f) != 0)
{
/* under Windows NT, unlink returns EACCES if the path
- is a directory. */
- if (errno == EISDIR || errno == EACCES)
+ is a directory. Under Windows 95, ENOENT. */
+ if (errno == EISDIR || errno == EACCES || errno == ENOENT)
return deep_remove_dir (f);
else
/* The file wasn't a directory and some other
@@ -486,7 +506,9 @@ deep_remove_dir (path)
struct dirent *dp;
char buf[PATH_MAX];
- if ( rmdir (path) != 0 && errno == ENOTEMPTY )
+ /* ENOTEMPTY for NT (obvious) but EACCES for Win95 (not obvious) */
+ if (rmdir (path) != 0
+ && (errno == ENOTEMPTY || errno == EACCES))
{
if ((dirp = opendir (path)) == NULL)
/* If unable to open the directory return
@@ -506,7 +528,14 @@ deep_remove_dir (path)
chmod (buf, _S_IWRITE);
if (unlink (buf) != 0 )
{
- if (errno == EISDIR || errno == EACCES)
+ /* Under Windows NT, unlink returns EACCES if the path
+ is a directory. Under Windows 95, ENOENT. It
+ isn't really clear to me whether checking errno is
+ better or worse than using _stat to check for a directory.
+ We aren't really trying to prevent race conditions here
+ (e.g. what if something changes between readdir and
+ unlink?) */
+ if (errno == EISDIR || errno == EACCES || errno == ENOENT)
{
if (deep_remove_dir (buf))
{
@@ -728,7 +757,21 @@ fnfold (char *filename)
}
}
+
+/* Generate a unique temporary filename. Returns a pointer to a newly
+ malloc'd string containing the name. Returns successfully or not at
+ all. */
+char *
+cvs_temp_name ()
+{
+ char *retval;
+ retval = _tempnam (NULL, NULL);
+ if (retval == NULL)
+ error (1, errno, "cannot generate temporary filename");
+ return retval;
+}
+
/* Return non-zero iff FILENAME is absolute.
Trivial under Unix, but more complicated under other systems. */
int
@@ -787,10 +830,37 @@ convert_file (char *infile, int inflags,
error (0, errno, "warning: couldn't close %s", infile);
}
+
+/* NT has two evironment variables, HOMEPATH and HOMEDRIVE, which,
+ when combined as ${HOMEDRIVE}${HOMEPATH}, give the unix equivalent
+ of HOME. Some NT users are just too unixy, though, and set the
+ HOME variable themselves. Therefore, we check for HOME first, and
+ then try to combine the other two if that fails. */
+
char *
get_homedir ()
{
- return getenv ("HOMEPATH");
+ static char pathbuf[PATH_MAX * 2];
+ char *hd, *hp;
+
+ if ((hd = getenv ("HOME")))
+ return hd;
+ else if ((hd = getenv ("HOMEDRIVE")) && (hp = getenv ("HOMEPATH")))
+ {
+ /* Watch for buffer overruns. */
+
+#define cvs_min(x,y) ((x <= y) ? (x) : (y))
+
+ int ld = cvs_min (PATH_MAX, strlen (hd));
+ int lp = cvs_min (PATH_MAX, strlen (hp));
+
+ strncpy (pathbuf, hd, ld);
+ strncpy (pathbuf + ld, hp, lp);
+
+ return pathbuf;
+ }
+ else
+ return NULL;
}
/* See cvs.h for description. */
@@ -817,6 +887,34 @@ expand_wild (argc, argv, pargc, pargv)
HANDLE h;
WIN32_FIND_DATA fdata;
+ /* These variables help us extract the directory name from the
+ given pathname. */
+
+ char *last_forw_slash, *last_back_slash, *end_of_dirname;
+ int dirname_length = 0;
+
+ /* FindFirstFile doesn't return pathnames, so we have to do
+ this ourselves. Luckily, it's no big deal, since globbing
+ characters under Win32s can only occur in the last segment
+ of the path. For example,
+ /a/path/q*.h valid
+ /w32/q*.dir/cant/do/this/q*.h invalid */
+
+ /* Win32 can handle both forward and backward slashes as
+ filenames -- check for both. */
+
+ last_forw_slash = strrchr (argv[i], '/');
+ last_back_slash = strrchr (argv[i], '\\');
+
+#define cvs_max(x,y) ((x >= y) ? (x) : (y))
+
+ end_of_dirname = cvs_max (last_forw_slash, last_back_slash);
+
+ if (end_of_dirname == NULL)
+ dirname_length = 0; /* no directory name */
+ else
+ dirname_length = end_of_dirname - argv[i] + 1; /* include slash */
+
h = FindFirstFile (argv[i], &fdata);
if (h == INVALID_HANDLE_VALUE)
{
@@ -842,7 +940,26 @@ expand_wild (argc, argv, pargc, pargv)
{
while (1)
{
- new_argv [new_argc++] = xstrdup (fdata.cFileName);
+ new_argv[new_argc] =
+ (char *) xmalloc (strlen (fdata.cFileName) + 1
+ + dirname_length);
+
+ /* Copy the directory name, if there is one. */
+
+ if (dirname_length)
+ {
+ strncpy (new_argv[new_argc], argv[i], dirname_length);
+ new_argv[new_argc][dirname_length] = '\0';
+ }
+ else
+ new_argv[new_argc][0] = '\0';
+
+ /* Copy the file name. */
+
+ strcat (new_argv[new_argc], fdata.cFileName);
+
+ new_argc++;
+
if (new_argc == max_new_argc)
{
max_new_argc *= 2;