1/* filesubr.c --- subroutines for dealing with files
2   Jim Blandy <jimb@cyclic.com>
3
4   This file is part of GNU CVS.
5
6   GNU CVS is free software; you can redistribute it and/or modify it
7   under the terms of the GNU General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.  */
15
16/* These functions were moved out of subr.c because they need different
17   definitions under operating systems (like, say, Windows NT) with different
18   file system semantics.  */
19
20#include <io.h>
21#include <windows.h>
22
23#include "cvs.h"
24
25static int deep_remove_dir PROTO((const char *path));
26
27/* Copies "from" to "to".  Note that the functionality here is similar
28   to the win32 function CopyFile, but (1) we copy LastAccessTime and
29   CopyFile doesn't, (2) we set file attributes to the default set by
30   the C library and CopyFile copies them.  Neither #1 nor #2 was intentional
31   as far as I know, but changing them could be confusing, unless there
32   is some reason they should be changed (this would need more
33   investigation).  */
34void
35copy_file (from, to)
36    const char *from;
37    const char *to;
38{
39    struct stat sb;
40    struct utimbuf t;
41    int fdin, fdout;
42
43    if (trace)
44#ifdef SERVER_SUPPORT
45	(void) fprintf (stderr, "%c-> copy(%s,%s)\n",
46			(server_active) ? 'S' : ' ', from, to);
47#else
48	(void) fprintf (stderr, "-> copy(%s,%s)\n", from, to);
49#endif
50    if (noexec)
51	return;
52
53    if ((fdin = open (from, O_RDONLY | O_BINARY)) < 0)
54	error (1, errno, "cannot open %s for copying", from);
55    if (fstat (fdin, &sb) < 0)
56	error (1, errno, "cannot fstat %s", from);
57    if ((fdout = open (to, O_CREAT | O_TRUNC | O_RDWR | O_BINARY,
58		       (int) sb.st_mode & 07777)) < 0)
59	error (1, errno, "cannot create %s for copying", to);
60    if (sb.st_size > 0)
61    {
62	char buf[BUFSIZ];
63	int n;
64
65	for (;;)
66	{
67	    n = read (fdin, buf, sizeof(buf));
68	    if (n == -1)
69	    {
70#ifdef EINTR
71		if (errno == EINTR)
72		    continue;
73#endif
74		error (1, errno, "cannot read file %s for copying", from);
75	    }
76            else if (n == 0)
77		break;
78
79	    if (write(fdout, buf, n) != n) {
80		error (1, errno, "cannot write file %s for copying", to);
81	    }
82	}
83
84#ifdef HAVE_FSYNC
85	if (fsync (fdout))
86	    error (1, errno, "cannot fsync file %s after copying", to);
87#endif
88    }
89
90    if (close (fdin) < 0)
91	error (0, errno, "cannot close %s", from);
92    if (close (fdout) < 0)
93	error (1, errno, "cannot close %s", to);
94
95    /* now, set the times for the copied file to match those of the original */
96    memset ((char *) &t, 0, sizeof (t));
97    t.actime = sb.st_atime;
98    t.modtime = sb.st_mtime;
99    (void) utime (to, &t);
100}
101
102/* FIXME-krp: these functions would benefit from caching the char * &
103   stat buf.  */
104
105/*
106 * Returns non-zero if the argument file is a directory, or is a symbolic
107 * link which points to a directory.
108 */
109int
110isdir (file)
111    const char *file;
112{
113    struct stat sb;
114
115    if (stat (file, &sb) < 0)
116	return (0);
117    return (S_ISDIR (sb.st_mode));
118}
119
120/*
121 * Returns non-zero if the argument file is a symbolic link.
122 */
123int
124islink (file)
125    const char *file;
126{
127#ifdef S_ISLNK
128    struct stat sb;
129
130    if (lstat (file, &sb) < 0)
131	return (0);
132    return (S_ISLNK (sb.st_mode));
133#else
134    return (0);
135#endif
136}
137
138/*
139 * Returns non-zero if the argument file exists.
140 */
141int
142isfile (file)
143    const char *file;
144{
145    return isaccessible(file, F_OK);
146}
147
148/*
149 * Returns non-zero if the argument file is readable.
150 */
151int
152isreadable (file)
153    const char *file;
154{
155    return isaccessible(file, R_OK);
156}
157
158/*
159 * Returns non-zero if the argument file is writable.
160 */
161int
162iswritable (file)
163    const char *file;
164{
165    return isaccessible(file, W_OK);
166}
167
168/*
169 * Returns non-zero if the argument file is accessable according to
170 * mode.  If compiled with SETXID_SUPPORT also works if cvs has setxid
171 * bits set.
172 */
173int
174isaccessible (file, mode)
175    const char *file;
176    const int mode;
177{
178#ifdef SETXID_SUPPORT
179    struct stat sb;
180    int umask = 0;
181    int gmask = 0;
182    int omask = 0;
183    int uid;
184
185    if (stat(file, &sb) == -1)
186	return 0;
187    if (mode == F_OK)
188	return 1;
189
190    uid = geteuid();
191    if (uid == 0)		/* superuser */
192    {
193	if (mode & X_OK)
194	    return sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH);
195	else
196	    return 1;
197    }
198
199    if (mode & R_OK)
200    {
201	umask |= S_IRUSR;
202	gmask |= S_IRGRP;
203	omask |= S_IROTH;
204    }
205    if (mode & W_OK)
206    {
207	umask |= S_IWUSR;
208	gmask |= S_IWGRP;
209	omask |= S_IWOTH;
210    }
211    if (mode & X_OK)
212    {
213	umask |= S_IXUSR;
214	gmask |= S_IXGRP;
215	omask |= S_IXOTH;
216    }
217
218    if (sb.st_uid == uid)
219	return (sb.st_mode & umask) == umask;
220    else if (sb.st_gid == getegid())
221	return (sb.st_mode & gmask) == gmask;
222    else
223	return (sb.st_mode & omask) == omask;
224#else
225    return access(file, mode) == 0;
226#endif
227}
228
229/*
230 * Open a file and die if it fails
231 */
232FILE *
233open_file (name, mode)
234    const char *name;
235    const char *mode;
236{
237    FILE *fp;
238
239    if ((fp = fopen (name, mode)) == NULL)
240	error (1, errno, "cannot open %s", name);
241    return (fp);
242}
243
244/*
245 * Make a directory and die if it fails
246 */
247void
248make_directory (name)
249    const char *name;
250{
251    struct stat sb;
252
253    if (stat (name, &sb) == 0 && (!S_ISDIR (sb.st_mode)))
254	    error (0, 0, "%s already exists but is not a directory", name);
255    if (!noexec && mkdir (name) < 0)
256	error (1, errno, "cannot make directory %s", name);
257}
258
259/*
260 * Make a path to the argument directory, printing a message if something
261 * goes wrong.
262 */
263void
264make_directories (name)
265    const char *name;
266{
267    char *cp;
268
269    if (noexec)
270	return;
271
272    if (mkdir (name) == 0 || errno == EEXIST)
273	return;
274    if (errno != ENOENT)
275    {
276	error (0, errno, "cannot make path to %s", name);
277	return;
278    }
279    if ((cp = strrchr (name, '/')) == NULL)
280	return;
281    *cp = '\0';
282    make_directories (name);
283    *cp++ = '/';
284    if (*cp == '\0')
285	return;
286    (void) mkdir (name);
287}
288
289/* Create directory NAME if it does not already exist; fatal error for
290   other errors.  Returns 0 if directory was created; 1 if it already
291   existed.  */
292int
293mkdir_if_needed (name)
294    char *name;
295{
296    if (mkdir (name) < 0)
297    {
298	if (errno != EEXIST
299#ifdef EACCESS
300	    /* This was copied over from the OS/2 code; I would guess it
301	       isn't needed here but that has not been verified.  */
302	    && errno != EACCESS
303#endif
304#ifdef EACCES
305	    /* This is said to be needed by NT on Alpha or PowerPC
306	       (not sure what version) --August, 1996.  */
307	    && errno != EACCES
308#endif
309	    )
310	    error (1, errno, "cannot make directory %s", name);
311	return 1;
312    }
313    return 0;
314}
315
316/*
317 * Change the mode of a file, either adding write permissions, or removing
318 * all write permissions.  Adding write permissions honors the current umask
319 * setting.
320 */
321void
322xchmod (fname, writable)
323    char *fname;
324    int writable;
325{
326    struct stat sb;
327    mode_t mode, oumask;
328
329    if (stat (fname, &sb) < 0)
330    {
331	if (!noexec)
332	    error (0, errno, "cannot stat %s", fname);
333	return;
334    }
335    if (writable)
336    {
337	oumask = umask (0);
338	(void) umask (oumask);
339	mode = sb.st_mode | ~oumask & (((sb.st_mode & S_IRUSR) ? S_IWUSR : 0) |
340				       ((sb.st_mode & S_IRGRP) ? S_IWGRP : 0) |
341				       ((sb.st_mode & S_IROTH) ? S_IWOTH : 0));
342    }
343    else
344    {
345	mode = sb.st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH);
346    }
347
348    if (trace)
349#ifdef SERVER_SUPPORT
350	(void) fprintf (stderr, "%c-> chmod(%s,%o)\n",
351			(server_active) ? 'S' : ' ', fname, mode);
352#else
353	(void) fprintf (stderr, "-> chmod(%s,%o)\n", fname, mode);
354#endif
355    if (noexec)
356	return;
357
358    if (chmod (fname, mode) < 0)
359	error (0, errno, "cannot change mode of file %s", fname);
360}
361
362
363/* Read the value of a symbolic link.
364   Under Windows NT, this function always returns EINVAL.  */
365int
366readlink (char *path, char *buf, int buf_size)
367{
368    errno = EINVAL;
369    return -1;
370}
371
372/* Rename for NT which works for read only files.  Apparently if we are
373   accessing FROM and TO via a Novell network, this is an issue.  */
374int
375wnt_rename (from, to)
376    const char *from;
377    const char *to;
378{
379    int result, save_errno;
380    int readonly = !iswritable (from);
381
382    if (readonly)
383    {
384	if (chmod (from, S_IWRITE) < 0)
385	    return -1;
386    }
387    result = rename (from, to);
388    save_errno = errno;
389    if (readonly)
390    {
391	if (result == 0)
392	{
393	    if (chmod (to, S_IREAD) < 0)
394		return -1;
395	}
396	else
397	{
398	    /* We have a choice of which error to report, if there is
399	       one here too; report the one from rename ().  */
400	    chmod (from, S_IREAD);
401	}
402	errno = save_errno;
403    }
404    return result;
405}
406
407/*
408 * Rename a file and die if it fails
409 */
410void
411rename_file (from, to)
412    const char *from;
413    const char *to;
414{
415    if (trace)
416#ifdef SERVER_SUPPORT
417	(void) fprintf (stderr, "%c-> rename(%s,%s)\n",
418			(server_active) ? 'S' : ' ', from, to);
419#else
420	(void) fprintf (stderr, "-> rename(%s,%s)\n", from, to);
421#endif
422    if (noexec)
423	return;
424
425    /* Win32 unlink is stupid --- it fails if the file is read-only  */
426    chmod(to, S_IWRITE);
427    unlink(to);
428    if (CVS_RENAME (from, to) < 0)
429	error (1, errno, "cannot rename file %s to %s", from, to);
430}
431
432/*
433 * unlink a file, if possible.
434 */
435int
436unlink_file (f)
437    const char *f;
438{
439    if (trace)
440#ifdef SERVER_SUPPORT
441	(void) fprintf (stderr, "%c-> unlink(%s)\n",
442			(server_active) ? 'S' : ' ', f);
443#else
444	(void) fprintf (stderr, "-> unlink(%s)\n", f);
445#endif
446    if (noexec)
447	return (0);
448
449    /* Win32 unlink is stupid - it fails if the file is read-only */
450    chmod (f, _S_IWRITE);
451    return (unlink (f));
452}
453
454/*
455 * Unlink a file or dir, if possible.  If it is a directory do a deep
456 * removal of all of the files in the directory.  Return -1 on error
457 * (in which case errno is set).
458 */
459int
460unlink_file_dir (f)
461    const char *f;
462{
463    if (trace)
464#ifdef SERVER_SUPPORT
465	(void) fprintf (stderr, "%c-> unlink_file_dir(%s)\n",
466			(server_active) ? 'S' : ' ', f);
467#else
468	(void) fprintf (stderr, "-> unlink_file_dir(%s)\n", f);
469#endif
470    if (noexec)
471	return (0);
472
473    /* Win32 unlink is stupid - it fails if the file is read-only */
474    chmod (f, _S_IWRITE);
475    if (unlink (f) != 0)
476    {
477	/* under Windows NT, unlink returns EACCES if the path
478	   is a directory.  Under Windows 95, ENOENT.  */
479        if (errno == EISDIR || errno == EACCES || errno == ENOENT)
480                return deep_remove_dir (f);
481        else
482		/* The file wasn't a directory and some other
483		 * error occured
484		 */
485                return -1;
486    }
487    /* We were able to remove the file from the disk */
488    return 0;
489}
490
491/* Remove a directory and everything it contains.  Returns 0 for
492 * success, -1 for failure (in which case errno is set).
493 */
494
495static int
496deep_remove_dir (path)
497    const char *path;
498{
499    DIR		  *dirp;
500    struct dirent *dp;
501    char	   buf[PATH_MAX];
502
503    /* ENOTEMPTY for NT (obvious) but EACCES for Win95 (not obvious) */
504    if (rmdir (path) != 0
505	&& (errno == ENOTEMPTY || errno == EACCES))
506    {
507	if ((dirp = opendir (path)) == NULL)
508	    /* If unable to open the directory return
509	     * an error
510	     */
511	    return -1;
512
513	while ((dp = readdir (dirp)) != NULL)
514	{
515	    if (strcmp (dp->d_name, ".") == 0 ||
516			strcmp (dp->d_name, "..") == 0)
517		continue;
518
519	    sprintf (buf, "%s/%s", path, dp->d_name);
520
521	    /* Win32 unlink is stupid - it fails if the file is read-only */
522	    chmod (buf, _S_IWRITE);
523	    if (unlink (buf) != 0 )
524	    {
525		/* Under Windows NT, unlink returns EACCES if the path
526		   is a directory.  Under Windows 95, ENOENT.  It
527		   isn't really clear to me whether checking errno is
528		   better or worse than using _stat to check for a directory.
529		   We aren't really trying to prevent race conditions here
530		   (e.g. what if something changes between readdir and
531		   unlink?)  */
532		if (errno == EISDIR || errno == EACCES || errno == ENOENT)
533		{
534		    if (deep_remove_dir (buf))
535		    {
536			closedir (dirp);
537			return -1;
538		    }
539		}
540		else
541		{
542		    /* buf isn't a directory, or there are
543		     * some sort of permision problems
544		     */
545		    closedir (dirp);
546		    return -1;
547		}
548	    }
549	}
550	closedir (dirp);
551	return rmdir (path);
552    }
553    /* Was able to remove the directory return 0 */
554    return 0;
555}
556
557/* Read NCHARS bytes from descriptor FD into BUF.
558   Return the number of characters successfully read.
559   The number returned is always NCHARS unless end-of-file or error.  */
560static size_t
561block_read (fd, buf, nchars)
562    int fd;
563    char *buf;
564    size_t nchars;
565{
566    char *bp = buf;
567    size_t nread;
568
569    do
570    {
571	nread = read (fd, bp, nchars);
572	if (nread == (size_t)-1)
573	{
574#ifdef EINTR
575	    if (errno == EINTR)
576		continue;
577#endif
578	    return (size_t)-1;
579	}
580
581	if (nread == 0)
582	    break;
583
584	bp += nread;
585	nchars -= nread;
586    } while (nchars != 0);
587
588    return bp - buf;
589}
590
591
592/*
593 * Compare "file1" to "file2". Return non-zero if they don't compare exactly.
594 */
595int
596xcmp (file1, file2)
597    const char *file1;
598    const char *file2;
599{
600    char *buf1, *buf2;
601    struct stat sb1, sb2;
602    int fd1, fd2;
603    int ret;
604
605    if ((fd1 = open (file1, O_RDONLY | O_BINARY)) < 0)
606	error (1, errno, "cannot open file %s for comparing", file1);
607    if ((fd2 = open (file2, O_RDONLY | O_BINARY)) < 0)
608	error (1, errno, "cannot open file %s for comparing", file2);
609    if (fstat (fd1, &sb1) < 0)
610	error (1, errno, "cannot fstat %s", file1);
611    if (fstat (fd2, &sb2) < 0)
612	error (1, errno, "cannot fstat %s", file2);
613
614    /* A generic file compare routine might compare st_dev & st_ino here
615       to see if the two files being compared are actually the same file.
616       But that won't happen in CVS, so we won't bother. */
617
618    if (sb1.st_size != sb2.st_size)
619	ret = 1;
620    else if (sb1.st_size == 0)
621	ret = 0;
622    else
623    {
624	/* FIXME: compute the optimal buffer size by computing the least
625	   common multiple of the files st_blocks field */
626	size_t buf_size = 8 * 1024;
627	size_t read1;
628	size_t read2;
629
630	buf1 = xmalloc (buf_size);
631	buf2 = xmalloc (buf_size);
632
633	do
634	{
635	    read1 = block_read (fd1, buf1, buf_size);
636	    if (read1 == (size_t)-1)
637		error (1, errno, "cannot read file %s for comparing", file1);
638
639	    read2 = block_read (fd2, buf2, buf_size);
640	    if (read2 == (size_t)-1)
641		error (1, errno, "cannot read file %s for comparing", file2);
642
643	    /* assert (read1 == read2); */
644
645	    ret = memcmp(buf1, buf2, read1);
646	} while (ret == 0 && read1 == buf_size);
647
648	free (buf1);
649	free (buf2);
650    }
651
652    (void) close (fd1);
653    (void) close (fd2);
654    return (ret);
655}
656
657/* Generate a unique temporary filename.  Returns a pointer to a newly
658 * malloc'd string containing the name.  Returns successfully or not at
659 * all.
660 *
661 *     THIS FUNCTION IS DEPRECATED!!!  USE cvs_temp_file INSTEAD!!!
662 *
663 * and yes, I know about the way the rcs commands use temp files.  I think
664 * they should be converted too but I don't have time to look into it right
665 * now.
666 */
667char *
668cvs_temp_name ()
669{
670    char *fn;
671    FILE *fp;
672
673    fp = cvs_temp_file (&fn);
674    if (fp == NULL)
675	error (1, errno, "Failed to create temporary file");
676    if (fclose (fp) == EOF)
677	error (0, errno, "Failed to close temporary file %s", fn);
678    return fn;
679}
680
681/* Generate a unique temporary filename and return an open file stream
682 * to the truncated file by that name
683 *
684 *  INPUTS
685 *	filename	where to place the pointer to the newly allocated file
686 *   			name string
687 *
688 *  OUTPUTS
689 *	filename	dereferenced, will point to the newly allocated file
690 *			name string.  This value is undefined if the function
691 *			returns an error.
692 *
693 *  RETURNS
694 *	An open file pointer to a read/write mode empty temporary file with the
695 *	unique file name or NULL on failure.
696 *
697 *  ERRORS
698 *	on error, errno will be set to some value either by CVS_FOPEN or
699 *	whatever system function is called to generate the temporary file name
700 */
701FILE *cvs_temp_file (filename)
702    char **filename;
703{
704    char *fn;
705    FILE *fp;
706
707    /* FIXME - I'd like to be returning NULL here in noexec mode, but I think
708     * some of the rcs & diff functions which rely on a temp file run in
709     * noexec mode too.
710     */
711
712    /* assert (filename != NULL); */
713
714    fn = _tempnam (Tmpdir, "cvs");
715    if (fn == NULL) fp = NULL;
716    else if ((fp = CVS_FOPEN (fn, "w+")) == NULL) free (fn);
717
718    /* tempnam returns a pointer to a newly malloc'd string, so there's
719     * no need for a xstrdup
720     */
721
722    *filename = fn;
723    return fp;
724}
725
726/* Return non-zero iff FILENAME is absolute.
727   Trivial under Unix, but more complicated under other systems.  */
728int
729isabsolute (filename)
730    const char *filename;
731{
732    /* FIXME: This routine seems to interact poorly with
733       strip_trailing_slashes.  For example, specify ":local:r:\" as
734       CVSROOT.  The CVS/Root file will contain ":local:r:" and then
735       isabsolute will complain about the root not being an absolute
736       pathname.  My guess is that strip_trailing_slashes is the right
737       place to fix this.  */
738    return (ISDIRSEP (filename[0])
739            || (filename[0] != '\0'
740                && filename[1] == ':'
741                && ISDIRSEP (filename[2])));
742}
743
744/* Return a pointer into PATH's last component.  */
745char *
746last_component (char *path)
747{
748    char *scan;
749    char *last = 0;
750
751    for (scan = path; *scan; scan++)
752        if (ISDIRSEP (*scan))
753	    last = scan;
754
755    if (last && (last != path))
756        return last + 1;
757    else
758        return path;
759}
760
761
762/* NT has two evironment variables, HOMEPATH and HOMEDRIVE, which,
763   when combined as ${HOMEDRIVE}${HOMEPATH}, give the unix equivalent
764   of HOME.  Some NT users are just too unixy, though, and set the
765   HOME variable themselves.  Therefore, we check for HOME first, and
766   then try to combine the other two if that fails.
767
768   Looking for HOME strikes me as bogus, particularly if the only reason
769   is to cater to "unixy users".  On the other hand, if the reasoning is
770   there should be a single variable, rather than requiring people to
771   set both HOMEDRIVE and HOMEPATH, then it starts to make a little more
772   sense.
773
774   Win95: The system doesn't set HOME, HOMEDRIVE, or HOMEPATH (at
775   least if you set it up as the "all users under one user ID" or
776   whatever the name of that option is).  Based on thing overheard on
777   the net, it seems that users of the pserver client have gotten in
778   the habit of setting HOME (if you don't use pserver, you can
779   probably get away without having a reasonable return from
780   get_homedir.  Of course you lose .cvsrc and .cvsignore, but many
781   users won't notice).  So it would seem that we should be somewhat
782   careful if we try to change the current behavior.
783
784   NT 3.51 or NT 4.0: I haven't checked this myself, but I am told
785   that HOME gets set, but not to the user's home directory.  It is
786   said to be set to c:\users\default by default.  */
787
788char *
789get_homedir ()
790{
791    static char *pathbuf;
792    char *hd, *hp;
793
794    if (pathbuf != NULL)
795	return pathbuf;
796    else if ((hd = getenv ("HOME")))
797	return hd;
798    else if ((hd = getenv ("HOMEDRIVE")) && (hp = getenv ("HOMEPATH")))
799    {
800	pathbuf = xmalloc (strlen (hd) + strlen (hp) + 5);
801	strcpy (pathbuf, hd);
802	strcat (pathbuf, hp);
803
804	return pathbuf;
805    }
806    else
807	return NULL;
808}
809
810/* See cvs.h for description.  */
811void
812expand_wild (argc, argv, pargc, pargv)
813    int argc;
814    char **argv;
815    int *pargc;
816    char ***pargv;
817{
818    int i;
819    int new_argc;
820    char **new_argv;
821    /* Allocated size of new_argv.  We arrange it so there is always room for
822	   one more element.  */
823    int max_new_argc;
824
825    new_argc = 0;
826    /* Add one so this is never zero.  */
827    max_new_argc = argc + 1;
828    new_argv = (char **) xmalloc (max_new_argc * sizeof (char *));
829    for (i = 0; i < argc; ++i)
830    {
831	HANDLE h;
832	WIN32_FIND_DATA fdata;
833
834	/* These variables help us extract the directory name from the
835           given pathname. */
836
837	char *last_forw_slash, *last_back_slash, *end_of_dirname;
838	int dirname_length = 0;
839
840	/* FIXME: If argv[i] is ".", this code will expand it to the
841	   name of the current directory in its parent directory which
842	   will cause start_recursion to do all manner of strange things
843	   with it (culminating in an error).  This breaks "cvs co .".
844	   As nearly as I can guess, this bug has existed since
845	   expand_wild was first created.  At least, it is in CVS 1.9 (I
846	   just tried it).  */
847
848	/* FindFirstFile doesn't return pathnames, so we have to do
849	   this ourselves.  Luckily, it's no big deal, since globbing
850	   characters under Win32s can only occur in the last segment
851	   of the path.  For example,
852                /a/path/q*.h                      valid
853	        /w32/q*.dir/cant/do/this/q*.h     invalid */
854
855	/* Win32 can handle both forward and backward slashes as
856           filenames -- check for both. */
857
858	last_forw_slash = strrchr (argv[i], '/');
859	last_back_slash = strrchr (argv[i], '\\');
860
861#define cvs_max(x,y) ((x >= y) ? (x) : (y))
862
863	/* FIXME: this comparing a NULL pointer to a non-NULL one is
864	   extremely ugly, and I strongly suspect *NOT* sanctioned by
865	   ANSI C.  The code should just use last_component instead.  */
866	end_of_dirname = cvs_max (last_forw_slash, last_back_slash);
867
868	if (end_of_dirname == NULL)
869	  dirname_length = 0;	/* no directory name */
870	else
871	  dirname_length = end_of_dirname - argv[i] + 1; /* include slash */
872
873	h = FindFirstFile (argv[i], &fdata);
874	if (h == INVALID_HANDLE_VALUE)
875	{
876	    if (GetLastError () == ENOENT)
877	    {
878		/* No match.  The file specified didn't contain a wildcard (in which case
879		   we clearly should return it unchanged), or it contained a wildcard which
880		   didn't match (in which case it might be better for it to be an error,
881		   but we don't try to do that).  */
882		new_argv [new_argc++] = xstrdup (argv[i]);
883		if (new_argc == max_new_argc)
884		{
885		    max_new_argc *= 2;
886		    new_argv = xrealloc (new_argv, max_new_argc * sizeof (char *));
887		}
888	    }
889	    else
890	    {
891		error (1, errno, "cannot find %s", argv[i]);
892	    }
893	}
894	else
895	{
896	    while (1)
897	    {
898		new_argv[new_argc] =
899		    (char *) xmalloc (strlen (fdata.cFileName) + 1
900				      + dirname_length);
901
902		/* Copy the directory name, if there is one. */
903
904		if (dirname_length)
905		{
906		    strncpy (new_argv[new_argc], argv[i], dirname_length);
907		    new_argv[new_argc][dirname_length] = '\0';
908		}
909		else
910		    new_argv[new_argc][0] = '\0';
911
912		/* Copy the file name. */
913
914		if (fncmp (argv[i] + dirname_length, fdata.cFileName) == 0)
915		    /* We didn't expand a wildcard; we just matched a filename.
916		       Use the file name as specified rather than the filename
917		       which exists in the directory (they may differ in case).
918		       This is needed to make cvs add on a directory consistently
919		       use the name specified on the command line, but it is
920		       probably a good idea in other contexts too.  */
921		    strcpy (new_argv[new_argc], argv[i]);
922		else
923		    strcat (new_argv[new_argc], fdata.cFileName);
924
925		new_argc++;
926
927		if (new_argc == max_new_argc)
928		{
929		    max_new_argc *= 2;
930		    new_argv = xrealloc (new_argv, max_new_argc * sizeof (char *));
931		}
932		if (!FindNextFile (h, &fdata))
933		{
934		    if (GetLastError () == ERROR_NO_MORE_FILES)
935			break;
936		    else
937			error (1, errno, "cannot find %s", argv[i]);
938		}
939	    }
940	    if (!FindClose (h))
941		error (1, GetLastError (), "cannot close %s", argv[i]);
942	}
943    }
944    *pargc = new_argc;
945    *pargv = new_argv;
946}
947
948static void check_statbuf (const char *file, struct stat *sb)
949{
950    struct tm *newtime;
951    time_t long_time;
952
953    /* Win32 processes file times in a 64 bit format
954       (see Win32 functions SetFileTime and GetFileTime).
955       If the file time on a file doesn't fit into the
956       32 bit time_t format, then stat will set that time
957       to -1.  This would be OK, except that functions
958       like ctime() don't check for validity.  So what we
959       do here is to give a error on -1.  A cleaner solution
960       might be to change CVS's interfaces to return a time
961       in RCS format (for example), and then implement it
962       on Win32 via GetFileTime, but that would be a lot of
963       hair and I'm not sure there is much payoff.  */
964    if (sb->st_mtime == (time_t) -1)
965	error (1, 0, "invalid modification time for %s", file);
966    if (sb->st_ctime == (time_t) -1)
967	/* I'm not sure what this means on windows.  It
968	   might be a creation time (unlike unix)....  */
969	error (1, 0, "invalid ctime for %s", file);
970    if (sb->st_atime == (time_t) -1)
971	error (1, 0, "invalid access time for %s", file);
972
973    time( &long_time );			/* Get time as long integer. */
974    newtime = localtime( &long_time );	/* Convert to local time. */
975
976    /* we know for a fact that the stat function under Windoze NT 4.0 and,
977     * by all reports, many other Windoze systems, will return file times
978     * 3600 seconds too big when daylight savings time is in effect.  This is
979     * a bug since it is defined as returning the time in UTC.
980     *
981     * So correct for it for now.
982     */
983    if (newtime->tm_isdst == 1)
984    {
985	sb->st_ctime -= 3600;
986	sb->st_mtime -= 3600;
987	sb->st_atime -= 3600;
988    }
989}
990
991int
992wnt_stat (const char *file, struct stat *sb)
993{
994    int retval;
995
996    retval = stat (file, sb);
997    if (retval < 0)
998	return retval;
999    check_statbuf (file, sb);
1000    return retval;
1001}
1002
1003int
1004wnt_lstat (const char *file, struct stat *sb)
1005{
1006    int retval;
1007
1008    retval = lstat (file, sb);
1009    if (retval < 0)
1010	return retval;
1011    check_statbuf (file, sb);
1012    return retval;
1013}
1014