Changeset 3221 for trunk/src/kmk/kmkbuiltin/cp.c
- Timestamp:
- Mar 31, 2018, 1:27:52 AM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/kmkbuiltin/cp.c
r3192 r3221 60 60 */ 61 61 62 63 /********************************************************************************************************************************* 64 * Header Files * 65 *********************************************************************************************************************************/ 66 #define FAKES_NO_GETOPT_H /* bird */ 62 67 #include "config.h" 63 68 #include <sys/types.h> … … 73 78 #include <string.h> 74 79 #include <unistd.h> 75 #include "getopt .h"80 #include "getopt_r.h" 76 81 #include "k/kDefs.h" 77 82 #ifdef _MSC_VER … … 87 92 88 93 94 /********************************************************************************************************************************* 95 * Defined Constants And Macros * 96 *********************************************************************************************************************************/ 89 97 #ifndef S_IFWHT 90 98 #define S_IFWHT 0 … … 116 124 } 117 125 126 /********************************************************************************************************************************* 127 * Structures and Typedefs * 128 *********************************************************************************************************************************/ 129 typedef struct CPINSTANCE 130 { 131 CPUTILSINSTANCE Utils; 132 int Rflag, rflag; 133 int cp_ignore_non_existing, cp_changed_only; 134 KBUILDPROTECTION g_ProtData; 135 } CPINSTANCE; 136 118 137 /* have wrappers for globals in cp_extern! */ 119 138 120 static KBUILDPROTECTION g_ProtData;121 const char *cp_argv0;122 static char emptystring[] = "";123 124 PATH_T to = { to.p_path, emptystring, "" };125 126 int fflag, iflag, nflag, pflag, vflag;127 static int Rflag, rflag;128 volatile sig_atomic_t info;129 static int cp_ignore_non_existing, cp_changed_only;130 139 131 140 enum op { FILE_TO_FILE, FILE_TO_DIR, DIR_TO_DNE }; 132 141 142 143 /********************************************************************************************************************************* 144 * Global Variables * 145 *********************************************************************************************************************************/ 133 146 enum cp_arg { 134 147 CP_OPT_HELP = 261, … … 142 155 CP_OPT_PROTECTION_DEPTH 143 156 }; 157 144 158 static struct option long_options[] = 145 159 { … … 156 170 }; 157 171 158 159 static int copy(PKMKBUILTINCTX pCtx, char *[], enum op, int); 172 static char emptystring[] = ""; 173 174 #if defined(SIGINFO) && defined(KMK_BUILTIN_STANDALONE) 175 volatile sig_atomic_t g_cp_info; 176 #endif 177 178 179 /********************************************************************************************************************************* 180 * Internal Functions * 181 *********************************************************************************************************************************/ 182 static int copy(CPINSTANCE *pThis, char * const *, enum op, int); 183 #ifdef FTSCALL 184 static int FTSCALL mastercmp(const FTSENT * const *, const FTSENT * const *); 185 #else 160 186 static int mastercmp(const FTSENT **, const FTSENT **); 161 #ifdef SIGINFO 187 #endif 188 #if defined(SIGINFO) && defined(KMK_BUILTIN_STANDALONE) 162 189 static void siginfo(int __unused); 163 190 #endif … … 167 194 kmk_builtin_cp(int argc, char **argv, char **envp, PKMKBUILTINCTX pCtx) 168 195 { 196 CPINSTANCE This; 197 struct getopt_state_r gos; 169 198 struct stat to_stat, tmp_stat; 170 199 enum op type; … … 173 202 174 203 /* init globals */ 175 cp_argv0 = argv[0]; 176 to.p_end = to.p_path; 177 to.target_end = emptystring; 178 memset(to.p_path, 0, sizeof(to.p_path)); 179 fflag = iflag = nflag = pflag = vflag = Rflag = rflag = 0; 180 info = 0; 181 cp_ignore_non_existing = cp_changed_only = 0; 182 kBuildProtectionInit(&g_ProtData, pCtx); 183 184 /* reset getopt and set progname. */ 185 opterr = 1; 186 optarg = NULL; 187 optopt = 0; 188 optind = 0; /* init */ 204 This.Utils.pCtx = pCtx; 205 This.Utils.to.p_end = This.Utils.to.p_path; 206 This.Utils.to.target_end = emptystring; 207 memset(This.Utils.to.p_path, 0, sizeof(This.Utils.to.p_path)); 208 This.Utils.fflag = 0; 209 This.Utils.iflag = 0; 210 This.Utils.nflag = 0; 211 This.Utils.pflag = 0; 212 This.Utils.vflag = 0; 213 This.Rflag = 0; 214 This.rflag = 0; 215 This.cp_ignore_non_existing = This.cp_changed_only = 0; 216 kBuildProtectionInit(&This.g_ProtData, pCtx); 189 217 190 218 Hflag = Lflag = Pflag = 0; 191 while ((ch = getopt_long(argc, argv, "HLPRfinprv", long_options, NULL)) != -1) 219 getopt_initialize_r(&gos, argc, argv, "HLPRfinprv", long_options, envp, pCtx); 220 while ((ch = getopt_long_r(&gos, NULL)) != -1) 192 221 switch (ch) { 193 222 case 'H': … … 204 233 break; 205 234 case 'R': 206 Rflag = 1;235 This.Rflag = 1; 207 236 break; 208 237 case 'f': 209 fflag = 1;210 iflag =nflag = 0;238 This.Utils.fflag = 1; 239 This.Utils.iflag = This.Utils.nflag = 0; 211 240 break; 212 241 case 'i': 213 iflag = 1;214 fflag =nflag = 0;242 This.Utils.iflag = 1; 243 This.Utils.fflag = This.Utils.nflag = 0; 215 244 break; 216 245 case 'n': 217 nflag = 1;218 fflag =iflag = 0;246 This.Utils.nflag = 1; 247 This.Utils.fflag = This.Utils.iflag = 0; 219 248 break; 220 249 case 'p': 221 pflag = 1;250 This.Utils.pflag = 1; 222 251 break; 223 252 case 'r': 224 rflag = 1;253 This.rflag = 1; 225 254 break; 226 255 case 'v': 227 vflag = 1;256 This.Utils.vflag = 1; 228 257 break; 229 258 case CP_OPT_HELP: 230 259 usage(pCtx, 0); 231 kBuildProtectionTerm(& g_ProtData);260 kBuildProtectionTerm(&This.g_ProtData); 232 261 return 0; 233 262 case CP_OPT_VERSION: 234 kBuildProtectionTerm(& g_ProtData);263 kBuildProtectionTerm(&This.g_ProtData); 235 264 return kbuild_version(argv[0]); 236 265 case CP_OPT_IGNORE_NON_EXISTING: 237 cp_ignore_non_existing = 1;266 This.cp_ignore_non_existing = 1; 238 267 break; 239 268 case CP_OPT_CHANGED: 240 cp_changed_only = 1;269 This.cp_changed_only = 1; 241 270 break; 242 271 case CP_OPT_DISABLE_PROTECTION: 243 kBuildProtectionDisable(& g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE);272 kBuildProtectionDisable(&This.g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE); 244 273 break; 245 274 case CP_OPT_ENABLE_PROTECTION: 246 kBuildProtectionEnable(& g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE);275 kBuildProtectionEnable(&This.g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE); 247 276 break; 248 277 case CP_OPT_ENABLE_FULL_PROTECTION: 249 kBuildProtectionEnable(& g_ProtData, KBUILDPROTECTIONTYPE_FULL);278 kBuildProtectionEnable(&This.g_ProtData, KBUILDPROTECTIONTYPE_FULL); 250 279 break; 251 280 case CP_OPT_DISABLE_FULL_PROTECTION: 252 kBuildProtectionDisable(& g_ProtData, KBUILDPROTECTIONTYPE_FULL);281 kBuildProtectionDisable(&This.g_ProtData, KBUILDPROTECTIONTYPE_FULL); 253 282 break; 254 283 case CP_OPT_PROTECTION_DEPTH: 255 if (kBuildProtectionSetDepth(& g_ProtData,optarg)) {256 kBuildProtectionTerm(& g_ProtData);284 if (kBuildProtectionSetDepth(&This.g_ProtData, gos.optarg)) { 285 kBuildProtectionTerm(&This.g_ProtData); 257 286 return 1; 258 287 } 259 288 break; 260 289 default: 261 kBuildProtectionTerm(& g_ProtData);290 kBuildProtectionTerm(&This.g_ProtData); 262 291 return usage(pCtx, 1); 263 292 } 264 argc -= optind;265 argv += optind;293 argc -= gos.optind; 294 argv += gos.optind; 266 295 267 296 if (argc < 2) { 268 kBuildProtectionTerm(& g_ProtData);297 kBuildProtectionTerm(&This.g_ProtData); 269 298 return usage(pCtx, 1); 270 299 } 271 300 272 301 fts_options = FTS_NOCHDIR | FTS_PHYSICAL; 273 if ( rflag) {274 if ( Rflag) {275 kBuildProtectionTerm(& g_ProtData);302 if (This.rflag) { 303 if (This.Rflag) { 304 kBuildProtectionTerm(&This.g_ProtData); 276 305 return errx(pCtx, 1, 277 306 "the -R and -r options may not be specified together."); … … 283 312 fts_options |= FTS_LOGICAL; 284 313 } 285 if ( Rflag) {314 if (This.Rflag) { 286 315 if (Hflag) 287 316 fts_options |= FTS_COMFOLLOW; … … 294 323 fts_options |= FTS_LOGICAL | FTS_COMFOLLOW; 295 324 } 296 #if def SIGINFO325 #if defined(SIGINFO) && defined(KMK_BUILTIN_STANDALONE) 297 326 (void)signal(SIGINFO, siginfo); 298 327 #endif … … 300 329 /* Save the target base in "to". */ 301 330 target = argv[--argc]; 302 if (strlcpy( to.p_path, target, sizeof(to.p_path)) >= sizeof(to.p_path)) {303 kBuildProtectionTerm(& g_ProtData);331 if (strlcpy(This.Utils.to.p_path, target, sizeof(This.Utils.to.p_path)) >= sizeof(This.Utils.to.p_path)) { 332 kBuildProtectionTerm(&This.g_ProtData); 304 333 return errx(pCtx, 1, "%s: name too long", target); 305 334 } 306 to.p_end = to.p_path + strlen(to.p_path);307 if ( to.p_path ==to.p_end) {308 * to.p_end++ = '.';309 * to.p_end = 0;335 This.Utils.to.p_end = This.Utils.to.p_path + strlen(This.Utils.to.p_path); 336 if (This.Utils.to.p_path == This.Utils.to.p_end) { 337 *This.Utils.to.p_end++ = '.'; 338 *This.Utils.to.p_end = 0; 310 339 } 311 have_trailing_slash = IS_SLASH( to.p_end[-1]);340 have_trailing_slash = IS_SLASH(This.Utils.to.p_end[-1]); 312 341 if (have_trailing_slash) 313 STRIP_TRAILING_SLASH( to);314 to.target_end =to.p_end;342 STRIP_TRAILING_SLASH(This.Utils.to); 343 This.Utils.to.target_end = This.Utils.to.p_end; 315 344 316 345 /* Set end of argument list for fts(3). */ … … 331 360 * In (2), the real target is not directory, but "directory/source". 332 361 */ 333 r = stat( to.p_path, &to_stat);362 r = stat(This.Utils.to.p_path, &to_stat); 334 363 if (r == -1 && errno != ENOENT) { 335 kBuildProtectionTerm(& g_ProtData);336 return err(pCtx, 1, "stat: %s", to.p_path);364 kBuildProtectionTerm(&This.g_ProtData); 365 return err(pCtx, 1, "stat: %s", This.Utils.to.p_path); 337 366 } 338 367 if (r == -1 || !S_ISDIR(to_stat.st_mode)) { … … 341 370 */ 342 371 if (argc > 1) { 343 kBuildProtectionTerm(& g_ProtData);372 kBuildProtectionTerm(&This.g_ProtData); 344 373 return usage(pCtx, 1); 345 374 } … … 352 381 */ 353 382 if (r == -1) { 354 if ( rflag || (Rflag && (Lflag || Hflag)))383 if (This.rflag || (This.Rflag && (Lflag || Hflag))) 355 384 stat(*argv, &tmp_stat); 356 385 else 357 386 lstat(*argv, &tmp_stat); 358 387 359 if (S_ISDIR(tmp_stat.st_mode) && ( Rflag ||rflag))388 if (S_ISDIR(tmp_stat.st_mode) && (This.Rflag || This.rflag)) 360 389 type = DIR_TO_DNE; 361 390 else … … 365 394 366 395 if (have_trailing_slash && type == FILE_TO_FILE) { 367 kBuildProtectionTerm(& g_ProtData);396 kBuildProtectionTerm(&This.g_ProtData); 368 397 if (r == -1) 369 398 return errx(pCtx, 1, "directory %s does not exist", 370 to.p_path);399 This.Utils.to.p_path); 371 400 else 372 return errx(pCtx, 1, "%s is not a directory", to.p_path);401 return errx(pCtx, 1, "%s is not a directory", This.Utils.to.p_path); 373 402 } 374 403 } else … … 380 409 /* Finally, check that the "to" directory isn't protected. */ 381 410 rc = 1; 382 if (!kBuildProtectionScanEnv(& g_ProtData, envp, "KMK_CP_")383 && !kBuildProtectionEnforce(& g_ProtData,384 Rflag ||rflag411 if (!kBuildProtectionScanEnv(&This.g_ProtData, envp, "KMK_CP_") 412 && !kBuildProtectionEnforce(&This.g_ProtData, 413 This.Rflag || This.rflag 385 414 ? KBUILDPROTECTIONTYPE_RECURSIVE 386 415 : KBUILDPROTECTIONTYPE_FULL, 387 to.p_path)) {388 rc = copy( pCtx, argv, type, fts_options);416 This.Utils.to.p_path)) { 417 rc = copy(&This, argv, type, fts_options); 389 418 } 390 419 391 kBuildProtectionTerm(& g_ProtData);420 kBuildProtectionTerm(&This.g_ProtData); 392 421 return rc; 393 422 } … … 402 431 403 432 static int 404 copy( PKMKBUILTINCTX pCtx, char *argv[], enum op type, int fts_options)433 copy(CPINSTANCE *pThis, char * const *argv, enum op type, int fts_options) 405 434 { 406 435 struct stat to_stat; … … 420 449 421 450 if ((ftsp = fts_open(argv, fts_options, mastercmp)) == NULL) 422 return err(p Ctx, 1, "fts_open");451 return err(pThis->Utils.pCtx, 1, "fts_open"); 423 452 for (badcp = rval = 0; (curr = fts_read(ftsp)) != NULL; badcp = 0) { 424 453 int copied = 0; … … 426 455 switch (curr->fts_info) { 427 456 case FTS_NS: 428 if ( cp_ignore_non_existing457 if ( pThis->cp_ignore_non_existing 429 458 && curr->fts_errno == ENOENT) { 430 if ( vflag) {431 warnx(p Ctx, "fts: %s: %s", curr->fts_path,459 if (pThis->Utils.vflag) { 460 warnx(pThis->Utils.pCtx, "fts: %s: %s", curr->fts_path, 432 461 strerror(curr->fts_errno)); 433 462 } … … 437 466 case FTS_DNR: 438 467 case FTS_ERR: 439 warnx(p Ctx, "fts: %s: %s",468 warnx(pThis->Utils.pCtx, "fts: %s: %s", 440 469 curr->fts_path, strerror(curr->fts_errno)); 441 470 badcp = rval = 1; 442 471 continue; 443 472 case FTS_DC: /* Warn, continue. */ 444 warnx(p Ctx, "%s: directory causes a cycle", curr->fts_path);473 warnx(pThis->Utils.pCtx, "%s: directory causes a cycle", curr->fts_path); 445 474 badcp = rval = 1; 446 475 continue; … … 492 521 p = &curr->fts_path[base]; 493 522 nlen = curr->fts_pathlen - base; 494 target_mid = to.target_end;523 target_mid = pThis->Utils.to.target_end; 495 524 if (!IS_SLASH(*p) && !IS_SLASH(target_mid[-1])) 496 525 *target_mid++ = '/'; 497 526 *target_mid = 0; 498 if (target_mid - to.p_path + nlen >= PATH_MAX) {499 warnx(p Ctx, "%s%s: name too long (not copied)",500 to.p_path, p);527 if (target_mid - pThis->Utils.to.p_path + nlen >= PATH_MAX) { 528 warnx(pThis->Utils.pCtx, "%s%s: name too long (not copied)", 529 pThis->Utils.to.p_path, p); 501 530 badcp = rval = 1; 502 531 continue; 503 532 } 504 533 (void)strncat(target_mid, p, nlen); 505 to.p_end = target_mid + nlen;506 * to.p_end = 0;507 STRIP_TRAILING_SLASH( to);534 pThis->Utils.to.p_end = target_mid + nlen; 535 *pThis->Utils.to.p_end = 0; 536 STRIP_TRAILING_SLASH(pThis->Utils.to); 508 537 } 509 538 … … 525 554 * normally want to preserve them on directories. 526 555 */ 527 if (p flag) {528 if ( setfile(pCtx, curr->fts_statp, -1))556 if (pThis->Utils.pflag) { 557 if (copy_file_attribs(&pThis->Utils, curr->fts_statp, -1)) 529 558 rval = 1; 530 559 } else { … … 532 561 if ((mode & (S_ISUID | S_ISGID | S_ISTXT)) || 533 562 ((mode | S_IRWXU) & mask) != (mode & mask)) 534 if (chmod( to.p_path, mode & mask) != 0){535 warn(p Ctx, "chmod: %s",to.p_path);563 if (chmod(pThis->Utils.to.p_path, mode & mask) != 0){ 564 warn(pThis->Utils.pCtx, "chmod: %s", pThis->Utils.to.p_path); 536 565 rval = 1; 537 566 } … … 541 570 542 571 /* Not an error but need to remember it happened */ 543 if (stat( to.p_path, &to_stat) == -1)572 if (stat(pThis->Utils.to.p_path, &to_stat) == -1) 544 573 dne = 1; 545 574 else { … … 548 577 to_stat.st_ino == curr->fts_statp->st_ino && 549 578 to_stat.st_ino != 0) { 550 warnx(p Ctx, "%s and %s are identical (not copied).",551 to.p_path, curr->fts_path);579 warnx(pThis->Utils.pCtx, "%s and %s are identical (not copied).", 580 pThis->Utils.to.p_path, curr->fts_path); 552 581 badcp = rval = 1; 553 582 if (S_ISDIR(curr->fts_statp->st_mode)) … … 557 586 if (!S_ISDIR(curr->fts_statp->st_mode) && 558 587 S_ISDIR(to_stat.st_mode)) { 559 warnx(p Ctx, "cannot overwrite directory %s with "588 warnx(pThis->Utils.pCtx, "cannot overwrite directory %s with " 560 589 "non-directory %s", 561 to.p_path, curr->fts_path);590 pThis->Utils.to.p_path, curr->fts_path); 562 591 badcp = rval = 1; 563 592 continue; … … 573 602 ((fts_options & FTS_COMFOLLOW) && 574 603 curr->fts_level == 0)) { 575 if (copy_file( pCtx, curr, dne,cp_changed_only, &copied))604 if (copy_file(&pThis->Utils, curr, dne, pThis->cp_changed_only, &copied)) 576 605 badcp = rval = 1; 577 606 } else { 578 if (copy_link( pCtx, curr, !dne))607 if (copy_link(&pThis->Utils, curr, !dne)) 579 608 badcp = rval = 1; 580 609 } … … 582 611 #endif 583 612 case S_IFDIR: 584 if (! Rflag && !rflag) {585 warnx(p Ctx, "%s is a directory (not copied).",613 if (!pThis->Rflag && !pThis->rflag) { 614 warnx(pThis->Utils.pCtx, "%s is a directory (not copied).", 586 615 curr->fts_path); 587 616 (void)fts_set(ftsp, curr, FTS_SKIP); … … 598 627 */ 599 628 if (dne) { 600 if (mkdir( to.p_path,629 if (mkdir(pThis->Utils.to.p_path, 601 630 curr->fts_statp->st_mode | S_IRWXU) < 0) 602 return err(p Ctx, 1, "mkdir: %s",to.p_path);631 return err(pThis->Utils.pCtx, 1, "mkdir: %s", pThis->Utils.to.p_path); 603 632 } else if (!S_ISDIR(to_stat.st_mode)) { 604 633 errno = ENOTDIR; 605 return err(p Ctx, 1, "to-mode: %s",to.p_path);634 return err(pThis->Utils.pCtx, 1, "to-mode: %s", pThis->Utils.to.p_path); 606 635 } 607 636 /* … … 610 639 * directory, or if the -p flag is in effect. 611 640 */ 612 curr->fts_number = p flag || dne;641 curr->fts_number = pThis->Utils.pflag || dne; 613 642 break; 614 643 #ifdef S_IFBLK … … 616 645 #endif 617 646 case S_IFCHR: 618 if ( Rflag) {619 if (copy_special( pCtx, curr->fts_statp, !dne))647 if (pThis->Rflag) { 648 if (copy_special(&pThis->Utils, curr->fts_statp, !dne)) 620 649 badcp = rval = 1; 621 650 } else { 622 if (copy_file( pCtx, curr, dne,cp_changed_only, &copied))651 if (copy_file(&pThis->Utils, curr, dne, pThis->cp_changed_only, &copied)) 623 652 badcp = rval = 1; 624 653 } … … 627 656 case S_IFIFO: 628 657 #endif 629 if ( Rflag) {630 if (copy_fifo( pCtx, curr->fts_statp, !dne))658 if (pThis->Rflag) { 659 if (copy_fifo(&pThis->Utils, curr->fts_statp, !dne)) 631 660 badcp = rval = 1; 632 661 } else { 633 if (copy_file( pCtx, curr, dne,cp_changed_only, &copied))662 if (copy_file(&pThis->Utils, curr, dne, pThis->cp_changed_only, &copied)) 634 663 badcp = rval = 1; 635 664 } 636 665 break; 637 666 default: 638 if (copy_file( pCtx, curr, dne,cp_changed_only, &copied))667 if (copy_file(&pThis->Utils, curr, dne, pThis->cp_changed_only, &copied)) 639 668 badcp = rval = 1; 640 669 break; 641 670 } 642 if ( vflag && !badcp)643 kmk_builtin_ctx_printf(p Ctx, 0, copied ? "%s -> %s\n" : "%s matches %s - not copied\n",644 curr->fts_path, to.p_path);671 if (pThis->Utils.vflag && !badcp) 672 kmk_builtin_ctx_printf(pThis->Utils.pCtx, 0, copied ? "%s -> %s\n" : "%s matches %s - not copied\n", 673 curr->fts_path, pThis->Utils.to.p_path); 645 674 } 646 675 if (errno) 647 return err(p Ctx, 1, "fts_read");676 return err(pThis->Utils.pCtx, 1, "fts_read"); 648 677 return (rval); 649 678 } … … 657 686 * files first reduces seeking. 658 687 */ 659 static int 660 mastercmp(const FTSENT **a, const FTSENT **b) 688 #ifdef FTSCALL 689 static int FTSCALL mastercmp(const FTSENT * const *a, const FTSENT * const *b) 690 #else 691 static int mastercmp(const FTSENT **a, const FTSENT **b) 692 #endif 661 693 { 662 694 int a_info, b_info; … … 675 707 } 676 708 677 #if def SIGINFO709 #if defined(SIGINFO) && defined(KMK_BUILTIN_STANDALONE) 678 710 static void 679 711 siginfo(int sig __unused) 680 712 { 681 713 682 info = 1;714 g_cp_info = 1; 683 715 } 684 716 #endif
Note:
See TracChangeset
for help on using the changeset viewer.