xref: /openbsd-src/gnu/usr.bin/cvs/src/filesubr.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
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 "cvs.h"
21 
22 static int deep_remove_dir PROTO((const char *path));
23 
24 /*
25  * Copies "from" to "to".
26  */
27 void
28 copy_file (from, to)
29     const char *from;
30     const char *to;
31 {
32     struct stat sb;
33     struct utimbuf t;
34     int fdin, fdout;
35 
36     if (trace)
37 	(void) fprintf (stderr, "%s-> copy(%s,%s)\n",
38 			CLIENT_SERVER_STR, from, to);
39     if (noexec)
40 	return;
41 
42     /* If the file to be copied is a link or a device, then just create
43        the new link or device appropriately. */
44     if (islink (from))
45     {
46 	char *source = xreadlink (from);
47 	symlink (source, to);
48 	free (source);
49 	return;
50     }
51 
52     if (isdevice (from))
53     {
54 #if defined(HAVE_MKNOD) && defined(HAVE_ST_RDEV)
55 	if (stat (from, &sb) < 0)
56 	    error (1, errno, "cannot stat %s", from);
57 	mknod (to, sb.st_mode, sb.st_rdev);
58 #else
59 	error (1, 0, "cannot copy device files on this system (%s)", from);
60 #endif
61     }
62     else
63     {
64 	/* Not a link or a device... probably a regular file. */
65 	if ((fdin = open (from, O_RDONLY)) < 0)
66 	    error (1, errno, "cannot open %s for copying", from);
67 	if (fstat (fdin, &sb) < 0)
68 	    error (1, errno, "cannot fstat %s", from);
69 	if ((fdout = creat (to, (int) sb.st_mode & 07777)) < 0)
70 	    error (1, errno, "cannot create %s for copying", to);
71 	if (sb.st_size > 0)
72 	{
73 	    char buf[BUFSIZ];
74 	    int n;
75 
76 	    for (;;)
77 	    {
78 		n = read (fdin, buf, sizeof(buf));
79 		if (n == -1)
80 		{
81 #ifdef EINTR
82 		    if (errno == EINTR)
83 			continue;
84 #endif
85 		    error (1, errno, "cannot read file %s for copying", from);
86 		}
87 		else if (n == 0)
88 		    break;
89 
90 		if (write(fdout, buf, n) != n) {
91 		    error (1, errno, "cannot write file %s for copying", to);
92 		}
93 	    }
94 
95 #ifdef HAVE_FSYNC
96 	    if (fsync (fdout))
97 		error (1, errno, "cannot fsync file %s after copying", to);
98 #endif
99 	}
100 
101 	if (close (fdin) < 0)
102 	    error (0, errno, "cannot close %s", from);
103 	if (close (fdout) < 0)
104 	    error (1, errno, "cannot close %s", to);
105     }
106 
107     /* now, set the times for the copied file to match those of the original */
108     memset ((char *) &t, 0, sizeof (t));
109     t.actime = sb.st_atime;
110     t.modtime = sb.st_mtime;
111     (void) utime (to, &t);
112 }
113 
114 /* FIXME-krp: these functions would benefit from caching the char * &
115    stat buf.  */
116 
117 /*
118  * Returns non-zero if the argument file is a directory, or is a symbolic
119  * link which points to a directory.
120  */
121 int
122 isdir (file)
123     const char *file;
124 {
125     struct stat sb;
126 
127     if (stat (file, &sb) < 0)
128 	return (0);
129     return (S_ISDIR (sb.st_mode));
130 }
131 
132 /*
133  * Returns non-zero if the argument file is a symbolic link.
134  */
135 int
136 islink (file)
137     const char *file;
138 {
139 #ifdef S_ISLNK
140     struct stat sb;
141 
142     if (CVS_LSTAT (file, &sb) < 0)
143 	return (0);
144     return (S_ISLNK (sb.st_mode));
145 #else
146     return (0);
147 #endif
148 }
149 
150 /*
151  * Returns non-zero if the argument file is a block or
152  * character special device.
153  */
154 int
155 isdevice (file)
156     const char *file;
157 {
158     struct stat sb;
159 
160     if (CVS_LSTAT (file, &sb) < 0)
161 	return (0);
162 #ifdef S_ISBLK
163     if (S_ISBLK (sb.st_mode))
164 	return 1;
165 #endif
166 #ifdef S_ISCHR
167     if (S_ISCHR (sb.st_mode))
168 	return 1;
169 #endif
170     return 0;
171 }
172 
173 /*
174  * Returns non-zero if the argument file exists.
175  */
176 int
177 isfile (file)
178     const char *file;
179 {
180     return isaccessible(file, F_OK);
181 }
182 
183 /*
184  * Returns non-zero if the argument file is readable.
185  */
186 int
187 isreadable (file)
188     const char *file;
189 {
190     return isaccessible(file, R_OK);
191 }
192 
193 /*
194  * Returns non-zero if the argument file is writable.
195  */
196 int
197 iswritable (file)
198     const char *file;
199 {
200     return isaccessible(file, W_OK);
201 }
202 
203 /*
204  * Returns non-zero if the argument file is accessable according to
205  * mode.  If compiled with SETXID_SUPPORT also works if cvs has setxid
206  * bits set.
207  */
208 int
209 isaccessible (file, mode)
210     const char *file;
211     const int mode;
212 {
213 #ifdef SETXID_SUPPORT
214     struct stat sb;
215     int umask = 0;
216     int gmask = 0;
217     int omask = 0;
218     int uid;
219 
220     if (stat(file, &sb) == -1)
221 	return 0;
222     if (mode == F_OK)
223 	return 1;
224 
225     uid = geteuid();
226     if (uid == 0)		/* superuser */
227     {
228 	if (mode & X_OK)
229 	    return sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH);
230 	else
231 	    return 1;
232     }
233 
234     if (mode & R_OK)
235     {
236 	umask |= S_IRUSR;
237 	gmask |= S_IRGRP;
238 	omask |= S_IROTH;
239     }
240     if (mode & W_OK)
241     {
242 	umask |= S_IWUSR;
243 	gmask |= S_IWGRP;
244 	omask |= S_IWOTH;
245     }
246     if (mode & X_OK)
247     {
248 	umask |= S_IXUSR;
249 	gmask |= S_IXGRP;
250 	omask |= S_IXOTH;
251     }
252 
253     if (sb.st_uid == uid)
254 	return (sb.st_mode & umask) == umask;
255     else if (sb.st_gid == getegid())
256 	return (sb.st_mode & gmask) == gmask;
257     else
258 	return (sb.st_mode & omask) == omask;
259 #else
260     return access(file, mode) == 0;
261 #endif
262 }
263 
264 /*
265  * Open a file and die if it fails
266  */
267 FILE *
268 open_file (name, mode)
269     const char *name;
270     const char *mode;
271 {
272     FILE *fp;
273 
274     if ((fp = fopen (name, mode)) == NULL)
275 	error (1, errno, "cannot open %s", name);
276     return (fp);
277 }
278 
279 /*
280  * Make a directory and die if it fails
281  */
282 void
283 make_directory (name)
284     const char *name;
285 {
286     struct stat sb;
287 
288     if (stat (name, &sb) == 0 && (!S_ISDIR (sb.st_mode)))
289 	    error (0, 0, "%s already exists but is not a directory", name);
290     if (!noexec && mkdir (name, 0777) < 0)
291 	error (1, errno, "cannot make directory %s", name);
292 }
293 
294 /*
295  * Make a path to the argument directory, printing a message if something
296  * goes wrong.
297  */
298 void
299 make_directories (name)
300     const char *name;
301 {
302     char *cp;
303 
304     if (noexec)
305 	return;
306 
307     if (mkdir (name, 0777) == 0 || errno == EEXIST)
308 	return;
309     if (! existence_error (errno))
310     {
311 	error (0, errno, "cannot make path to %s", name);
312 	return;
313     }
314     if ((cp = strrchr (name, '/')) == NULL)
315 	return;
316     *cp = '\0';
317     make_directories (name);
318     *cp++ = '/';
319     if (*cp == '\0')
320 	return;
321     (void) mkdir (name, 0777);
322 }
323 
324 /* Create directory NAME if it does not already exist; fatal error for
325    other errors.  Returns 0 if directory was created; 1 if it already
326    existed.  */
327 int
328 mkdir_if_needed (name)
329     char *name;
330 {
331     if (mkdir (name, 0777) < 0)
332     {
333 	if (!(errno == EEXIST
334 	      || (errno == EACCES && isdir (name))))
335 	    error (1, errno, "cannot make directory %s", name);
336 	return 1;
337     }
338     return 0;
339 }
340 
341 /*
342  * Change the mode of a file, either adding write permissions, or removing
343  * all write permissions.  Either change honors the current umask setting.
344  *
345  * Don't do anything if PreservePermissions is set to `yes'.  This may
346  * have unexpected consequences for some uses of xchmod.
347  */
348 void
349 xchmod (fname, writable)
350     char *fname;
351     int writable;
352 {
353     struct stat sb;
354     mode_t mode, oumask;
355 
356     if (preserve_perms)
357 	return;
358 
359     if (stat (fname, &sb) < 0)
360     {
361 	if (!noexec)
362 	    error (0, errno, "cannot stat %s", fname);
363 	return;
364     }
365     oumask = umask (0);
366     (void) umask (oumask);
367     if (writable)
368     {
369 	mode = sb.st_mode | (~oumask
370 			     & (((sb.st_mode & S_IRUSR) ? S_IWUSR : 0)
371 				| ((sb.st_mode & S_IRGRP) ? S_IWGRP : 0)
372 				| ((sb.st_mode & S_IROTH) ? S_IWOTH : 0)));
373     }
374     else
375     {
376 	mode = sb.st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH) & ~oumask;
377     }
378 
379     if (trace)
380 	(void) fprintf (stderr, "%s-> chmod(%s,%o)\n",
381 			CLIENT_SERVER_STR, fname,
382 			(unsigned int) mode);
383     if (noexec)
384 	return;
385 
386     if (chmod (fname, mode) < 0)
387 	error (0, errno, "cannot change mode of file %s", fname);
388 }
389 
390 /*
391  * Rename a file and die if it fails
392  */
393 void
394 rename_file (from, to)
395     const char *from;
396     const char *to;
397 {
398     if (trace)
399 	(void) fprintf (stderr, "%s-> rename(%s,%s)\n",
400 			CLIENT_SERVER_STR, from, to);
401     if (noexec)
402 	return;
403 
404     if (rename (from, to) < 0)
405 	error (1, errno, "cannot rename file %s to %s", from, to);
406 }
407 
408 /*
409  * unlink a file, if possible.
410  */
411 int
412 unlink_file (f)
413     const char *f;
414 {
415     if (trace)
416 	(void) fprintf (stderr, "%s-> unlink(%s)\n",
417 			CLIENT_SERVER_STR, f);
418     if (noexec)
419 	return (0);
420 
421     return (unlink (f));
422 }
423 
424 /*
425  * Unlink a file or dir, if possible.  If it is a directory do a deep
426  * removal of all of the files in the directory.  Return -1 on error
427  * (in which case errno is set).
428  */
429 int
430 unlink_file_dir (f)
431     const char *f;
432 {
433     struct stat sb;
434 
435     if (trace
436 #ifdef SERVER_SUPPORT
437 	/* This is called by the server parent process in contexts where
438 	   it is not OK to send output (e.g. after we sent "ok" to the
439 	   client).  */
440 	&& !server_active
441 #endif
442 	)
443 	(void) fprintf (stderr, "-> unlink_file_dir(%s)\n", f);
444 
445     if (noexec)
446 	return (0);
447 
448     /* For at least some unices, if root tries to unlink() a directory,
449        instead of doing something rational like returning EISDIR,
450        the system will gleefully go ahead and corrupt the filesystem.
451        So we first call stat() to see if it is OK to call unlink().  This
452        doesn't quite work--if someone creates a directory between the
453        call to stat() and the call to unlink(), we'll still corrupt
454        the filesystem.  Where is the Unix Haters Handbook when you need
455        it?  */
456     if (stat (f, &sb) < 0)
457     {
458 	if (existence_error (errno))
459 	{
460 	    /* The file or directory doesn't exist anyhow.  */
461 	    return -1;
462 	}
463     }
464     else if (S_ISDIR (sb.st_mode))
465 	return deep_remove_dir (f);
466 
467     return unlink (f);
468 }
469 
470 /* Remove a directory and everything it contains.  Returns 0 for
471  * success, -1 for failure (in which case errno is set).
472  */
473 
474 static int
475 deep_remove_dir (path)
476     const char *path;
477 {
478     DIR		  *dirp;
479     struct dirent *dp;
480 
481     if (rmdir (path) != 0)
482     {
483 	if (errno == ENOTEMPTY
484 	    || errno == EEXIST
485 	    /* Ugly workaround for ugly AIX 4.1 (and 3.2) header bug
486 	       (it defines ENOTEMPTY and EEXIST to 17 but actually
487 	       returns 87).  */
488 	    || (ENOTEMPTY == 17 && EEXIST == 17 && errno == 87))
489 	{
490 	    if ((dirp = opendir (path)) == NULL)
491 		/* If unable to open the directory return
492 		 * an error
493 		 */
494 		return -1;
495 
496 	    errno = 0;
497 	    while ((dp = readdir (dirp)) != NULL)
498 	    {
499 		char *buf;
500 
501 		if (strcmp (dp->d_name, ".") == 0 ||
502 			    strcmp (dp->d_name, "..") == 0)
503 		    continue;
504 
505 		buf = xmalloc (strlen (path) + strlen (dp->d_name) + 5);
506 		sprintf (buf, "%s/%s", path, dp->d_name);
507 
508 		/* See comment in unlink_file_dir explanation of why we use
509 		   isdir instead of just calling unlink and checking the
510 		   status.  */
511 		if (isdir(buf))
512 		{
513 		    if (deep_remove_dir(buf))
514 		    {
515 			closedir(dirp);
516 			free (buf);
517 			return -1;
518 		    }
519 		}
520 		else
521 		{
522 		    if (unlink (buf) != 0)
523 		    {
524 			closedir(dirp);
525 			free (buf);
526 			return -1;
527 		    }
528 		}
529 		free (buf);
530 
531 		errno = 0;
532 	    }
533 	    if (errno != 0)
534 	    {
535 		int save_errno = errno;
536 		closedir (dirp);
537 		errno = save_errno;
538 		return -1;
539 	    }
540 	    closedir (dirp);
541 	    return rmdir (path);
542 	}
543 	else
544 	    return -1;
545     }
546 
547     /* Was able to remove the directory return 0 */
548     return 0;
549 }
550 
551 /* Read NCHARS bytes from descriptor FD into BUF.
552    Return the number of characters successfully read.
553    The number returned is always NCHARS unless end-of-file or error.  */
554 static size_t
555 block_read (fd, buf, nchars)
556     int fd;
557     char *buf;
558     size_t nchars;
559 {
560     char *bp = buf;
561     size_t nread;
562 
563     do
564     {
565 	nread = read (fd, bp, nchars);
566 	if (nread == (size_t)-1)
567 	{
568 #ifdef EINTR
569 	    if (errno == EINTR)
570 		continue;
571 #endif
572 	    return (size_t)-1;
573 	}
574 
575 	if (nread == 0)
576 	    break;
577 
578 	bp += nread;
579 	nchars -= nread;
580     } while (nchars != 0);
581 
582     return bp - buf;
583 }
584 
585 
586 /*
587  * Compare "file1" to "file2". Return non-zero if they don't compare exactly.
588  * If FILE1 and FILE2 are special files, compare their salient characteristics
589  * (i.e. major/minor device numbers, links, etc.
590  */
591 int
592 xcmp (file1, file2)
593     const char *file1;
594     const char *file2;
595 {
596     char *buf1, *buf2;
597     struct stat sb1, sb2;
598     int fd1, fd2;
599     int ret;
600 
601     if (CVS_LSTAT (file1, &sb1) < 0)
602 	error (1, errno, "cannot lstat %s", file1);
603     if (CVS_LSTAT (file2, &sb2) < 0)
604 	error (1, errno, "cannot lstat %s", file2);
605 
606     /* If FILE1 and FILE2 are not the same file type, they are unequal. */
607     if ((sb1.st_mode & S_IFMT) != (sb2.st_mode & S_IFMT))
608 	return 1;
609 
610     /* If FILE1 and FILE2 are symlinks, they are equal if they point to
611        the same thing. */
612     if (S_ISLNK (sb1.st_mode) && S_ISLNK (sb2.st_mode))
613     {
614 	int result;
615 	buf1 = xreadlink (file1);
616 	buf2 = xreadlink (file2);
617 	result = (strcmp (buf1, buf2) == 0);
618 	free (buf1);
619 	free (buf2);
620 	return result;
621     }
622 
623     /* If FILE1 and FILE2 are devices, they are equal if their device
624        numbers match. */
625     if (S_ISBLK (sb1.st_mode) || S_ISCHR (sb1.st_mode))
626     {
627 #ifdef HAVE_ST_RDEV
628 	if (sb1.st_rdev == sb2.st_rdev)
629 	    return 0;
630 	else
631 	    return 1;
632 #else
633 	error (1, 0, "cannot compare device files on this system (%s and %s)",
634 	       file1, file2);
635 #endif
636     }
637 
638     if ((fd1 = open (file1, O_RDONLY)) < 0)
639 	error (1, errno, "cannot open file %s for comparing", file1);
640     if ((fd2 = open (file2, O_RDONLY)) < 0)
641 	error (1, errno, "cannot open file %s for comparing", file2);
642 
643     /* A generic file compare routine might compare st_dev & st_ino here
644        to see if the two files being compared are actually the same file.
645        But that won't happen in CVS, so we won't bother. */
646 
647     if (sb1.st_size != sb2.st_size)
648 	ret = 1;
649     else if (sb1.st_size == 0)
650 	ret = 0;
651     else
652     {
653 	/* FIXME: compute the optimal buffer size by computing the least
654 	   common multiple of the files st_blocks field */
655 	size_t buf_size = 8 * 1024;
656 	size_t read1;
657 	size_t read2;
658 
659 	buf1 = xmalloc (buf_size);
660 	buf2 = xmalloc (buf_size);
661 
662 	do
663 	{
664 	    read1 = block_read (fd1, buf1, buf_size);
665 	    if (read1 == (size_t)-1)
666 		error (1, errno, "cannot read file %s for comparing", file1);
667 
668 	    read2 = block_read (fd2, buf2, buf_size);
669 	    if (read2 == (size_t)-1)
670 		error (1, errno, "cannot read file %s for comparing", file2);
671 
672 	    /* assert (read1 == read2); */
673 
674 	    ret = memcmp(buf1, buf2, read1);
675 	} while (ret == 0 && read1 == buf_size);
676 
677 	free (buf1);
678 	free (buf2);
679     }
680 
681     (void) close (fd1);
682     (void) close (fd2);
683     return (ret);
684 }
685 
686 /* Generate a unique temporary filename.  Returns a pointer to a newly
687    malloc'd string containing the name.  Returns successfully or not at
688    all.  */
689 /* There are at least three functions for generating temporary
690    filenames.  We use tempnam (SVID 3) if possible, else mktemp (BSD
691    4.3), and as last resort tmpnam (POSIX). Reason is that tempnam and
692    mktemp both allow to specify the directory in which the temporary
693    file will be created.  */
694 #ifdef HAVE_TEMPNAM
695 char *
696 cvs_temp_name ()
697 {
698     char *retval;
699 
700     retval = tempnam (Tmpdir, "cvs");
701     if (retval == NULL)
702 	error (1, errno, "cannot generate temporary filename");
703     /* tempnam returns a pointer to a newly malloc'd string, so there's
704        no need for a xstrdup  */
705     return retval;
706 }
707 #else
708 char *
709 cvs_temp_name ()
710 {
711 #  ifdef HAVE_MKTEMP
712     char *value;
713     char *retval;
714 
715     value = xmalloc (strlen (Tmpdir) + 40);
716     sprintf (value, "%s/%s", Tmpdir, "cvsXXXXXX" );
717     retval = mktemp (value);
718 
719     if (retval == NULL)
720 	error (1, errno, "cannot generate temporary filename");
721     return value;
722 #  else
723     char value[L_tmpnam + 1];
724     char *retval;
725 
726     retval = tmpnam (value);
727     if (retval == NULL)
728 	error (1, errno, "cannot generate temporary filename");
729     return xstrdup (value);
730 #  endif
731 }
732 #endif
733 
734 /* Return non-zero iff FILENAME is absolute.
735    Trivial under Unix, but more complicated under other systems.  */
736 int
737 isabsolute (filename)
738     const char *filename;
739 {
740     return filename[0] == '/';
741 }
742 
743 /*
744  * Return a string (dynamically allocated) with the name of the file to which
745  * LINK is symlinked.
746  */
747 char *
748 xreadlink (link)
749     const char *link;
750 {
751     char *file = NULL;
752     char *tfile;
753     int buflen = 128;
754     int link_name_len;
755 
756     if (!islink (link))
757 	return NULL;
758 
759     /* Get the name of the file to which `from' is linked.
760        FIXME: what portability issues arise here?  Are readlink &
761        ENAMETOOLONG defined on all systems? -twp */
762     do
763     {
764 	file = xrealloc (file, buflen);
765 	link_name_len = readlink (link, file, buflen - 1);
766 	buflen *= 2;
767     }
768     while (link_name_len < 0 && errno == ENAMETOOLONG);
769 
770     if (link_name_len < 0)
771 	error (1, errno, "cannot readlink %s", link);
772 
773     file[link_name_len] = '\0';
774 
775     tfile = xstrdup (file);
776     free (file);
777 
778     return tfile;
779 }
780 
781 
782 /* Return a pointer into PATH's last component.  */
783 char *
784 last_component (path)
785     char *path;
786 {
787     char *last = strrchr (path, '/');
788 
789     if (last && (last != path))
790         return last + 1;
791     else
792         return path;
793 }
794 
795 /* Return the home directory.  Returns a pointer to storage
796    managed by this function or its callees (currently getenv).
797    This function will return the same thing every time it is
798    called.  Returns NULL if there is no home directory.
799 
800    Note that for a pserver server, this may return root's home
801    directory.  What typically happens is that upon being started from
802    inetd, before switching users, the code in cvsrc.c calls
803    get_homedir which remembers root's home directory in the static
804    variable.  Then the switch happens and get_homedir might return a
805    directory that we don't even have read or execute permissions for
806    (which is bad, when various parts of CVS try to read there).  One
807    fix would be to make the value returned by get_homedir only good
808    until the next call (which would free the old value).  Another fix
809    would be to just always malloc our answer, and let the caller free
810    it (that is best, because some day we may need to be reentrant).
811 
812    The workaround is to put -f in inetd.conf which means that
813    get_homedir won't get called until after the switch in user ID.
814 
815    The whole concept of a "home directory" on the server is pretty
816    iffy, although I suppose some people probably are relying on it for
817    .cvsrc and such, in the cases where it works.  */
818 char *
819 get_homedir ()
820 {
821     static char *home = NULL;
822     char *env = getenv ("HOME");
823     struct passwd *pw;
824 
825     if (home != NULL)
826 	return home;
827 
828     if (env)
829 	home = env;
830     else if ((pw = (struct passwd *) getpwuid (getuid ()))
831 	     && pw->pw_dir)
832 	home = xstrdup (pw->pw_dir);
833     else
834 	return 0;
835 
836     return home;
837 }
838 
839 /* See cvs.h for description.  On unix this does nothing, because the
840    shell expands the wildcards.  */
841 void
842 expand_wild (argc, argv, pargc, pargv)
843     int argc;
844     char **argv;
845     int *pargc;
846     char ***pargv;
847 {
848     int i;
849     *pargc = argc;
850     *pargv = (char **) xmalloc (argc * sizeof (char *));
851     for (i = 0; i < argc; ++i)
852 	(*pargv)[i] = xstrdup (argv[i]);
853 }
854 
855 #ifdef SERVER_SUPPORT
856 /* Case-insensitive string compare.  I know that some systems
857    have such a routine, but I'm not sure I see any reasons for
858    dealing with the hair of figuring out whether they do (I haven't
859    looked into whether this is a performance bottleneck; I would guess
860    not).  */
861 int
862 cvs_casecmp (str1, str2)
863     char *str1;
864     char *str2;
865 {
866     char *p;
867     char *q;
868     int pqdiff;
869 
870     p = str1;
871     q = str2;
872     while ((pqdiff = tolower (*p) - tolower (*q)) == 0)
873     {
874 	if (*p == '\0')
875 	    return 0;
876 	++p;
877 	++q;
878     }
879     return pqdiff;
880 }
881 
882 /* Case-insensitive file open.  As you can see, this is an expensive
883    call.  We don't regard it as our main strategy for dealing with
884    case-insensitivity.  Returns errno code or 0 for success.  Puts the
885    new file in *FP.  NAME and MODE are as for fopen.  If PATHP is not
886    NULL, then put a malloc'd string containing the pathname as found
887    into *PATHP.  *PATHP is only set if the return value is 0.
888 
889    Might be cleaner to separate the file finding (which just gives
890    *PATHP) from the file opening (which the caller can do).  For one
891    thing, might make it easier to know whether to put NAME or *PATHP
892    into error messages.  */
893 int
894 fopen_case (name, mode, fp, pathp)
895     char *name;
896     char *mode;
897     FILE **fp;
898     char **pathp;
899 {
900     struct dirent *dp;
901     DIR *dirp;
902     char *dir;
903     char *fname;
904     char *found_name;
905     int retval;
906 
907     /* Separate NAME into directory DIR and filename within the directory
908        FNAME.  */
909     dir = xstrdup (name);
910     fname = strrchr (dir, '/');
911     if (fname == NULL)
912 	error (1, 0, "internal error: relative pathname in fopen_case");
913     *fname++ = '\0';
914 
915     found_name = NULL;
916     dirp = CVS_OPENDIR (dir);
917     if (dirp == NULL)
918     {
919 	if (existence_error (errno))
920 	{
921 	    /* This can happen if we are looking in the Attic and the Attic
922 	       directory does not exist.  Return the error to the caller;
923 	       they know what to do with it.  */
924 	    retval = errno;
925 	    goto out;
926 	}
927 	else
928 	{
929 	    /* Give a fatal error; that way the error message can be
930 	       more specific than if we returned the error to the caller.  */
931 	    error (1, errno, "cannot read directory %s", dir);
932 	}
933     }
934     errno = 0;
935     while ((dp = readdir (dirp)) != NULL)
936     {
937 	if (cvs_casecmp (dp->d_name, fname) == 0)
938 	{
939 	    if (found_name != NULL)
940 		error (1, 0, "%s is ambiguous; could mean %s or %s",
941 		       fname, dp->d_name, found_name);
942 	    found_name = xstrdup (dp->d_name);
943 	}
944     }
945     if (errno != 0)
946 	error (1, errno, "cannot read directory %s", dir);
947     closedir (dirp);
948 
949     if (found_name == NULL)
950     {
951 	*fp = NULL;
952 	retval = ENOENT;
953     }
954     else
955     {
956 	char *p;
957 
958 	/* Copy the found name back into DIR.  We are assuming that
959 	   found_name is the same length as fname, which is true as
960 	   long as the above code is just ignoring case and not other
961 	   aspects of filename syntax.  */
962 	p = dir + strlen (dir);
963 	*p++ = '/';
964 	strcpy (p, found_name);
965 	*fp = fopen (dir, mode);
966 	if (*fp == NULL)
967 	    retval = errno;
968 	else
969 	    retval = 0;
970     }
971 
972     if (pathp == NULL)
973 	free (dir);
974     else if (retval != 0)
975 	free (dir);
976     else
977 	*pathp = dir;
978     free (found_name);
979  out:
980     return retval;
981 }
982 #endif /* SERVER_SUPPORT */
983