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