Changeset 3192 for trunk/src/kmk/kmkbuiltin/install.c
- Timestamp:
- Mar 26, 2018, 10:25:56 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/kmkbuiltin/install.c
r3145 r3192 122 122 #endif 123 123 124 static gid_t gid; 125 static uid_t uid; 126 static int dobackup, docompare, dodir, dopreserve, dostrip, nommap, safecopy, verbose, mode_given; 127 static mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 128 static const char *suffix = BACKUP_SUFFIX; 129 static int ignore_perm_errors; 130 static int hard_link_files_when_possible; 131 static int dos2unix; 132 124 /********************************************************************************************************************************* 125 * Structures and Typedefs * 126 *********************************************************************************************************************************/ 127 typedef struct INSTALLINSTANCE 128 { 129 PKMKBUILTINCTX pCtx; 130 131 gid_t gid; 132 uid_t uid; 133 int dobackup, docompare, dodir, dopreserve, dostrip, nommap, safecopy, verbose, mode_given; 134 mode_t mode; 135 const char *suffix; 136 int ignore_perm_errors; 137 int hard_link_files_when_possible; 138 int dos2unix; 139 } INSTALLINSTANCE; 140 typedef INSTALLINSTANCE *PINSTALLINSTANCE; 141 142 143 /********************************************************************************************************************************* 144 * Global Variables * 145 *********************************************************************************************************************************/ 133 146 static struct option long_options[] = 134 147 { … … 145 158 146 159 147 static int copy( int, const char *, int *, const char *);160 static int copy(PINSTALLINSTANCE, int, const char *, int *, const char *); 148 161 static int compare(int, size_t, int, size_t); 149 static int create_newfile( const char *, int, struct stat *);162 static int create_newfile(PINSTALLINSTANCE, const char *, int, struct stat *); 150 163 static int create_tempfile(const char *, char *, size_t); 151 static int install( const char *, const char *, u_long, u_int);152 static int install_dir( char *);153 static u_long numeric_id( const char *, const char *);154 static int strip( const char *);155 static int usage( FILE *);164 static int install(PINSTALLINSTANCE, const char *, const char *, u_long, u_int); 165 static int install_dir(PINSTALLINSTANCE, char *); 166 static u_long numeric_id(PINSTALLINSTANCE, const char *, const char *); 167 static int strip(PINSTALLINSTANCE, const char *); 168 static int usage(PKMKBUILTINCTX, int); 156 169 static char *last_slash(const char *); 157 170 static KBOOL needs_dos2unix_conversion(const char *pszFilename); … … 159 172 160 173 int 161 kmk_builtin_install(int argc, char *argv[], char ** envp) 162 { 174 kmk_builtin_install(int argc, char *argv[], char ** envp, PKMKBUILTINCTX pCtx) 175 { 176 INSTALLINSTANCE This; 163 177 struct stat from_sb, to_sb; 164 178 mode_t *set; … … 170 184 (void)envp; 171 185 172 /* reinitialize globals */ 173 mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 174 suffix = BACKUP_SUFFIX; 175 gid = 0; 176 uid = 0; 177 dobackup = docompare = dodir = dopreserve = dostrip = nommap = safecopy = verbose = mode_given = 0; 178 ignore_perm_errors = geteuid() != 0; 179 hard_link_files_when_possible = 0; 180 dos2unix = 0; 186 /* Initialize global instance data. */ 187 This.pCtx = pCtx; 188 This.mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 189 This.suffix = BACKUP_SUFFIX; 190 This.gid = 0; 191 This.uid = 0; 192 This.dobackup = 0; 193 This.docompare = 0; 194 This.dodir = 0; 195 This.dopreserve = 0; 196 This.dostrip = 0; 197 This.nommap = 0; 198 This.safecopy = 0; 199 This.verbose = 0; 200 This.mode_given = 0; 201 This.ignore_perm_errors = geteuid() != 0; 202 This.hard_link_files_when_possible = 0; 203 This.dos2unix = 0; 181 204 182 205 /* reset getopt and set progname. */ 183 g_progname = argv[0];184 206 opterr = 1; 185 207 optarg = NULL; … … 192 214 switch(ch) { 193 215 case 'B': 194 suffix = optarg;216 This.suffix = optarg; 195 217 /* FALLTHROUGH */ 196 218 case 'b': 197 dobackup = 1;219 This.dobackup = 1; 198 220 break; 199 221 case 'C': 200 docompare = 1;222 This.docompare = 1; 201 223 break; 202 224 case 'c': … … 204 226 break; 205 227 case 'd': 206 dodir = 1;228 This.dodir = 1; 207 229 break; 208 230 case 'f': … … 210 232 flags = optarg; 211 233 if (strtofflags(&flags, &fset, NULL)) 212 return errx( EX_USAGE, "%s: invalid flag", flags);234 return errx(pCtx, EX_USAGE, "%s: invalid flag", flags); 213 235 iflags |= SETFLAGS; 214 236 #else … … 220 242 break; 221 243 case 'M': 222 nommap = 1;244 This.nommap = 1; 223 245 break; 224 246 case 'm': 225 247 if (!(set = bsd_setmode(optarg))) 226 return errx(EX_USAGE, "invalid file mode: %s", 227 optarg); 228 mode = bsd_getmode(set, 0); 248 return errx(pCtx, EX_USAGE, "invalid file mode: %s", optarg); 249 This.mode = bsd_getmode(set, 0); 229 250 free(set); 230 mode_given = 1;251 This.mode_given = 1; 231 252 break; 232 253 case 'o': … … 234 255 break; 235 256 case 'p': 236 docompare =dopreserve = 1;257 This.docompare = This.dopreserve = 1; 237 258 break; 238 259 case 'S': 239 safecopy = 1;260 This.safecopy = 1; 240 261 break; 241 262 case 's': 242 dostrip = 1;263 This.dostrip = 1; 243 264 break; 244 265 case 'v': 245 verbose = 1;266 This.verbose = 1; 246 267 break; 247 268 case 261: 248 usage( stdout);269 usage(pCtx, 0); 249 270 return 0; 250 271 case 262: 251 272 return kbuild_version(argv[0]); 252 273 case 263: 253 ignore_perm_errors = 1;274 This.ignore_perm_errors = 1; 254 275 break; 255 276 case 264: 256 ignore_perm_errors = 0;277 This.ignore_perm_errors = 0; 257 278 break; 258 279 case 265: 259 hard_link_files_when_possible = 1;280 This.hard_link_files_when_possible = 1; 260 281 break; 261 282 case 266: 262 hard_link_files_when_possible = 0;283 This.hard_link_files_when_possible = 0; 263 284 break; 264 285 case 267: 265 dos2unix = 1;286 This.dos2unix = 1; 266 287 break; 267 288 case 268: 268 dos2unix = -1;289 This.dos2unix = -1; 269 290 break; 270 291 case '?': 271 292 default: 272 return usage( stderr);293 return usage(pCtx, 1); 273 294 } 274 295 argc -= optind; … … 276 297 277 298 /* some options make no sense when creating directories */ 278 if ( dostrip &&dodir) {279 warnx( "-d and -s may not be specified together");280 return usage( stderr);299 if (This.dostrip && This.dodir) { 300 warnx(pCtx, "-d and -s may not be specified together"); 301 return usage(pCtx, 1); 281 302 } 282 303 283 304 /* must have at least two arguments, except when creating directories */ 284 if (argc == 0 || (argc == 1 && ! dodir))285 return usage( stderr);305 if (argc == 0 || (argc == 1 && !This.dodir)) 306 return usage(pCtx, 1); 286 307 287 308 /* and unix2dos doesn't combine well with a couple of other options. */ 288 if ( dos2unix != 0) {289 if ( docompare) {290 warnx( "-C/-p and --dos2unix/unix2dos may not be specified together");291 return usage( stderr);292 } 293 if ( dostrip) {294 warnx( "-s and --dos2unix/unix2dos may not be specified together");295 return usage( stderr);309 if (This.dos2unix != 0) { 310 if (This.docompare) { 311 warnx(pCtx, "-C/-p and --dos2unix/unix2dos may not be specified together"); 312 return usage(pCtx, 1); 313 } 314 if (This.dostrip) { 315 warnx(pCtx, "-s and --dos2unix/unix2dos may not be specified together"); 316 return usage(pCtx, 1); 296 317 } 297 318 } 298 319 299 320 /* need to make a temp copy so we can compare stripped version */ 300 if ( docompare &&dostrip)301 safecopy = 1;321 if (This.docompare && This.dostrip) 322 This.safecopy = 1; 302 323 303 324 /* get group and owner id's */ … … 310 331 #endif 311 332 { 312 gid = (gid_t)numeric_id(group, "group");313 if ( gid == (gid_t)-1)333 This.gid = (gid_t)numeric_id(&This, group, "group"); 334 if (This.gid == (gid_t)-1) 314 335 return 1; 315 336 } 316 337 } else 317 gid = (gid_t)-1;338 This.gid = (gid_t)-1; 318 339 319 340 if (owner != NULL) { … … 325 346 #endif 326 347 { 327 uid = (uid_t)numeric_id(owner, "user");328 if ( uid == (uid_t)-1)348 This.uid = (uid_t)numeric_id(&This, owner, "user"); 349 if (This.uid == (uid_t)-1) 329 350 return 1; 330 351 } 331 352 } else 332 uid = (uid_t)-1;333 334 if ( dodir) {353 This.uid = (uid_t)-1; 354 355 if (This.dodir) { 335 356 for (; *argv != NULL; ++argv) { 336 int rc = install_dir( *argv);357 int rc = install_dir(&This, *argv); 337 358 if (rc) 338 359 return rc; … … 345 366 if (!no_target && S_ISDIR(to_sb.st_mode)) { 346 367 for (; *argv != to_name; ++argv) { 347 int rc = install( *argv, to_name, fset, iflags | DIRECTORY);368 int rc = install(&This, *argv, to_name, fset, iflags | DIRECTORY); 348 369 if (rc) 349 370 return rc; … … 354 375 /* can't do file1 file2 directory/file */ 355 376 if (argc != 2) { 356 warnx( "wrong number or types of arguments");357 return usage( stderr);377 warnx(pCtx, "wrong number or types of arguments"); 378 return usage(pCtx, 1); 358 379 } 359 380 360 381 if (!no_target) { 361 382 if (stat(*argv, &from_sb)) 362 return err( EX_OSERR, "%s", *argv);383 return err(pCtx, EX_OSERR, "%s", *argv); 363 384 if (!S_ISREG(to_sb.st_mode)) { 364 385 errno = EFTYPE; 365 return err( EX_OSERR, "%s", to_name);386 return err(pCtx, EX_OSERR, "%s", to_name); 366 387 } 367 388 if (to_sb.st_dev == from_sb.st_dev && … … 369 390 to_sb.st_ino == from_sb.st_ino && 370 391 to_sb.st_ino != 0 && 371 ! hard_link_files_when_possible)372 return errx( EX_USAGE,392 !This.hard_link_files_when_possible) 393 return errx(pCtx, EX_USAGE, 373 394 "%s and %s are the same file", *argv, to_name); 374 395 } 375 return install(*argv, to_name, fset, iflags); 376 } 396 return install(&This, *argv, to_name, fset, iflags); 397 } 398 399 #ifdef KMK_BUILTIN_STANDALONE 400 int main(int argc, char **argv, char **envp) 401 { 402 KMKBUILTINCTX Ctx = { "kmk_install", NULL }; 403 return kmk_builtin_install(argc, argv, envp, &Ctx); 404 } 405 #endif 377 406 378 407 static u_long 379 numeric_id( const char *name, const char *type)408 numeric_id(PINSTALLINSTANCE pThis, const char *name, const char *type) 380 409 { 381 410 u_long val; … … 389 418 val = strtoul(name, &ep, 10); 390 419 if (errno) 391 return err( -1, "%s", name);420 return err(pThis->pCtx, -1, "%s", name); 392 421 if (*ep != '\0') 393 return errx( -1, "unknown %s %s", type, name);422 return errx(pThis->pCtx, -1, "unknown %s %s", type, name); 394 423 return (val); 395 424 } … … 400 429 */ 401 430 static int 402 install( const char *from_name, const char *to_name, u_long fset, u_int flags)431 install(PINSTALLINSTANCE pThis, const char *from_name, const char *to_name, u_long fset, u_int flags) 403 432 { 404 433 struct stat from_sb, temp_sb, to_sb; … … 428 457 ) { 429 458 if (stat(from_name, &from_sb)) 430 return err( EX_OSERR, "%s", from_name);459 return err(pThis->pCtx, EX_OSERR, "%s", from_name); 431 460 if (!S_ISREG(from_sb.st_mode)) { 432 461 errno = EFTYPE; 433 return err( EX_OSERR, "%s", from_name);462 return err(pThis->pCtx, EX_OSERR, "%s", from_name); 434 463 } 435 464 /* Build the target path. */ … … 450 479 if (target && !S_ISREG(to_sb.st_mode)) { 451 480 errno = EFTYPE; 452 warn( "%s", to_name);481 warn(pThis->pCtx, "%s", to_name); 453 482 return EX_OK; 454 483 } 455 484 456 485 /* Only copy safe if the target exists. */ 457 tempcopy = safecopy && target;486 tempcopy = pThis->safecopy && target; 458 487 459 488 /* Try hard linking if wanted and possible. */ 460 if ( hard_link_files_when_possible)489 if (pThis->hard_link_files_when_possible) 461 490 { 462 491 #ifdef KBUILD_OS_OS2 … … 466 495 if (devnull) { 467 496 why_not = "/dev/null"; 468 } else if ( dostrip) {497 } else if (pThis->dostrip) { 469 498 why_not = "strip (-s)"; 470 } else if ( docompare) {499 } else if (pThis->docompare) { 471 500 why_not = "compare (-C)"; 472 } else if ( dobackup) {501 } else if (pThis->dobackup) { 473 502 why_not = "backup (-b/-B)"; 474 } else if ( safecopy) {503 } else if (pThis->safecopy) { 475 504 why_not = "safe copy (-S)"; 476 505 } else if (lstat(from_name, &temp_sb)) { … … 481 510 why_not = "not regular file"; 482 511 # if defined(KBUILD_OS_WINDOWS) || defined(KBUILD_OS_OS2) 483 } else if (( mode & S_IWUSR) != (from_sb.st_mode & S_IWUSR)) {512 } else if ((pThis->mode & S_IWUSR) != (from_sb.st_mode & S_IWUSR)) { 484 513 # else 485 } else if ( mode != (from_sb.st_mode & ALLPERMS)) {514 } else if (pThis->mode != (from_sb.st_mode & ALLPERMS)) { 486 515 # endif 487 printf("install: warning: Not hard linking, mode differs: 0%03o, desires 0%03o\n" 488 "install: src path '%s'\n" 489 "install: dst path '%s'\n", 490 (from_sb.st_mode & ALLPERMS), mode, from_name, to_name); 516 kmk_builtin_ctx_printf(pThis->pCtx, 0, 517 "install: warning: Not hard linking, mode differs: 0%03o, desires 0%03o\n" 518 "install: src path '%s'\n" 519 "install: dst path '%s'\n", 520 (from_sb.st_mode & ALLPERMS), pThis->mode, from_name, to_name); 491 521 why_not = NULL; 492 } else if ( uid != (uid_t)-1 && gid != from_sb.st_uid) {522 } else if (pThis->uid != (uid_t)-1 && pThis->uid != from_sb.st_uid) { 493 523 why_not = "uid mismatch"; 494 } else if ( gid != (gid_t)-1 &&gid != from_sb.st_gid) {524 } else if (pThis->gid != (gid_t)-1 && pThis->gid != from_sb.st_gid) { 495 525 why_not = "gid mismatch"; 496 } else if ( dos2unix > 0 && needs_dos2unix_conversion(from_name)) {526 } else if (pThis->dos2unix > 0 && needs_dos2unix_conversion(from_name)) { 497 527 why_not = "dos2unix"; 498 } else if ( dos2unix < 0 && needs_unix2dos_conversion(from_name)) {528 } else if (pThis->dos2unix < 0 && needs_unix2dos_conversion(from_name)) { 499 529 why_not = "unix2dos"; 500 530 } else { … … 505 535 } 506 536 if (rcLink == 0) { 507 if (verbose) 508 printf("install: %s -> %s (hardlinked)\n", from_name, to_name); 537 if (pThis->verbose) 538 kmk_builtin_ctx_printf(pThis->pCtx, 0, 539 "install: %s -> %s (hardlinked)\n", from_name, to_name); 509 540 goto l_done; 510 541 } 511 if ( verbose)512 printf("install: hard linking '%s' to '%s' failed: %s\n",542 if (pThis->verbose) 543 kmk_builtin_ctx_printf(pThis->pCtx, 0, "install: hard linking '%s' to '%s' failed: %s\n", 513 544 to_name, from_name, strerror(errno)); 514 545 why_not = NULL; 515 546 } 516 547 #endif 517 if ( verbose && why_not)518 printf("install: not hard linking '%s' to '%s' because: %s\n",519 to_name, from_name, why_not);548 if (pThis->verbose && why_not) 549 kmk_builtin_ctx_printf(pThis->pCtx, 0, "install: not hard linking '%s' to '%s' because: %s\n", 550 to_name, from_name, why_not); 520 551 521 552 /* Can't hard link or we failed, continue as nothing happend. */ … … 523 554 524 555 if (!devnull && (from_fd = open(from_name, O_RDONLY | O_BINARY, 0)) < 0) 525 return err( EX_OSERR, "%s", from_name);556 return err(pThis->pCtx, EX_OSERR, "%s", from_name); 526 557 527 558 /* If we don't strip, we can compare first. */ 528 if ( docompare && !dostrip && target) {559 if (pThis->docompare && !pThis->dostrip && target) { 529 560 if ((to_fd = open(to_name, O_RDONLY | O_BINARY, 0)) < 0) { 530 rc = err( EX_OSERR, "%s", to_name);561 rc = err(pThis->pCtx, EX_OSERR, "%s", to_name); 531 562 goto l_done; 532 563 } … … 549 580 sizeof(tempfile)); 550 581 if (to_fd < 0) { 551 rc = err( EX_OSERR, "%s", tempfile);582 rc = err(pThis->pCtx, EX_OSERR, "%s", tempfile); 552 583 goto l_done; 553 584 } 554 585 } else { 555 if ((to_fd = create_newfile(to_name, target, 556 &to_sb)) < 0) { 557 rc = err(EX_OSERR, "%s", to_name); 586 if ((to_fd = create_newfile(pThis, to_name, target, &to_sb)) < 0) { 587 rc = err(pThis->pCtx, EX_OSERR, "%s", to_name); 558 588 goto l_done; 559 589 } 560 if (verbose) 561 (void)printf("install: %s -> %s\n", 562 from_name, to_name); 590 if (pThis->verbose) 591 kmk_builtin_ctx_printf(pThis->pCtx, 0, "install: %s -> %s\n", from_name, to_name); 563 592 } 564 593 if (!devnull) { 565 rc = copy( from_fd, from_name, &to_fd, tempcopy ? tempfile : to_name);594 rc = copy(pThis, from_fd, from_name, &to_fd, tempcopy ? tempfile : to_name); 566 595 if (rc) 567 596 goto l_done; … … 569 598 } 570 599 571 if ( dostrip) {600 if (pThis->dostrip) { 572 601 #if defined(__EMX__) || defined(_MSC_VER) 573 602 /* close before we strip. */ … … 575 604 to_fd = -1; 576 605 #endif 577 rc = strip( tempcopy ? tempfile : to_name);606 rc = strip(pThis, tempcopy ? tempfile : to_name); 578 607 if (rc) 579 608 goto l_done; … … 588 617 to_fd = open(tempcopy ? tempfile : to_name, O_RDONLY | O_BINARY, 0); 589 618 if (to_fd < 0) { 590 rc = err( EX_OSERR, "stripping %s", to_name);619 rc = err(pThis->pCtx, EX_OSERR, "stripping %s", to_name); 591 620 goto l_done; 592 621 } … … 596 625 * Compare the stripped temp file with the target. 597 626 */ 598 if ( docompare &&dostrip && target) {627 if (pThis->docompare && pThis->dostrip && target) { 599 628 temp_fd = to_fd; 600 629 601 630 /* Re-open to_fd using the real target name. */ 602 631 if ((to_fd = open(to_name, O_RDONLY | O_BINARY, 0)) < 0) { 603 rc = err( EX_OSERR, "%s", to_name);632 rc = err(pThis->pCtx, EX_OSERR, "%s", to_name); 604 633 goto l_done; 605 634 } … … 609 638 (void)unlink(tempfile); 610 639 errno = serrno; 611 rc = err( EX_OSERR, "%s", tempfile);640 rc = err(pThis->pCtx, EX_OSERR, "%s", tempfile); 612 641 goto l_done; 613 642 } … … 649 678 (void)chflags(to_name, to_sb.st_flags & ~NOCHANGEBITS); 650 679 #endif 651 if ( dobackup) {652 if ( (size_t)snprintf(backup, MAXPATHLEN, "%s%s", to_name,653 suffix) != strlen(to_name) + strlen(suffix)) {680 if (pThis->dobackup) { 681 if ( (size_t)snprintf(backup, MAXPATHLEN, "%s%s", to_name, pThis->suffix) 682 != strlen(to_name) + strlen(pThis->suffix)) { 654 683 unlink(tempfile); 655 rc = errx( EX_OSERR, "%s: backup filename too long",684 rc = errx(pThis->pCtx, EX_OSERR, "%s: backup filename too long", 656 685 to_name); 657 686 goto l_done; 658 687 } 659 if ( verbose)660 (void)printf("install: %s -> %s\n", to_name, backup);688 if (pThis->verbose) 689 kmk_builtin_ctx_printf(pThis->pCtx, 0, "install: %s -> %s\n", to_name, backup); 661 690 if (rename(to_name, backup) < 0) { 662 691 serrno = errno; 663 692 unlink(tempfile); 664 693 errno = serrno; 665 rc = err( EX_OSERR, "rename: %s to %s", to_name,694 rc = err(pThis->pCtx, EX_OSERR, "rename: %s to %s", to_name, 666 695 backup); 667 696 goto l_done; 668 697 } 669 698 } 670 if ( verbose)671 (void)printf("install: %s -> %s\n", from_name, to_name);699 if (pThis->verbose) 700 kmk_builtin_ctx_printf(pThis->pCtx, 0, "install: %s -> %s\n", from_name, to_name); 672 701 if (rename(tempfile, to_name) < 0) { 673 702 serrno = errno; 674 703 unlink(tempfile); 675 704 errno = serrno; 676 rc = err(EX_OSERR, "rename: %s to %s", 677 tempfile, to_name); 705 rc = err(pThis->pCtx, EX_OSERR, "rename: %s to %s", tempfile, to_name); 678 706 goto l_done; 679 707 } … … 682 710 (void) close(to_fd); 683 711 if ((to_fd = open(to_name, O_RDONLY | O_BINARY, 0)) < 0) { 684 rc = err( EX_OSERR, "%s", to_name);712 rc = err(pThis->pCtx, EX_OSERR, "%s", to_name); 685 713 goto l_done; 686 714 } … … 690 718 * Preserve the timestamp of the source file if necessary. 691 719 */ 692 if ( dopreserve && !files_match && !devnull) {720 if (pThis->dopreserve && !files_match && !devnull) { 693 721 tvb[0].tv_sec = from_sb.st_atime; 694 722 tvb[0].tv_usec = 0; … … 702 730 (void)unlink(to_name); 703 731 errno = serrno; 704 rc = err( EX_OSERR, "%s", to_name);732 rc = err(pThis->pCtx, EX_OSERR, "%s", to_name); 705 733 goto l_done; 706 734 } … … 720 748 #endif 721 749 722 if ((gid != (gid_t)-1 && gid != to_sb.st_gid) || 723 (uid != (uid_t)-1 && uid != to_sb.st_uid)) 724 if (fchown(to_fd, uid, gid) == -1) { 725 if (errno == EPERM && ignore_perm_errors) { 726 warn("%s: ignoring chown uid=%d gid=%d failure", to_name, (int)uid, (int)gid); 750 if ((pThis->gid != (gid_t)-1 && pThis->gid != to_sb.st_gid) || 751 (pThis->uid != (uid_t)-1 && pThis->uid != to_sb.st_uid)) 752 if (fchown(to_fd, pThis->uid, pThis->gid) == -1) { 753 if (errno == EPERM && pThis->ignore_perm_errors) { 754 warn(pThis->pCtx, "%s: ignoring chown uid=%d gid=%d failure", 755 to_name, (int)pThis->uid, (int)pThis->gid); 727 756 } else { 728 757 serrno = errno; 729 758 (void)unlink(to_name); 730 759 errno = serrno; 731 rc = err( EX_OSERR,"%s: chown/chgrp", to_name);760 rc = err(pThis->pCtx, EX_OSERR,"%s: chown/chgrp", to_name); 732 761 goto l_done; 733 762 } 734 763 } 735 764 736 if ( mode != (to_sb.st_mode & ALLPERMS))737 if (fchmod(to_fd, mode)) {765 if (pThis->mode != (to_sb.st_mode & ALLPERMS)) 766 if (fchmod(to_fd, pThis->mode)) { 738 767 serrno = errno; 739 if (serrno == EPERM && ignore_perm_errors) {740 fchmod(to_fd, mode & (ALLPERMS & ~0007000));768 if (serrno == EPERM && pThis->ignore_perm_errors) { 769 fchmod(to_fd, pThis->mode & (ALLPERMS & ~0007000)); 741 770 errno = errno; 742 warn( "%s: ignoring chmod 0%o failure", to_name, (int)(mode & ALLPERMS));771 warn(pThis->pCtx, "%s: ignoring chmod 0%o failure", to_name, (int)(pThis->mode & ALLPERMS)); 743 772 } else { 744 773 serrno = errno; 745 774 (void)unlink(to_name); 746 775 errno = serrno; 747 rc = err( EX_OSERR, "%s: chmod", to_name);776 rc = err(pThis->pCtx, EX_OSERR, "%s: chmod", to_name); 748 777 goto l_done; 749 778 } … … 758 787 */ 759 788 #ifdef UF_IMMUTABLE 760 if (!devnull && (flags & SETFLAGS || 761 (from_sb.st_flags & ~UF_NODUMP) != to_sb.st_flags) && 762 fchflags(to_fd, 763 flags & SETFLAGS ? fset : from_sb.st_flags & ~UF_NODUMP)) { 789 if ( !devnull 790 && (flags & SETFLAGS || (from_sb.st_flags & ~UF_NODUMP) != to_sb.st_flags) 791 && fchflags(to_fd, flags & SETFLAGS ? fset : from_sb.st_flags & ~UF_NODUMP)) { 764 792 if (flags & SETFLAGS) { 765 793 if (errno == EOPNOTSUPP) 766 warn( "%s: chflags", to_name);794 warn(pThis->pCtx, "%s: chflags", to_name); 767 795 else { 768 796 serrno = errno; 769 797 (void)unlink(to_name); 770 798 errno = serrno; 771 rc = err( EX_OSERR, "%s: chflags", to_name);799 rc = err(pThis->pCtx, EX_OSERR, "%s: chflags", to_name); 772 800 goto l_done; 773 801 } … … 851 879 */ 852 880 int 853 create_newfile( const char *path, int target, struct stat *sbp)881 create_newfile(PINSTALLINSTANCE pThis, const char *path, int target, struct stat *sbp) 854 882 { 855 883 char backup[MAXPATHLEN]; … … 868 896 #endif 869 897 870 if (dobackup) { 871 if ((size_t)snprintf(backup, MAXPATHLEN, "%s%s", 872 path, suffix) != strlen(path) + strlen(suffix)) { 873 errx(EX_OSERR, "%s: backup filename too long", 874 path); 898 if (pThis->dobackup) { 899 if ( (size_t)snprintf(backup, MAXPATHLEN, "%s%s", path, pThis->suffix) 900 != strlen(path) + strlen(pThis->suffix)) { 901 errx(pThis->pCtx, EX_OSERR, "%s: backup filename too long", path); 875 902 errno = ENAMETOOLONG; 876 903 return -1; 877 904 } 878 (void)snprintf(backup, MAXPATHLEN, "%s%s", 879 path, suffix); 880 if (verbose) 881 (void)printf("install: %s -> %s\n", 882 path, backup); 905 (void)snprintf(backup, MAXPATHLEN, "%s%s", path, pThis->suffix); 906 if (pThis->verbose) 907 kmk_builtin_ctx_printf(pThis->pCtx, 0, "install: %s -> %s\n", path, backup); 883 908 if (rename(path, backup) < 0) { 884 err( EX_OSERR, "rename: %s to %s", path, backup);909 err(pThis->pCtx, EX_OSERR, "rename: %s to %s", path, backup); 885 910 return -1; 886 911 } … … 899 924 * Write error handler. 900 925 */ 901 static int write_error( int *ptr_to_fd, const char *to_name, int nw)926 static int write_error(PINSTALLINSTANCE pThis, int *ptr_to_fd, const char *to_name, int nw) 902 927 { 903 928 int serrno = errno; … … 906 931 (void)unlink(to_name); 907 932 errno = nw > 0 ? EIO : serrno; 908 return err( EX_OSERR, "%s", to_name);933 return err(pThis->pCtx, EX_OSERR, "%s", to_name); 909 934 } 910 935 … … 912 937 * Read error handler. 913 938 */ 914 static int read_error( const char *from_name, int *ptr_to_fd, const char *to_name)939 static int read_error(PINSTALLINSTANCE pThis, const char *from_name, int *ptr_to_fd, const char *to_name) 915 940 { 916 941 int serrno = errno; … … 919 944 (void)unlink(to_name); 920 945 errno = serrno; 921 return err( EX_OSERR, "%s", from_name);946 return err(pThis->pCtx, EX_OSERR, "%s", from_name); 922 947 } 923 948 … … 927 952 */ 928 953 static int 929 copy( int from_fd, const char *from_name, int *ptr_to_fd, const char *to_name)954 copy(PINSTALLINSTANCE pThis, int from_fd, const char *from_name, int *ptr_to_fd, const char *to_name) 930 955 { 931 956 KBOOL fPendingCr = K_FALSE; … … 937 962 /* Rewind file descriptors. */ 938 963 if (lseek(from_fd, (off_t)0, SEEK_SET) == (off_t)-1) 939 return err( EX_OSERR, "lseek: %s", from_name);964 return err(pThis->pCtx, EX_OSERR, "lseek: %s", from_name); 940 965 if (lseek(to_fd, (off_t)0, SEEK_SET) == (off_t)-1) 941 return err( EX_OSERR, "lseek: %s", to_name);942 943 if ( dos2unix == 0) {966 return err(pThis->pCtx, EX_OSERR, "lseek: %s", to_name); 967 968 if (pThis->dos2unix == 0) { 944 969 /* 945 970 * Copy bytes, no conversion. … … 947 972 while ((nr = read(from_fd, buf, sizeof(buf))) > 0) 948 973 if ((nw = write(to_fd, buf, nr)) != nr) 949 return write_error(p tr_to_fd, to_name, nw);950 } else if ( dos2unix > 0) {974 return write_error(pThis, ptr_to_fd, to_name, nw); 975 } else if (pThis->dos2unix > 0) { 951 976 /* 952 977 * CRLF -> LF is a reduction, so we can work with full buffers. … … 956 981 && buf[0] != '\n' 957 982 && (nw = write(to_fd, "\r", 1)) != 1) 958 return write_error(p tr_to_fd, to_name, nw);983 return write_error(pThis, ptr_to_fd, to_name, nw); 959 984 960 985 fPendingCr = dos2unix_convert_to_unix(buf, nr, buf, &cchDst); … … 962 987 nw = write(to_fd, buf, cchDst); 963 988 if (nw != (int)cchDst) 964 return write_error(p tr_to_fd, to_name, nw);989 return write_error(pThis, ptr_to_fd, to_name, nw); 965 990 } 966 991 } else { … … 978 1003 && pchSrc[0] != '\n' 979 1004 && (nw = write(to_fd, "\r", 1))!= 1) 980 return write_error(p tr_to_fd, to_name, nw);1005 return write_error(pThis, ptr_to_fd, to_name, nw); 981 1006 982 1007 fPendingCr = dos2unix_convert_to_dos(pchSrc, nr, buf, &cchDst); … … 984 1009 nw = write(to_fd, buf, cchDst); 985 1010 if (nw != (int)cchDst) 986 return write_error(p tr_to_fd, to_name, nw);1011 return write_error(pThis, ptr_to_fd, to_name, nw); 987 1012 } 988 1013 } … … 990 1015 /* Check for read error. */ 991 1016 if (nr != 0) 992 return read_error( from_name, ptr_to_fd, to_name);1017 return read_error(pThis, from_name, ptr_to_fd, to_name); 993 1018 994 1019 /* When converting, we might have a pending final CR to write. */ 995 996 997 return write_error(p tr_to_fd, to_name, nw);1020 if ( fPendingCr 1021 && (nw = write(to_fd, "\r", 1))!= 1) 1022 return write_error(pThis, ptr_to_fd, to_name, nw); 998 1023 999 1024 return EX_OK; … … 1005 1030 */ 1006 1031 static int 1007 strip( const char *to_name)1032 strip(PINSTALLINSTANCE pThis, const char *to_name) 1008 1033 { 1009 1034 #if defined(__EMX__) || defined(_MSC_VER) … … 1011 1036 if (stripbin == NULL) 1012 1037 stripbin = "strip"; 1038 (void)pThis; 1013 1039 return spawnlp(P_WAIT, stripbin, stripbin, to_name, NULL); 1014 1040 #else … … 1023 1049 (void)unlink(to_name); 1024 1050 errno = serrno; 1025 return err( EX_TEMPFAIL, "fork");1051 return err(pThis->pCtx, EX_TEMPFAIL, "fork"); 1026 1052 case 0: 1027 1053 stripbin = getenv("STRIPBIN"); … … 1029 1055 stripbin = "strip"; 1030 1056 execlp(stripbin, stripbin, to_name, (char *)NULL); 1031 err( EX_OSERR, "exec(%s)", stripbin);1057 err(pThis->pCtx, EX_OSERR, "exec(%s)", stripbin); 1032 1058 exit(EX_OSERR); 1033 1059 default: … … 1036 1062 (void)unlink(to_name); 1037 1063 errno = serrno; 1038 return err( EX_SOFTWARE, "waitpid");1064 return err(pThis->pCtx, EX_SOFTWARE, "waitpid"); 1039 1065 /* NOTREACHED */ 1040 1066 } … … 1049 1075 */ 1050 1076 static int 1051 install_dir( char *path)1077 install_dir(PINSTALLINSTANCE pThis, char *path) 1052 1078 { 1053 1079 char *p; … … 1067 1093 if (stat(path, &sb)) { 1068 1094 if (errno != ENOENT || mkdir(path, 0755) < 0) { 1069 return err( EX_OSERR, "mkdir %s", path);1095 return err(pThis->pCtx, EX_OSERR, "mkdir %s", path); 1070 1096 /* NOTREACHED */ 1071 } else if (verbose) 1072 (void)printf("install: mkdir %s\n", 1073 path); 1097 } else if (pThis->verbose) 1098 kmk_builtin_ctx_printf(pThis->pCtx, 0, "install: mkdir %s\n", path); 1074 1099 } else if (!S_ISDIR(sb.st_mode)) 1075 return errx( EX_OSERR, "%s exists but is not a directory", path);1100 return errx(pThis->pCtx, EX_OSERR, "%s exists but is not a directory", path); 1076 1101 if (!(*p = ch)) 1077 1102 break; 1078 1103 } 1079 1104 1080 if (( gid != (gid_t)-1 || uid != (uid_t)-1) && chown(path, uid,gid))1081 warn( "chown %u:%u %s", uid,gid, path);1082 if (chmod(path, mode))1083 warn( "chmod %o %s",mode, path);1105 if ((pThis->gid != (gid_t)-1 || pThis->uid != (uid_t)-1) && chown(path, pThis->uid, pThis->gid)) 1106 warn(pThis->pCtx, "chown %u:%u %s", pThis->uid, pThis->gid, path); 1107 if (chmod(path, pThis->mode)) 1108 warn(pThis->pCtx, "chmod %o %s", pThis->mode, path); 1084 1109 return EX_OK; 1085 1110 } … … 1090 1115 */ 1091 1116 static int 1092 usage( FILE *pf)1093 { 1094 fprintf(pf,1117 usage(PKMKBUILTINCTX pCtx, int fIsErr) 1118 { 1119 kmk_builtin_ctx_printf(pCtx, fIsErr, 1095 1120 "usage: %s [-bCcpSsv] [--[no-]hard-link-files-when-possible]\n" 1096 1121 " [--[no-]ignore-perm-errors] [-B suffix] [-f flags] [-g group]\n" … … 1101 1126 " or: %s --help\n" 1102 1127 " or: %s --version\n", 1103 g_progname, g_progname, g_progname, g_progname, g_progname); 1128 pCtx->pszProgName, pCtx->pszProgName, pCtx->pszProgName, 1129 pCtx->pszProgName, pCtx->pszProgName); 1104 1130 return EX_USAGE; 1105 1131 }
Note:
See TracChangeset
for help on using the changeset viewer.