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