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
 
4
#include "ZipOp.h"
5
#include "dz_errs.h"
6
 
7
#undef _DZ_FILE_
8
#define _DZ_FILE_ DZ_ZIPPRC_CPP
9
 
10
/* DLLzip.c * Copyright (C) 1990-1996 Mark Adler, Richard B. Wales, Jean-loup Gailly,
11
 * Kai Uwe Rommel, Onno van der Linden and Igor Mandrichenko.
12
 * This version modified by Chris Vleghert and Eric Engler for BCB/Delphi Zip.
13
 ** distributed under LGPL license
14
 
15
  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.
16
 
17
  See the accompanying file LICENSE, version 2007-Mar-4 or later
18
  (the contents of which are also included in zip.h) for terms of use.
19
  If, for some reason, all these files are missing, the Info-ZIP license
20
  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
21
 
22
  parts Copyright (C) 1997 Mike White, Eric W. Engler
23
************************************************************************
24
 Copyright (C) 2009, 2010  by Russell J. Peters, Roger Aelbrecht
25
 
26
   This file is part of TZipMaster Version 1.9.
27
 
28
    TZipMaster is free software: you can redistribute it and/or modify
29
    it under the terms of the GNU Lesser General Public License as published by
30
    the Free Software Foundation, either version 3 of the License, or
31
    (at your option) any later version.
32
 
33
    TZipMaster is distributed in the hope that it will be useful,
34
    but WITHOUT ANY WARRANTY; without even the implied warranty of
35
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
36
    GNU Lesser General Public License for more details.
37
 
38
    You should have received a copy of the GNU Lesser General Public License
39
    along with TZipMaster.  If not, see <http://www.gnu.org/licenses/>.
40
 
41
    contact: problems@delphizip.org (include ZipMaster in the subject).
42
    updates: http://www.delphizip.org
43
    DelphiZip maillist subscribe at http://www.freelists.org/list/delphizip
44
************************************************************************
45
*/
46
 
47
#include <process.h>
48
#include <signal.h>
49
#include <errno.h>
50
#include <stdlib.h>
51
#include <io.h>
52
 
53
// Local option flags
54
#define PURGE   0 // RCV Changed: was DELETE. (delete is also a function)
55
#define ADD     1
56
#define UPDATE  2
57
#define FRESHEN 3
58
 
59
#define MARK_PURGE      -1
60
#define MARK_KEEP       0
61
#define MARK_UPDATE     1
62
#define MARK_RENAMED    2
63
#define MARK_VERSION    3
64
#define MARK_NEW        4
65
 
66
#ifndef UNICODE
67
#define __access _access
68
#endif
69
 
70
// Process -o and -m options (if specified), free up malloc'ed stuff, and
71
//   exit with the code e. e :: Exit code.
72
void ZipFunc::finish(void)
73
{
74
    int r; // return value from trash()
75
    ulg t; // latest time in zip file
76
 
77
        ZipItem *z; // pointer into zfile list
78
 
79
    if (flatest && fzipfile.Compare(_T("-")))
80
    {
81
        diag(_T("changing time of zip file to time of latest file in it"));
82
 
83
        // find latest time in zip file
84
        if (fzfiles == NULL)
85
        {
86
            Notify(IWARNING,
87
                   _T("zip file is empty, can't make it as old as latest entry"));
88
        }
89
        else
90
        {
91
            t = 0;
92
 
93
                        for (z = fzfiles; z != NULL; z = z->nxt) // Ignore directories in time comparisons
94
            if (!z->IsFolder && t < z->tim)
95
                                t = z->tim;
96
            // set modified time of zip file to that time
97
            if (t != 0)
98
                stamp(fzipfile, t);
99
            else
100
                Notify(IWARNING,
101
                       _T("zip file has only directories, can't make it as old as latest entry"));
102
        }
103
    }
104
 
105
    // If dispose, delete all files in the zfiles list that are marked
106
    if (fdispose && !Abort_Flag)
107
    {
108
        // v1.6017
109
        diag(_T("deleting files that were added to zip file"));
110
 
111
        if ((r = trash()) != DZ_ERR_GOOD)
112
            DZError(r);
113
    }
114
}
115
 
116
void ZipFunc::ZipCleanup(void)
117
{
118
    delete [] fhwbuf;
119
    fhwbuf = NULL;
120
 
121
    if (ftempzip && (ftempzip != fzipfile))
122
    {
123
        // using temp file
124
        if (fZipOutfile)
125
        {
126
            delete fZipOutfile;
127
            fZipOutfile = NULL;
128
        }
129
 
130
        // remove bad file - if it exists
131
        EraseFile(ftempzip, false);
132
    }
133
 
134
    Close_Handle(&fhInz);
135
 
136
    if (fZipOutfile)
137
    {
138
        bool wasopen =  fZipOutfile->IsOpen() && fZipOutfile->IsFile;
139
        delete fZipOutfile;
140
        fZipOutfile = NULL;
141
        // remove damaged file
142
 
143
        if (wasopen)
144
        {
145
            if (Verbose)
146
                Notify(IVERBOSE, _T("deleting damaged %s"), fzipfile.c_str());
147
 
148
            EraseFile(fzipfile, false);
149
        }
150
    }
151
 
152
    ftempzip = "";
153
}
154
 
155
int DriveType(const DZStrW& pth)
156
{
157
    TCHAR root[3];
158
    root[0] = pth.IsEmpty() ? (char)0 : pth[0];
159
    root[1] = ':';
160
    root[2] = 0;
161
 
162
    if (root[0] == BSLASH)
163
        root[1] = 0;
164
 
165
    return GetDriveType(root);
166
}
167
 
