diff options
Diffstat (limited to 'gnu/usr.bin/cvs/windows-NT/filesubr.c')
-rw-r--r-- | gnu/usr.bin/cvs/windows-NT/filesubr.c | 147 |
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; |