Subversion Repositories autosfx

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 daniel-mar 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