168
const char hx[16] = "0123456789ABCDEF";
169
char hxbuf[16];
170
char* toHex(unsigned val)
171
{
172
    char* p = &hxbuf[15];
173
    *p = 0;
174
    while (val)
175
    {
176
        *--p = hx[val & 0x0f];
177
        val >>= 4;
178
    }
179
    return p;
180
}
181
 
182
 
183
int __fastcall ZipFunc::NameVer(ZipItem* z)
184
{
185
        int r;
186
        DZStrW name = z->IName;
187
        int i = name.ReverseFind(_T('.'));
188
 
189
    if (!VerDate)
190
    {
191
        FILETIME now;
192
        WORD d, t;
193
        GetSystemTimeAsFileTime(&now);
194
 
195
        if (FileTimeToDosDateTime(&now, &d, &t))
196
            VerDate = (d << 16) | t;
197
        else
198
            VerDate = z->tim;
199
    }
200
 
201
    DZStrW nx, nn(name);
202
    nx = _T("}");
203
 
204
    if (i >= 0)
205
    {
206
        nn = name.Left(i);
207
        nx += name.Mid(i);
208
    }
209
 
210
    i = -1;
211
 
212
    nn.AppendFormat(_T(".{%X"), VerDate);
213
    name = nn;
214
        name += nx;
215
        DZStrA hn = StrIntSep(name);
216
 
217
        const XItem* n;
218
        while ((n = IntList->FindName(name)) != NULL)
219
        {
220
                // exists
221
                if (++i == MAXINT)
222
                        return -2;  // give up
223
 
224
                name.Format(_T("%s-%X%s"), nn.c_str(), i, nx.c_str());
225
        }
226
        hn = StrIntSep(name);
227
        if (Verbose < 0)
228
                Notify(IVERBOSE, _T("%s versioned as %s"), z->iname, name.c_str());
229
        z->IName = name;
230
        z->HName = hn;
231
        // prepare header name
232
        if ((r = PrepareHeaderName(z, true)) != 0)
233
                return r;
234
 
235
    if (!n)
236
        n = IntList->AddNode(z);
237
 
238
    return n ? -1 : 0;
239
}
240
 
241
void ZipFunc::DupName(bool fatal, const XItem* o, const XItem* n, const DZStrW name)
242
{
243
    // duplicate found
244
        Notify(IWARNING, _T("internal name in zip file repeated: %s"), name.c_str());
245
    Notify(IWARNING, _T("  first full name: %s"), o->xname);
246
    Notify(IWARNING, _T(" second full name: %s"), n->xname);
247
 
248
    if (fatal)
249
                throw DZException(DZ_ERM_DUPNAME);
250
        Notify(IWARNING, _T(" rejecting: %s"), n->xname);
251
}
252
 
253
int __fastcall ZipFunc::PrepareHeaderName(ZipItem* z, bool NoComment)
254
{
255
        if (!NoComment)
256
    {
257
//        // free any old data - probably obsolete
258
//        z->cextra.Empty();
259
//        z->extra.Empty();
260
        if (z->ntfs)
261
        {
262
            delete z->ntfs;
263
            z->ntfs = NULL;
264
        }
265
 
266
        // get or change the comment
267
        CB->Msg2 = z->Comment;
268
        if (CB->UserCB(zacComment, z->IName) == CALLBACK_TRUE)
269
        {
270
            // User changed the comment
271
            z->Comment.Empty();
272
            z->com = CB->Arg1;
273
 
274
            if (z->com)
275
            {
276
                DZStrW tc(CB->Msg, z->com);
277
                z->Comment = tc;
278
            }
279
        }
280
    }
281
        // ****** set header name and encoding
282
        z->options.needutf8 = 0;
283
        z->options.nameextd = z->IName.BadDOS();
284
        z->options.cmntextd = z->com && z->Comment.BadDOS();
285
        z->options.namenew = 0;
286
 
287
        DZStrW iiname = StrIntSep(z->IName);
288
        bool wantOEM = true;
289
        int bad = 0;
290
        if (!z->options.nameextd && !z->options.cmntextd)
291
        {
292
                // mimic WinZip
293
                z->Enc = zeoOEM;
294
        }
295
        else
296
        {
297
        unsigned doenc = fEncodeAs;
298
        if (doenc == zeoAuto)
299
        {
300
                        doenc = zeoUPATH;
301
                        if (z->options.nameextd && z->options.cmntextd)
302
                                doenc = zeoUTF8; // recommended
303
        }
304
 
305
                z->Enc = doenc;
306
                if (doenc == zeoUPATH)
307
                {
308
                        z->HName = iiname.SafeNarrow(CP_OEM); // default oem name
309
                        z->options.dosflag = 2;                 // FAT
310
                        wantOEM = false;
311
                }
312
                else
313
                if (doenc == zeoUTF8)
314
                {
315
                        z->HName = StrToUTF8(iiname);
316
                        z->options.nameutf8 = 1;   // so we set the flag
317
                        z->options.dosflag = 2;  // assume header strings usable on MSDOS
318
                        wantOEM = false;
319
                }
320
                else
321
                if (doenc == zeoNone)
322
                {
323
                        z->HName = iiname.SafeNarrow(CP_ACP, bad);
324
                        z->options.nameutf8 = 0;   // so we set the flag
325
                        bool ntfs = z->HName.BadDOS();
326
                        if (!ntfs && z->options.cmntextd)
327
                        {
328
                                DZStrA tmp = z->Comment.SafeNarrow(CP_ACP);
329
                                ntfs = tmp.BadDOS();
330
                        }
331
                        z->options.dosflag = ntfs ? 0 : 1;  // assume header strings usable on NTFS
332
                        wantOEM = false;
333
                }
334
        }
335
        if (wantOEM)
336
        {
337
                z->HName = iiname.SafeNarrow(CP_OEM, bad); // default oem name
338
                z->options.dosflag = 2;                 // FAT
339
        }
340
        if (bad)
341
        {
342
                z->options.namenew = 1; // name was made safe
343
                unsigned cp = wantOEM ? CP_OEM : CP_ACP;
344
                DZStrW xname(cp, z->hname, z->HName.length());
345
                if (Verbose < 0)
346
                        Notify(IVERBOSE, _T("%s made safe as %hs"),     iiname.c_str(), xname.c_str());
347
        }
348
#ifdef ZDEBUG
349
        if (Verbose < 0)
350
        {
351
                Notify(ITRACE, _T("Prepare %s need %x dos %X"), z->iname, z->ver,
352
                           z->options.dosflag);
353
        }
354
#endif
355
 
356
    return 0;
357
}
358
 
