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 char buf[PATH_MAX]; 467 468 if (rmdir (path) != 0) 469 { 470 if (errno == ENOTEMPTY 471 || errno == EEXIST 472 /* Ugly workaround for ugly AIX 4.1 (and 3.2) header bug 473 (it defines ENOTEMPTY and EEXIST to 17 but actually 474 returns 87). */ 475 || (ENOTEMPTY == 17 && EEXIST == 17 && errno == 87)) 476 { 477 if ((dirp = opendir (path)) == NULL) 478 /* If unable to open the directory return 479 * an error 480 */ 481 return -1; 482 483 while ((dp = readdir (dirp)) != NULL) 484 { 485 if (strcmp (dp->d_name, ".") == 0 || 486 strcmp (dp->d_name, "..") == 0) 487 continue; 488 489 sprintf (buf, "%s/%s", path, dp->d_name); 490 491 /* See comment in unlink_file_dir explanation of why we use 492 isdir instead of just calling unlink and checking the 493 status. */ 494 if (isdir(buf)) 495 { 496 if (deep_remove_dir(buf)) 497 { 498 closedir(dirp); 499 return -1; 500 } 501 } 502 else 503 { 504 if (unlink (buf) != 0) 505 { 506 closedir(dirp); 507 return -1; 508 } 509 } 510 } 511 closedir (dirp); 512 return rmdir (path); 513 } 514 else 515 return -1; 516 } 517 518 /* Was able to remove the directory return 0 */ 519 return 0; 520 } 521 522 /* Read NCHARS bytes from descriptor FD into BUF. 523 Return the number of characters successfully read. 524 The number returned is always NCHARS unless end-of-file or error. */ 525 static size_t 526 block_read (fd, buf, nchars) 527 int fd; 528 char *buf; 529 size_t nchars; 530 { 531 char *bp = buf; 532 size_t nread; 533 534 do 535 { 536 nread = read (fd, bp, nchars); 537 if (nread == (size_t)-1) 538 { 539 #ifdef EINTR 540 if (errno == EINTR) 541 continue; 542 #endif 543 return (size_t)-1; 544 } 545 546 if (nread == 0) 547 break; 548 549 bp += nread; 550 nchars -= nread; 551 } while (nchars != 0); 552 553 return bp - buf; 554 } 555 556 557 /* 558 * Compare "file1" to "file2". Return non-zero if they don't compare exactly. 559 */ 560 int 561 xcmp (file1, file2) 562 const char *file1; 563 const char *file2; 564 { 565 char *buf1, *buf2; 566 struct stat sb1, sb2; 567 int fd1, fd2; 568 int ret; 569 570 if ((fd1 = open (file1, O_RDONLY)) < 0) 571 error (1, errno, "cannot open file %s for comparing", file1); 572 if ((fd2 = open (file2, O_RDONLY)) < 0) 573 error (1, errno, "cannot open file %s for comparing", file2); 574 if (fstat (fd1, &sb1) < 0) 575 error (1, errno, "cannot fstat %s", file1); 576 if (fstat (fd2, &sb2) < 0) 577 error (1, errno, "cannot fstat %s", file2); 578 579 /* A generic file compare routine might compare st_dev & st_ino here 580 to see if the two files being compared are actually the same file. 581 But that won't happen in CVS, so we won't bother. */ 582 583 if (sb1.st_size != sb2.st_size) 584 ret = 1; 585 else if (sb1.st_size == 0) 586 ret = 0; 587 else 588 { 589 /* FIXME: compute the optimal buffer size by computing the least 590 common multiple of the files st_blocks field */ 591 size_t buf_size = 8 * 1024; 592 size_t read1; 593 size_t read2; 594 595 buf1 = xmalloc (buf_size); 596 buf2 = xmalloc (buf_size); 597 598 do 599 { 600 read1 = block_read (fd1, buf1, buf_size); 601 if (read1 == (size_t)-1) 602 error (1, errno, "cannot read file %s for comparing", file1); 603 604 read2 = block_read (fd2, buf2, buf_size); 605 if (read2 == (size_t)-1) 606 error (1, errno, "cannot read file %s for comparing", file2); 607 608 /* assert (read1 == read2); */ 609 610 ret = memcmp(buf1, buf2, read1); 611 } while (ret == 0 && read1 == buf_size); 612 613 free (buf1); 614 free (buf2); 615 } 616 617 (void) close (fd1); 618 (void) close (fd2); 619 return (ret); 620 } 621 622 /* Just in case this implementation does not define this. */ 623 #ifndef L_tmpnam 624 #define L_tmpnam 50 625 #endif 626 627 #ifdef LOSING_TMPNAM_FUNCTION 628 char * 629 cvs_temp_name () 630 { 631 char value[L_tmpnam + 1]; 632 633 /* FIXME: Should be using TMPDIR. */ 634 strcpy (value, "/tmp/cvsXXXXXX"); 635 mktemp (value); 636 return xstrdup (value); 637 } 638 #else 639 /* Generate a unique temporary filename. Returns a pointer to a newly 640 malloc'd string containing the name. Returns successfully or not at 641 all. */ 642 char * 643 cvs_temp_name () 644 { 645 char value[L_tmpnam + 1]; 646 char *retval; 647 648 /* FIXME: should be using TMPDIR, perhaps by using tempnam on systems 649 which have it. */ 650 retval = tmpnam (value); 651 if (retval == NULL) 652 error (1, errno, "cannot generate temporary filename"); 653 return xstrdup (retval); 654 } 655 #endif 656 657 /* Return non-zero iff FILENAME is absolute. 658 Trivial under Unix, but more complicated under other systems. */ 659 int 660 isabsolute (filename) 661 const char *filename; 662 { 663 return filename[0] == '/'; 664 } 665 666 667 /* Return a pointer into PATH's last component. */ 668 char * 669 last_component (path) 670 char *path; 671 { 672 char *last = strrchr (path, '/'); 673 674 if (last) 675 return last + 1; 676 else 677 return path; 678 } 679 680 /* Return the home directory. Returns a pointer to storage 681 managed by this function or its callees (currently getenv). 682 This function will return the same thing every time it is 683 called. */ 684 char * 685 get_homedir () 686 { 687 static char *home = NULL; 688 char *env = getenv ("HOME"); 689 struct passwd *pw; 690 691 if (home != NULL) 692 return home; 693 694 if (env) 695 home = env; 696 else if ((pw = (struct passwd *) getpwuid (getuid ())) 697 && pw->pw_dir) 698 home = xstrdup (pw->pw_dir); 699 else 700 return 0; 701 702 return home; 703 } 704 705 /* See cvs.h for description. On unix this does nothing, because the 706 shell expands the wildcards. */ 707 void 708 expand_wild (argc, argv, pargc, pargv) 709 int argc; 710 char **argv; 711 int *pargc; 712 char ***pargv; 713 { 714 int i; 715 *pargc = argc; 716 *pargv = (char **) xmalloc (argc * sizeof (char *)); 717 for (i = 0; i < argc; ++i) 718 (*pargv)[i] = xstrdup (argv[i]); 719 } 720