Home | History | Annotate | Line # | Download | only in src
      1 /* filesubr.c --- subroutines for dealing with files
      2    Jim Blandy <jimb (at) 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.7 2025/05/25 15:20:17 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
     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
    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
    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
    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
    186 isfile (const char *file)
    187 {
    188     return isaccessible (file, F_OK);
    189 }
    190 
    191 #ifdef SETXID_SUPPORT
    192 int
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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 		return 1;
    680 	    }
    681 
    682 	    read2 = block_read (fd2, buf2, buf_size);
    683 	    if (read2 == (size_t)-1) {
    684 		error (1, errno, "cannot read file %s for comparing", file2);
    685 		return 1;
    686 	    }
    687 
    688 	    /* assert (read1 == read2); */
    689 
    690 	    ret = memcmp(buf1, buf2, read1);
    691 	} while (ret == 0 && read1 == buf_size);
    692 
    693 	free (buf1);
    694 	free (buf2);
    695     }
    696 
    697     (void) close (fd1);
    698     (void) close (fd2);
    699     return (ret);
    700 }
    701 
    702 /* Generate a unique temporary filename.  Returns a pointer to a newly
    704  * malloc'd string containing the name.  Returns successfully or not at
    705  * all.
    706  *
    707  *     THIS FUNCTION IS DEPRECATED!!!  USE cvs_temp_file INSTEAD!!!
    708  *
    709  * and yes, I know about the way the rcs commands use temp files.  I think
    710  * they should be converted too but I don't have time to look into it right
    711  * now.
    712  */
    713 char *
    714 cvs_temp_name (void)
    715 {
    716     char *fn;
    717     FILE *fp;
    718 
    719     fp = cvs_temp_file (&fn);
    720     if (fp == NULL)
    721 	error (1, errno, "Failed to create temporary file");
    722     if (fclose (fp) == EOF)
    723 	error (0, errno, "Failed to close temporary file %s", fn);
    724     return fn;
    725 }
    726 
    727 /* Generate a unique temporary filename and return an open file stream
    728  * to the truncated file by that name
    729  *
    730  *  INPUTS
    731  *	filename	where to place the pointer to the newly allocated file
    732  *   			name string
    733  *
    734  *  OUTPUTS
    735  *	filename	dereferenced, will point to the newly allocated file
    736  *			name string.  This value is undefined if the function
    737  *			returns an error.
    738  *
    739  *  RETURNS
    740  *	An open file pointer to a read/write mode empty temporary file with the
    741  *	unique file name or NULL on failure.
    742  *
    743  *  ERRORS
    744  *	On error, errno will be set to some value either by CVS_FOPEN or
    745  *	whatever system function is called to generate the temporary file name.
    746  *	The value of filename is undefined on error.
    747  */
    748 FILE *
    749 cvs_temp_file (char **filename)
    750 {
    751     char *fn;
    752     FILE *fp;
    753     int fd;
    754 
    755     /* FIXME - I'd like to be returning NULL here in noexec mode, but I think
    756      * some of the rcs & diff functions which rely on a temp file run in
    757      * noexec mode too.
    758      */
    759 
    760     assert (filename != NULL);
    761 
    762     fn = Xasprintf ("%s/%s", get_cvs_tmp_dir (), "cvsXXXXXX");
    763     fd = mkstemp (fn);
    764 
    765     /* a NULL return will be interpreted by callers as an error and
    766      * errno should still be set
    767      */
    768     if (fd == -1)
    769 	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 	free (fn);
    785 
    786     /* mkstemp is defined to open mode 0600 using glibc 2.0.7+.  There used
    787      * to be a complicated #ifdef checking the library versions here and then
    788      * a chmod 0600 on the temp file for versions of glibc less than 2.1.  This
    789      * is rather a special case, leaves a race condition open regardless, and
    790      * one could hope that sysadmins have read the relevant security
    791      * announcements and upgraded by now to a version with a fix committed in
    792      * January of 1999.
    793      *
    794      * If it is decided at some point that old, buggy versions of glibc should
    795      * still be catered to, a umask of 0600 should be set before file creation
    796      * instead then reset after file creation since this would avoid the race
    797      * condition that the chmod left open to exploitation.
    798      */
    799 
    800     *filename = fn;
    801     return fp;
    802 }
    803 
    804 
    805 
    806 /* Return a pointer into PATH's last component.  */
    807 const char *
    808 last_component (const char *path)
    809 {
    810     const char *last = strrchr (path, '/');
    811 
    812     if (last && (last != path))
    813         return last + 1;
    814     else
    815         return path;
    816 }
    817 
    818 
    819 
    820 /* Return the home directory.  Returns a pointer to storage
    821    managed by this function or its callees (currently getenv).
    822    This function will return the same thing every time it is
    823    called.  Returns NULL if there is no home directory.
    824 
    825    Note that for a pserver server, this may return root's home
    826    directory.  What typically happens is that upon being started from
    827    inetd, before switching users, the code in cvsrc.c calls
    828    get_homedir which remembers root's home directory in the static
    829    variable.  Then the switch happens and get_homedir might return a
    830    directory that we don't even have read or execute permissions for
    831    (which is bad, when various parts of CVS try to read there).  One
    832    fix would be to make the value returned by get_homedir only good
    833    until the next call (which would free the old value).  Another fix
    834    would be to just always malloc our answer, and let the caller free
    835    it (that is best, because some day we may need to be reentrant).
    836 
    837    The workaround is to put -f in inetd.conf which means that
    838    get_homedir won't get called until after the switch in user ID.
    839 
    840    The whole concept of a "home directory" on the server is pretty
    841    iffy, although I suppose some people probably are relying on it for
    842    .cvsrc and such, in the cases where it works.  */
    843 char *
    844 get_homedir (void)
    845 {
    846     static char *home = NULL;
    847     char *env;
    848     struct passwd *pw;
    849 
    850     if (home != NULL)
    851 	return home;
    852 
    853     if (!server_active && (env = getenv ("HOME")) != NULL)
    854 	home = env;
    855     else if ((pw = (struct passwd *) getpwuid (getuid ()))
    856 	     && pw->pw_dir)
    857 	home = xstrdup (pw->pw_dir);
    858     else
    859 	return 0;
    860 
    861     return home;
    862 }
    863 
    864 /* Compose a path to a file in the home directory.  This is necessary because
    865  * of different behavior on UNIX and VMS.  See the notes in vms/filesubr.c.
    866  *
    867  * A more clean solution would be something more along the lines of a
    868  * "join a directory to a filename" kind of thing which was not specific to
    869  * the homedir.  This should aid portability between UNIX, Mac, Windows, VMS,
    870  * and possibly others.  This is already handled by Perl - it might be
    871  * interesting to see how much of the code was written in C since Perl is under
    872  * the GPL and the Artistic license - we might be able to use it.
    873  */
    874 char *
    875 strcat_filename_onto_homedir (const char *dir, const char *file)
    876 {
    877     char *path = Xasprintf ("%s/%s", dir, file);
    878     return path;
    879 }
    880 
    881 /* See cvs.h for description.  On unix this does nothing, because the
    882    shell expands the wildcards.  */
    883 void
    884 expand_wild (int argc, char **argv, int *pargc, char ***pargv)
    885 {
    886     int i;
    887     if (size_overflow_p (xtimes (argc, sizeof (char *)))) {
    888 	*pargc = 0;
    889 	*pargv = NULL;
    890 	error (0, 0, "expand_wild: too many arguments");
    891 	return;
    892     }
    893     *pargc = argc;
    894     *pargv = xnmalloc (argc, sizeof (char *));
    895     for (i = 0; i < argc; ++i)
    896 	(*pargv)[i] = xstrdup (argv[i]);
    897 }
    898 
    899 
    900 
    901 static char *tmpdir_env;
    902 
    903 /* Return path to temp directory.
    904  */
    905 const char *
    906 get_system_temp_dir (void)
    907 {
    908     if (!tmpdir_env) tmpdir_env = getenv (TMPDIR_ENV);
    909     return tmpdir_env;
    910 }
    911 
    912 
    913 
    914 void
    915 push_env_temp_dir (void)
    916 {
    917     const char *tmpdir = get_cvs_tmp_dir ();
    918     if (tmpdir_env && strcmp (tmpdir_env, tmpdir))
    919 	setenv (TMPDIR_ENV, tmpdir, 1);
    920 }
    921