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