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