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 /* 23 * I don't know of a convenient way to test this at configure time, or else 24 * I'd certainly do it there. 25 */ 26 #if defined(NeXT) 27 #define LOSING_TMPNAM_FUNCTION 28 #endif 29 30 static int deep_remove_dir PROTO((const char *path)); 31 32 /* 33 * Copies "from" to "to". 34 */ 35 void 36 copy_file (from, to) 37 const char *from; 38 const char *to; 39 { 40 struct stat sb; 41 struct utimbuf t; 42 int fdin, fdout; 43 44 if (trace) 45 #ifdef SERVER_SUPPORT 46 (void) fprintf (stderr, "%c-> copy(%s,%s)\n", 47 (server_active) ? 'S' : ' ', from, to); 48 #else 49 (void) fprintf (stderr, "-> copy(%s,%s)\n", from, to); 50 #endif 51 if (noexec) 52 return; 53 54 if ((fdin = open (from, O_RDONLY)) < 0) 55 error (1, errno, "cannot open %s for copying", from); 56 if (fstat (fdin, &sb) < 0) 57 error (1, errno, "cannot fstat %s", from); 58 if ((fdout = creat (to, (int) sb.st_mode & 07777)) < 0) 59 error (1, errno, "cannot create %s for copying", to); 60 if (sb.st_size > 0) 61 { 62 char buf[BUFSIZ]; 63 int n; 64 65 for (;;) 66 { 67 n = read (fdin, buf, sizeof(buf)); 68 if (n == -1) 69 { 70 #ifdef EINTR 71 if (errno == EINTR) 72 continue; 73 #endif 74 error (1, errno, "cannot read file %s for copying", from); 75 } 76 else if (n == 0) 77 break; 78 79 if (write(fdout, buf, n) != n) { 80 error (1, errno, "cannot write file %s for copying", to); 81 } 82 } 83 84 #ifdef HAVE_FSYNC 85 if (fsync (fdout)) 86 error (1, errno, "cannot fsync file %s after copying", to); 87 #endif 88 } 89 90 if (close (fdin) < 0) 91 error (0, errno, "cannot close %s", from); 92 if (close (fdout) < 0) 93 error (1, errno, "cannot close %s", to); 94 95 /* now, set the times for the copied file to match those of the original */ 96 memset ((char *) &t, 0, sizeof (t)); 97 t.actime = sb.st_atime; 98 t.modtime = sb.st_mtime; 99 (void) utime (to, &t); 100 } 101 102 /* FIXME-krp: these functions would benefit from caching the char * & 103 stat buf. */ 104 105 /* 106 * Returns non-zero if the argument file is a directory, or is a symbolic 107 * link which points to a directory. 108 */ 109 int 110 isdir (file) 111 const char *file; 112 { 113 struct stat sb; 114 115 if (stat (file, &sb) < 0) 116 return (0); 117 return (S_ISDIR (sb.st_mode)); 118 } 119 120 /* 121 * Returns non-zero if the argument file is a symbolic link. 122 */ 123 int 124 islink (file) 125 const char *file; 126 { 127 #ifdef S_ISLNK 128 struct stat sb; 129 130 if (lstat (file, &sb) < 0) 131 return (0); 132 return (S_ISLNK (sb.st_mode)); 133 #else 134 return (0); 135 #endif 136 } 137 138 /* 139 * Returns non-zero if the argument file exists. 140 */ 141 int 142 isfile (file) 143 const char *file; 144 { 145 return isaccessible(file, F_OK); 146 } 147 148 /* 149 * Returns non-zero if the argument file is readable. 150 */ 151 int 152 isreadable (file) 153 const char *file; 154 { 155 return isaccessible(file, R_OK); 156 } 157 158 /* 159 * Returns non-zero if the argument file is writable. 160 */ 161 int 162 iswritable (file) 163 const char *file; 164 { 165 return isaccessible(file, W_OK); 166 } 167 168 /* 169 * Returns non-zero if the argument file is accessable according to 170 * mode. If compiled with SETXID_SUPPORT also works if cvs has setxid 171 * bits set. 172 */ 173 int 174 isaccessible (file, mode) 175 const char *file; 176 const int mode; 177 { 178 #ifdef SETXID_SUPPORT 179 struct stat sb; 180 int umask = 0; 181 int gmask = 0; 182 int omask = 0; 183 int uid; 184 185 if (stat(file, &sb) == -1) 186 return 0; 187 if (mode == F_OK) 188 return 1; 189 190 uid = geteuid(); 191 if (uid == 0) /* superuser */ 192 { 193 if (mode & X_OK) 194 return sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH); 195 else 196 return 1; 197 } 198 199 if (mode & R_OK) 200 { 201 umask |= S_IRUSR; 202 gmask |= S_IRGRP; 203 omask |= S_IROTH; 204 } 205 if (mode & W_OK) 206 { 207 umask |= S_IWUSR; 208 gmask |= S_IWGRP; 209 omask |= S_IWOTH; 210 } 211 if (mode & X_OK) 212 { 213 umask |= S_IXUSR; 214 gmask |= S_IXGRP; 215 omask |= S_IXOTH; 216 } 217 218 if (sb.st_uid == uid) 219 return (sb.st_mode & umask) == umask; 220 else if (sb.st_gid == getegid()) 221 return (sb.st_mode & gmask) == gmask; 222 else 223 return (sb.st_mode & omask) == omask; 224 #else 225 return access(file, mode) == 0; 226 #endif 227 } 228 229 /* 230 * Open a file and die if it fails 231 */ 232 FILE * 233 open_file (name, mode) 234 const char *name; 235 const char *mode; 236 { 237 FILE *fp; 238 239 if ((fp = fopen (name, mode)) == NULL) 240 error (1, errno, "cannot open %s", name); 241 return (fp); 242 } 243 244 /* 245 * Make a directory and die if it fails 246 */ 247 void 248 make_directory (name) 249 const char *name; 250 { 251 struct stat sb; 252 253 if (stat (name, &sb) == 0 && (!S_ISDIR (sb.st_mode))) 254 error (0, 0, "%s already exists but is not a directory", name); 255 if (!noexec && mkdir (name, 0777) < 0) 256 error (1, errno, "cannot make directory %s", name); 257 } 258 259 /* 260 * Make a path to the argument directory, printing a message if something 261 * goes wrong. 262 */ 263 void 264 make_directories (name) 265 const char *name; 266 { 267 char *cp; 268 269 if (noexec) 270 return; 271 272 if (mkdir (name, 0777) == 0 || errno == EEXIST) 273 return; 274 if (! existence_error (errno)) 275 { 276 error (0, errno, "cannot make path to %s", name); 277 return; 278 } 279 if ((cp = strrchr (name, '/')) == NULL) 280 return; 281 *cp = '\0'; 282 make_directories (name); 283 *cp++ = '/'; 284 if (*cp == '\0') 285 return; 286 (void) mkdir (name, 0777); 287 } 288 289 /* Create directory NAME if it does not already exist; fatal error for 290 other errors. Returns 0 if directory was created; 1 if it already 291 existed. */ 292 int 293 mkdir_if_needed (name) 294 char *name; 295 { 296 if (mkdir (name, 0777) < 0) 297 { 298 if (errno != EEXIST) 299 error (1, errno, "cannot make directory %s", name); 300 return 1; 301 } 302 return 0; 303 } 304 305 /* 306 * Change the mode of a file, either adding write permissions, or removing 307 * all write permissions. Either change honors the current umask setting. 308 */ 309 void 310 xchmod (fname, writable) 311 char *fname; 312 int writable; 313 { 314 struct stat sb; 315 mode_t mode, oumask; 316 317 if (stat (fname, &sb) < 0) 318 { 319 if (!noexec) 320 error (0, errno, "cannot stat %s", fname); 321 return; 322 } 323 oumask = umask (0); 324 (void) umask (oumask); 325 if (writable) 326 { 327 mode = sb.st_mode | (~oumask 328 & (((sb.st_mode & S_IRUSR) ? S_IWUSR : 0) 329 | ((sb.st_mode & S_IRGRP) ? S_IWGRP : 0) 330 | ((sb.st_mode & S_IROTH) ? S_IWOTH : 0))); 331 } 332 else 333 { 334 mode = sb.st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH) & ~oumask; 335 } 336 337 if (trace) 338 #ifdef SERVER_SUPPORT 339 (void) fprintf (stderr, "%c-> chmod(%s,%o)\n", 340 (server_active) ? 'S' : ' ', fname, 341 (unsigned int) mode); 342 #else 343 (void) fprintf (stderr, "-> chmod(%s,%o)\n", fname, 344 (unsigned int) mode); 345 #endif 346 if (noexec) 347 return; 348 349 if (chmod (fname, mode) < 0) 350 error (0, errno, "cannot change mode of file %s", fname); 351 } 352 353 /* 354 * Rename a file and die if it fails 355 */ 356 void 357 rename_file (from, to) 358 const char *from; 359 const char *to; 360 { 361 if (trace) 362 #ifdef SERVER_SUPPORT 363 (void) fprintf (stderr, "%c-> rename(%s,%s)\n", 364 (server_active) ? 'S' : ' ', from, to); 365 #else 366 (void) fprintf (stderr, "-> rename(%s,%s)\n", from, to); 367 #endif 368 if (noexec) 369 return; 370 371 if (rename (from, to) < 0) 372 error (1, errno, "cannot rename file %s to %s", from, to); 373 } 374 375 /* 376 * link a file, if possible. Warning: the Windows NT version of this 377 * function just copies the file, so only use this function in ways 378 * that can deal with either a link or a copy. 379 */ 380 int 381 link_file (from, to) 382 const char *from; 383 const char *to; 384 { 385 if (trace) 386 #ifdef SERVER_SUPPORT 387 (void) fprintf (stderr, "%c-> link(%s,%s)\n", 388 (server_active) ? 'S' : ' ', from, to); 389 #else 390 (void) fprintf (stderr, "-> link(%s,%s)\n", from, to); 391 #endif 392 if (noexec) 393 return (0); 394 395 return (link (from, to)); 396 } 397 398 /* 399 * unlink a file, if possible. 400 */ 401 int 402 unlink_file (f) 403 const char *f; 404 { 405 if (trace) 406 #ifdef SERVER_SUPPORT 407 (void) fprintf (stderr, "%c-> unlink(%s)\n", 408 (server_active) ? 'S' : ' ', f); 409 #else 410 (void) fprintf (stderr, "-> unlink(%s)\n", f); 411 #endif 412 if (noexec) 413 return (0); 414 415 return (unlink (f)); 416 } 417 418 /* 419 * Unlink a file or dir, if possible. If it is a directory do a deep 420 * removal of all of the files in the directory. Return -1 on error 421 * (in which case errno is set). 422 */ 423 int 424 unlink_file_dir (f) 425 const char *f; 426 { 427 if (trace) 428 #ifdef SERVER_SUPPORT 429 (void) fprintf (stderr, "%c-> unlink_file_dir(%s)\n", 430 (server_active) ? 'S' : ' ', f); 431 #else 432 (void) fprintf (stderr, "-> unlink_file_dir(%s)\n", f); 433 #endif 434 if (noexec) 435 return (0); 436 437 /* For at least some unices, if root tries to unlink() a directory, 438 instead of doing something rational like returning EISDIR, 439 the system will gleefully go ahead and corrupt the filesystem. 440 So we first call isdir() to see if it is OK to call unlink(). This 441 doesn't quite work--if someone creates a directory between the 442 call to isdir() and the call to unlink(), we'll still corrupt 443 the filesystem. Where is the Unix Haters Handbook when you need 444 it? */ 445 if (isdir(f)) 446 return deep_remove_dir(f); 447 else 448 { 449 if (unlink (f) != 0) 450 return -1; 451 } 452 /* We were able to remove the file from the disk */ 453 return 0; 454 } 455 456 /* Remove a directory and everything it contains. Returns 0 for 457 * success, -1 for failure (in which case errno is set). 458 */ 459 460 static int 461 deep_remove_dir (path) 462 const char *path; 463 { 464 DIR *dirp; 465 struct dirent *dp; 466 467 if (rmdir (path) != 0) 468 { 469 if (errno == ENOTEMPTY 470 || errno == EEXIST 471 /* Ugly workaround for ugly AIX 4.1 (and 3.2) header bug 472 (it defines ENOTEMPTY and EEXIST to 17 but actually 473 returns 87). */ 474 || (ENOTEMPTY == 17 && EEXIST == 17 && errno == 87)) 475 { 476 if ((dirp = opendir (path)) == NULL) 477 /* If unable to open the directory return 478 * an error 479 */ 480 return -1; 481 482 while ((dp = readdir (dirp)) != NULL) 483 { 484 char *buf; 485 486 if (strcmp (dp->d_name, ".") == 0 || 487 strcmp (dp->d_name, "..") == 0) 488 continue; 489 490 buf = xmalloc (strlen (path) + strlen (dp->d_name) + 5); 491 sprintf (buf, "%s/%s", path, dp->d_name); 492 493 /* See comment in unlink_file_dir explanation of why we use 494 isdir instead of just calling unlink and checking the 495 status. */ 496 if (isdir(buf)) 497 { 498 if (deep_remove_dir(buf)) 499 { 500 closedir(dirp); 501 free (buf); 502 return -1; 503 } 504 } 505 else 506 { 507 if (unlink (buf) != 0) 508 { 509 closedir(dirp); 510 free (buf); 511 return -1; 512 } 513 } 514 free (buf); 515 } 516 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 /* Read NCHARS bytes from descriptor FD into BUF. 528 Return the number of characters successfully read. 529 The number returned is always NCHARS unless end-of-file or error. */ 530 static size_t 531 block_read (fd, buf, nchars) 532 int fd; 533 char *buf; 534 size_t nchars; 535 { 536 char *bp = buf; 537 size_t nread; 538 539 do 540 { 541 nread = read (fd, bp, nchars); 542 if (nread == (size_t)-1) 543 { 544 #ifdef EINTR 545 if (errno == EINTR) 546 continue; 547 #endif 548 return (size_t)-1; 549 } 550 551 if (nread == 0) 552 break; 553 554 bp += nread; 555 nchars -= nread; 556 } while (nchars != 0); 557 558 return bp - buf; 559 } 560 561 562 /* 563 * Compare "file1" to "file2". Return non-zero if they don't compare exactly. 564 */ 565 int 566 xcmp (file1, file2) 567 const char *file1; 568 const char *file2; 569 { 570 char *buf1, *buf2; 571 struct stat sb1, sb2; 572 int fd1, fd2; 573 int ret; 574 575 if ((fd1 = open (file1, O_RDONLY)) < 0) 576 error (1, errno, "cannot open file %s for comparing", file1); 577 if ((fd2 = open (file2, O_RDONLY)) < 0) 578 error (1, errno, "cannot open file %s for comparing", file2); 579 if (fstat (fd1, &sb1) < 0) 580 error (1, errno, "cannot fstat %s", file1); 581 if (fstat (fd2, &sb2) < 0) 582 error (1, errno, "cannot fstat %s", file2); 583 584 /* A generic file compare routine might compare st_dev & st_ino here 585 to see if the two files being compared are actually the same file. 586 But that won't happen in CVS, so we won't bother. */ 587 588 if (sb1.st_size != sb2.st_size) 589 ret = 1; 590 else if (sb1.st_size == 0) 591 ret = 0; 592 else 593 { 594 /* FIXME: compute the optimal buffer size by computing the least 595 common multiple of the files st_blocks field */ 596 size_t buf_size = 8 * 1024; 597 size_t read1; 598 size_t read2; 599 600 buf1 = xmalloc (buf_size); 601 buf2 = xmalloc (buf_size); 602 603 do 604 { 605 read1 = block_read (fd1, buf1, buf_size); 606 if (read1 == (size_t)-1) 607 error (1, errno, "cannot read file %s for comparing", file1); 608 609 read2 = block_read (fd2, buf2, buf_size); 610 if (read2 == (size_t)-1) 611 error (1, errno, "cannot read file %s for comparing", file2); 612 613 /* assert (read1 == read2); */ 614 615 ret = memcmp(buf1, buf2, read1); 616 } while (ret == 0 && read1 == buf_size); 617 618 free (buf1); 619 free (buf2); 620 } 621 622 (void) close (fd1); 623 (void) close (fd2); 624 return (ret); 625 } 626 627 /* Just in case this implementation does not define this. */ 628 #ifndef L_tmpnam 629 #define L_tmpnam 50 630 #endif 631 632 #ifdef LOSING_TMPNAM_FUNCTION 633 char * 634 cvs_temp_name () 635 { 636 char value[L_tmpnam + 1]; 637 638 /* FIXME: Should be using TMPDIR. */ 639 strcpy (value, "/tmp/cvsXXXXXX"); 640 mktemp (value); 641 return xstrdup (value); 642 } 643 #else 644 /* Generate a unique temporary filename. Returns a pointer to a newly 645 malloc'd string containing the name. Returns successfully or not at 646 all. */ 647 char * 648 cvs_temp_name () 649 { 650 char value[L_tmpnam + 1]; 651 char *retval; 652 653 /* FIXME: should be using TMPDIR, perhaps by using tempnam on systems 654 which have it. */ 655 retval = tmpnam (value); 656 if (retval == NULL) 657 error (1, errno, "cannot generate temporary filename"); 658 return xstrdup (retval); 659 } 660 #endif 661 662 /* Return non-zero iff FILENAME is absolute. 663 Trivial under Unix, but more complicated under other systems. */ 664 int 665 isabsolute (filename) 666 const char *filename; 667 { 668 return filename[0] == '/'; 669 } 670 671 672 /* Return a pointer into PATH's last component. */ 673 char * 674 last_component (path) 675 char *path; 676 { 677 char *last = strrchr (path, '/'); 678 679 if (last) 680 return last + 1; 681 else 682 return path; 683 } 684 685 /* Return the home directory. Returns a pointer to storage 686 managed by this function or its callees (currently getenv). 687 This function will return the same thing every time it is 688 called. */ 689 char * 690 get_homedir () 691 { 692 static char *home = NULL; 693 char *env = getenv ("HOME"); 694 struct passwd *pw; 695 696 if (home != NULL) 697 return home; 698 699 if (env) 700 home = env; 701 else if ((pw = (struct passwd *) getpwuid (getuid ())) 702 && pw->pw_dir) 703 home = xstrdup (pw->pw_dir); 704 else 705 return 0; 706 707 return home; 708 } 709 710 /* See cvs.h for description. On unix this does nothing, because the 711 shell expands the wildcards. */ 712 void 713 expand_wild (argc, argv, pargc, pargv) 714 int argc; 715 char **argv; 716 int *pargc; 717 char ***pargv; 718 { 719 int i; 720 *pargc = argc; 721 *pargv = (char **) xmalloc (argc * sizeof (char *)); 722 for (i = 0; i < argc; ++i) 723 (*pargv)[i] = xstrdup (argv[i]); 724 } 725