xref: /netbsd/external/gpl2/xcvs/dist/src/filesubr.c (revision 3feae4e4)
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 #include <sys/cdefs.h>
16 __RCSID("$NetBSD: filesubr.c,v 1.6 2017/09/15 21:03:26 christos Exp $");
17 
18 /* These functions were moved out of subr.c because they need different
19    definitions under operating systems (like, say, Windows NT) with different
20    file system semantics.  */
21 
22 #include "cvs.h"
23 #include "lstat.h"
24 #include "save-cwd.h"
25 #include "xsize.h"
26 
27 static int deep_remove_dir (const char *path);
28 #ifndef S_ISBLK
29 #define S_ISBLK(a) 0
30 #endif
31 #ifndef S_ISCHR
32 #define S_ISCHR(a) 0
33 #endif
34 #define IS_DEVICE(sbp) (S_ISBLK((sbp)->st_mode) || S_ISCHR((sbp)->st_mode))
35 
36 /*
37  * Copies "from" to "to".
38  */
39 void
copy_file(const char * from,const char * to)40 copy_file (const char *from, const char *to)
41 {
42     struct stat sb;
43     struct utimbuf t;
44     int fdin, fdout;
45     ssize_t rsize;
46 
47     TRACE (TRACE_FUNCTION, "copy(%s,%s)", from, to);
48 
49     if (noexec)
50 	return;
51 
52     /* If the file to be copied is a link or a device, then just create
53        the new link or device appropriately. */
54     if ((rsize = islink (from, &sb)) > 0)
55     {
56 	char *source = Xreadlink (from, rsize);
57 	if (symlink (source, to) == -1)
58 	    error (1, errno, "cannot symlink %s to %s", source, to);
59 	free (source);
60 	return;
61     }
62 
63     if (sb.st_ino != -1 && IS_DEVICE (&sb))
64     {
65 #if defined(HAVE_MKNOD) && defined(HAVE_STRUCT_STAT_ST_RDEV)
66 	mknod (to, sb.st_mode, sb.st_rdev);
67 #else
68 	error (1, 0, "cannot copy device files on this system (%s)", from);
69 #endif
70     }
71     else
72     {
73 	/* Not a link or a device... probably a regular file. */
74 	if ((fdin = open (from, O_RDONLY)) < 0)
75 	    error (1, errno, "cannot open %s for copying", from);
76 	if (fstat (fdin, &sb) < 0)
77 	    error (1, errno, "cannot fstat %s", from);
78 	if ((fdout = creat (to, (int) sb.st_mode & 07777)) < 0)
79 	    error (1, errno, "cannot create %s for copying", to);
80 	if (sb.st_size > 0)
81 	{
82 	    char buf[BUFSIZ];
83 	    int n;
84 
85 	    for (;;)
86 	    {
87 		n = read (fdin, buf, sizeof(buf));
88 		if (n == -1)
89 		{
90 #ifdef EINTR
91 		    if (errno == EINTR)
92 			continue;
93 #endif
94 		    error (1, errno, "cannot read file %s for copying", from);
95 		}
96 		else if (n == 0)
97 		    break;
98 
99 		if (write(fdout, buf, n) != n) {
100 		    error (1, errno, "cannot write file %s for copying", to);
101 		}
102 	    }
103 	}
104 
105 	if (close (fdin) < 0)
106 	    error (0, errno, "cannot close %s", from);
107 	if (close (fdout) < 0)
108 	    error (1, errno, "cannot close %s", to);
109     }
110 
111     /* preserve last access & modification times */
112     memset ((char *) &t, 0, sizeof (t));
113     t.actime = sb.st_atime;
114     t.modtime = sb.st_mtime;
115     (void) utime (to, &t);
116 }
117 
118 
119 
120 /* FIXME-krp: these functions would benefit from caching the char * &
121    stat buf.  */
122 
123 /*
124  * Returns true if the argument file is a directory, or is a symbolic
125  * link which points to a directory.
126  */
127 bool
isdir(const char * file)128 isdir (const char *file)
129 {
130     struct stat sb;
131 
132     if (stat (file, &sb) < 0)
133 	return false;
134     return S_ISDIR (sb.st_mode);
135 }
136 
137 
138 
139 /*
140  * Returns 0 if the argument file is not a symbolic link.
141  * Returns size of the link if it is a symbolic link.
142  */
143 ssize_t
islink(const char * file,struct stat * sbp)144 islink (const char *file, struct stat *sbp)
145 {
146     ssize_t retsize = 0;
147 #ifdef S_ISLNK
148     struct stat sb;
149     if (sbp == NULL)
150 	sbp = &sb;
151 
152     if (lstat (file, sbp) < 0) {
153 	sbp->st_ino = -1;
154 	return 0;
155     }
156     if (S_ISLNK (sbp->st_mode))
157 	retsize = sbp->st_size;
158 #else
159     sbp->st_ino = -1;
160 #endif
161     return retsize;
162 }
163 
164 
165 
166 /*
167  * Returns true if the argument file is a block or
168  * character special device.
169  */
170 bool
isdevice(const char * file)171 isdevice (const char *file)
172 {
173     struct stat sb;
174 
175     if (lstat (file, &sb) < 0)
176 	return false;
177     return IS_DEVICE(&sb);
178 }
179 
180 
181 
182 /*
183  * Returns true if the argument file exists.
184  */
185 bool
isfile(const char * file)186 isfile (const char *file)
187 {
188     return isaccessible (file, F_OK);
189 }
190 
191 #ifdef SETXID_SUPPORT
192 int
ingroup(gid_t gid)193 ingroup(gid_t gid)
194 {
195     gid_t *gidp;
196     int i, ngroups;
197 
198     if (gid == getegid())
199 	return 1;
200 
201     ngroups = getgroups(0, NULL);
202     if (ngroups == -1)
203 	return 0;
204 
205     if ((gidp = malloc(sizeof(gid_t) * ngroups)) == NULL)
206 	return 0;
207 
208     if (getgroups(ngroups, gidp) == -1) {
209 	free(gidp);
210 	return 0;
211     }
212 
213     for (i = 0; i < ngroups; i++)
214 	if (gid == gidp[i])
215 	    break;
216 
217     free(gidp);
218     return i != ngroups;
219 }
220 #endif
221 
222 /*
223  * Returns non-zero if the argument file is readable.
224  */
225 bool
isreadable(const char * file)226 isreadable (const char *file)
227 {
228     return isaccessible (file, R_OK);
229 }
230 
231 
232 
233 /*
234  * Returns non-zero if the argument file is writable.
235  */
236 bool
iswritable(const char * file)237 iswritable (const char *file)
238 {
239     return isaccessible (file, W_OK);
240 }
241 
242 
243 
244 /*
245  * Returns true if the argument file is accessable according to
246  * mode.  If compiled with SETXID_SUPPORT also works if cvs has setxid
247  * bits set.
248  */
249 bool
isaccessible(const char * file,const int mode)250 isaccessible (const char *file, const int mode)
251 {
252 #ifdef SETXID_SUPPORT
253     struct stat sb;
254     int umask = 0;
255     int gmask = 0;
256     int omask = 0;
257     int uid, mask;
258 
259     if (stat (file, &sb)== -1)
260 	return false;
261     if (mode == F_OK)
262 	return true;
263 
264     uid = geteuid();
265     if (uid == 0)		/* superuser */
266     {
267 	if (!(mode & X_OK) || (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
268 	    return true;
269 
270 	errno = EACCES;
271 	return false;
272     }
273 
274     if (mode & R_OK)
275     {
276 	umask |= S_IRUSR;
277 	gmask |= S_IRGRP;
278 	omask |= S_IROTH;
279     }
280     if (mode & W_OK)
281     {
282 	umask |= S_IWUSR;
283 	gmask |= S_IWGRP;
284 	omask |= S_IWOTH;
285     }
286     if (mode & X_OK)
287     {
288 	umask |= S_IXUSR;
289 	gmask |= S_IXGRP;
290 	omask |= S_IXOTH;
291     }
292 
293     mask = sb.st_uid == uid ? umask : ingroup(sb.st_gid) ? gmask : omask;
294     if ((sb.st_mode & mask) == mask)
295 	return true;
296     errno = EACCES;
297     return false;
298 #else /* !SETXID_SUPPORT */
299     return access (file, mode) == 0;
300 #endif /* SETXID_SUPPORT */
301 }
302 
303 
304 
305 /*
306  * Make a directory and die if it fails
307  */
308 void
make_directory(const char * name)309 make_directory (const char *name)
310 {
311     struct stat sb;
312 
313     if (stat (name, &sb) == 0 && (!S_ISDIR (sb.st_mode)))
314 	    error (0, 0, "%s already exists but is not a directory", name);
315     if (!noexec && mkdir (name, 0777) < 0)
316 	error (1, errno, "cannot make directory %s", name);
317 }
318 
319 /*
320  * Make a path to the argument directory, printing a message if something
321  * goes wrong.
322  */
323 void
make_directories(const char * name)324 make_directories (const char *name)
325 {
326     char *cp;
327 
328     if (noexec)
329 	return;
330 
331     if (mkdir (name, 0777) == 0 || errno == EEXIST)
332 	return;
333     if (! existence_error (errno))
334     {
335 	error (0, errno, "cannot make path to %s", name);
336 	return;
337     }
338     if ((cp = strrchr (name, '/')) == NULL)
339 	return;
340     *cp = '\0';
341     make_directories (name);
342     *cp++ = '/';
343     if (*cp == '\0')
344 	return;
345     (void) mkdir (name, 0777);
346 }
347 
348 /* Create directory NAME if it does not already exist; fatal error for
349    other errors.  Returns 0 if directory was created; 1 if it already
350    existed.  */
351 int
mkdir_if_needed(const char * name)352 mkdir_if_needed (const char *name)
353 {
354     if (mkdir (name, 0777) < 0)
355     {
356 	int save_errno = errno;
357 	if (save_errno != EEXIST && !isdir (name))
358 	    error (1, save_errno, "cannot make directory %s", name);
359 	return 1;
360     }
361     return 0;
362 }
363 
364 /*
365  * Change the mode of a file, either adding write permissions, or removing
366  * all write permissions.  Either change honors the current umask setting.
367  *
368  * Don't do anything if PreservePermissions is set to `yes'.  This may
369  * have unexpected consequences for some uses of xchmod.
370  */
371 void
xchmod(const char * fname,int writable)372 xchmod (const char *fname, int writable)
373 {
374     struct stat sb;
375     mode_t mode, oumask;
376 
377 #ifdef PRESERVE_PERMISSIONS_SUPPORT
378     if (config->preserve_perms)
379 	return;
380 #endif /* PRESERVE_PERMISSIONS_SUPPORT */
381 
382     if (stat (fname, &sb) < 0)
383     {
384 	if (!noexec)
385 	    error (0, errno, "cannot stat %s", fname);
386 	return;
387     }
388     oumask = umask (0);
389     (void) umask (oumask);
390     if (writable)
391     {
392 	mode = sb.st_mode | (~oumask
393 			     & (((sb.st_mode & S_IRUSR) ? S_IWUSR : 0)
394 				| ((sb.st_mode & S_IRGRP) ? S_IWGRP : 0)
395 				| ((sb.st_mode & S_IROTH) ? S_IWOTH : 0)));
396     }
397     else
398     {
399 	mode = sb.st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH) & ~oumask;
400     }
401 
402     TRACE (TRACE_FUNCTION, "chmod(%s,%o)", fname, (unsigned int) mode);
403 
404     if (noexec)
405 	return;
406 
407     if (chmod (fname, mode) < 0)
408 	error (0, errno, "cannot change mode of file %s", fname);
409 }
410 
411 /*
412  * Rename a file and die if it fails
413  */
414 void
rename_file(const char * from,const char * to)415 rename_file (const char *from, const char *to)
416 {
417     TRACE (TRACE_FUNCTION, "rename(%s,%s)", from, to);
418 
419     if (noexec)
420 	return;
421 
422     if (rename (from, to) < 0)
423 	error (1, errno, "cannot rename file %s to %s", from, to);
424 }
425 
426 /*
427  * unlink a file, if possible.
428  */
429 int
unlink_file(const char * f)430 unlink_file (const char *f)
431 {
432     TRACE (TRACE_FUNCTION, "unlink_file(%s)", f);
433 
434     if (noexec)
435 	return (0);
436 
437     return (CVS_UNLINK (f));
438 }
439 
440 
441 
442 /*
443  * Unlink a file or dir, if possible.  If it is a directory do a deep
444  * removal of all of the files in the directory.  Return -1 on error
445  * (in which case errno is set).
446  */
447 int
unlink_file_dir(const char * f)448 unlink_file_dir (const char *f)
449 {
450     struct stat sb;
451 
452     /* This is called by the server parent process in contexts where
453        it is not OK to send output (e.g. after we sent "ok" to the
454        client).  */
455     if (!server_active)
456 	TRACE (TRACE_FUNCTION, "unlink_file_dir(%s)", f);
457 
458     if (noexec)
459 	return 0;
460 
461     /* For at least some unices, if root tries to unlink() a directory,
462        instead of doing something rational like returning EISDIR,
463        the system will gleefully go ahead and corrupt the filesystem.
464        So we first call stat() to see if it is OK to call unlink().  This
465        doesn't quite work--if someone creates a directory between the
466        call to stat() and the call to unlink(), we'll still corrupt
467        the filesystem.  Where is the Unix Haters Handbook when you need
468        it?  */
469     if (stat (f, &sb) < 0)
470     {
471 	if (existence_error (errno))
472 	{
473 	    /* The file or directory doesn't exist anyhow.  */
474 	    return -1;
475 	}
476     }
477     else if (S_ISDIR (sb.st_mode))
478 	return deep_remove_dir (f);
479 
480     return CVS_UNLINK (f);
481 }
482 
483 
484 
485 /* Remove a directory and everything it contains.  Returns 0 for
486  * success, -1 for failure (in which case errno is set).
487  */
488 
489 static int
deep_remove_dir(const char * path)490 deep_remove_dir (const char *path)
491 {
492     DIR		  *dirp;
493     struct dirent *dp;
494 
495     if (rmdir (path) != 0)
496     {
497 	if (errno == ENOTEMPTY
498 	    || errno == EEXIST
499 	    /* Ugly workaround for ugly AIX 4.1 (and 3.2) header bug
500 	       (it defines ENOTEMPTY and EEXIST to 17 but actually
501 	       returns 87).  */
502 	    || (ENOTEMPTY == 17 && EEXIST == 17 && errno == 87))
503 	{
504 	    if ((dirp = CVS_OPENDIR (path)) == NULL)
505 		/* If unable to open the directory return
506 		 * an error
507 		 */
508 		return -1;
509 
510 	    errno = 0;
511 	    while ((dp = CVS_READDIR (dirp)) != NULL)
512 	    {
513 		char *buf;
514 
515 		if (strcmp (dp->d_name, ".") == 0 ||
516 			    strcmp (dp->d_name, "..") == 0)
517 		    continue;
518 
519 		buf = Xasprintf ("%s/%s", path, dp->d_name);
520 
521 		/* See comment in unlink_file_dir explanation of why we use
522 		   isdir instead of just calling unlink and checking the
523 		   status.  */
524 		if (isdir (buf))
525 		{
526 		    if (deep_remove_dir (buf))
527 		    {
528 			CVS_CLOSEDIR (dirp);
529 			free (buf);
530 			return -1;
531 		    }
532 		}
533 		else
534 		{
535 		    if (CVS_UNLINK (buf) != 0)
536 		    {
537 			CVS_CLOSEDIR (dirp);
538 			free (buf);
539 			return -1;
540 		    }
541 		}
542 		free (buf);
543 
544 		errno = 0;
545 	    }
546 	    if (errno != 0)
547 	    {
548 		int save_errno = errno;
549 		CVS_CLOSEDIR (dirp);
550 		errno = save_errno;
551 		return -1;
552 	    }
553 	    CVS_CLOSEDIR (dirp);
554 	    return rmdir (path);
555 	}
556 	else
557 	    return -1;
558     }
559 
560     /* Was able to remove the directory return 0 */
561     return 0;
562 }
563 
564 
565 
566 /* Read NCHARS bytes from descriptor FD into BUF.
567    Return the number of characters successfully read.
568    The number returned is always NCHARS unless end-of-file or error.  */
569 static size_t
block_read(int fd,char * buf,size_t nchars)570 block_read (int fd, char *buf, size_t nchars)
571 {
572     char *bp = buf;
573     size_t nread;
574 
575     do
576     {
577 	nread = read (fd, bp, nchars);
578 	if (nread == (size_t)-1)
579 	{
580 #ifdef EINTR
581 	    if (errno == EINTR)
582 		continue;
583 #endif
584 	    return (size_t)-1;
585 	}
586 
587 	if (nread == 0)
588 	    break;
589 
590 	bp += nread;
591 	nchars -= nread;
592     } while (nchars != 0);
593 
594     return bp - buf;
595 }
596 
597 
598 /*
599  * Compare "file1" to "file2". Return non-zero if they don't compare exactly.
600  * If FILE1 and FILE2 are special files, compare their salient characteristics
601  * (i.e. major/minor device numbers, links, etc.
602  */
603 int
xcmp(const char * file1,const char * file2)604 xcmp (const char *file1, const char *file2)
605 {
606     char *buf1, *buf2;
607     struct stat sb1, sb2;
608     int fd1, fd2;
609     int ret;
610 
611     if (lstat (file1, &sb1) < 0)
612 	error (1, errno, "cannot lstat %s", file1);
613     if (lstat (file2, &sb2) < 0)
614 	error (1, errno, "cannot lstat %s", file2);
615 
616     /* If FILE1 and FILE2 are not the same file type, they are unequal. */
617     if ((sb1.st_mode & S_IFMT) != (sb2.st_mode & S_IFMT))
618 	return 1;
619 
620     /* If FILE1 and FILE2 are symlinks, they are equal if they point to
621        the same thing. */
622 #ifdef S_ISLNK
623     if (S_ISLNK (sb1.st_mode) && S_ISLNK (sb2.st_mode))
624     {
625 	int result;
626 	buf1 = Xreadlink (file1, sb1.st_size);
627 	buf2 = Xreadlink (file2, sb2.st_size);
628 	result = (strcmp (buf1, buf2) == 0);
629 	free (buf1);
630 	free (buf2);
631 	return result;
632     }
633 #endif
634 
635     /* If FILE1 and FILE2 are devices, they are equal if their device
636        numbers match. */
637     if (S_ISBLK (sb1.st_mode) || S_ISCHR (sb1.st_mode))
638     {
639 #ifdef HAVE_STRUCT_STAT_ST_RDEV
640 	if (sb1.st_rdev == sb2.st_rdev)
641 	    return 0;
642 	else
643 	    return 1;
644 #else
645 	error (1, 0, "cannot compare device files on this system (%s and %s)",
646 	       file1, file2);
647 #endif
648     }
649 
650     if ((fd1 = open (file1, O_RDONLY)) < 0)
651 	error (1, errno, "cannot open file %s for comparing", file1);
652     if ((fd2 = open (file2, O_RDONLY)) < 0)
653 	error (1, errno, "cannot open file %s for comparing", file2);
654 
655     /* A generic file compare routine might compare st_dev & st_ino here
656        to see if the two files being compared are actually the same file.
657        But that won't happen in CVS, so we won't bother. */
658 
659     if (sb1.st_size != sb2.st_size)
660 	ret = 1;
661     else if (sb1.st_size == 0)
662 	ret = 0;
663     else
664     {
665 	/* FIXME: compute the optimal buffer size by computing the least
666 	   common multiple of the files st_blocks field */
667 	size_t buf_size = 8 * 1024;
668 	size_t read1;
669 	size_t read2;
670 
671 	buf1 = xmalloc (buf_size);
672 	buf2 = xmalloc (buf_size);
673 
674 	do
675 	{
676 	    read1 = block_read (fd1, buf1, buf_size);
677 	    if (read1 == (size_t)-1)
678 		error (1, errno, "cannot read file %s for comparing", file1);
679 
680 	    read2 = block_read (fd2, buf2, buf_size);
681 	    if (read2 == (size_t)-1)
682 		error (1, errno, "cannot read file %s for comparing", file2);
683 
684 	    /* assert (read1 == read2); */
685 
686 	    ret = memcmp(buf1, buf2, read1);
687 	} while (ret == 0 && read1 == buf_size);
688 
689 	free (buf1);
690 	free (buf2);
691     }
692 
693     (void) close (fd1);
694     (void) close (fd2);
695     return (ret);
696 }
697 
698 /* Generate a unique temporary filename.  Returns a pointer to a newly
699  * malloc'd string containing the name.  Returns successfully or not at
700  * all.
701  *
702  *     THIS FUNCTION IS DEPRECATED!!!  USE cvs_temp_file INSTEAD!!!
703  *
704  * and yes, I know about the way the rcs commands use temp files.  I think
705  * they should be converted too but I don't have time to look into it right
706  * now.
707  */
708 char *
cvs_temp_name(void)709 cvs_temp_name (void)
710 {
711     char *fn;
712     FILE *fp;
713 
714     fp = cvs_temp_file (&fn);
715     if (fp == NULL)
716 	error (1, errno, "Failed to create temporary file");
717     if (fclose (fp) == EOF)
718 	error (0, errno, "Failed to close temporary file %s", fn);
719     return fn;
720 }
721 
722 /* Generate a unique temporary filename and return an open file stream
723  * to the truncated file by that name
724  *
725  *  INPUTS
726  *	filename	where to place the pointer to the newly allocated file
727  *   			name string
728  *
729  *  OUTPUTS
730  *	filename	dereferenced, will point to the newly allocated file
731  *			name string.  This value is undefined if the function
732  *			returns an error.
733  *
734  *  RETURNS
735  *	An open file pointer to a read/write mode empty temporary file with the
736  *	unique file name or NULL on failure.
737  *
738  *  ERRORS
739  *	On error, errno will be set to some value either by CVS_FOPEN or
740  *	whatever system function is called to generate the temporary file name.
741  *	The value of filename is undefined on error.
742  */
743 FILE *
cvs_temp_file(char ** filename)744 cvs_temp_file (char **filename)
745 {
746     char *fn;
747     FILE *fp;
748     int fd;
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     fn = Xasprintf ("%s/%s", get_cvs_tmp_dir (), "cvsXXXXXX");
758     fd = mkstemp (fn);
759 
760     /* a NULL return will be interpreted by callers as an error and
761      * errno should still be set
762      */
763     if (fd == -1)
764 	fp = NULL;
765     else if ((fp = CVS_FDOPEN (fd, "w+")) == NULL)
766     {
767 	/* Attempt to close and unlink the file since mkstemp returned
768 	 * sucessfully and we believe it's been created and opened.
769 	 */
770  	int save_errno = errno;
771 	if (close (fd))
772 	    error (0, errno, "Failed to close temporary file %s", fn);
773 	if (CVS_UNLINK (fn))
774 	    error (0, errno, "Failed to unlink temporary file %s", fn);
775 	errno = save_errno;
776     }
777 
778     if (fp == NULL)
779 	free (fn);
780 
781     /* mkstemp is defined to open mode 0600 using glibc 2.0.7+.  There used
782      * to be a complicated #ifdef checking the library versions here and then
783      * a chmod 0600 on the temp file for versions of glibc less than 2.1.  This
784      * is rather a special case, leaves a race condition open regardless, and
785      * one could hope that sysadmins have read the relevant security
786      * announcements and upgraded by now to a version with a fix committed in
787      * January of 1999.
788      *
789      * If it is decided at some point that old, buggy versions of glibc should
790      * still be catered to, a umask of 0600 should be set before file creation
791      * instead then reset after file creation since this would avoid the race
792      * condition that the chmod left open to exploitation.
793      */
794 
795     *filename = fn;
796     return fp;
797 }
798 
799 
800 
801 /* Return a pointer into PATH's last component.  */
802 const char *
last_component(const char * path)803 last_component (const char *path)
804 {
805     const char *last = strrchr (path, '/');
806 
807     if (last && (last != path))
808         return last + 1;
809     else
810         return path;
811 }
812 
813 
814 
815 /* Return the home directory.  Returns a pointer to storage
816    managed by this function or its callees (currently getenv).
817    This function will return the same thing every time it is
818    called.  Returns NULL if there is no home directory.
819 
820    Note that for a pserver server, this may return root's home
821    directory.  What typically happens is that upon being started from
822    inetd, before switching users, the code in cvsrc.c calls
823    get_homedir which remembers root's home directory in the static
824    variable.  Then the switch happens and get_homedir might return a
825    directory that we don't even have read or execute permissions for
826    (which is bad, when various parts of CVS try to read there).  One
827    fix would be to make the value returned by get_homedir only good
828    until the next call (which would free the old value).  Another fix
829    would be to just always malloc our answer, and let the caller free
830    it (that is best, because some day we may need to be reentrant).
831 
832    The workaround is to put -f in inetd.conf which means that
833    get_homedir won't get called until after the switch in user ID.
834 
835    The whole concept of a "home directory" on the server is pretty
836    iffy, although I suppose some people probably are relying on it for
837    .cvsrc and such, in the cases where it works.  */
838 char *
get_homedir(void)839 get_homedir (void)
840 {
841     static char *home = NULL;
842     char *env;
843     struct passwd *pw;
844 
845     if (home != NULL)
846 	return home;
847 
848     if (!server_active && (env = getenv ("HOME")) != NULL)
849 	home = env;
850     else if ((pw = (struct passwd *) getpwuid (getuid ()))
851 	     && pw->pw_dir)
852 	home = xstrdup (pw->pw_dir);
853     else
854 	return 0;
855 
856     return home;
857 }
858 
859 /* Compose a path to a file in the home directory.  This is necessary because
860  * of different behavior on UNIX and VMS.  See the notes in vms/filesubr.c.
861  *
862  * A more clean solution would be something more along the lines of a
863  * "join a directory to a filename" kind of thing which was not specific to
864  * the homedir.  This should aid portability between UNIX, Mac, Windows, VMS,
865  * and possibly others.  This is already handled by Perl - it might be
866  * interesting to see how much of the code was written in C since Perl is under
867  * the GPL and the Artistic license - we might be able to use it.
868  */
869 char *
strcat_filename_onto_homedir(const char * dir,const char * file)870 strcat_filename_onto_homedir (const char *dir, const char *file)
871 {
872     char *path = Xasprintf ("%s/%s", dir, file);
873     return path;
874 }
875 
876 /* See cvs.h for description.  On unix this does nothing, because the
877    shell expands the wildcards.  */
878 void
expand_wild(int argc,char ** argv,int * pargc,char *** pargv)879 expand_wild (int argc, char **argv, int *pargc, char ***pargv)
880 {
881     int i;
882     if (size_overflow_p (xtimes (argc, sizeof (char *)))) {
883 	*pargc = 0;
884 	*pargv = NULL;
885 	error (0, 0, "expand_wild: too many arguments");
886 	return;
887     }
888     *pargc = argc;
889     *pargv = xnmalloc (argc, sizeof (char *));
890     for (i = 0; i < argc; ++i)
891 	(*pargv)[i] = xstrdup (argv[i]);
892 }
893 
894 
895 
896 static char *tmpdir_env;
897 
898 /* Return path to temp directory.
899  */
900 const char *
get_system_temp_dir(void)901 get_system_temp_dir (void)
902 {
903     if (!tmpdir_env) tmpdir_env = getenv (TMPDIR_ENV);
904     return tmpdir_env;
905 }
906 
907 
908 
909 void
push_env_temp_dir(void)910 push_env_temp_dir (void)
911 {
912     const char *tmpdir = get_cvs_tmp_dir ();
913     if (tmpdir_env && strcmp (tmpdir_env, tmpdir))
914 	setenv (TMPDIR_ENV, tmpdir, 1);
915 }
916