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