- Timestamp:
- Jan 22, 2019, 10:29:08 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kDeDup/kDeDup.c
r3129 r3296 29 29 *******************************************************************************/ 30 30 #include <k/kTypes.h> 31 //#include <stdlib.h> 32 #include <wchar.h> 31 #include <errno.h> 33 32 #include <string.h> 34 33 #include <stdio.h> 34 #include <wchar.h> 35 #if K_OS != K_OS_WINDOWS 36 # include <stdlib.h> 37 # include <unistd.h> 38 # include <sys/fcntl.h> 39 # include <sys/stat.h> 40 #endif 35 41 36 42 #include "md5.h" 37 43 //#include "sha2.h" 38 44 39 #include "nt/ntstuff.h" 40 #include "nt/ntstat.h" 41 #include "nt/fts-nt.h" 42 #include "nt/nthlp.h" 43 #include "nt/ntunlink.h" 45 #if K_OS == K_OS_WINDOWS 46 # include "nt/ntstuff.h" 47 # include "nt/ntstat.h" 48 # include "nt/fts-nt.h" 49 # include "nt/nthlp.h" 50 # include "nt/ntunlink.h" 51 #else 52 # include "fts.h" 53 #endif 44 54 45 55 … … 87 97 88 98 /** The path to this file (variable size). */ 99 #if K_OS == K_OS_WINDOWS 89 100 wchar_t wszPath[1]; 101 #else 102 char szPath[1]; 103 #endif 90 104 } KDUPFILENODE; 105 106 #if K_OS == K_OS_WINDOWS 107 # define PATH_PRI "ls" 108 # define PATH_MEMB wszPath 109 # define FTS_ACCPATH fts_wcsaccpath 110 #else 111 # define PATH_PRI "s" 112 # define PATH_MEMB szPath 113 # define FTS_ACCPATH fts_accpath 114 #endif 91 115 92 116 /*#define KAVL_EQUAL_ALLOWED*/ … … 108 132 #define register 109 133 #include <k/kAvlTmpl/kAvlBase.h> 110 #include <k/kAvlTmpl/kAvlDoWithAll.h>134 //#include <k/kAvlTmpl/kAvlDoWithAll.h> 111 135 //#include <k/kAvlTmpl/kAvlEnum.h> - busted 112 136 #include <k/kAvlTmpl/kAvlGet.h> 113 #include <k/kAvlTmpl/kAvlGetBestFit.h>114 #include <k/kAvlTmpl/kAvlGetWithParent.h>115 #include <k/kAvlTmpl/kAvlRemove2.h>116 #include <k/kAvlTmpl/kAvlRemoveBestFit.h>137 //#include <k/kAvlTmpl/kAvlGetBestFit.h> 138 //#include <k/kAvlTmpl/kAvlGetWithParent.h> 139 //#include <k/kAvlTmpl/kAvlRemove2.h> 140 //#include <k/kAvlTmpl/kAvlRemoveBestFit.h> 117 141 #include <k/kAvlTmpl/kAvlUndef.h> 118 142 #undef register … … 155 179 156 180 #include <k/kAvlTmpl/kAvlBase.h> 157 #include <k/kAvlTmpl/kAvlDoWithAll.h>181 //#include <k/kAvlTmpl/kAvlDoWithAll.h> 158 182 //#include <k/kAvlTmpl/kAvlEnum.h> - busted 159 183 #include <k/kAvlTmpl/kAvlGet.h> 160 #include <k/kAvlTmpl/kAvlGetBestFit.h>161 #include <k/kAvlTmpl/kAvlGetWithParent.h>162 #include <k/kAvlTmpl/kAvlRemove2.h>163 #include <k/kAvlTmpl/kAvlRemoveBestFit.h>184 //#include <k/kAvlTmpl/kAvlGetBestFit.h> 185 //#include <k/kAvlTmpl/kAvlGetWithParent.h> 186 //#include <k/kAvlTmpl/kAvlRemove2.h> 187 //#include <k/kAvlTmpl/kAvlRemoveBestFit.h> 164 188 #include <k/kAvlTmpl/kAvlUndef.h> 165 189 … … 217 241 if (pvRet) 218 242 return pvRet; 219 fprintf(stderr, "kDeDup: error: out of memory! (cb=%#z )\n", cb);243 fprintf(stderr, "kDeDup: error: out of memory! (cb=%#zx)\n", cb); 220 244 return NULL; 221 245 } … … 223 247 /** Wrapper around free() for symmetry. */ 224 248 #define kDupFree(ptr) free(ptr) 249 250 #if K_OS != K_OS_WINDOWS 251 /** Wrapper around read() that hides EINTR and such. */ 252 static ssize_t kDupReadFile(int fd, void *pvBuf, size_t cbToRead) 253 { 254 ssize_t cbRet; 255 do 256 cbRet = read(fd, pvBuf, cbToRead); 257 while (cbRet < 0 && errno == EINTR); 258 if (cbRet > 0 && (size_t)cbRet != cbToRead) 259 { 260 for (;;) 261 { 262 size_t cbLeft = cbToRead - (size_t)cbRet; 263 ssize_t cbPart; 264 do 265 cbPart = read(fd, (KU8 *)pvBuf + (size_t)cbRet, cbLeft); 266 while (cbPart < 0 && errno == EINTR); 267 if (cbPart <= 0) 268 break; 269 cbRet += cbPart; 270 } 271 } 272 return cbRet; 273 } 274 #endif 225 275 226 276 … … 233 283 * Open the file. 234 284 */ 285 #if K_OS == K_OS_WINDOWS 235 286 HANDLE hFile; 236 287 if (pFtsEnt && pFtsEnt->fts_parent && pFtsEnt->fts_parent->fts_dirfd != INVALID_HANDLE_VALUE) … … 251 302 OBJ_CASE_INSENSITIVE); 252 303 if (hFile != INVALID_HANDLE_VALUE) 304 #else /* K_OS != K_OS_WINDOWS */ 305 # ifdef O_BINARY 306 int fd = open(pFileNode->szPath, O_RDONLY | O_BINARY); 307 # else 308 int fd = open(pFileNode->szPath, O_RDONLY); 309 # endif 310 if (fd >= 0) 311 #endif /* K_OS != K_OS_WINDOWS */ 253 312 { 254 313 /* … … 269 328 { 270 329 static KU8 s_abBuffer[2*1024*1024]; 330 #if K_OS == K_OS_WINDOWS 271 331 MY_NTSTATUS rcNt; 272 332 MY_IO_STATUS_BLOCK Ios; … … 296 356 return; 297 357 } 358 #else /* K_OS != K_OS_WINDOWS */ 359 ssize_t cbRead = kDupReadFile(fd, s_abBuffer, sizeof(s_abBuffer)); 360 if (cbRead > 0) 361 { 362 MD5Update(&Md5Ctx, s_abBuffer, (unsigned)cbRead); 363 //SHA256Update(&Sha256Ctx, s_abBuffer, (unsigned)cbRead); 364 } 365 else if (cbRead == 0) 366 { 367 MD5Final(pFileNode->mKey.abMd5, &Md5Ctx); 368 //Sha256Final(pFileNode->mKey.abSha2, &Sha256Ctx); 369 close(fd); 370 return; 371 } 372 else 373 { 374 fprintf(stderr, "kDeDup: warning: Error reading '%s': %s (%d)\n", pFileNode->szPath, strerror(errno), errno); 375 break; 376 } 377 #endif /* K_OS != K_OS_WINDOWS */ 298 378 } 299 379 380 #if K_OS == K_OS_WINDOWS 300 381 birdCloseFile(hFile); 382 #else 383 close(fd); 384 #endif 301 385 } 302 386 else 303 fprintf(stderr, "kDeDup: warning: Failed to open '%ls': %s (%d)\n", pFileNode->wszPath, strerror(errno), errno); 387 fprintf(stderr, "kDeDup: warning: Failed to open '%" PATH_PRI "': %s (%d)\n", 388 pFileNode->PATH_MEMB, strerror(errno), errno); 304 389 305 390 /* … … 324 409 { 325 410 KU64 cbFile; 411 #if K_OS == K_OS_WINDOWS 412 struct stat const *pStat = &pFtsEnt->fts_stat; 413 #else 414 struct stat const *pStat = pFtsEnt->fts_statp; 415 #endif 326 416 327 417 if (g_cVerbosity >= 2) 328 printf("debug: kDupDoFile(% ls)\n", pFtsEnt->fts_wcsaccpath);418 printf("debug: kDupDoFile(%" PATH_PRI ")\n", pFtsEnt->FTS_ACCPATH); 329 419 330 420 /* 331 421 * Check that it's within the size range. 332 422 */ 333 cbFile = p FtsEnt->fts_stat.st_size;423 cbFile = pStat->st_size; 334 424 if ( cbFile >= g_cbMinFileSize 335 425 && cbFile <= g_cbMaxFileSize) … … 339 429 * allocate all the structures we might possibly need. 340 430 */ 431 #if K_OS == K_OS_WINDOWS 341 432 size_t cbAccessPath = (wcslen(pFtsEnt->fts_wcsaccpath) + 1) * sizeof(wchar_t); 433 #else 434 size_t cbAccessPath = strlen(pFtsEnt->fts_accpath) + 1; 435 #endif 342 436 PKDUPFILENODE pFileNode = (PKDUPFILENODE)kDupAlloc(sizeof(*pFileNode) + cbAccessPath); 343 437 PKDUPSIZENODE pSizeNode = (PKDUPSIZENODE)kDupAlloc(sizeof(*pSizeNode)); … … 350 444 pFileNode->pNextDup = NULL; 351 445 pFileNode->pNextGlobalDup = NULL; 352 pFileNode->uDev = p FtsEnt->fts_stat.st_dev;353 pFileNode->uInode = p FtsEnt->fts_stat.st_ino;354 memcpy(pFileNode-> wszPath, pFtsEnt->fts_wcsaccpath, cbAccessPath);446 pFileNode->uDev = pStat->st_dev; 447 pFileNode->uInode = pStat->st_ino; 448 memcpy(pFileNode->PATH_MEMB, pFtsEnt->FTS_ACCPATH, cbAccessPath); 355 449 356 450 pSizeNode->mKey = cbFile; … … 384 478 pFirstFileNode->pNextHardLink = pFileNode; 385 479 if (g_cVerbosity >= 1) 386 printf("Found hardlinked: '% ls' -> '%ls' (ino:%#" KX64_PRI " dev:%#" KX64_PRI ")\n",387 pFileNode-> wszPath, pFirstFileNode->wszPath, pFileNode->uInode, pFileNode->uDev);480 printf("Found hardlinked: '%" PATH_PRI "' -> '%" PATH_PRI "' (ino:%#" KX64_PRI " dev:%#" KX64_PRI ")\n", 481 pFileNode->PATH_MEMB, pFirstFileNode->PATH_MEMB, pFileNode->uInode, pFileNode->uDev); 388 482 g_cHardlinked += 1; 389 483 return 0; … … 409 503 pDupFileNode->pNextHardLink = pFileNode; 410 504 if (g_cVerbosity >= 1) 411 printf("Found hardlinked: '% ls' -> '%ls' (ino:%#" KX64_PRI " dev:%#" KX64_PRI ")\n",412 pFileNode-> wszPath, pDupFileNode->wszPath, pFileNode->uInode, pFileNode->uDev);505 printf("Found hardlinked: '%" PATH_PRI "' -> '%" PATH_PRI "' (ino:%#" KX64_PRI " dev:%#" KX64_PRI ")\n", 506 pFileNode->PATH_MEMB, pDupFileNode->PATH_MEMB, pFileNode->uInode, pFileNode->uDev); 413 507 g_cHardlinked += 1; 414 508 } … … 436 530 { 437 531 g_cDuplicatesSaved += 1; 438 g_cbDuplicatesSaved += pFtsEnt->fts_stat.st_blocks * BIRD_STAT_BLOCK_SIZE; 532 #if K_OS == K_OS_WINDOWS 533 g_cbDuplicatesSaved += pStat->st_blocks * BIRD_STAT_BLOCK_SIZE; 534 #else 535 g_cbDuplicatesSaved += pStat->st_size; 536 #endif 439 537 if (g_cVerbosity >= 1) 440 printf("Found duplicate: '%ls' <-> '%ls'\n", pFileNode->wszPath, pDupFileNode->wszPath); 538 printf("Found duplicate: '%" PATH_PRI "' <-> '%" PATH_PRI "'\n", 539 pFileNode->PATH_MEMB, pDupFileNode->PATH_MEMB); 441 540 } 442 541 else if (g_cVerbosity >= 1) 443 printf("Found duplicate: '%ls' <-> '%ls' (devices differ).\n", pFileNode->wszPath, pDupFileNode->wszPath); 542 printf("Found duplicate: '%" PATH_PRI "' <-> '%" PATH_PRI "' (devices differ).\n", 543 pFileNode->PATH_MEMB, pDupFileNode->PATH_MEMB); 444 544 } 445 545 } … … 447 547 } 448 548 else if (g_cVerbosity >= 1) 449 printf("Skipping '%ls' because %" KU64_PRI " bytes is outside the size range.\n", 450 pFtsEnt->fts_wcsaccpath, cbFile); 549 printf("Skipping '%" PATH_PRI "' because %" KU64_PRI " bytes is outside the size range.\n", pFtsEnt->FTS_ACCPATH, cbFile); 451 550 return 0; 452 551 } … … 460 559 * @param fFtsOptions The FTS options. 461 560 */ 561 #if K_OS == K_OS_WINDOWS 462 562 static int kDupReadAll(wchar_t **papwszFtsArgs, unsigned fFtsOptions) 563 #else 564 static int kDupReadAll(char **papszFtsArgs, unsigned fFtsOptions) 565 #endif 463 566 { 464 567 int rcExit = 0; 568 #if K_OS == K_OS_WINDOWS 465 569 FTS *pFts = nt_fts_openw(papwszFtsArgs, fFtsOptions, NULL /*pfnCompare*/); 570 #else 571 FTS *pFts = fts_open(papszFtsArgs, fFtsOptions, NULL /*pfnCompare*/); 572 #endif 466 573 if (pFts != NULL) 467 574 { 468 575 for (;;) 469 576 { 577 #if K_OS == K_OS_WINDOWS 470 578 FTSENT *pFtsEnt = nt_fts_read(pFts); 579 #else 580 FTSENT *pFtsEnt = fts_read(pFts); 581 #endif 471 582 if (pFtsEnt) 472 583 { … … 483 594 || pFtsEnt->fts_level == FTS_ROOTLEVEL) /* enumerate dirs on the command line */ 484 595 continue; 596 #if K_OS == K_OS_WINDOWS 485 597 rcExit = nt_fts_set(pFts, pFtsEnt, FTS_SKIP); 598 #else 599 rcExit = fts_set(pFts, pFtsEnt, FTS_SKIP); 600 #endif 486 601 if (rcExit == 0) 487 602 continue; … … 495 610 496 611 case FTS_SL: 612 { 613 #if K_OS == K_OS_WINDOWS 497 614 /* The nice thing on windows is that we already know whether it's a 498 615 directory or file when encountering the symbolic link. */ 499 616 if ( (pFtsEnt->fts_stat.st_isdirsymlink ? g_fRecursiveViaSymlinks : g_fFollowSymlinkedFiles) 500 && pFtsEnt->fts_number == 0) 617 && pFtsEnt->fts_number == 0) 618 #else 619 struct stat St; 620 if ( pFtsEnt->fts_number == 0 621 && ( (g_fRecursiveViaSymlinks && g_fFollowSymlinkedFiles) 622 || ( stat(pFtsEnt->fts_accpath, &St) == 0 623 && (S_ISDIR(St.st_mode) ? g_fRecursiveViaSymlinks : g_fFollowSymlinkedFiles)))) 624 #endif 501 625 { 502 626 pFtsEnt->fts_number++; 627 #if K_OS == K_OS_WINDOWS 503 628 rcExit = nt_fts_set(pFts, pFtsEnt, FTS_FOLLOW); 629 #else 630 rcExit = fts_set(pFts, pFtsEnt, FTS_FOLLOW); 631 #endif 504 632 if (rcExit == 0) 505 633 continue; … … 508 636 } 509 637 break; 638 } 510 639 511 640 case FTS_DC: 512 fprintf(stderr, "kDeDup: warning: Ignoring cycle '% ls'!\n", pFtsEnt->fts_wcsaccpath);641 fprintf(stderr, "kDeDup: warning: Ignoring cycle '%" PATH_PRI "'!\n", pFtsEnt->FTS_ACCPATH); 513 642 continue; 514 643 515 644 case FTS_NS: 516 fprintf(stderr, "kDeDup: warning: Failed to stat '% ls': %s (%d)\n",517 pFtsEnt-> fts_wcsaccpath, strerror(pFtsEnt->fts_errno), pFtsEnt->fts_errno);645 fprintf(stderr, "kDeDup: warning: Failed to stat '%" PATH_PRI "': %s (%d)\n", 646 pFtsEnt->FTS_ACCPATH, strerror(pFtsEnt->fts_errno), pFtsEnt->fts_errno); 518 647 continue; 519 648 520 649 case FTS_DNR: 521 fprintf(stderr, "kDeDup: error: Error reading directory '% ls': %s (%d)\n",522 pFtsEnt-> fts_wcsaccpath, strerror(pFtsEnt->fts_errno), pFtsEnt->fts_errno);650 fprintf(stderr, "kDeDup: error: Error reading directory '%" PATH_PRI "': %s (%d)\n", 651 pFtsEnt->FTS_ACCPATH, strerror(pFtsEnt->fts_errno), pFtsEnt->fts_errno); 523 652 rcExit = 1; 524 653 break; 525 654 526 655 case FTS_ERR: 527 fprintf(stderr, "kDeDup: error: Error on '% ls': %s (%d)\n",528 pFtsEnt-> fts_wcsaccpath, strerror(pFtsEnt->fts_errno), pFtsEnt->fts_errno);656 fprintf(stderr, "kDeDup: error: Error on '%" PATH_PRI "': %s (%d)\n", 657 pFtsEnt->FTS_ACCPATH, strerror(pFtsEnt->fts_errno), pFtsEnt->fts_errno); 529 658 rcExit = 1; 530 659 break; … … 538 667 /* Not supposed to get here. */ 539 668 default: 540 fprintf(stderr, "kDeDup: internal error: fts_info=%d - '% ls'\n",541 pFtsEnt->fts_info, pFtsEnt-> fts_wcsaccpath);669 fprintf(stderr, "kDeDup: internal error: fts_info=%d - '%" PATH_PRI "'\n", 670 pFtsEnt->fts_info, pFtsEnt->FTS_ACCPATH); 542 671 rcExit = 1; 543 672 break; … … 554 683 } 555 684 685 #if K_OS == K_OS_WINDOWS 556 686 if (nt_fts_close(pFts) != 0) 687 #else 688 if (fts_close(pFts) != 0) 689 #endif 557 690 { 558 691 fprintf(stderr, "kDeDup: error: nt_fts_close failed: %s (%d)\n", strerror(errno), errno); … … 567 700 568 701 return rcExit; 702 } 703 704 705 /** 706 * Compares the content of the two files. 707 * 708 * @returns 0 if equal, 1 if not equal, -1 on open/read error. 709 * @param pFile1 The first file. 710 * @param pFile2 The second file. 711 */ 712 static int kDupCompareFiles(PKDUPFILENODE pFile1, PKDUPFILENODE pFile2) 713 { 714 #if K_OS == K_OS_WINDOWS 715 int rcRet = 0; 716 K_NOREF(pFile1); 717 K_NOREF(pFile2); 718 /** @todo compare files. */ 719 #else 720 int rcRet = -1; 721 # ifdef O_BINARY 722 int fOpen = O_RDONLY | O_BINARY; 723 # else 724 int fOpen = O_RDONLY; 725 # endif 726 /* 727 * Open the two files. 728 */ 729 int fd1 = open(pFile1->szPath, fOpen); 730 if (fd1 >= 0) 731 { 732 int fd2 = open(pFile2->szPath, fOpen); 733 if (fd1 >= 0) 734 { 735 /* 736 * Read and compare all the data. 737 */ 738 static KU8 s_abBuf1[2*1024*1024]; 739 static KU8 s_abBuf2[2*1024*1024]; 740 KU64 off = 0; 741 for (;;) 742 { 743 ssize_t cb1 = kDupReadFile(fd1, s_abBuf1, sizeof(s_abBuf1)); 744 ssize_t cb2 = kDupReadFile(fd2, s_abBuf2, sizeof(s_abBuf2)); 745 if (cb1 < 0 || cb2 < 0) 746 { 747 if (cb1 < 0) 748 fprintf(stderr, "kDeDup: error: reading from '%s': %s (%d)\n", pFile1->szPath, strerror(errno), errno); 749 if (cb2 < 0) 750 fprintf(stderr, "kDeDup: error: reading from '%s': %s (%d)\n", pFile2->szPath, strerror(errno), errno); 751 break; 752 } 753 if (cb1 != cb2) 754 { 755 fprintf(stderr, "kDeDup: warning: '%s' now differs from '%s' in size...\n", pFile1->szPath, pFile2->szPath); 756 rcRet = 1; 757 break; 758 } 759 if (cb1 == 0) 760 { 761 rcRet = 0; 762 break; 763 } 764 if (memcmp(s_abBuf1, s_abBuf2, cb1) != 0) 765 { 766 fprintf(stderr, "kDeDup: warning: hash collision: '%s' differs from '%s' (" KX64_PRI " LB %#x)\n", 767 pFile1->szPath, pFile2->szPath, off, (unsigned)cb1); 768 rcRet = 1; 769 break; 770 } 771 off += cb1; 772 } 773 774 close(fd2); 775 } 776 close(fd1); 777 } 778 #endif 779 return rcRet; 569 780 } 570 781 … … 588 799 if (pDupFile->uDev == pTargetFile->uDev) 589 800 { 590 /** @todo compare the files? */ 591 if (1) 801 if (kDupCompareFiles(pDupFile, pTargetFile) == 0) 592 802 { 593 803 /* 594 804 * Start by renaming the orinal file before we try create the hard link. 595 805 */ 806 #if K_OS == K_OS_WINDOWS 596 807 static const wchar_t s_wszBackupSuffix[] = L".kDepBackup"; 597 808 wchar_t wszBackup[0x4000]; … … 623 834 if (!MoveFileW(wszBackup, pDupFile->wszPath)) 624 835 { 625 fprintf(stderr, "kDeDup: fatal: Restore back '%ls' to '%ls' after hardlinking faild: %u\n",836 fprintf(stderr, "kDeDup: fatal: Restore '%ls' to '%ls' after hardlinking failed: %u\n", 626 837 wszBackup, pDupFile->wszPath, GetLastError()); 627 838 return 8; … … 642 853 rcExit = 1; 643 854 } 855 #else /* K_OS != K_OS_WINDOWS */ 856 static const char s_szBackupSuffix[] = ".kDepBackup"; 857 char szBackup[0x4000]; 858 size_t cchPath = strlen(pDupFile->szPath); 859 if (cchPath + sizeof(s_szBackupSuffix) < sizeof(szBackup)) 860 { 861 struct stat StTmp; 862 memcpy(szBackup, pDupFile->szPath, cchPath); 863 memcpy(&szBackup[cchPath], s_szBackupSuffix, sizeof(s_szBackupSuffix)); 864 if (stat(szBackup, &StTmp) != 0) 865 { 866 if (rename(pDupFile->szPath, szBackup) == 0) 867 { 868 if (link(pTargetFile->szPath, pDupFile->szPath) == 0) 869 { 870 if (unlink(szBackup) == 0) 871 { 872 if (g_cVerbosity >= 1) 873 printf("Hardlinked '%s' to '%s'.\n", pDupFile->szPath, pTargetFile->szPath); 874 } 875 else 876 { 877 fprintf(stderr, "kDeDup: fatal: failed to delete '%s' after hardlinking: %s (%d)\n", 878 szBackup, strerror(errno), errno); 879 return 8; 880 } 881 } 882 else 883 { 884 fprintf(stderr, "kDeDup: error: failed to hard link '%s' to '%s': %s (%d)\n", 885 pDupFile->szPath, szBackup, strerror(errno), errno); 886 if (rename(szBackup, pDupFile->szPath) != 0) 887 { 888 fprintf(stderr, "kDeDup: fatal: Restore '%s' to '%s' after hardlinking failed: %s (%d)\n", 889 szBackup, pDupFile->szPath, strerror(errno), errno); 890 return 8; 891 } 892 rcExit = 1; 893 } 894 } 895 else 896 { 897 fprintf(stderr, "kDeDup: error: failed to rename '%s' to '%s': %s (%d)\n", 898 pDupFile->szPath, szBackup, strerror(errno), errno); 899 rcExit = 1; 900 } 901 } 902 else 903 { 904 fprintf(stderr, "kDeDup: error: failed to rename '%s' to '%s': file already exist (st_mode=%#x)\n", 905 pDupFile->szPath, szBackup, StTmp.st_mode); 906 rcExit = 1; 907 } 908 } 909 else 910 { 911 fprintf(stderr, "kDeDup: error: too long backup path: '%s'\n", pDupFile->szPath); 912 rcExit = 1; 913 } 914 #endif /* K_OS != K_OS_WINDOWS */ 644 915 } 645 916 } … … 690 961 691 962 963 #if K_OS == K_OS_WINDOWS 692 964 int wmain(int argc, wchar_t **argv) 965 #else 966 int main(int argc, char **argv) 967 #endif 693 968 { 694 969 int rcExit; … … 697 972 * Process parameters. Position. 698 973 */ 974 unsigned cFtsArgs = 0; 975 #if K_OS == K_OS_WINDOWS 699 976 wchar_t **papwszFtsArgs = (wchar_t **)calloc(argc + 1, sizeof(wchar_t *)); 700 unsigned cFtsArgs = 0;701 977 unsigned fFtsOptions = FTS_NOCHDIR | FTS_NO_ANSI; 978 #else 979 char **papszFtsArgs = (char **)calloc(argc + 1, sizeof(char *)); 980 unsigned fFtsOptions = FTS_NOCHDIR; 981 #endif 702 982 KBOOL fEndOfOptions = K_FALSE; 703 983 KBOOL fHardlinkDups = K_FALSE; … … 705 985 for (i = 1; i < argc; i++) 706 986 { 987 #if K_OS == K_OS_WINDOWS 707 988 wchar_t *pwszArg = argv[i]; 708 989 if ( *pwszArg == '-' 709 990 && !fEndOfOptions) 991 #else 992 char *pszArg = argv[i]; 993 if ( *pszArg == '-' 994 && !fEndOfOptions) 995 #endif 710 996 { 997 #if K_OS != K_OS_WINDOWS 998 wchar_t wszOpt[1024] = { 0 }; 999 wchar_t *pwszArg = wszOpt; 1000 mbsrtowcs(wszOpt, (const char **)&pszArg, 1024 - 1, NULL); 1001 #endif 711 1002 wchar_t wcOpt = *++pwszArg; 712 1003 pwszArg++; … … 805 1096 806 1097 default: 1098 #if K_OS == K_OS_WINDOWS 807 1099 fprintf(stderr, "kDeDup: syntax error: Unknown option '-%lc'\n", wcOpt); 1100 #else 1101 fprintf(stderr, "kDeDup: syntax error: Unknown option '-%c'\n", (int)wcOpt); 1102 #endif 808 1103 return 2; 809 1104 } … … 817 1112 * Append non-option arguments to the FTS argument vector. 818 1113 */ 1114 #if K_OS == K_OS_WINDOWS 819 1115 papwszFtsArgs[cFtsArgs] = pwszArg; 1116 #else 1117 papszFtsArgs[cFtsArgs] = pszArg; 1118 #endif 820 1119 cFtsArgs++; 821 1120 } … … 826 1125 */ 827 1126 kDupSizeTree_Init(&g_SizeRoot); 1127 #if K_OS == K_OS_WINDOWS 828 1128 rcExit = kDupReadAll(papwszFtsArgs, fFtsOptions); 1129 #else 1130 rcExit = kDupReadAll(papszFtsArgs, fFtsOptions); 1131 #endif 829 1132 if (rcExit == 0) 830 1133 { … … 839 1142 } 840 1143 1144 K_NOREF(kDupFileTree_Remove); 1145 K_NOREF(kDupSizeTree_Remove); 841 1146 return rcExit; 842 1147 }
Note:
See TracChangeset
for help on using the changeset viewer.