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 /* 294 * Change the mode of a file, either adding write permissions, or removing 295 * all write permissions. Either change honors the current umask setting. 296 */ 297 void 298 xchmod (fname, writable) 299 char *fname; 300 int writable; 301 { 302 struct stat sb; 303 mode_t mode, oumask; 304 305 if (stat (fname, &sb) < 0) 306 { 307 if (!noexec) 308 error (0, errno, "cannot stat %s", fname); 309 return; 310 } 311 oumask = umask (0); 312 (void) umask (oumask); 313 if (writable) 314 { 315 mode = sb.st_mode | (~oumask 316 & (((sb.st_mode & S_IRUSR) ? S_IWUSR : 0) 317 | ((sb.st_mode & S_IRGRP) ? S_IWGRP : 0) 318 | ((sb.st_mode & S_IROTH) ? S_IWOTH : 0))); 319 } 320 else 321 { 322 mode = sb.st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH) & ~oumask; 323 } 324 325 if (trace) 326 #ifdef SERVER_SUPPORT 327 (void) fprintf (stderr, "%c-> chmod(%s,%o)\n", 328 (server_active) ? 'S' : ' ', fname, 329 (unsigned int) mode); 330 #else 331 (void) fprintf (stderr, "-> chmod(%s,%o)\n", fname, 332 (unsigned int) mode); 333 #endif 334 if (noexec) 335 return; 336 337 if (chmod (fname, mode) < 0) 338 error (0, errno, "cannot change mode of file %s", fname); 339 } 340 341 /* 342 * Rename a file and die if it fails 343 */ 344 void 345 rename_file (from, to) 346 const char *from; 347 const char *to; 348 { 349 if (trace) 350 #ifdef SERVER_SUPPORT 351 (void) fprintf (stderr, "%c-> rename(%s,%s)\n", 352 (server_active) ? 'S' : ' ', from, to); 353 #else 354 (void) fprintf (stderr, "-> rename(%s,%s)\n", from, to); 355 #endif 356 if (noexec) 357 return; 358 359 if (rename (from, to) < 0) 360 error (1, errno, "cannot rename file %s to %s", from, to); 361 } 362 363 /* 364 * link a file, if possible. Warning: the Windows NT version of this 365 * function just copies the file, so only use this function in ways 366 * that can deal with either a link or a copy. 367 */ 368 int 369 link_file (from, to) 370 const char *from; 371 const char *to; 372 { 373 if (trace) 374 #ifdef SERVER_SUPPORT 375 (void) fprintf (stderr, "%c-> link(%s,%s)\n", 376 (server_active) ? 'S' : ' ', from, to); 377 #else 378 (void) fprintf (stderr, "-> link(%s,%s)\n", from, to); 379 #endif 380 if (noexec) 381 return (0); 382 383 return (link (from, to)); 384 } 385 386 /* 387 * unlink a file, if possible. 388 */ 389 int 390 unlink_file (f) 391 const char *f; 392 { 393 if (trace) 394 #ifdef SERVER_SUPPORT 395 (void) fprintf (stderr, "%c-> unlink(%s)\n", 396 (server_active) ? 'S' : ' ', f); 397 #else 398 (void) fprintf (stderr, "-> unlink(%s)\n", f); 399 #endif 400 if (noexec) 401 return (0); 402 403 return (unlink (f)); 404 } 405 406 /* 407 * Unlink a file or dir, if possible. If it is a directory do a deep 408 * removal of all of the files in the directory. Return -1 on error 409 * (in which case errno is set). 410 */ 411 int 412 unlink_file_dir (f) 413 const char *f; 414 { 415 if (trace) 416 #ifdef SERVER_SUPPORT 417 (void) fprintf (stderr, "%c-> unlink_file_dir(%s)\n", 418 (server_active) ? 'S' : ' ', f); 419 #else 420 (void) fprintf (stderr, "-> unlink_file_dir(%s)\n", f); 421 #endif 422 if (noexec) 423 return (0); 424 425 /* For at least some unices, if root tries to unlink() a directory, 426 instead of doing something rational like returning EISDIR, 427 the system will gleefully go ahead and corrupt the filesystem. 428 So we first call isdir() to see if it is OK to call unlink(). This 429 doesn't quite work--if someone creates a directory between the 430 call to isdir() and the call to unlink(), we'll still corrupt 431 the filesystem. Where is the Unix Haters Handbook when you need 432 it? */ 433 if (isdir(f)) 434 return deep_remove_dir(f); 435 else 436 { 437 if (unlink (f) != 0) 438 return -1; 439 } 440 /* We were able to remove the file from the disk */ 441 return 0; 442 } 443 444 /* Remove a directory and everything it contains. Returns 0 for 445 * success, -1 for failure (in which case errno is set). 446 */ 447 448 static int 449 deep_remove_dir (path) 450 const char *path; 451 { 452 DIR *dirp; 453 struct dirent *dp; 454 char buf[PATH_MAX]; 455 456 if (rmdir (path) != 0 && (errno == ENOTEMPTY || errno == EEXIST)) 457 { 458 if ((dirp = opendir (path)) == NULL) 459 /* If unable to open the directory return 460 * an error 461 */ 462 return -1; 463 464 while ((dp = readdir (dirp)) != NULL) 465 { 466 if (strcmp (dp->d_name, ".") == 0 || 467 strcmp (dp->d_name, "..") == 0) 468 continue; 469 470 sprintf (buf, "%s/%s", path, dp->d_name); 471 472 /* See comment in unlink_file_dir explanation of why we use 473 isdir instead of just calling unlink and checking the 474 status. */ 475 if (isdir(buf)) 476 { 477 if (deep_remove_dir(buf)) 478 { 479 closedir(dirp); 480 return -1; 481 } 482 } 483 else 484 { 485 if (unlink (buf) != 0) 486 { 487 closedir(dirp); 488 return -1; 489 } 490 } 491 } 492 closedir (dirp); 493 return rmdir (path); 494 } 495 496 /* Was able to remove the directory return 0 */ 497 return 0; 498 } 499 500 /* Read NCHARS bytes from descriptor FD into BUF. 501 Return the number of characters successfully read. 502 The number returned is always NCHARS unless end-of-file or error. */ 503 static size_t 504 block_read (fd, buf, nchars) 505 int fd; 506 char *buf; 507 size_t nchars; 508 { 509 char *bp = buf; 510 size_t nread; 511 512 do 513 { 514 nread = read (fd, bp, nchars); 515 if (nread == (size_t)-1) 516 { 517 #ifdef EINTR 518 if (errno == EINTR) 519 continue; 520 #endif 521 return (size_t)-1; 522 } 523 524 if (nread == 0) 525 break; 526 527 bp += nread; 528 nchars -= nread; 529 } while (nchars != 0); 530 531 return bp - buf; 532 } 533 534 535 /* 536 * Compare "file1" to "file2". Return non-zero if they don't compare exactly. 537 */ 538 int 539 xcmp (file1, file2) 540 const char *file1; 541 const char *file2; 542 { 543 char *buf1, *buf2; 544 struct stat sb1, sb2; 545 int fd1, fd2; 546 int ret; 547 548 if ((fd1 = open (file1, O_RDONLY)) < 0) 549 error (1, errno, "cannot open file %s for comparing", file1); 550 if ((fd2 = open (file2, O_RDONLY)) < 0) 551 error (1, errno, "cannot open file %s for comparing", file2); 552 if (fstat (fd1, &sb1) < 0) 553 error (1, errno, "cannot fstat %s", file1); 554 if (fstat (fd2, &sb2) < 0) 555 error (1, errno, "cannot fstat %s", file2); 556 557 /* A generic file compare routine might compare st_dev & st_ino here 558 to see if the two files being compared are actually the same file. 559 But that won't happen in CVS, so we won't bother. */ 560 561 if (sb1.st_size != sb2.st_size) 562 ret = 1; 563 else if (sb1.st_size == 0) 564 ret = 0; 565 else 566 { 567 /* FIXME: compute the optimal buffer size by computing the least 568 common multiple of the files st_blocks field */ 569 size_t buf_size = 8 * 1024; 570 size_t read1; 571 size_t read2; 572 573 buf1 = xmalloc (buf_size); 574 buf2 = xmalloc (buf_size); 575 576 do 577 { 578 read1 = block_read (fd1, buf1, buf_size); 579 if (read1 == (size_t)-1) 580 error (1, errno, "cannot read file %s for comparing", file1); 581 582 read2 = block_read (fd2, buf2, buf_size); 583 if (read2 == (size_t)-1) 584 error (1, errno, "cannot read file %s for comparing", file2); 585 586 /* assert (read1 == read2); */ 587 588 ret = memcmp(buf1, buf2, read1); 589 } while (ret == 0 && read1 == buf_size); 590 591 free (buf1); 592 free (buf2); 593 } 594 595 (void) close (fd1); 596 (void) close (fd2); 597 return (ret); 598 } 599 600 #ifdef LOSING_TMPNAM_FUNCTION 601 char *tmpnam(char *s) 602 { 603 static char value[L_tmpnam+1]; 604 605 if (s){ 606 strcpy(s,"/tmp/cvsXXXXXX"); 607 mktemp(s); 608 return s; 609 }else{ 610 strcpy(value,"/tmp/cvsXXXXXX"); 611 mktemp(s); 612 return value; 613 } 614 } 615 #endif 616 617 /* Return non-zero iff FILENAME is absolute. 618 Trivial under Unix, but more complicated under other systems. */ 619 int 620 isabsolute (filename) 621 const char *filename; 622 { 623 return filename[0] == '/'; 624 } 625 626 627 /* Return a pointer into PATH's last component. */ 628 char * 629 last_component (path) 630 char *path; 631 { 632 char *last = strrchr (path, '/'); 633 634 if (last) 635 return last + 1; 636 else 637 return path; 638 } 639 640 /* Return the home directory. Returns a pointer to storage 641 managed by this function or its callees (currently getenv). */ 642 char * 643 get_homedir () 644 { 645 return getenv ("HOME"); 646 } 647 648 /* See cvs.h for description. On unix this does nothing, because the 649 shell expands the wildcards. */ 650 void 651 expand_wild (argc, argv, pargc, pargv) 652 int argc; 653 char **argv; 654 int *pargc; 655 char ***pargv; 656 { 657 int i; 658 *pargc = argc; 659 *pargv = (char **) xmalloc (argc * sizeof (char *)); 660 for (i = 0; i < argc; ++i) 661 (*pargv)[i] = xstrdup (argv[i]); 662 } 663