Changeset 370 for trunk/src/gmake/kmkbuiltin/install.c
- Timestamp:
- Dec 18, 2005, 4:48:02 AM (20 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/gmake/kmkbuiltin/install.c
r368 r370 42 42 static char sccsid[] = "@(#)xinstall.c 8.1 (Berkeley) 7/21/93"; 43 43 #endif /* not lint */ 44 #endif45 44 46 45 #include <sys/cdefs.h> 47 46 __FBSDID("$FreeBSD: src/usr.bin/xinstall/xinstall.c,v 1.66 2005/01/25 14:34:57 ssouhlal Exp $"); 48 47 #endif 48 49 #ifndef _MSC_VER 49 50 #include <sys/param.h> 51 #ifdef USE_MMAP 50 52 #include <sys/mman.h> 53 #endif 51 54 #include <sys/mount.h> 55 #include <sys/wait.h> 56 #include <sys/time.h> 57 #else 58 #include <process.h> 59 #endif 52 60 #include <sys/stat.h> 53 #include <sys/time.h>54 #include <sys/wait.h>55 61 56 62 #include <ctype.h> 57 #include <err.h>63 #include "err.h" 58 64 #include <errno.h> 59 65 #include <fcntl.h> 66 #ifndef _MSC_VER 60 67 #include <grp.h> 61 68 #include <paths.h> 62 69 #include <pwd.h> 70 #endif 63 71 #include <stdio.h> 64 72 #include <stdlib.h> 65 73 #include <string.h> 74 #ifndef _MSC_VER 66 75 #include <sysexits.h> 67 76 #include <unistd.h> 77 #else 78 #include "mscfakes.h" 79 #endif 80 81 extern void * setmode(const char *p); 82 extern mode_t getmode(const void *bbox, mode_t omode); 83 84 #ifndef __unused 85 # define __unused 86 #endif 87 88 #ifndef MAXBSIZE 89 # define MAXBSIZE 16384 90 #endif 68 91 69 92 /* Bootstrap aid - this doesn't exist in most older releases */ … … 83 106 #endif 84 107 85 static struct passwd *pp;86 static struct group *gp;87 108 static gid_t gid; 88 109 static uid_t uid; … … 91 112 static const char *suffix = BACKUP_SUFFIX; 92 113 93 static voidcopy(int, const char *, int, const char *, off_t);114 static int copy(int, const char *, int, const char *, off_t); 94 115 static int compare(int, const char *, size_t, int, const char *, size_t); 95 116 static int create_newfile(const char *, int, struct stat *); 96 117 static int create_tempfile(const char *, char *, size_t); 97 static voidinstall(const char *, const char *, u_long, u_int);98 static voidinstall_dir(char *);118 static int install(const char *, const char *, u_long, u_int); 119 static int install_dir(char *); 99 120 static u_long numeric_id(const char *, const char *); 100 static void strip(const char *); 121 static int strip(const char *); 122 #ifdef USE_MMAP 101 123 static int trymmap(int); 102 static void usage(void); 124 #endif 125 static int usage(void); 103 126 104 127 int … … 107 130 struct stat from_sb, to_sb; 108 131 mode_t *set; 109 u_long fset ;132 u_long fset = 0; 110 133 int ch, no_target; 111 134 u_int iflags; … … 132 155 dodir = 1; 133 156 break; 134 157 case 'f': 135 158 #ifdef UF_IMMUTABLE 136 159 flags = optarg; 137 160 if (strtofflags(&flags, &fset, NULL)) 138 errx(EX_USAGE, "%s: invalid flag", flags);161 return errx(EX_USAGE, "%s: invalid flag", flags); 139 162 iflags |= SETFLAGS; 163 #else 164 (void)flags; 140 165 #endif 141 166 break; … … 152 177 if (!(set = setmode(optarg))) 153 178 #endif 154 errx(EX_USAGE, "invalid file mode: %s",155 optarg);179 return errx(EX_USAGE, "invalid file mode: %s", 180 optarg); 156 181 mode = getmode(set, 0); 157 182 free(set); … … 174 199 case '?': 175 200 default: 176 usage();201 return usage(); 177 202 } 178 203 argc -= optind; … … 182 207 if (dostrip && dodir) { 183 208 warnx("-d and -s may not be specified together"); 184 usage();209 return usage(); 185 210 } 186 211 187 212 /* must have at least two arguments, except when creating directories */ 188 213 if (argc == 0 || (argc == 1 && !dodir)) 189 usage();214 return usage(); 190 215 191 216 /* need to make a temp copy so we can compare stripped version */ … … 195 220 /* get group and owner id's */ 196 221 if (group != NULL) { 222 #ifndef _MSC_VER 223 struct group *gp; 197 224 if ((gp = getgrnam(group)) != NULL) 198 225 gid = gp->gr_gid; 199 226 else 227 #endif 228 { 200 229 gid = (gid_t)numeric_id(group, "group"); 230 if (gid == (gid_t)-1) 231 return 1; 232 } 201 233 } else 202 234 gid = (gid_t)-1; 203 235 204 236 if (owner != NULL) { 237 #ifndef _MSC_VER 238 struct passwd *pp; 205 239 if ((pp = getpwnam(owner)) != NULL) 206 240 uid = pp->pw_uid; 207 241 else 242 #endif 243 { 208 244 uid = (uid_t)numeric_id(owner, "user"); 245 if (uid == (uid_t)-1) 246 return 1; 247 } 209 248 } else 210 249 uid = (uid_t)-1; 211 250 212 251 if (dodir) { 213 for (; *argv != NULL; ++argv) 214 install_dir(*argv); 215 exit(EX_OK); 252 for (; *argv != NULL; ++argv) { 253 int rc = install_dir(*argv); 254 if (rc) 255 return rc; 256 } 257 return EX_OK; 216 258 /* NOTREACHED */ 217 259 } … … 219 261 no_target = stat(to_name = argv[argc - 1], &to_sb); 220 262 if (!no_target && S_ISDIR(to_sb.st_mode)) { 221 for (; *argv != to_name; ++argv) 222 install(*argv, to_name, fset, iflags | DIRECTORY); 223 exit(EX_OK); 224 /* NOTREACHED */ 263 for (; *argv != to_name; ++argv) { 264 int rc = install(*argv, to_name, fset, iflags | DIRECTORY); 265 if (rc) 266 return rc; 267 } 268 return EX_OK; 225 269 } 226 270 … … 228 272 if (argc != 2) { 229 273 warnx("wrong number or types of arguments"); 230 usage();274 return usage(); 231 275 } 232 276 233 277 if (!no_target) { 234 278 if (stat(*argv, &from_sb)) 235 err(EX_OSERR, "%s", *argv);279 return err(EX_OSERR, "%s", *argv); 236 280 if (!S_ISREG(to_sb.st_mode)) { 237 281 errno = EFTYPE; 238 err(EX_OSERR, "%s", to_name);282 return err(EX_OSERR, "%s", to_name); 239 283 } 240 284 if (to_sb.st_dev == from_sb.st_dev && 241 to_sb.st_ino == from_sb.st_ino) 242 errx(EX_USAGE,243 "%s and %s are the same file", *argv, to_name);244 }245 install(*argv, to_name, fset, iflags);246 exit(EX_OK);247 /* NOTREACHED */248 } 249 250 u_long285 to_sb.st_dev != 0 && 286 to_sb.st_ino == from_sb.st_ino && 287 to_sb.st_ino != 0) 288 return errx(EX_USAGE, 289 "%s and %s are the same file", *argv, to_name); 290 } 291 return install(*argv, to_name, fset, iflags); 292 } 293 294 static u_long 251 295 numeric_id(const char *name, const char *type) 252 296 { … … 261 305 val = strtoul(name, &ep, 10); 262 306 if (errno) 263 err(EX_NOUSER, "%s", name);307 return err(-1, "%s", name); 264 308 if (*ep != '\0') 265 errx(EX_NOUSER, "unknown %s %s", type, name);309 return errx(-1, "unknown %s %s", type, name); 266 310 return (val); 267 311 } … … 271 315 * build a path name and install the file 272 316 */ 273 void 317 static int 274 318 install(const char *from_name, const char *to_name, u_long fset, u_int flags) 275 319 { … … 279 323 int tempcopy, temp_fd, to_fd; 280 324 char backup[MAXPATHLEN], *p, pathbuf[MAXPATHLEN], tempfile[MAXPATHLEN]; 325 int rc = EX_OK; 281 326 282 327 files_match = 0; 283 328 from_fd = -1; 284 329 to_fd = -1; 330 temp_fd = -1; 285 331 286 332 /* If try to install NULL file to a directory, fails. */ 287 if (flags & DIRECTORY || strcmp(from_name, _PATH_DEVNULL)) { 333 if (flags & DIRECTORY 334 #if defined(__EMX__) || defined(_MSC_VER) 335 || ( stricmp(from_name, _PATH_DEVNULL) 336 && stricmp(from_name, "nul") 337 #ifdef __EMX__ 338 && stricmp(from_name, "/dev/nul") 339 #endif 340 ) 341 #else 342 || strcmp(from_name, _PATH_DEVNULL) 343 #endif 344 ) { 288 345 if (stat(from_name, &from_sb)) 289 err(EX_OSERR, "%s", from_name);346 return err(EX_OSERR, "%s", from_name); 290 347 if (!S_ISREG(from_sb.st_mode)) { 291 348 errno = EFTYPE; 292 err(EX_OSERR, "%s", from_name);349 return err(EX_OSERR, "%s", from_name); 293 350 } 294 351 /* Build the target path. */ … … 310 367 errno = EFTYPE; 311 368 warn("%s", to_name); 312 return ;369 return EX_OK; 313 370 } 314 371 … … 317 374 318 375 if (!devnull && (from_fd = open(from_name, O_RDONLY | O_BINARY, 0)) < 0) 319 err(EX_OSERR, "%s", from_name);376 return err(EX_OSERR, "%s", from_name); 320 377 321 378 /* If we don't strip, we can compare first. */ 322 379 if (docompare && !dostrip && target) { 323 if ((to_fd = open(to_name, O_RDONLY | O_BINARY, 0)) < 0) 324 err(EX_OSERR, "%s", to_name); 380 if ((to_fd = open(to_name, O_RDONLY | O_BINARY, 0)) < 0) { 381 rc = err(EX_OSERR, "%s", to_name); 382 goto l_done; 383 } 325 384 if (devnull) 326 385 files_match = to_sb.st_size == 0; … … 331 390 332 391 /* Close "to" file unless we match. */ 333 if (!files_match) 392 if (!files_match) { 334 393 (void)close(to_fd); 394 to_fd = -1; 395 } 335 396 } 336 397 … … 339 400 to_fd = create_tempfile(to_name, tempfile, 340 401 sizeof(tempfile)); 341 if (to_fd < 0) 342 err(EX_OSERR, "%s", tempfile); 402 if (to_fd < 0) { 403 rc = err(EX_OSERR, "%s", tempfile); 404 goto l_done; 405 } 343 406 } else { 344 407 if ((to_fd = create_newfile(to_name, target, 345 &to_sb)) < 0) 346 err(EX_OSERR, "%s", to_name); 408 &to_sb)) < 0) { 409 rc = err(EX_OSERR, "%s", to_name); 410 goto l_done; 411 } 347 412 if (verbose) 348 413 (void)printf("install: %s -> %s\n", 349 414 from_name, to_name); 350 415 } 351 if (!devnull) 352 copy(from_fd, from_name, to_fd, 353 tempcopy ? tempfile : to_name, from_sb.st_size); 416 if (!devnull) { 417 rc = copy(from_fd, from_name, to_fd, 418 tempcopy ? tempfile : to_name, from_sb.st_size); 419 if (rc) 420 goto l_done; 421 } 354 422 } 355 423 356 424 if (dostrip) { 357 strip(tempcopy ? tempfile : to_name); 425 #if defined(__EMX__) || defined(_MSC_VER) 426 /* close before we strip. */ 427 close(to_fd); 428 to_fd = -1; 429 #endif 430 rc = strip(tempcopy ? tempfile : to_name); 431 if (rc) 432 goto l_done; 358 433 359 434 /* … … 361 436 * that does not work in-place -- like GNU binutils strip. 362 437 */ 438 #if !defined(__EMX__) && !defined(_MSC_VER) 363 439 close(to_fd); 440 #endif 364 441 to_fd = open(tempcopy ? tempfile : to_name, O_RDONLY | O_BINARY, 0); 365 if (to_fd < 0) 366 err(EX_OSERR, "stripping %s", to_name); 442 if (to_fd < 0) { 443 rc = err(EX_OSERR, "stripping %s", to_name); 444 goto l_done; 445 } 367 446 } 368 447 … … 374 453 375 454 /* Re-open to_fd using the real target name. */ 376 if ((to_fd = open(to_name, O_RDONLY | O_BINARY, 0)) < 0) 377 err(EX_OSERR, "%s", to_name); 455 if ((to_fd = open(to_name, O_RDONLY | O_BINARY, 0)) < 0) { 456 rc = err(EX_OSERR, "%s", to_name); 457 goto l_done; 458 } 378 459 379 460 if (fstat(temp_fd, &temp_sb)) { … … 381 462 (void)unlink(tempfile); 382 463 errno = serrno; 383 err(EX_OSERR, "%s", tempfile); 464 rc = err(EX_OSERR, "%s", tempfile); 465 goto l_done; 384 466 } 385 467 … … 391 473 * Need to preserve target file times, though. 392 474 */ 475 #if !defined(_MSC_VER) && !defined(__EMX__) 393 476 if (to_sb.st_nlink != 1) { 394 477 tvb[0].tv_sec = to_sb.st_atime; … … 397 480 tvb[1].tv_usec = 0; 398 481 (void)utimes(tempfile, tvb); 399 } else { 482 } else 483 #endif 484 { 485 400 486 files_match = 1; 401 487 (void)unlink(tempfile); 402 488 } 403 489 (void) close(temp_fd); 490 temp_fd = -1; 404 491 } 405 492 } … … 419 506 suffix) != strlen(to_name) + strlen(suffix)) { 420 507 unlink(tempfile); 421 errx(EX_OSERR, "%s: backup filename too long", 422 to_name); 508 rc = errx(EX_OSERR, "%s: backup filename too long", 509 to_name); 510 goto l_done; 423 511 } 424 512 if (verbose) … … 428 516 unlink(tempfile); 429 517 errno = serrno; 430 err(EX_OSERR, "rename: %s to %s", to_name, 431 backup); 518 rc = err(EX_OSERR, "rename: %s to %s", to_name, 519 backup); 520 goto l_done; 432 521 } 433 522 } … … 438 527 unlink(tempfile); 439 528 errno = serrno; 440 err(EX_OSERR, "rename: %s to %s", 441 tempfile, to_name); 529 rc = err(EX_OSERR, "rename: %s to %s", 530 tempfile, to_name); 531 goto l_done; 442 532 } 443 533 444 534 /* Re-open to_fd so we aren't hosed by the rename(2). */ 445 535 (void) close(to_fd); 446 if ((to_fd = open(to_name, O_RDONLY | O_BINARY, 0)) < 0) 447 err(EX_OSERR, "%s", to_name); 536 if ((to_fd = open(to_name, O_RDONLY | O_BINARY, 0)) < 0) { 537 rc = err(EX_OSERR, "%s", to_name); 538 goto l_done; 539 } 448 540 } 449 541 … … 463 555 (void)unlink(to_name); 464 556 errno = serrno; 465 err(EX_OSERR, "%s", to_name); 557 rc = err(EX_OSERR, "%s", to_name); 558 goto l_done; 466 559 } 467 560 … … 486 579 (void)unlink(to_name); 487 580 errno = serrno; 488 err(EX_OSERR,"%s: chown/chgrp", to_name); 581 rc = err(EX_OSERR,"%s: chown/chgrp", to_name); 582 goto l_done; 489 583 } 490 584 … … 494 588 (void)unlink(to_name); 495 589 errno = serrno; 496 err(EX_OSERR, "%s: chmod", to_name); 590 rc = err(EX_OSERR, "%s: chmod", to_name); 591 goto l_done; 497 592 } 498 593 … … 516 611 (void)unlink(to_name); 517 612 errno = serrno; 518 err(EX_OSERR, "%s: chflags", to_name); 519 } 520 } 521 } 522 #endif 523 524 (void)close(to_fd); 613 rc = err(EX_OSERR, "%s: chflags", to_name); 614 goto l_done; 615 } 616 } 617 } 618 #endif 619 620 l_done: 621 if (to_fd >= 0) 622 (void)close(to_fd); 623 if (temp_fd >= 0) 624 (void)close(temp_fd); 525 625 if (!devnull) 526 626 (void)close(from_fd); 627 return rc; 527 628 } 528 629 … … 531 632 * compare two files; non-zero means files differ 532 633 */ 533 int634 static int 534 635 compare(int from_fd, const char *from_name __unused, size_t from_len, 535 636 int to_fd, const char *to_name __unused, size_t to_len) … … 544 645 545 646 if (from_len <= MAX_CMP_SIZE) { 546 #if !defined(__EMX__) && !defined(_MSC_VER)647 #ifdef USE_MMAP 547 648 done_compare = 0; 548 649 if (trymmap(from_fd) && trymmap(to_fd)) { … … 561 662 done_compare = 1; 562 663 } 563 #endif564 664 out: 665 #else 666 (void)p; (void)q; 667 done_compare = 0; 668 #endif 565 669 if (!done_compare) { 566 670 char buf1[MAXBSIZE]; … … 637 741 if (dobackup) { 638 742 if ((size_t)snprintf(backup, MAXPATHLEN, "%s%s", 639 path, suffix) != strlen(path) + strlen(suffix)) 743 path, suffix) != strlen(path) + strlen(suffix)) { 640 744 errx(EX_OSERR, "%s: backup filename too long", 641 path); 745 path); 746 errno = ENAMETOOLONG; 747 return -1; 748 } 642 749 (void)snprintf(backup, MAXPATHLEN, "%s%s", 643 750 path, suffix); … … 645 752 (void)printf("install: %s -> %s\n", 646 753 path, backup); 647 if (rename(path, backup) < 0) 754 if (rename(path, backup) < 0) { 648 755 err(EX_OSERR, "rename: %s to %s", path, backup); 756 return -1; 757 } 649 758 } else 650 759 if (unlink(path) < 0) … … 662 771 * copy from one file to another 663 772 */ 664 void 773 static int 665 774 copy(int from_fd, const char *from_name, int to_fd, const char *to_name, 666 775 off_t size) … … 673 782 /* Rewind file descriptors. */ 674 783 if (lseek(from_fd, (off_t)0, SEEK_SET) == (off_t)-1) 675 err(EX_OSERR, "lseek: %s", from_name);784 return err(EX_OSERR, "lseek: %s", from_name); 676 785 if (lseek(to_fd, (off_t)0, SEEK_SET) == (off_t)-1) 677 err(EX_OSERR, "lseek: %s", to_name);786 return err(EX_OSERR, "lseek: %s", to_name); 678 787 679 788 /* … … 683 792 */ 684 793 done_copy = 0; 685 #if !defined(__EMX__) && !defined(_MSC_VER)794 #ifdef USE_MMAP 686 795 if (size <= 8 * 1048576 && trymmap(from_fd) && 687 796 (p = mmap(NULL, (size_t)size, PROT_READ, MAP_SHARED, … … 695 804 done_copy = 1; 696 805 } 806 #else 807 (void)p; 697 808 #endif 698 809 if (!done_copy) { … … 702 813 (void)unlink(to_name); 703 814 errno = nw > 0 ? EIO : serrno; 704 err(EX_OSERR, "%s", to_name);815 return err(EX_OSERR, "%s", to_name); 705 816 } 706 817 if (nr != 0) { … … 708 819 (void)unlink(to_name); 709 820 errno = serrno; 710 err(EX_OSERR, "%s", from_name); 711 } 712 } 821 return err(EX_OSERR, "%s", from_name); 822 } 823 } 824 return EX_OK; 713 825 } 714 826 … … 717 829 * use strip(1) to strip the target file 718 830 */ 719 void 831 static int 720 832 strip(const char *to_name) 721 833 { 834 #if defined(__EMX__) || defined(_MSC_VER) 835 const char *stripbin = getenv("STRIPBIN"); 836 if (stripbin == NULL) 837 stripbin = "strip"; 838 return spawnlp(P_WAIT, stripbin, stripbin, to_name, NULL); 839 #else 722 840 const char *stripbin; 723 841 int serrno, status; … … 743 861 } 744 862 } 863 #endif 745 864 } 746 865 … … 749 868 * build directory heirarchy 750 869 */ 751 void 870 static int 752 871 install_dir(char *path) 753 872 { … … 762 881 if (stat(path, &sb)) { 763 882 if (errno != ENOENT || mkdir(path, 0755) < 0) { 764 err(EX_OSERR, "mkdir %s", path);883 return err(EX_OSERR, "mkdir %s", path); 765 884 /* NOTREACHED */ 766 885 } else if (verbose) … … 768 887 path); 769 888 } else if (!S_ISDIR(sb.st_mode)) 770 errx(EX_OSERR, "%s exists but is not a directory", path);889 return errx(EX_OSERR, "%s exists but is not a directory", path); 771 890 if (!(*p = ch)) 772 891 break; … … 777 896 if (chmod(path, mode)) 778 897 warn("chmod %o %s", mode, path); 898 return EX_OK; 779 899 } 780 900 … … 783 903 * print a usage message and die 784 904 */ 785 void 905 static int 786 906 usage() 787 907 { … … 792 912 " [-o owner] file1 ... fileN directory\n" 793 913 " install -d [-v] [-g group] [-m mode] [-o owner] directory ...\n"); 794 exit(EX_USAGE);795 /* NOTREACHED */ 796 } 797 914 return EX_USAGE; 915 } 916 917 #ifdef USE_MMAP 798 918 /* 799 919 * trymmap -- 800 920 * return true (1) if mmap should be tried, false (0) if not. 801 921 */ 802 int922 static int 803 923 trymmap(int fd) 804 924 { … … 818 938 return (0); 819 939 } 940 #endif
Note:
See TracChangeset
for help on using the changeset viewer.