Subversion Repositories autosfx

Rev

Blame | Last modification | View Log | RSS feed

  1. #include "stdafx.h"
  2. #pragma hdrstop
  3. #include <stdlib.h>
  4. #include "ZipOp.h"
  5. #include "ZipFnc.h"
  6. #include "dz_errs.h"
  7.  
  8. #undef _DZ_FILE_
  9. #define _DZ_FILE_ DZ_ZIPFIO_CPP
  10.  
  11. /* FileIO.c
  12.  * Copyright (C) 1990-1996 Mark Ad\ler, Richard B. Wales, Jean-loup Gailly,
  13.  * Kai Uwe Rommel, Onno van der Linden and Igor Mandrichenko.
  14.  * This version modified by Chris Vleghert and Eric Engler for BCB/Delphi Zip.
  15.  * distributed under LGPL license
  16.  ** see license.txt for details
  17.  
  18.   Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.
  19.  
  20.   See the accompanying file LICENSE, version 2007-Mar-4 or later
  21.   (the contents of which are also included in zip.h) for terms of use.
  22.   If, for some reason, all these files are missing, the Info-ZIP license
  23.   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
  24.  
  25.   parts Copyright (C) 1997 Mike White, Eric W. Engler
  26. ************************************************************************
  27.  Copyright (C) 2009, 2010  by Russell J. Peters, Roger Aelbrecht
  28.  
  29.    This file is part of TZipMaster Version 1.9.
  30.  
  31.     TZipMaster is free software: you can redistribute it and/or modify
  32.     it under the terms of the GNU Lesser General Public License as published by
  33.     the Free Software Foundation, either version 3 of the License, or
  34.     (at your option) any later version.
  35.  
  36.     TZipMaster is distributed in the hope that it will be useful,
  37.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  38.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  39.     GNU Lesser General Public License for more details.
  40.  
  41.     You should have received a copy of the GNU Lesser General Public License
  42.     along with TZipMaster.  If not, see <http://www.gnu.org/licenses/>.
  43.  
  44.     contact: problems@delphizip.org (include ZipMaster in the subject).
  45.     updates: http://www.delphizip.org
  46.     DelphiZip maillist subscribe at http://www.freelists.org/list/delphizip
  47. ************************************************************************/
  48.  
  49.  
  50. #include <time.h>
  51. #include <errno.h>
  52. #include <shellapi.h>
  53. #include <io.h>
  54.  
  55. //#define PAD     0
  56. #define ENOTSAM 17
  57.  
  58. #ifndef FOF_NORECURSION
  59. #define FOF_NORECURSION            0x1000  // don't recurse into directories.
  60. #endif
  61.  
  62.  
  63. // Return a pointer to the start of the last path component. For a directory
  64. //   name terminated by the character in c, the return value is an empty
  65. //   string. p :: Sequence of path components. c :: Path components separator
  66. //   character.
  67. DZStrW last(const DZStrW &p, CHAR c)
  68. {
  69.     int t = p.ReverseFind(c);
  70.     if (t < 0)
  71.         return p;
  72.         return p.Mid(t+1);
  73. }
  74.  
  75.  
  76. int ZipFunc::check_dupExt(void)
  77. {
  78.         FndItem  *f;       // steps through found linked list
  79.         if (!ffound)
  80.                 ffcount = 0;
  81.         HashListExt fnds(ffcount);
  82.         // Try adding each entry
  83.         f = ffound;
  84.     FndItem *p = NULL;
  85.     while (f)
  86.     {
  87.         if (fnds.AddNode(f))
  88.         {
  89.             // duplicate found
  90. //            if (Verbose)
  91.                 Notify(IWARNING,
  92.                        _T("duplicate filename removed: %s "), f->xname);
  93.  
  94.             if (p)
  95.               p->nxt = f->nxt;
  96.             delete f;
  97.             f = p->nxt;
  98.                         ffcount--;
  99.         }
  100.         else
  101.         {
  102.             p = f;
  103.             f = f->nxt;
  104.         }
  105.     }
  106.     return DZ_ERR_GOOD;
  107. }
  108.  
  109. // Return true if the attributes are those of a symbolic link a ::
  110. //   Attributes returned by filetime().
  111. int issymlnk(ulg)// a)
  112. {
  113.         return 0;// (int)a & 0;  // Avoid warning on unused parameter.
  114. #pragma argused
  115. }
  116.                                                    
  117. #ifndef UNICODE
  118. int ZipFunc::replaceOrig(const DZStrW &d, const DZStrW& s)
  119. {
  120.     struct stati64 t;        // results of stat()
  121.     int         copy = 0;
  122.     int         d_exists;
  123.  
  124.         d_exists = _tstati64(d, &t) == 0;
  125.         if (d_exists)
  126.         {
  127.                 // respect existing soft and hard links!
  128.                 if (t.st_nlink > 1)
  129.                         copy = 1;
  130.         else
  131.         {
  132.             if (_tunlink(d))
  133.                 return DZ_ERM_ERROR_CREATE;      // Can't erase zip file--give up
  134.             Sleep(5);
  135.         }
  136.     }
  137.     if (!copy)
  138.     {
  139.             // Just move s on top of d
  140.         if (_trename(s, d))// !MoveFile(s, d))
  141.         {
  142.             if (Verbose < 0)
  143.                 Notify(IERROR, _T(" replace failed %s (%s)"), s, errno);
  144.             copy = 1;                   // failed ?
  145.             if (errno != ENOTSAM)
  146.                                 return DZ_ERM_ERROR_CREATE;
  147.         }
  148.     }
  149.  
  150.     if (copy)
  151.     {
  152.         HANDLE  f,
  153.         g;                    // source and destination files
  154.         int     r;                    // temporary variable
  155.         diag(_T("in replace - open for read"));
  156.  
  157.         if ((f = CreateFile(s, GENERIC_READ, 0, NULL, OPEN_EXISTING,
  158.                             FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL)) <= 0)
  159.         {
  160.             diag(_T("in replace - bad open for Read"));
  161.             Notify(0, _T(" replace: can't open %s [%s]"), s, SysMsg());
  162.  
  163.                         return DZ_ERM_TEMP_FAILED;
  164.         }
  165.  
  166.         diag(_T("in replace - fopen for write"));
  167.  
  168.         if ((g = CreateFile(d, GENERIC_WRITE, 0, NULL, CREATE_NEW,
  169.                             FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL)) <= 0)
  170.         {
  171.             Close_Handle(&f);
  172.             diag(_T("in replace - bad open for Write"));
  173.                         return DZ_ERM_ERROR_CREATE;
  174.         }
  175.  
  176.         r = filecopy(f, g);
  177.  
  178.         Close_Handle(&f);
  179.         if (!Close_Handle(&g) || r != DZ_ERR_GOOD)
  180.         {
  181.             DeleteFile(d);
  182.             return r ? (DZ_ERR(r) == DZ_ERR_TEMP_FAILED ? DZ_ERR_ERROR_WRITE : r) : DZ_ERM_ERROR_WRITE;
  183.         }
  184.  
  185.         DeleteFile(s);
  186.     }
  187.  
  188.     return DZ_ERR_GOOD;
  189. }
  190. #endif
  191.  
  192. DWORD CALLBACK MoveProgress(
  193.     LARGE_INTEGER TotalFileSize,
  194.     LARGE_INTEGER TotalBytesTransferred,
  195.     LARGE_INTEGER StreamSize,
  196.     LARGE_INTEGER StreamBytesTransferred,
  197.     DWORD dwStreamNumber,
  198.     DWORD dwCallbackReason,
  199.     HANDLE hSourceFile,
  200.     HANDLE hDestinationFile,
  201.     LPVOID lpData
  202. )
  203. {
  204.     long cnt = 0;
  205.     ZipFunc *pG = (ZipFunc *)lpData;
  206.     if (!pG)
  207.         return PROGRESS_CONTINUE;
  208.     if (TotalFileSize.QuadPart && TotalBytesTransferred.QuadPart)
  209.     {
  210.         cnt = (long)((100 * TotalBytesTransferred.QuadPart) / TotalFileSize.QuadPart);
  211.     }
  212.     if (pG->Verbose)
  213.         pG->Notify(IVERBOSE, _T("replace %d%%"), cnt);
  214.     return pG->CB->UserXProgress(cnt, 2) < CALLBACK_IGNORED ?
  215.             PROGRESS_CANCEL : PROGRESS_CONTINUE;
  216. #pragma argsused
  217. }
  218.  
  219. typedef BOOL(WINAPI *MoveWithProgress)(
  220.     LPCTSTR lpExistingFileName,
  221.     LPCTSTR lpNewFileName,
  222.     LPPROGRESS_ROUTINE lpProgressRoutine,
  223.     LPVOID lpData,
  224.     DWORD dwFlags
  225. );
  226.  
  227. int ZipFunc::replace(const DZStrW &d, const DZStrW &s)
  228. {
  229. #ifndef UNICODE
  230.     int             r;
  231.     HINSTANCE       hKernal;
  232.     MoveWithProgress mover;
  233. #endif
  234.  
  235.     if (Verbose)
  236.         Notify(IVERBOSE, _T("replace '%s' with '%s'"), d.c_str(), s.c_str());
  237.     else
  238.       CB->UserCB(zacTick);  // take a little time
  239.  
  240.     if (d.IsEmpty() || s.IsEmpty())
  241.     {
  242.         diag(_T("in replace - missing filename"));
  243.                 return DZ_ERM_TEMP_FAILED;
  244.     }
  245. #ifdef UNICODE
  246.     if (!MoveFileWithProgress(s, d, MoveProgress, this,
  247.                   MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING))
  248.     {
  249.            int re = DZ_ERM_TEMP_FAILED;
  250.         Notify(re, _T(" replace: Move failed -[%s]"),  SysMsg().c_str());
  251.         return re;
  252.     }
  253.     return DZ_ERR_GOOD;
  254. #else
  255.     hKernal = LoadLibrary("kernel32.dll");
  256.     if (hKernal == NULL)
  257.         return replaceOrig(d, s);
  258.     mover = (MoveWithProgress) GetProcAddressA(hKernal, "MoveFileWithProgressA");
  259.     if (mover == NULL)
  260.     {
  261.         FreeLibrary(hKernal);
  262.         return replaceOrig(d, s);
  263.     }
  264.     r = DZ_ERR_GOOD;
  265.  
  266.     CB->UserXItem(100, 2, _T("Copying Temporary File"));
  267.     if (!((mover)(s, d, MoveProgress, this,
  268.                   MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING)))
  269.     {
  270.         r = DZ_ERM_TEMP_FAILED;
  271.         Notify(DZ_ERM_TEMP_FAILED, _T(" replace: Move failed [%s]"), SysMsg());
  272.     }
  273.  
  274.     FreeLibrary(hKernal);
  275.     return r;
  276. #endif
  277. }
  278.  
  279. // Return the file attributes for file f or 0 if failure. f :: File path.
  280. // int getfileattr(char *f) { struct stat s; return SSTAT(f, &
  281. //   s) == 0 ? s.st_mode : 0; }
  282. // Give the file f the attributes a, return non-zero on failure. f :: file
  283. //   path. a :: attributes returned by getfileattr().
  284. int setfileattr(const DZStrW &f, int a)
  285. {
  286.     return _tchmod(f, a);
  287. }
  288.  
  289. // Return a temporary file name in its own malloc'ed space, using tempath.
  290. DZStrW ZipFunc::tempname(void)
  291. {
  292.     int i;
  293.  
  294.     DZStrW pat = ftempath;
  295.     pat.Trim();
  296.     // p -> last char tempath (pat)
  297.     DZStrW tempBase;
  298.     if (!pat.IsEmpty() && pat[0] == WILDALL)
  299.     {
  300.         GetTempPath(MAX_PATH, tempBase.GetBuffer(MAX_PATH));
  301.         tempBase.ReleaseBuffer();
  302.         // skip leading dots in pat
  303.         pat.TrimLeft(WILDALL);
  304.     }
  305.     // get path, name, ext
  306.     int ldf = pat.ReverseFind(DOT);
  307.     int lpf = pat.ReverseFind(BSLASH);
  308.     if (ldf < lpf)
  309.         ldf = -1;
  310.     DZStrW ext;
  311.     DZStrW nam;
  312.     if (ldf >= 0)
  313.     {
  314.         ext = nam.Mid(ldf);
  315.     }
  316.     if (ldf > lpf)
  317.     {
  318.         if (lpf > 0)
  319.             nam = pat.Mid(lpf + 1, (ldf - lpf) -1);
  320.         else
  321.             nam = pat.Mid(ldf + 1);
  322.     }
  323.     // add path to base (if any of either)
  324.     if (lpf >= 0)
  325.     {
  326.         tempBase += pat.Left(lpf);
  327.     }
  328.     if (ext.IsEmpty())
  329.         ext = _T(".zip");
  330.     if (nam.IsEmpty())
  331.         nam = _T("temp");
  332.  
  333.     if (!tempBase.IsEmpty() && tempBase.LastChar() != BSLASH)
  334.         tempBase += BSLASH;
  335.  
  336.     // allow 256 attempts
  337.     for (i = 0; i < 256; i++)
  338.     {
  339.         WIN32_FIND_DATA fdata;
  340.         HANDLE          fh;
  341.         DZStrW name = tempBase + nam;
  342.         name.AppendFormat(_T("%04.4x"), rand());
  343.                 name += ext;
  344.  
  345.         fh = FindFirstFile(name, &fdata);
  346.         if (fh == INVALID_HANDLE_VALUE)
  347.             return name;
  348.  
  349.         FindClose(fh);
  350.     }
  351.  
  352.  
  353.     // could not do it so try old way
  354.     DZStrW name = tempBase + _T("ZipTmpXXXXXX");
  355.     if (_tmktemp(name.GetBuffer(MAX_PATH+2)) == NULL)
  356.     {
  357.         name.ReleaseBuffer();
  358.         name.Empty();
  359.     }
  360.     else
  361.         name.ReleaseBuffer();
  362.  
  363.     return name;
  364. }
  365.  
  366.  
  367. // new 1,72 Copy from file *f to file *g, until EOF Return an error code in
  368. //   the ZEN_ class. b :: malloc'ed buffer for copying. k :: Result of fread().
  369. //   m :: Bytes copied so far.
  370. int ZipFunc::filecopy(HANDLE f, HANDLE g)
  371. {
  372.     unsigned long cnt;            // bytes done
  373.     ZInt64           m;              // bytes copied so far
  374.     ZInt64          n;              // file size
  375.     BY_HANDLE_FILE_INFORMATION info;
  376.     if (Verbose)
  377.         Notify(IVERBOSE, _T("Copying File"));
  378.  
  379.     if (!GetFileInformationByHandle(f, &info))
  380.         return DZ_ERM_ERROR_READ;
  381.     n = info.nFileSizeLow + ((ZInt64)info.nFileSizeHigh << 32);
  382.     m = 0;
  383.     CB->UserXItem(n, 2, _T("Copying Temporary File"));
  384.         while (m < n)
  385.     {
  386.         if (Abort_Flag)
  387.                         Fatal(DZ_ERM_ABORT, 0);
  388.         cnt = (unsigned long)ZWSIZE;
  389.         if ((m + cnt) > n)
  390.             cnt = (unsigned long)(n - m);
  391.  
  392.  
  393.         if (!ReadFile(f, fwindow, cnt, &cnt, NULL))
  394.                         return DZ_ERM_ERROR_READ;
  395.  
  396.         if (!cnt)
  397.             break;  // none read - finished
  398.         if (!WriteFile(g, fwindow, cnt, &cnt, NULL))
  399.         {
  400.             Notify(0, _T(" filecopy: write error"));
  401.                         return DZ_ERM_TEMP_FAILED;
  402.                 }
  403.         fBytesWritten += cnt;
  404.  
  405.         m += cnt;
  406.         CB->UserXProgress(cnt, 2);
  407.     }
  408.  
  409.     return DZ_ERR_GOOD;
  410. }
  411.  
  412. // changed 1.71 - copies n bytes only (not to eof) Copy n bytes from file *f
  413. //   to file *g. Return an error code in the ZEN_ class. b :: malloc'ed buffer
  414. //   for copying. k :: Result of fread(). m :: Bytes copied so far.
  415. int ZipFunc::fcopy(ZInt64 n)
  416. {
  417.     char  *b;   // buffer for copying
  418.     ulg   k;
  419.     ZInt64   m;    // bytes copied so far
  420.  
  421.     b = (char *) fwindow;
  422.     m = 0;
  423.     while (m < n)
  424.     {
  425.         k = ZWSIZE;
  426.         if ((m + k) > n)
  427.             k = (ulg)(n - m);
  428.  
  429.         if (!ReadFile(fhInz, b, k, &k, NULL))
  430.                         return DZ_ERM_ERROR_READ;
  431.  
  432.         if (!k)
  433.             break;  // none read - finished
  434.         if (!fZipOutfile->Write(b, k, &k))
  435.         {
  436.             Notify(0, _T(" fcopy: write error"));
  437.                         return DZ_ERM_TEMP_FAILED;
  438.                 }
  439.         fBytesWritten += k;
  440.  
  441.                 m += k;
  442.                 CB->UserProgress(k); // Added for progress bar support.
  443.     }
  444.  
  445.     return DZ_ERR_GOOD;
  446. }
  447.  
  448.  
  449.  
  450.  
  451.