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