359
// Add, update, freshen, or delete zip entries in a zip file. argc; /*
360
//   Number of tokens in command line. argv; /* Command line tokens.
361
int ZipFunc::ZipProcess(void)
362
{
363
    int a;                // attributes of zip file
364
    ZInt64 censtt;        // start of central directory
365
 
366
    FndItem *f;           // steps through "found" linked list
367
    FndItem *tempf;
368
    int k;                // next argument type, marked counter, comment size, entry count
369
    int marks;            // replaces k as marked counter
370
        int r;                // temporary variable
371
        int err;                          // temporary error variable
372
    ulg t;                // file time, length of central directory
373
 
374
        ZipItem *v;           // temporary variable
375
    ZipItem *z;           // steps through "zfiles" linked list
376
    const TCHAR *Actions[4] = {_T("PURGE"), _T("ADD"), _T("UPDATE"), _T("FRESHEN")};
377
 
378
    int DestType;         //  destination drive type
379
    unsigned long TotFiles = 0;
380
    __int64 TotSize = 0;
381
        unsigned long KeptCnt = 0;  // number of 'kept' files
382
        __int64 KeptSize = 0;       // size of 'kept' files
383
    __int64 VerSize = 0;        // size of 'kept' files
384
        __int64 fsz;                // file size;
385
    int No_File;                // 1.75 try if file does not exist
386
    // Process arguments
387
    diag(_T("processing lists"));
388
 
389
        if (Verbose)
390
        {
391
                Notify(IVERBOSE, _T("action = %s"), Actions[faction]);
392
 
393
        // zcount is no. of entries in linked-list
394
        // zfiles is name of the linked-list of filenames for the archive
395
        Notify(IVERBOSE, _T("zcount=%d (no. of files in ZIP already)"), fzcount);
396
    }
397
 
398
    if (!fzipbeg)
399
        fjunk_sfx = 0;   // nothing to junk
400
 
401
    if (!fzfiles)
402
        fadjust = 0;     // nothing to adjust
403
 
404
 
405
    if ((r = check_dupExt()) != DZ_ERR_GOOD)   // remove duplicates in ffound
406
        return DZError(r);
407
 
408
    // Check option combinations
409
    // ?????
410
    if (faction == PURGE && (fdispose || frecurse || fkey))
411
                return DZError(DZ_ERM_BAD_OPTIONS);
412
 
413
    // AllowGrow is the "allow append" indicator
414
    if (!fzcount && ((faction == ADD) || (faction == UPDATE)))
415
        fAllowGrow = 55; // create new file normally
416
 
417
    // if zcount is 0, then zipfile doesn't exist, or is empty
418
    if (fzcount == 0 && ((faction != ADD && faction != UPDATE)
419
                         || !fAllowGrow))
420
    {
421
        // RCV150199 added UPDATE
422
        Notify(IWARNING, _T("%s: not found or empty"), fzipfile.c_str());
423
        return 0;
424
    }
425
 
426
    if (fndlist)
427
    {
428
        delete fndlist;
429
        fndlist = NULL;
430
    }
431
 
432
    DestType = DriveType(fzipfile);
433
 
434
    if (Verbose < 0)
435
        Notify(IVERBOSE, _T("Destination type = %d"), DestType);
436
 
437
    // RP - check destination type - if CD set tempath to Windows Temp
438
    if (ftempath.IsEmpty() && (DestType != DRIVE_FIXED &&
439
                               DestType != DRIVE_RAMDISK))
440
    {
441
        GetTempPath(2047, ftempath.GetBuffer(2047));
442
        ftempath.ReleaseBuffer();
443
    }
444
 
445
    // If -b not specified, set temporary path to zipfile path
446
    int pp;
447
 
448
    if (ftempath.IsEmpty() && ((pp = fzipfile.ReverseFind(BSLASH)) >= 0
449
                               || (pp = fzipfile.ReverseFind(_T(':'))) >= 0))
450
    {
451
        if (fzipfile[pp] == _T(':'))
452
            pp++;
453
 
454
        ftempath = fzipfile.Left(pp);
455
    }
456
 
457
    // if first_listarg is 0, then we didn't got any fspecs on cmd line
458
    if (fdoall && (faction == UPDATE || faction == FRESHEN))
459
    {
460
        // if -update or -freshen with no args, do all, but, when present, apply
461
        //   filters
462
        for (z = fzfiles; z != NULL; z = z->nxt)
463
            z->mark = fpcount ? !ZMatch(fExcludes, z->IName) : 1;
464
    }
465
 
466
    // NOTE: "k" is being redefined below this point. Now, it going to
467
    // track the no. of marked files in the "zfiles" linked list.
468
    // For each marked entry in "zfiles" linked list, if not deleting, check
469
    //   if a corresponding "external" file exists. If updating or freshening,
470
    //   compare date of "external" file with entry in orig zipfile. Unmark if it
471
    //   external file doesn't exist or is too old, else mark it. Entries that
472
    //   are marked will cause that file to be rezipped.
473
    diag(_T("checking marked entries"));
474
    marks = 0; // Initialize marked count
475
    ZipItem **zlast;          // pointer to last link in "zfiles" list
476
    ZipItem **verlast = &VerFiles;   // pointer to last link
477
        ZipItem **fndlast = &fzfound;
478
        int vercount = 0;
479
                for (z = fzfiles; z != NULL; z = z->nxt)
480
                {
481
                        if (z->mark)
482
                        {
483
                                ulg FileAttr;
484
                                if (faction != PURGE)
485
                                {
486
                    t = zfiletime(z->FullPath(), &FileAttr, &fsz, NULL);
487
 
488
                    if ((t == 0 || t < fbefore
489
                            || ((faction == UPDATE || faction == FRESHEN) &&
490
                                t <= z->tim)
491
                            || (fArchiveFiles && faction == FRESHEN &&
492
                                !(FileAttr &A_ARCHIVE)))
493
                       )
494
                    {
495
                        z->mark = MARK_KEEP;      // keep
496
                        z->trash = (t && t >= fbefore);
497
                        // delete if -um or -fm
498
 
499
                        if (Verbose)
500
                        {
501
                            const TCHAR *expl;
502
 
503
                            if (t)
504
                                expl = z->trash ?  _T("up to date") : _T("early");
505
                            else
506
                                expl = _T("missing");
507
 
508
                                                        Notify(0, _T("%s is %s"), z->xname, expl);
509
                        }
510
                    }
511
                    else
512
                    {
513
                                                // replace
514
                        TotSize += fsz;
515
                        TotFiles++;
516
                        marks++;
517
                        z->mark = MARK_UPDATE;    // marker for replace
518
 
519
                        if (z->options.keepver)
520
                        {
521
                                                        ZipItem* vz = new ZipItem(*z);
522
                                                        *(verlast) = vz;
523
                                                        verlast = &vz->nxt;
524
                                                        vz->nxt = NULL;
525
                                                        vz->Passw = fkey;
526
                                                        vz->Base = CurBase->Base;
527
                            vercount++;
528
                        }
529
                    }
530
                }
531
                else
532
                {
533
                    // PURGE
534
                    marks++;    // incr. number of marked entries
535
                                        z->mark = MARK_PURGE;  // marker for Purge
536
                                }
537
            }
538
                }
539
    // RP - verify file specified to 'Purge'
540
    if (faction == PURGE && !marks)
541
        return DZError(DZ_ERM_NOTHING_TO_DO);
542
 
543
    // Remove entries from "found" linked list if: Action is PURGE or FRESHEN
544
    //   or No "external" matching file is found, or if found, but is too old or
545
    //   The external file is equal to the ziparchive name while ziparchive name
546
    //   != "-" If filetime() returns any valid time, then at least we know the
547
    //   file was found.
548
    diag(_T("checking new entries"));
549
        FndItem *prev = NULL;
550
        // fileio.c built the found list
551
        for (f = ffound; f != NULL;)
552
        {
553
                if (faction == PURGE || faction == FRESHEN
554
                                || (t = zfiletime(f->xname, NULL, NULL, NULL)) == 0
555
                                || t < fbefore
556
                                || (ZMatch(f->FullPath(), fzipfile)))
557
                {
558
                        if (Verbose && t < fbefore)
559
                                Notify(IVERBOSE, _T("rejecting %s as too early"), f->xname);
560
 
561
                        if (Verbose < 0)
562
                                Notify(ITRACE, _T("expel being called for %s"), f->xname);
563
                        tempf = f;
564
                        f = f->nxt;
565
                        if (prev)
566
                                prev->nxt = f;
567
                        else
568
                                ffound = f;     // new first
569
                        delete tempf;
570
                        ffcount--;
571
                }
572
                else                 // file found, and not too old.
573
                {
574
                        prev = f;
575
                        f = f->nxt;         // save this one, link it up.
576
                }
577
        }
578
    if (Verbose)
579
    {
580
        if (ffound == NULL)
581
            Notify(IVERBOSE, _T("found list empty - a"));
582
        else
583
            Notify(IVERBOSE, _T("found list has at least one entry - a"));
584
    }
585
    // 'fix' safe and header names
586
        IntList = new HashListInt(ffcount + fzcount + vercount);
587
        // add 'keep' files - no duplicate allowed but should not happen
588
        ZipItem  *prv = NULL;
589
        for (z = fzfiles; z != NULL; /* z = z->nxt */)
590
        {
591
                FndItem  *e;
592
                if (z->mark >= MARK_KEEP)
593
                {
594
                        // add internal name to list - check for duplicate
595
                        if ((e = (FndItem*) IntList->AddNode(z)) != 0)
596
                        {
597
                                DupName(Skipping(z->XName, DZ_ERM_DUPNAME, SKIPPED_DUP_NAME),
598
                                                e, z, z->IName);
599
                                // delete later duplicate
600
                                ZipItem  *x = z->nxt;
601
                                if (prv)
602
                                        prv->nxt = x;
603
                                else
604
                                        fzfiles = x;
605
                                delete z;
606
                                z = x;
607
                                fzcount--;
608
                                continue;
609
                        }
610
                }
611
                prv = z;
612
                z = z->nxt;
613
    }
614
 
615
        // now new files - no duplicates
616
    while ((f = ffound) != NULL)
617
        {
618
                ZipItem **prvlast = fndlast;            // save
619
                ZipItem *prvlastnxt = *(fndlast);   // save
620
        ZipItem *zi = new ZipItem(f);       // copy as ZipItem
621
                *(fndlast) = zi;
622
        fndlast = &zi->nxt;
623
                zi->mark = MARK_NEW;
624
        ffound = f->nxt;
625
        delete f;
626
 
627
                // set comment and header name
628
                if ((r = PrepareHeaderName(zi, false)) != 0)
629
                        return r;
630
                FndItem  *e;
631
                if ((e = (FndItem*) IntList->AddNode(zi)) != 0)
632
                {
633
                        DupName(Skipping(zi->XName, 0, SKIPPED_DUP_NAME),
634
                                        e, f, f->IName);
635
                        // delete later duplicate
636
                        fndlast = prvlast;              // restore
637
                        *(fndlast) = prvlastnxt;        // restore
638
                        delete zi;
639
                        ffcount--;
640
        }
641
        }
642
        // now rename versions to unique internal names
643
        if (vercount)
644
        {
645
                fAllowGrow = 0; // append not allowed
646
        }
647
        //
648
        if (fadjust <= 0)
649
        fadjust = 0;
650
 
651
    // Make sure there's something left to do
652
    if (marks == 0 && fzfound == NULL && !(fzfiles != NULL && (flatest ||
653
                                          fadjust || fjunk_sfx)))
654
    {
655
        // FOUND WAS NULL HERE, so just figure out which error message to show
656
        if (faction == UPDATE || faction == FRESHEN)
657
        {
658
            finish();
659
            Notify(IWARNING, _T("no files %s"), (faction == UPDATE) ? _T("updated")
660
                   : _T("freshened"));
661
            return 0;
662
        }
663
        else
664
        {
665
            if (fzfiles == NULL && (flatest || fadjust || fjunk_sfx))
666
                return DZError(DZ_ERM_EMPTY_ZIP);
667
            return DZError(DZ_ERM_NOTHING_TO_DO);
668
        }
669
    }
670
 
671
    // AllowGrow is false if writing temporary file
672
    fAllowGrow = (fAllowGrow && (marks == 0)
673
                  // is allowed and no changes to existing
674
                  && (fzipbeg || fzfiles != NULL) // something to append to
675
                 );
676
 
677
    // continue on to add new files
678
    a = 0;
679
 
680
    // ignore self-extracting code in front of the zip file (for -J)
681
    if (fjunk_sfx)
682
        fzipbeg = 0;
683
 
684
    // Calc size of version files
685
    for (z = VerFiles; z; z = z->nxt)
686
    {
687
        if (Abort_Flag)
688
                        Fatal(DZ_ERM_ABORT, 0);
689
 
690
        VerSize += (z->siz + (ulg)(4 + LOCHEAD) + (ulg)z->nam + (ulg)z->ext);
691
 
692
        if (z->lflg &8)
693
            VerSize += 16;
694
    }
695
 
696
    // Count files and sizes which we have to Keep; RP Added
697
    zlast = &fzfiles;
698
    while ((z =  *zlast) != NULL)
699
    {
700
        if (Abort_Flag)
701
                        Fatal(DZ_ERM_ABORT, 0);
702
 
703
        if (!z->mark)
704
        {
705
            KeptSize += (z->siz + (ulg)(4 + LOCHEAD) + (ulg)z->nam + (ulg)z->ext);
706
 
707
            if (z->lflg &8)
708
                KeptSize += 16;
709
 
710
            KeptCnt++;
711
        }
712
 
713
        zlast = &z->nxt;
714
    }
715
 
716
    //Inform(pG, 0, IDIAG, "Kept = %u %Lu Total = %Lu %Lu", KeptCnt, KeptSize, TotFiles, TotSize);
717
    // Count files and sizes which we have to process; RCV Added
718
    // First the files in the old zip file...
719
    // RP - already calculated with new sizes
720
    // And the found list...
721
    z = fzfound;
722
    while (z)
723
    {
724
                if (Abort_Flag)
725
            Fatal(DZ_ERM_ABORT, 0);
726
 
727
        TotSize += z->len;
728
        TotFiles++;
729
        z = z->nxt;
730
        }
731
 
732
    fhInz = INVALID_HANDLE_VALUE;
733
    fOutPosn = 0;
734
 
735
    if (!fAllowGrow)
736
    {
737
        // check file exists
738
        No_File = _taccess(fzipfile, 0) && errno == ENOENT;
739
 
740
        if (No_File && DestType == DRIVE_FIXED || DestType == DRIVE_RAMDISK)
741
        {
742
            // create file using given name
743
                        diag(_T("Processing - ready to create new file"));
744
            fZipOutfile = new ZFile(this, fzipfile, GENERIC_WRITE, 0, NULL,
745
                                    CREATE_NEW, FILE_ATTRIBUTE_NORMAL);
746
 
747
            if (fZipOutfile->IsOpen())
748
            {
749
                ftempzip = fzipfile;
750
                fAllowGrow =  -1; // new files do grow
751
            }
752
            else
753
                if (Verbose < 0)
754
                    Notify(DZ_ERM_ERROR_CREATE, _T("CreateFile failed %s [%s]"),
755
                           fzipfile.c_str(), SysMsg().c_str());
756
        }
757
    }
758
 
759
    if (fAllowGrow > 0)
760
    {
761
        // zipfile is not stdout, and we are allowed to append
762
        // AllowGrow is true if we're just appending (-g)
763
                diag(_T("Processing - ready to open for appending"));
764
        fZipOutfile = new ZFile(this, fzipfile, GENERIC_READ | GENERIC_WRITE, 0,
765
                                NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL);
766
 
767
        if (!fZipOutfile->IsOpen())
768
        {
769
            if (Verbose < 0)
770
                Notify(DZ_ERM_ERROR_CREATE, _T("CreateFile failed 2 %s [%s]"),
771
                       fzipfile.c_str(), SysMsg().c_str());
772
 
773
            return DZError(DZ_ERM_ERROR_CREATE);
774
        }
775
 
776
        ftempzip = fzipfile;
777
 
778
        if (fZipOutfile->SetPosition(fcenbeg, FILE_BEGIN) == -1)
779
            return DZError(GetLastError() ? DZ_ERM_ERROR_SEEK : DZ_ERM_ZIP_EOF);
780
 
781
        fOutPosn = fcenbeg;
782
    }
783
 
784
    if (!fAllowGrow)
785
    {
786
        diag(_T("Processing - ready to open for Exclusive Read"));
787
 
788
        if ((fzfiles != NULL || fzipbeg) &&
789
            (fhInz = CreateFile(fzipfile, GENERIC_READ, 0, NULL, OPEN_EXISTING,
790
                FILE_ATTRIBUTE_NORMAL |  FILE_FLAG_SEQUENTIAL_SCAN, NULL)) ==
791
                    INVALID_HANDLE_VALUE)
792
        {
793
            if (Verbose < 0)
794
                Notify(DZ_ERM_ERROR_CREATE, _T("CreateFile failed 3 %s [%s]"),
795
                       fzipfile.c_str(), SysMsg().c_str());
796
 
797
            return DZError(DZ_ERM_ERROR_CREATE);
798
        }
799
 
800
        ftempzip = tempname();
801
 
802
        if (Verbose)
803
            Notify(IVERBOSE, _T("Temp Filename = %s"), ftempzip.c_str());
804
 
805
        fZipOutfile = new ZFile(this, ftempzip, GENERIC_WRITE, 0,
806
                                NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL);
807
 
808
        if (!fZipOutfile->IsOpen())
809
        {
810
            if (Verbose < 0)
811
                Notify(DZ_ERR_ERROR_CREATE | ITRACE, _T("CreateFile failed 3 %s [%s]"),
812
                       ftempzip.c_str(), SysMsg().c_str());
813
 
814
            return DZError(DZ_ERM_TEMP_FAILED);
815
        }
816
    }
817
 
818
    if (!fAllowGrow)
819
    {
820
        TotFiles += KeptCnt + vercount;
821
        TotSize += KeptSize + VerSize;
822
    }
823
 
824
    // Pass total number of files and Total Filesize.
825
    CB->Arg1 = TotFiles;
826
    CB->UserCB(zacCount);
827
 
828
    CB->FileSize = TotSize;
829
    CB->UserCB(zacSize);
830
 
831
    fBatchStarted = 1;
832
 
833
    if (!fAllowGrow && fzipbeg)
834
    {
835
        if (Verbose)
836
            Notify(IVERBOSE, _T("Copying SFX stub [%X]"), fzipbeg);
837
 
838
        // copy a compressed file from old archive to new archive
839
        CB->FileSize = fzipbeg;
840
        CB->Msg = _T("SFX");
841
        CB->UserCB(zacItem);
842
 
843
        if ((r = fcopy(fzipbeg)) != DZ_ERR_GOOD)
844
            return DZError(r);
845
 
846
        fOutPosn = fzipbeg;
847
    }
848
 
849
    // Process zip file, copying from old archive to new archive. Rezip any
850
    //   marked files
851
    if (fzfiles != NULL)
852
        diag(_T("going through old zip file"));
853
 
854
    zlast = &fzfiles;
855
    while ((z =  *zlast) != NULL)
856
    {
857
        if (Abort_Flag)
858
                        Fatal(DZ_ERM_ABORT, 0);
859
 
860
        if (z->mark == MARK_UPDATE)
861
        {
862
            // This file is marked
863
                        // if not deleting, rezip it
864
                        Notify(0, _T("updating: %s"), z->iname);
865
                        ZipItem zr = *z;        // make copy
866
                        // update comment and name (if required)
867
                        if ((r = PrepareHeaderName(z, false)) != 0)
868
                                return r;
869
                        r = zipup(z);
870
                        int dze = DZ_ERR(r);
871
                        if (dze == DZ_ERR_NO_FILE_OPEN || dze == DZ_ERR_MISS || //)
872
                                dze == DZ_ERR_ERROR_READ || dze ==DZ_ERR_SKIPPED)
873
                        {
874
                                _TCHAR *msg;
875
 
876
                                *z = zr; // restore and try to keep
877
                                if (dze == DZ_ERR_NO_FILE_OPEN)
878
                                        msg = _T("could not open for reading: %s");
879
                                else if (dze == DZ_ERR_MISS)
880
                                        msg = _T("file and directory with the same name: %s");
881
                                else
882
                                        msg = _T("skipped: %s");
883
                                Notify(IWARNING, msg, z->xname);
884
                                CB->UserMsg(r, z->xname);
885
                                dze = 0;        // handled that error
886
                                Notify(IWARNING, _T("will just use old version: %s"), z->iname);
887
                if ((r = zipcopy(z)) != DZ_ERR_GOOD)
888
                {
889
                                        Notify(IERROR, _T("was copying %s"), z->iname);
890
                                        dze = -1;       // has error in r
891
                                }
892
                                else
893
                                        z->mark = 0;
894
                        }
895
                        if (dze != DZ_ERR_GOOD)
896
                                return DZError(r);
897
 
898
            zlast = &z->nxt;
899
                        ffiles_acted_on++;
900
                }
901
        else
902
        if (z->mark == MARK_PURGE)
903
        {
904
            // desired action is DELETE, this file marked
905
            Notify(0, _T("deleting: %s"), z->iname);
906
 
907
            v = z->nxt; // delete entry from list
908
            delete z;
909
            *zlast = v;           // link prev to next
910
            fzcount--;
911
            ffiles_acted_on++;
912
        }
913
        else   // mark != 1
914
        {
915
            // this file wasn't marked
916
            // copy the original entry verbatim
917
            if (!fAllowGrow)
918
            {
919
                Notify(0, _T("keeping: %s"), z->iname);
920
 
921
                if ((r = zipcopy(z)) != DZ_ERR_GOOD)
922
                {
923
                    Notify(IERROR, _T("was copying %s"), z->iname);
924
                    return DZError(r);
925
                }
926
            }
927
 
928
            zlast = &z->nxt;
929
        }
930
    } // end while
931
 
932
    // Process the 'Version' files
933
    if (vercount)
934
    {
935
        if (Verbose < 0)
936
            Notify(ITRACE, _T("Copying %d version entries"), vercount);
937
 
938
        while ((z = VerFiles) != NULL)
939
        {
940
            if (Abort_Flag)
941
                                Fatal(DZ_ERM_ABORT, 0);
942
 
943
            if (Verbose)
944
                Notify(0, _T("Versioning: %s"), z->iname);
945
 
946
            VerFiles = VerFiles->nxt;
947
            z->nxt = NULL;
948
 
949
            *zlast = z;     // link to prev->nxt (allow cleanup)
950
                        // make new internal and header names
951
                        if ((r = NameVer(z)) != 0)
952
                                return r;
953
 
954
            if ((r = zipVersion(z)) != DZ_ERR_GOOD)
955
            {
956
                Notify(IERROR, _T("was copying %s"), z->iname);
957
                return DZError(r);
958
            }
959
 
960
            // "zipup" of this file was good
961
            *zlast = z;
962
            zlast = &z->nxt;
963
            fzcount++;
964
            ffiles_acted_on++;
965
        }
966
    }
967
 
968
    // Process the "found" list, adding them to the zip file.
969
    // This is used to add files that weren't already in the archive.
970
    if (Verbose)
971
        Notify(IVERBOSE, _T("Zipping up %d NEW entries from found list"), ffcount);
972
 
973
    // For each new file to add (src names in found list), make a new entry
974
    //   for it in the "zfiles" linked list, zip up the new file, then remove the
975
    //   entry from the found list.
976
    // The last item in the for loop control deallocates spc for fname that
977
        //   was just zipped up
978
 
979
    while ((z = fzfound) != NULL)
980
    {
981
        // add a new entry to "zfiles" list, before we zip up the file. That way
982
        //   we'll be ready to update the ZIP file's directory later.
983
        if (Abort_Flag)
984
                        Fatal(DZ_ERM_ABORT, 0);
985
 
986
        fzfound = z->nxt;
987
        ffcount--;
988
        *zlast = z;     // link to prev->nxt (allow cleanup)
989
        z->nxt = NULL;
990
        z->mark = MARK_NEW;
991
 
992
                // zip it up
993
                if (z->options.namenew)
994
                        Notify(0, _T("  adding: %s as %hs"), z->iname, z->hname);
995
                else
996
                        Notify(0, _T("  adding: %s"), z->iname);
997
 
998
                // This is it - try to zip up new file
999
                r = zipup(z);
1000
                if (r == DZ_ERR_GOOD)
1001
                {
1002
                        // "zipup" of this file was good
1003
                        *zlast = z;
1004
                        zlast = &z->nxt;
1005
                        fzcount++;
1006
                        ffiles_acted_on++;
1007
                        continue;
1008
                }
1009
                err = DZ_ERR(r);
1010
                if (err != DZ_ERR_NO_FILE_OPEN && err != DZ_ERR_MISS &&//)
1011
                                err != DZ_ERR_ERROR_READ && err != DZ_ERR_SKIPPED)
1012
                        return DZError(r);
1013
//              if ((r = zipup(z)) != DZ_ERR_GOOD
1014
//                              && DZ_ERR(r) != DZ_ERR_NO_FILE_OPEN && DZ_ERR(r) != DZ_ERR_MISS)
1015
//                      return DZError(r);
1016
 
1017
//              if (DZ_ERR(r) == DZ_ERR_NO_FILE_OPEN || DZ_ERR(r) == DZ_ERR_MISS)
1018
//              if (err == DZ_ERR_NO_FILE_OPEN || err == DZ_ERR_MISS ||
1019
//                              err == DZ_ERR_ERROR_READ || err ==DZ_ERR_SKIPPED)
1020
//              if (r != DZ_ERR_GOOD)
1021
//              {
1022
//            if (DZ_ERR(r) == DZ_ERR_NO_FILE_OPEN)
1023
                        if (err == DZ_ERR_NO_FILE_OPEN)
1024
                                Notify(r | IWARNING, _T("could not open for reading: %s"), z->xname);
1025
                        else
1026
//                              Notify(IWARNING, _T("file and directory with the same name: %s"), z->xname);
1027
                        {
1028
                                _TCHAR *msg;
1029
                                if (err == DZ_ERR_MISS)
1030
                                        msg = _T("file and directory with the same name: %s");
1031
                                else
1032
                                        msg = _T("skipped: %s");
1033
                                Notify(IWARNING, msg, z->xname);
1034
                        }
1035
            *zlast = NULL;  // remove from list
1036
            delete z;
1037
//        }
1038
//              else
1039
//              {
1040
//                      // "zipup" of this file was good
1041
//                      *zlast = z;
1042
//                      zlast = &z->nxt;
1043
//                      fzcount++;
1044
//                      ffiles_acted_on++;
1045
//        }
1046
    }
1047
 
1048
    // Write central directory and end header to temporary zip
1049
    diag(_T("writing central directory"));
1050
 
1051
    // get start of central directory
1052
//    Assert(fOutPosn == SetFilePointer64(fhOutz, 0, 2), _T("invalid out posn dlz 983"));
1053
 
1054
    censtt = fOutPosn;
1055
    k = 0; // keep count of new fnames for ZIPfile's end header
1056
    __int64 usiz = 0;
1057
    __int64 csiz = 0;
1058
    CB->Arg1 = 7;    // type
1059
    CB->FileSize = fzcount;
1060
 
1061
    CB->Msg = _T("*writing central directory");
1062
    CB->UserCB(zacXItem);
1063
 
1064
    for (z = fzfiles; z != NULL; z = z->nxt)
1065
    {
1066
        if ((r = putcentral(z)) != DZ_ERR_GOOD)
1067
            return DZError(r);
1068
 
1069
        usiz += z->len;
1070
        csiz += z->siz;
1071
        k++;
1072
 
1073
        CB->UserXProgress(1, 7);
1074
    }
1075
 
1076
    if (k == 0)
1077
        Notify(IWARNING, _T("zip file empty"));
1078
 
1079
    if ((Verbose) && (faction == ADD) && (!fglobal_error_code)
1080
            && (ffiles_acted_on > 0))
1081
    {
1082
        Notify(IVERBOSE, _T("Total Bytes=%Lu, compr bytes=%Lu -> %d%% savings"), usiz, csiz,
1083
               percent(usiz, csiz));
1084
    }
1085
 
1086
    diag(_T("writing end of central directory"));
1087
//    Assert(fOutPosn == SetFilePointer64(fhOutz, 0, 1), _T("invalid out posn dlz 1055"));
1088
 
1089
    if (k && ((r = PutEnd(k, censtt)) != DZ_ERR_GOOD))
1090
        return DZError(r);
1091
 
1092
    Close_Handle(&fhInz);
1093
 
1094
    delete fZipOutfile;
1095
    fZipOutfile = NULL;
1096
 
1097
    // Replace old zip file with new zip file, leaving only the new one
1098
    if (!fAllowGrow && (k || faction != PURGE))
1099
    {
1100
        diag(_T("replacing old zip file with new zip file"));
1101
 
1102
        if ((r = replace(fzipfile, ftempzip)) != DZ_ERR_GOOD)
1103
        {
1104
            Notify(IWARNING, _T("new zip file left as: %s"), ftempzip.c_str());
1105
            return DZError(r);
1106
        }
1107
    }
1108
 
1109
    // 1.78.1.2
1110
    if (!k && faction == PURGE)
1111
        // empty file - remove
1112
    {
1113
        a = flatest = 0;
1114
        DeleteFile(fzipfile);
1115
 
1116
        if (!fAllowGrow)
1117
            DeleteFile(ftempzip);
1118
    }
1119
    if (a)
1120
        setfileattr(fzipfile, a);
1121
 
1122
    // Reset the archive bit when needed for all successfull zipped files
1123
    if (fResetArchiveBit && faction != PURGE)
1124
    {
1125
        unsigned cnt = 0; // 1.71.0.0 added extra callbacks
1126
        diag(_T("resetting archive bits"));
1127
 
1128
        for (z = fzfiles; z != NULL; z = z->nxt)
1129
            if (z->mark)
1130
                cnt++;
1131
 
1132
        if (cnt)
1133
        {
1134
            // new file op.
1135
            // Pass total number of files. filesize.
1136
            CB->Arg1 = 1;    // type
1137
            CB->FileSize = cnt;
1138
            CB->Msg = _T("*resetting archive bits");
1139
            CB->UserCB(zacXItem);
1140
        }
1141
 
1142
        cnt = 0;
1143
 
1144
        for (z = fzfiles; z != NULL; z = z->nxt)
1145
        {
1146
            if (z->mark)
1147
            {
1148
                if (++cnt == 30)
1149
                {
1150
                    CB->UserXProgress(cnt, 1);
1151
                    cnt = 0;
1152
                    if (Abort_Flag)
1153
                        break;
1154
                }
1155
 
1156
                DZStrW fullname = z->FullPath();
1157
 
1158
                if (!SetFileAttributes(fullname, GetFileAttributes(fullname)
1159
                                       &~FILE_ATTRIBUTE_ARCHIVE))
1160
                    Notify(IWARNING, _T("Archive bit could not be set for: %s [%s]"),
1161
                         fullname.c_str(), SysMsg().c_str());
1162
            }
1163
        }
1164
 
1165
        if (cnt)
1166
            CB->UserXProgress(cnt, 1);
1167
    }
1168
    finish();
1169
 
1170
    return 0;
1171
}
1172
 
1173
 
1174
 
1175
 
1176