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 22 static int deep_remove_dir PROTO((const char *path)); 23 24 /* 25 * Copies "from" to "to". 26 */ 27 void 28 copy_file (from, to) 29 const char *from; 30 const char *to; 31 { 32 struct stat sb; 33 struct utimbuf t; 34 int fdin, fdout; 35 36 if (trace) 37 #ifdef SERVER_SUPPORT 38 (void) fprintf (stderr, "%c-> copy(%s,%s)\n", 39 (server_active) ? 'S' : ' ', from, to); 40 #else 41 (void) fprintf (stderr, "-> copy(%s,%s)\n", from, to); 42 #endif 43 if (noexec) 44 return; 45 46 /* If the file to be copied is a link or a device, then just create 47 the new link or device appropriately. */ 48 if (islink (from)) 49 { 50 char *source = xreadlink (from); 51 symlink (source, to); 52 free (source); 53 return; 54 } 55 56 if (isdevice (from)) 57 { 58 if (stat (from, &sb) < 0) 59 error (1, errno, "cannot stat %s", from); 60 mknod (to, sb.st_mode, sb.st_rdev); 61 } 62 else 63 { 64 /* Not a link or a device... probably a regular file. */ 65 if ((fdin = open (from, O_RDONLY)) < 0) 66 error (1, errno, "cannot open %s for copying", from); 67 if (fstat (fdin, &sb) < 0) 68 error (1, errno, "cannot fstat %s", from); 69 if ((fdout = creat (to, (int) sb.st_mode & 07777)) < 0) 70 error (1, errno, "cannot create %s for copying", to); 71 if (sb.st_size > 0) 72 { 73 char buf[BUFSIZ]; 74 int n; 75 76 for (;;) 77 { 78 n = read (fdin, buf, sizeof(buf)); 79 if (n == -1) 80 { 81 #ifdef EINTR 82 if (errno == EINTR) 83 continue; 84 #endif 85 error (1, errno, "cannot read file %s for copying", from); 86 } 87 else if (n == 0) 88 break; 89 90 if (write(fdout, buf, n) != n) { 91 error (1, errno, "cannot write file %s for copying", to); 92 } 93 } 94 95 #ifdef HAVE_FSYNC 96 if (fsync (fdout)) 97 error (1, errno, "cannot fsync file %s after copying", to); 98 #endif 99 } 100 101 if (close (fdin) < 0) 102 error (0, errno, "cannot close %s", from); 103 if (close (fdout) < 0) 104 error (1, errno, "cannot close %s", to); 105 } 106 107 /* now, set the times for the copied file to match those of the original */ 108 memset ((char *) &t, 0, sizeof (t)); 109 t.actime = sb.st_atime; 110 t.modtime = sb.st_mtime; 111 (void) utime (to, &t); 112 } 113 114 /* FIXME-krp: these functions would benefit from caching the char * & 115 stat buf. */ 116 117 /* 118 * Returns non-zero if the argument file is a directory, or is a symbolic 119 * link which points to a directory. 120 */ 121 int 122 isdir (file) 123 const char *file; 124 { 125 struct stat sb; 126 127 if (stat (file, &sb) < 0) 128 return (0); 129 return (S_ISDIR (sb.st_mode)); 130 } 131 132 /* 133 * Returns non-zero if the argument file is a symbolic link. 134 */ 135 int 136 islink (file) 137 const char *file; 138 { 139 #ifdef S_ISLNK 140 struct stat sb; 141 142 if (CVS_LSTAT (file, &sb) < 0) 143 return (0); 144 return (S_ISLNK (sb.st_mode)); 145 #else 146 return (0); 147 #endif 148 } 149 150 /* 151 * Returns non-zero if the argument file is a block or 152 * character special device. 153 */ 154 int 155 isdevice (file) 156 const char *file; 157 { 158 struct stat sb; 159 160 if (CVS_LSTAT (file, &sb) < 0) 161 return (0); 162 #ifdef S_ISBLK 163 if (S_ISBLK (sb.st_mode)) 164 return 1; 165 #endif 166 #ifdef S_ISCHR 167 if (S_ISCHR (sb.st_mode)) 168 return 1; 169 #endif 170 return 0; 171 } 172 173 /* 174 * Returns non-zero if the argument file exists. 175 */ 176 int 177 isfile (file) 178 const char *file; 179 { 180 return isaccessible(file, F_OK); 181 } 182 183 /* 184 * Returns non-zero if the argument file is readable. 185 */ 186 int 187 isreadable (file) 188 const char *file; 189 { 190 return isaccessible(file, R_OK); 191 } 192 193 /* 194 * Returns non-zero if the argument file is writable. 195 */ 196 int 197 iswritable (file) 198 const char *file; 199 { 200 return isaccessible(file, W_OK); 201 } 202 203 /* 204 * Returns non-zero if the argument file is accessable according to 205 * mode. If compiled with SETXID_SUPPORT also works if cvs has setxid 206 * bits set. 207 */ 208 int 209 isaccessible (file, mode) 210 const char *file; 211 const int mode; 212 { 213 #ifdef SETXID_SUPPORT 214 struct stat sb; 215 int umask = 0; 216 int gmask = 0; 217 int omask = 0; 218 int uid; 219 220 if (stat(file, &sb) == -1) 221 return 0; 222 if (mode == F_OK) 223 return 1; 224 225 uid = geteuid(); 226 if (uid == 0) /* superuser */ 227 { 228 if (mode & X_OK) 229 return sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH); 230 else 231 return 1; 232 } 233 234 if (mode & R_OK) 235 { 236 umask |= S_IRUSR; 237 gmask |= S_IRGRP; 238 omask |= S_IROTH; 239 } 240 if (mode & W_OK) 241 { 242 umask |= S_IWUSR; 243 gmask |= S_IWGRP; 244 omask |= S_IWOTH; 245 } 246 if (mode & X_OK) 247 { 248 umask |= S_IXUSR; 249 gmask |= S_IXGRP; 250 omask |= S_IXOTH; 251 } 252 253 if (sb.st_uid == uid) 254 return (sb.st_mode & umask) == umask; 255 else if (sb.st_gid == getegid()) 256 return (sb.st_mode & gmask) == gmask; 257 else 258 return (sb.st_mode & omask) == omask; 259 #else 260 return access(file, mode) == 0; 261 #endif 262 } 263 264 /* 265 * Open a file and die if it fails 266 */ 267 FILE * 268 open_file (name, mode) 269 const char *name; 270 const char *mode; 271 { 272 FILE *fp; 273 274 if ((fp = fopen (name, mode)) == NULL) 275 error (1, errno, "cannot open %s", name); 276 return (fp); 277 } 278 279 /* 280 * Make a directory and die if it fails 281 */ 282 void 283 make_directory (name) 284 const char *name; 285 { 286 struct stat sb; 287 288 if (stat (name, &sb) == 0 && (!S_ISDIR (sb.st_mode))) 289 error (0, 0, "%s already exists but is not a directory", name); 290 if (!noexec && mkdir (name, 0777) < 0) 291 error (1, errno, "cannot make directory %s", name); 292 } 293 294 /* 295 * Make a path to the argument directory, printing a message if something 296 * goes wrong. 297 */ 298 void 299 make_directories (name) 300 const char *name; 301 { 302 char *cp; 303 304 if (noexec) 305 return; 306 307 if (mkdir (name, 0777) == 0 || errno == EEXIST) 308 return; 309 if (! existence_error (errno)) 310 { 311 error (0, errno, "cannot make path to %s", name); 312 return; 313 } 314 if ((cp = strrchr (name, '/')) == NULL) 315 return; 316 *cp = '\0'; 317 make_directories (name); 318 *cp++ = '/'; 319 if (*cp == '\0') 320 return; 321 (void) mkdir (name, 0777); 322 } 323 324 /* Create directory NAME if it does not already exist; fatal error for 325 other errors. Returns 0 if directory was created; 1 if it already 326 existed. */ 327 int 328 mkdir_if_needed (name) 329 char *name; 330 { 331 if (mkdir (name, 0777) < 0) 332 { 333 if (!(errno == EEXIST 334 || (errno == EACCES && isdir (name)))) 335 error (1, errno, "cannot make directory %s", name); 336 return 1; 337 } 338 return 0; 339 } 340 341 /* 342 * Change the mode of a file, either adding write permissions, or removing 343 * all write permissions. Either change honors the current umask setting. 344 * 345 * Don't do anything if PreservePermissions is set to `yes'. This may 346 * have unexpected consequences for some uses of xchmod. 347 */ 348 void 349 xchmod (fname, writable) 350 char *fname; 351 int writable; 352 { 353 struct stat sb; 354 mode_t mode, oumask; 355 356 if (preserve_perms) 357 return; 358 359 if (stat (fname, &sb) < 0) 360 { 361 if (!noexec) 362 error (0, errno, "cannot stat %s", fname); 363 return; 364 } 365 oumask = umask (0); 366 (void) umask (oumask); 367 if (writable) 368 { 369 mode = sb.st_mode | (~oumask 370 & (((sb.st_mode & S_IRUSR) ? S_IWUSR : 0) 371 | ((sb.st_mode & S_IRGRP) ? S_IWGRP : 0) 372 | ((sb.st_mode & S_IROTH) ? S_IWOTH : 0))); 373 } 374 else 375 { 376 mode = sb.st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH) & ~oumask; 377 } 378 379 if (trace) 380 #ifdef SERVER_SUPPORT 381 (void) fprintf (stderr, "%c-> chmod(%s,%o)\n", 382 (server_active) ? 'S' : ' ', fname, 383 (unsigned int) mode); 384 #else 385 (void) fprintf (stderr, "-> chmod(%s,%o)\n", fname, 386 (unsigned int) mode); 387 #endif 388 if (noexec) 389 return; 390 391 if (chmod (fname, mode) < 0) 392 error (0, errno, "cannot change mode of file %s", fname); 393 } 394 395 /* 396 * Rename a file and die if it fails 397 */ 398 void 399 rename_file (from, to) 400 const char *from; 401 const char *to; 402 { 403 if (trace) 404 #ifdef SERVER_SUPPORT 405 (void) fprintf (stderr, "%c-> rename(%s,%s)\n", 406 (server_active) ? 'S' : ' ', from, to); 407 #else 408 (void) fprintf (stderr, "-> rename(%s,%s)\n", from, to); 409 #endif 410 if (noexec) 411 return; 412 413 if (rename (from, to) < 0) 414 error (1, errno, "cannot rename file %s to %s", from, to); 415 } 416 417 /* 418 * unlink a file, if possible. 419 */ 420 int 421 unlink_file (f) 422 const char *f; 423 { 424 if (trace) 425 #ifdef SERVER_SUPPORT 426 (void) fprintf (stderr, "%c-> unlink(%s)\n", 427 (server_active) ? 'S' : ' ', f); 428 #else 429 (void) fprintf (stderr, "-> unlink(%s)\n", f); 430 #endif 431 if (noexec) 432 return (0); 433 434 return (unlink (f)); 435 } 436 437 /* 438 * Unlink a file or dir, if possible. If it is a directory do a deep 439 * removal of all of the files in the directory. Return -1 on error 440 * (in which case errno is set). 441 */ 442 int 443 unlink_file_dir (f) 444 const char *f; 445 { 446 struct stat sb; 447 448 if (trace 449 #ifdef SERVER_SUPPORT 450 /* This is called by the server parent process in contexts where 451 it is not OK to send output (e.g. after we sent "ok" to the 452 client). */ 453 && !server_active 454 #endif 455 ) 456 (void) fprintf (stderr, "-> unlink_file_dir(%s)\n", 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 unlink (f); 481 } 482 483 /* Remove a directory and everything it contains. Returns 0 for 484 * success, -1 for failure (in which case errno is set). 485 */ 486 487 static int 488 deep_remove_dir (path) 489 const char *path; 490 { 491 DIR *dirp; 492 struct dirent *dp; 493 494 if (rmdir (path) != 0) 495 { 496 if (errno == ENOTEMPTY 497 || errno == EEXIST 498 /* Ugly workaround for ugly AIX 4.1 (and 3.2) header bug 499 (it defines ENOTEMPTY and EEXIST to 17 but actually 500 returns 87). */ 501 || (ENOTEMPTY == 17 && EEXIST == 17 && errno == 87)) 502 { 503 if ((dirp = opendir (path)) == NULL) 504 /* If unable to open the directory return 505 * an error 506 */ 507 return -1; 508 509 while ((dp = readdir (dirp)) != NULL) 510 { 511 char *buf; 512 513 if (strcmp (dp->d_name, ".") == 0 || 514 strcmp (dp->d_name, "..") == 0) 515 continue; 516 517 buf = xmalloc (strlen (path) + strlen (dp->d_name) + 5); 518 sprintf (buf, "%s/%s", path, dp->d_name); 519 520 /* See comment in unlink_file_dir explanation of why we use 521 isdir instead of just calling unlink and checking the 522 status. */ 523 if (isdir(buf)) 524 { 525 if (deep_remove_dir(buf)) 526 { 527 closedir(dirp); 528 free (buf); 529 return -1; 530 } 531 } 532 else 533 { 534 if (unlink (buf) != 0) 535 { 536 closedir(dirp); 537 free (buf); 538 return -1; 539 } 540 } 541 free (buf); 542 } 543 closedir (dirp); 544 return rmdir (path); 545 } 546 else 547 return -1; 548 } 549 550 /* Was able to remove the directory return 0 */ 551 return 0; 552 } 553 554 /* Read NCHARS bytes from descriptor FD into BUF. 555 Return the number of characters successfully read. 556 The number returned is always NCHARS unless end-of-file or error. */ 557 static size_t 558 block_read (fd, buf, nchars) 559 int fd; 560 char *buf; 561 size_t nchars; 562 { 563 char *bp = buf; 564 size_t nread; 565 566 do 567 { 568 nread = read (fd, bp, nchars); 569 if (nread == (size_t)-1) 570 { 571 #ifdef EINTR 572 if (errno == EINTR) 573 continue; 574 #endif 575 return (size_t)-1; 576 } 577 578 if (nread == 0) 579 break; 580 581 bp += nread; 582 nchars -= nread; 583 } while (nchars != 0); 584 585 return bp - buf; 586 } 587 588 589 /* 590 * Compare "file1" to "file2". Return non-zero if they don't compare exactly. 591 * If FILE1 and FILE2 are special files, compare their salient characteristics 592 * (i.e. major/minor device numbers, links, etc. 593 */ 594 int 595 xcmp (file1, file2) 596 const char *file1; 597 const char *file2; 598 { 599 char *buf1, *buf2; 600 struct stat sb1, sb2; 601 int fd1, fd2; 602 int ret; 603 604 if (CVS_LSTAT (file1, &sb1) < 0) 605 error (1, errno, "cannot lstat %s", file1); 606 if (CVS_LSTAT (file2, &sb2) < 0) 607 error (1, errno, "cannot lstat %s", file2); 608 609 /* If FILE1 and FILE2 are not the same file type, they are unequal. */ 610 if ((sb1.st_mode & S_IFMT) != (sb2.st_mode & S_IFMT)) 611 return 1; 612 613 /* If FILE1 and FILE2 are symlinks, they are equal if they point to 614 the same thing. */ 615 if (S_ISLNK (sb1.st_mode) && S_ISLNK (sb2.st_mode)) 616 { 617 int result; 618 buf1 = xreadlink (file1); 619 buf2 = xreadlink (file2); 620 result = (strcmp (buf1, buf2) == 0); 621 free (buf1); 622 free (buf2); 623 return result; 624 } 625 626 /* If FILE1 and FILE2 are devices, they are equal if their device 627 numbers match. */ 628 if (S_ISBLK (sb1.st_mode) || S_ISCHR (sb1.st_mode)) 629 { 630 if (sb1.st_rdev == sb2.st_rdev) 631 return 0; 632 else 633 return 1; 634 } 635 636 if ((fd1 = open (file1, O_RDONLY)) < 0) 637 error (1, errno, "cannot open file %s for comparing", file1); 638 if ((fd2 = open (file2, O_RDONLY)) < 0) 639 error (1, errno, "cannot open file %s for comparing", file2); 640 641 /* A generic file compare routine might compare st_dev & st_ino here 642 to see if the two files being compared are actually the same file. 643 But that won't happen in CVS, so we won't bother. */ 644 645 if (sb1.st_size != sb2.st_size) 646 ret = 1; 647 else if (sb1.st_size == 0) 648 ret = 0; 649 else 650 { 651 /* FIXME: compute the optimal buffer size by computing the least 652 common multiple of the files st_blocks field */ 653 size_t buf_size = 8 * 1024; 654 size_t read1; 655 size_t read2; 656 657 buf1 = xmalloc (buf_size); 658 buf2 = xmalloc (buf_size); 659 660 do 661 { 662 read1 = block_read (fd1, buf1, buf_size); 663 if (read1 == (size_t)-1) 664 error (1, errno, "cannot read file %s for comparing", file1); 665 666 read2 = block_read (fd2, buf2, buf_size); 667 if (read2 == (size_t)-1) 668 error (1, errno, "cannot read file %s for comparing", file2); 669 670 /* assert (read1 == read2); */ 671 672 ret = memcmp(buf1, buf2, read1); 673 } while (ret == 0 && read1 == buf_size); 674 675 free (buf1); 676 free (buf2); 677 } 678 679 (void) close (fd1); 680 (void) close (fd2); 681 return (ret); 682 } 683 684 /* Generate a unique temporary filename. Returns a pointer to a newly 685 malloc'd string containing the name. Returns successfully or not at 686 all. */ 687 /* There are at least three functions for generating temporary 688 filenames. We use tempnam (SVID 3) if possible, else mktemp (BSD 689 4.3), and as last resort tmpnam (POSIX). Reason is that tempnam and 690 mktemp both allow to specify the directory in which the temporary 691 file will be created. */ 692 #ifdef HAVE_TEMPNAM 693 char * 694 cvs_temp_name () 695 { 696 char *retval; 697 698 retval = tempnam (Tmpdir, "cvs"); 699 if (retval == NULL) 700 error (1, errno, "cannot generate temporary filename"); 701 /* tempnam returns a pointer to a newly malloc'd string, so there's 702 no need for a xstrdup */ 703 return retval; 704 } 705 #else 706 char * 707 cvs_temp_name () 708 { 709 # ifdef HAVE_MKTEMP 710 char *value; 711 char *retval; 712 713 value = xmalloc (strlen (Tmpdir) + 40); 714 sprintf (value, "%s/%s", Tmpdir, "cvsXXXXXX" ); 715 retval = mktemp (value); 716 717 if (retval == NULL) 718 error (1, errno, "cannot generate temporary filename"); 719 return value; 720 # else 721 char value[L_tmpnam + 1]; 722 char *retval; 723 724 retval = tmpnam (value); 725 if (retval == NULL) 726 error (1, errno, "cannot generate temporary filename"); 727 return xstrdup (value); 728 # endif 729 } 730 #endif 731 732 /* Return non-zero iff FILENAME is absolute. 733 Trivial under Unix, but more complicated under other systems. */ 734 int 735 isabsolute (filename) 736 const char *filename; 737 { 738 return filename[0] == '/'; 739 } 740 741 /* 742 * Return a string (dynamically allocated) with the name of the file to which 743 * LINK is symlinked. 744 */ 745 char * 746 xreadlink (link) 747 const char *link; 748 { 749 char *file = NULL; 750 char *tfile; 751 int buflen = 128; 752 int link_name_len; 753 754 if (!islink (link)) 755 return NULL; 756 757 /* Get the name of the file to which `from' is linked. 758 FIXME: what portability issues arise here? Are readlink & 759 ENAMETOOLONG defined on all systems? -twp */ 760 do 761 { 762 file = xrealloc (file, buflen); 763 link_name_len = readlink (link, file, buflen - 1); 764 buflen *= 2; 765 } 766 while (link_name_len < 0 && errno == ENAMETOOLONG); 767 768 if (link_name_len < 0) 769 error (1, errno, "cannot readlink %s", link); 770 771 file[link_name_len] = '\0'; 772 773 tfile = xstrdup (file); 774 free (file); 775 776 return tfile; 777 } 778 779 780 /* Return a pointer into PATH's last component. */ 781 char * 782 last_component (path) 783 char *path; 784 { 785 char *last = strrchr (path, '/'); 786 787 if (last && (last != path)) 788 return last + 1; 789 else 790 return path; 791 } 792 793 /* Return the home directory. Returns a pointer to storage 794 managed by this function or its callees (currently getenv). 795 This function will return the same thing every time it is 796 called. Returns NULL if there is no home directory. 797 798 Note that for a pserver server, this may return root's home 799 directory. What typically happens is that upon being started from 800 inetd, before switching users, the code in cvsrc.c calls 801 get_homedir which remembers root's home directory in the static 802 variable. Then the switch happens and get_homedir might return a 803 directory that we don't even have read or execute permissions for 804 (which is bad, when various parts of CVS try to read there). One 805 fix would be to make the value returned by get_homedir only good 806 until the next call (which would free the old value). Another fix 807 would be to just always malloc our answer, and let the caller free 808 it (that is best, because some day we may need to be reentrant). 809 810 The workaround is to put -f in inetd.conf which means that 811 get_homedir won't get called until after the switch in user ID. 812 813 The whole concept of a "home directory" on the server is pretty 814 iffy, although I suppose some people probably are relying on it for 815 .cvsrc and such, in the cases where it works. */ 816 char * 817 get_homedir () 818 { 819 static char *home = NULL; 820 char *env = getenv ("HOME"); 821 struct passwd *pw; 822 823 if (home != NULL) 824 return home; 825 826 if (env) 827 home = env; 828 else if ((pw = (struct passwd *) getpwuid (getuid ())) 829 && pw->pw_dir) 830 home = xstrdup (pw->pw_dir); 831 else 832 return 0; 833 834 return home; 835 } 836 837 /* See cvs.h for description. On unix this does nothing, because the 838 shell expands the wildcards. */ 839 void 840 expand_wild (argc, argv, pargc, pargv) 841 int argc; 842 char **argv; 843 int *pargc; 844 char ***pargv; 845 { 846 int i; 847 *pargc = argc; 848 *pargv = (char **) xmalloc (argc * sizeof (char *)); 849 for (i = 0; i < argc; ++i) 850 (*pargv)[i] = xstrdup (argv[i]); 851 } 852 853 #ifdef SERVER_SUPPORT 854 /* Case-insensitive string compare. I know that some systems 855 have such a routine, but I'm not sure I see any reasons for 856 dealing with the hair of figuring out whether they do (I haven't 857 looked into whether this is a performance bottleneck; I would guess 858 not). */ 859 int 860 cvs_casecmp (str1, str2) 861 char *str1; 862 char *str2; 863 { 864 char *p; 865 char *q; 866 int pqdiff; 867 868 p = str1; 869 q = str2; 870 while ((pqdiff = tolower (*p) - tolower (*q)) == 0) 871 { 872 if (*p == '\0') 873 return 0; 874 ++p; 875 ++q; 876 } 877 return pqdiff; 878 } 879 880 /* Case-insensitive file open. As you can see, this is an expensive 881 call. We don't regard it as our main strategy for dealing with 882 case-insensitivity. Returns errno code or 0 for success. Puts the 883 new file in *FP. NAME and MODE are as for fopen. If PATHP is not 884 NULL, then put a malloc'd string containing the pathname as found 885 into *PATHP. *PATHP is only set if the return value is 0. 886 887 Might be cleaner to separate the file finding (which just gives 888 *PATHP) from the file opening (which the caller can do). For one 889 thing, might make it easier to know whether to put NAME or *PATHP 890 into error messages. */ 891 int 892 fopen_case (name, mode, fp, pathp) 893 char *name; 894 char *mode; 895 FILE **fp; 896 char **pathp; 897 { 898 struct dirent *dp; 899 DIR *dirp; 900 char *dir; 901 char *fname; 902 char *found_name; 903 int retval; 904 905 /* Separate NAME into directory DIR and filename within the directory 906 FNAME. */ 907 dir = xstrdup (name); 908 fname = strrchr (dir, '/'); 909 if (fname == NULL) 910 error (1, 0, "internal error: relative pathname in fopen_case"); 911 *fname++ = '\0'; 912 913 found_name = NULL; 914 dirp = CVS_OPENDIR (dir); 915 if (dirp == NULL) 916 { 917 if (existence_error (errno)) 918 { 919 /* This can happen if we are looking in the Attic and the Attic 920 directory does not exist. Return the error to the caller; 921 they know what to do with it. */ 922 retval = errno; 923 goto out; 924 } 925 else 926 { 927 /* Give a fatal error; that way the error message can be 928 more specific than if we returned the error to the caller. */ 929 error (1, errno, "cannot read directory %s", dir); 930 } 931 } 932 errno = 0; 933 while ((dp = readdir (dirp)) != NULL) 934 { 935 if (cvs_casecmp (dp->d_name, fname) == 0) 936 { 937 if (found_name != NULL) 938 error (1, 0, "%s is ambiguous; could mean %s or %s", 939 fname, dp->d_name, found_name); 940 found_name = xstrdup (dp->d_name); 941 } 942 } 943 if (errno != 0) 944 error (1, errno, "cannot read directory %s", dir); 945 closedir (dirp); 946 947 if (found_name == NULL) 948 { 949 *fp = NULL; 950 retval = ENOENT; 951 } 952 else 953 { 954 char *p; 955 956 /* Copy the found name back into DIR. We are assuming that 957 found_name is the same length as fname, which is true as 958 long as the above code is just ignoring case and not other 959 aspects of filename syntax. */ 960 p = dir + strlen (dir); 961 *p++ = '/'; 962 strcpy (p, found_name); 963 *fp = fopen (dir, mode); 964 if (*fp == NULL) 965 retval = errno; 966 else 967 retval = 0; 968 } 969 970 if (pathp == NULL) 971 free (dir); 972 else if (retval != 0) 973 free (dir); 974 else 975 *pathp = dir; 976 free (found_name); 977 out: 978 return retval; 979 } 980 #endif /* SERVER_SUPPORT */ 981