Changeset 3296 for trunk


Ignore:
Timestamp:
Jan 22, 2019, 10:29:08 PM (6 years ago)
Author:
bird
Message:

kDeDup: Made it work on linux (a bit ugly).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kDeDup/kDeDup.c

    r3129 r3296  
    2929*******************************************************************************/
    3030#include <k/kTypes.h>
    31 //#include <stdlib.h>
    32 #include <wchar.h>
     31#include <errno.h>
    3332#include <string.h>
    3433#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
    3541
    3642#include "md5.h"
    3743//#include "sha2.h"
    3844
    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
    4454
    4555
     
    8797
    8898    /** The path to this file (variable size). */
     99#if K_OS == K_OS_WINDOWS
    89100    wchar_t         wszPath[1];
     101#else
     102    char            szPath[1];
     103#endif
    90104} 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
    91115
    92116/*#define KAVL_EQUAL_ALLOWED*/
     
    108132#define register
    109133#include <k/kAvlTmpl/kAvlBase.h>
    110 #include <k/kAvlTmpl/kAvlDoWithAll.h>
     134//#include <k/kAvlTmpl/kAvlDoWithAll.h>
    111135//#include <k/kAvlTmpl/kAvlEnum.h> - busted
    112136#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>
    117141#include <k/kAvlTmpl/kAvlUndef.h>
    118142#undef register
     
    155179
    156180#include <k/kAvlTmpl/kAvlBase.h>
    157 #include <k/kAvlTmpl/kAvlDoWithAll.h>
     181//#include <k/kAvlTmpl/kAvlDoWithAll.h>
    158182//#include <k/kAvlTmpl/kAvlEnum.h> - busted
    159183#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>
    164188#include <k/kAvlTmpl/kAvlUndef.h>
    165189
     
    217241    if (pvRet)
    218242        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);
    220244    return NULL;
    221245}
     
    223247/** Wrapper around free() for symmetry. */
    224248#define kDupFree(ptr) free(ptr)
     249
     250#if K_OS != K_OS_WINDOWS
     251/** Wrapper around read() that hides EINTR and such. */
     252static 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
    225275
    226276
     
    233283     * Open the file.
    234284     */
     285#if K_OS == K_OS_WINDOWS
    235286    HANDLE hFile;
    236287    if (pFtsEnt && pFtsEnt->fts_parent && pFtsEnt->fts_parent->fts_dirfd != INVALID_HANDLE_VALUE)
     
    251302                                OBJ_CASE_INSENSITIVE);
    252303    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 */
    253312    {
    254313        /*
     
    269328        {
    270329            static KU8          s_abBuffer[2*1024*1024];
     330#if K_OS == K_OS_WINDOWS
    271331            MY_NTSTATUS         rcNt;
    272332            MY_IO_STATUS_BLOCK  Ios;
     
    296356                return;
    297357            }
     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 */
    298378        }
    299379
     380#if K_OS == K_OS_WINDOWS
    300381        birdCloseFile(hFile);
     382#else
     383        close(fd);
     384#endif
    301385    }
    302386    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);
    304389
    305390    /*
     
    324409{
    325410    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
    326416
    327417    if (g_cVerbosity >= 2)
    328         printf("debug: kDupDoFile(%ls)\n", pFtsEnt->fts_wcsaccpath);
     418        printf("debug: kDupDoFile(%" PATH_PRI ")\n", pFtsEnt->FTS_ACCPATH);
    329419
    330420    /*
    331421     * Check that it's within the size range.
    332422     */
    333     cbFile = pFtsEnt->fts_stat.st_size;
     423    cbFile = pStat->st_size;
    334424    if (   cbFile >= g_cbMinFileSize
    335425        && cbFile <= g_cbMaxFileSize)
     
    339429         * allocate all the structures we might possibly need.
    340430         */
     431#if K_OS == K_OS_WINDOWS
    341432        size_t        cbAccessPath = (wcslen(pFtsEnt->fts_wcsaccpath) + 1) * sizeof(wchar_t);
     433#else
     434        size_t        cbAccessPath = strlen(pFtsEnt->fts_accpath) + 1;
     435#endif
    342436        PKDUPFILENODE pFileNode = (PKDUPFILENODE)kDupAlloc(sizeof(*pFileNode) + cbAccessPath);
    343437        PKDUPSIZENODE pSizeNode = (PKDUPSIZENODE)kDupAlloc(sizeof(*pSizeNode));
     
    350444        pFileNode->pNextDup         = NULL;
    351445        pFileNode->pNextGlobalDup   = NULL;
    352         pFileNode->uDev             = pFtsEnt->fts_stat.st_dev;
    353         pFileNode->uInode           = pFtsEnt->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);
    355449
    356450        pSizeNode->mKey = cbFile;
     
    384478                    pFirstFileNode->pNextHardLink = pFileNode;
    385479                    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);
    388482                    g_cHardlinked += 1;
    389483                    return 0;
     
    409503                    pDupFileNode->pNextHardLink = pFileNode;
    410504                    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);
    413507                    g_cHardlinked += 1;
    414508                }
     
    436530                    {
    437531                        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
    439537                        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);
    441540                    }
    442541                    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);
    444544                }
    445545            }
     
    447547    }
    448548    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);
    451550    return 0;
    452551}
     
    460559 * @param   fFtsOptions     The FTS options.
    461560 */
     561#if K_OS == K_OS_WINDOWS
    462562static int kDupReadAll(wchar_t **papwszFtsArgs, unsigned fFtsOptions)
     563#else
     564static int kDupReadAll(char **papszFtsArgs, unsigned fFtsOptions)
     565#endif
    463566{
    464567    int  rcExit = 0;
     568#if K_OS == K_OS_WINDOWS
    465569    FTS *pFts = nt_fts_openw(papwszFtsArgs, fFtsOptions, NULL /*pfnCompare*/);
     570#else
     571    FTS *pFts = fts_open(papszFtsArgs, fFtsOptions, NULL /*pfnCompare*/);
     572#endif
    466573    if (pFts != NULL)
    467574    {
    468575        for (;;)
    469576        {
     577#if K_OS == K_OS_WINDOWS
    470578            FTSENT *pFtsEnt = nt_fts_read(pFts);
     579#else
     580            FTSENT *pFtsEnt = fts_read(pFts);
     581#endif
    471582            if (pFtsEnt)
    472583            {
     
    483594                            || pFtsEnt->fts_level == FTS_ROOTLEVEL) /* enumerate dirs on the command line */
    484595                            continue;
     596#if K_OS == K_OS_WINDOWS
    485597                        rcExit = nt_fts_set(pFts, pFtsEnt, FTS_SKIP);
     598#else
     599                        rcExit = fts_set(pFts, pFtsEnt, FTS_SKIP);
     600#endif
    486601                        if (rcExit == 0)
    487602                            continue;
     
    495610
    496611                    case FTS_SL:
     612                    {
     613#if K_OS == K_OS_WINDOWS
    497614                        /* The nice thing on windows is that we already know whether it's a
    498615                           directory or file when encountering the symbolic link. */
    499616                        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
    501625                        {
    502626                            pFtsEnt->fts_number++;
     627#if K_OS == K_OS_WINDOWS
    503628                            rcExit = nt_fts_set(pFts, pFtsEnt, FTS_FOLLOW);
     629#else
     630                            rcExit = fts_set(pFts, pFtsEnt, FTS_FOLLOW);
     631#endif
    504632                            if (rcExit == 0)
    505633                                continue;
     
    508636                        }
    509637                        break;
     638                    }
    510639
    511640                    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);
    513642                        continue;
    514643
    515644                    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);
    518647                        continue;
    519648
    520649                    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);
    523652                        rcExit = 1;
    524653                        break;
    525654
    526655                    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);
    529658                        rcExit = 1;
    530659                        break;
     
    538667                    /* Not supposed to get here. */
    539668                    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);
    542671                        rcExit = 1;
    543672                        break;
     
    554683        }
    555684
     685#if K_OS == K_OS_WINDOWS
    556686        if (nt_fts_close(pFts) != 0)
     687#else
     688        if (fts_close(pFts) != 0)
     689#endif
    557690        {
    558691            fprintf(stderr, "kDeDup: error: nt_fts_close failed: %s (%d)\n", strerror(errno), errno);
     
    567700
    568701    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 */
     712static 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;
    569780}
    570781
     
    588799            if (pDupFile->uDev == pTargetFile->uDev)
    589800            {
    590                 /** @todo compare the files?   */
    591                 if (1)
     801                if (kDupCompareFiles(pDupFile, pTargetFile) == 0)
    592802                {
    593803                    /*
    594804                     * Start by renaming the orinal file before we try create the hard link.
    595805                     */
     806#if K_OS == K_OS_WINDOWS
    596807                    static const wchar_t s_wszBackupSuffix[] = L".kDepBackup";
    597808                    wchar_t wszBackup[0x4000];
     
    623834                                if (!MoveFileW(wszBackup, pDupFile->wszPath))
    624835                                {
    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",
    626837                                            wszBackup, pDupFile->wszPath, GetLastError());
    627838                                    return 8;
     
    642853                        rcExit = 1;
    643854                    }
     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 */
    644915                }
    645916            }
     
    690961
    691962
     963#if K_OS == K_OS_WINDOWS
    692964int wmain(int argc, wchar_t **argv)
     965#else
     966int main(int argc, char **argv)
     967#endif
    693968{
    694969    int             rcExit;
     
    697972     * Process parameters.  Position.
    698973     */
     974    unsigned    cFtsArgs      = 0;
     975#if K_OS == K_OS_WINDOWS
    699976    wchar_t   **papwszFtsArgs = (wchar_t **)calloc(argc + 1, sizeof(wchar_t *));
    700     unsigned    cFtsArgs      = 0;
    701977    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
    702982    KBOOL       fEndOfOptions = K_FALSE;
    703983    KBOOL       fHardlinkDups = K_FALSE;
     
    705985    for (i = 1; i < argc; i++)
    706986    {
     987#if K_OS == K_OS_WINDOWS
    707988        wchar_t *pwszArg = argv[i];
    708989        if (   *pwszArg == '-'
    709990            && !fEndOfOptions)
     991#else
     992        char *pszArg = argv[i];
     993        if (   *pszArg == '-'
     994            && !fEndOfOptions)
     995#endif
    710996        {
     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
    7111002            wchar_t wcOpt = *++pwszArg;
    7121003            pwszArg++;
     
    8051096
    8061097                    default:
     1098#if K_OS == K_OS_WINDOWS
    8071099                        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
    8081103                        return 2;
    8091104                }
     
    8171112             * Append non-option arguments to the FTS argument vector.
    8181113             */
     1114#if K_OS == K_OS_WINDOWS
    8191115            papwszFtsArgs[cFtsArgs] = pwszArg;
     1116#else
     1117            papszFtsArgs[cFtsArgs] = pszArg;
     1118#endif
    8201119            cFtsArgs++;
    8211120        }
     
    8261125     */
    8271126    kDupSizeTree_Init(&g_SizeRoot);
     1127#if K_OS == K_OS_WINDOWS
    8281128    rcExit = kDupReadAll(papwszFtsArgs, fFtsOptions);
     1129#else
     1130    rcExit = kDupReadAll(papszFtsArgs, fFtsOptions);
     1131#endif
    8291132    if (rcExit == 0)
    8301133    {
     
    8391142    }
    8401143
     1144    K_NOREF(kDupFileTree_Remove);
     1145    K_NOREF(kDupSizeTree_Remove);
    8411146    return rcExit;
    8421147}
Note: See TracChangeset for help on using the changeset viewer.