Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libpz/pzsplit.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1998-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
22
/*
23
* pzip split partition support
24
*/
25
26
#include "pzlib.h"
27
28
#include <cdt.h>
29
30
struct Deflate_s;
31
struct Inflate_s;
32
struct Id_s;
33
34
typedef struct Id_s
35
{
36
Dtlink_t byid;
37
Dtlink_t byseq;
38
int seq;
39
int use;
40
Pzpart_t* part;
41
Sfio_t* sp;
42
unsigned long id;
43
int row;
44
size_t size;
45
size_t count;
46
char* bp;
47
char* name;
48
unsigned long used;
49
unsigned long windows;
50
Sfulong_t modules;
51
Sfulong_t total;
52
} Id_t;
53
54
typedef struct Deflate_s
55
{
56
Sfio_t* xp;
57
Dt_t* ids;
58
Pz_t* pz;
59
unsigned int seq;
60
Dt_t* sqs;
61
} Deflate_t;
62
63
typedef struct Inflate_s
64
{
65
Dt_t* ids;
66
Pz_t* pz;
67
} Inflate_t;
68
69
#undef state
70
71
static struct
72
{
73
Sfio_t* buf;
74
char* comment;
75
unsigned long flags;
76
Sfio_t* opt;
77
Sfio_t* tmp;
78
int total;
79
int verbose;
80
size_t window;
81
Sfulong_t windows;
82
Sfulong_t records;
83
Sfulong_t modules;
84
} state;
85
86
#if _ast_intswap
87
88
/*
89
* order by signed int
90
*/
91
92
static int
93
byint(Dt_t* dt, void*a, void* b, Dtdisc_t* disc)
94
{
95
return *(int*)a - *(int*)b;
96
}
97
98
/*
99
* order by unsigned long
100
*/
101
102
static int
103
byulong(Dt_t* dt, void*a, void* b, Dtdisc_t* disc)
104
{
105
if (*(unsigned long*)a < *(unsigned long*)b)
106
return -1;
107
if (*(unsigned long*)a > *(unsigned long*)b)
108
return 1;
109
return 0;
110
}
111
112
#endif
113
114
/*
115
* free Id_t
116
*/
117
118
static void
119
freeid(Dt_t* dt, Void_t* ip, Dtdisc_t* disc)
120
{
121
if (((Id_t*)ip)->sp)
122
sfclose(((Id_t*)ip)->sp);
123
free(ip);
124
}
125
126
/*
127
* flush the current partition window
128
* this function determines the file layout
129
*/
130
131
static int
132
flush(Deflate_t* dp, size_t w, Sfio_t* op)
133
{
134
register Id_t* ip;
135
register size_t n;
136
Sfio_t* io;
137
char* file;
138
int i;
139
int line;
140
141
static size_t use;
142
143
if (!use && (!(dp->pz->test & 04) || !(file = getenv("_AST_pzip_debug_use")) || !(use = strton(file, NiL, NiL, 1))))
144
use = 8 * 1024;
145
dp->pz->count.windows++;
146
if ((dp->pz->flags & (PZ_DUMP|PZ_VERBOSE)) && dp->pz->disc->errorf)
147
(*dp->pz->disc->errorf)(dp->pz, dp->pz->disc, 0, "window %I*u %I*u", sizeof(dp->pz->count.windows), dp->pz->count.windows, sizeof(w), w);
148
149
/*
150
* write the actual window size
151
*/
152
153
sfputu(op, w);
154
155
/*
156
* count the number of active partitions for this window
157
*/
158
159
i = 0;
160
for (ip = (Id_t*)dtfirst(dp->ids); ip; ip = (Id_t*)dtnext(dp->ids, ip))
161
if (n = sfstrtell(ip->sp))
162
{
163
i++;
164
ip->windows++;
165
if (n >= use && (!ip->row || (n / ip->row) > 16))
166
{
167
if (!ip->used++ && !ip->part && !streq(ip->name, "0") && dp->pz->disc->errorf && (dp->pz->flags & (PZ_SUMMARY|PZ_VERBOSE|PZ_DUMP)))
168
(*dp->pz->disc->errorf)(dp->pz, dp->pz->disc, 1, "%s: generate a partition to improve compression", ip->name);
169
if (ip->use = !(dp->pz->flags & PZ_NOPZIP) && ip->part)
170
ip->part->flags |= PZ_UPDATE;
171
}
172
else
173
ip->use = 0;
174
}
175
else if (ip->part)
176
ip->part->flags &= ~PZ_UPDATE;
177
178
/*
179
* write any PZ_UPDATE partition headers
180
*/
181
182
if (pzpartwrite(dp->pz, op))
183
return -1;
184
185
/*
186
* write the number of partitions for this window
187
* followed by the table entry for each partition
188
*/
189
190
sfputu(op, i);
191
for (ip = (Id_t*)dtfirst(dp->sqs); ip; ip = (Id_t*)dtnext(dp->sqs, ip))
192
if (n = sfstrtell(ip->sp))
193
{
194
sfputu(op, ip->row);
195
sfputu(op, ip->use);
196
sfputu(op, n);
197
sfputr(op, ip->name, 0);
198
if ((dp->pz->flags & PZ_DUMP) && dp->pz->disc->errorf)
199
(*dp->pz->disc->errorf)(dp->pz, dp->pz->disc, 0, "%8d %12s %2d %4d %4I*u %12I*u%s", ip->seq, ip->name, !!ip->part, ip->use, sizeof(ip->row), ip->row, sizeof(n), n, ip->windows == 1 ? " NEW" : "");
200
}
201
if (sferror(op))
202
{
203
if (dp->pz->disc->errorf)
204
(*dp->pz->disc->errorf)(dp->pz, dp->pz->disc, ERROR_SYSTEM|2, "partition table write error");
205
return -1;
206
}
207
208
/*
209
* write the data for each pzip partition
210
*/
211
212
file = error_info.file;
213
line = error_info.line;
214
io = dp->pz->io;
215
for (ip = (Id_t*)dtfirst(dp->sqs); ip; ip = (Id_t*)dtnext(dp->sqs, ip))
216
if (ip->use && (n = sfstrtell(ip->sp)))
217
{
218
error_info.file = ip->name;
219
error_info.line = n;
220
sfstrseek(ip->sp, 0, SEEK_SET);
221
if (!pzpartset(dp->pz, ip->part))
222
goto bad;
223
sfstrbuf(state.buf, sfstrbase(ip->sp), n, 0);
224
dp->pz->io = state.buf;
225
if (pzdeflate(dp->pz, op))
226
goto bad;
227
ip->seq = 0;
228
}
229
230
/*
231
* write the data for the remaining partitions
232
*/
233
234
for (ip = (Id_t*)dtfirst(dp->sqs); ip; ip = (Id_t*)dtnext(dp->sqs, ip))
235
if (n = sfstrtell(ip->sp))
236
{
237
sfstrseek(ip->sp, 0, SEEK_SET);
238
if (sfwrite(op, sfstrbase(ip->sp), n) != n || sferror(op))
239
{
240
error_info.file = ip->name;
241
error_info.line = n;
242
if (dp->pz->disc->errorf)
243
(*dp->pz->disc->errorf)(dp->pz, dp->pz->disc, ERROR_SYSTEM|2, "partition data write error");
244
goto bad;
245
}
246
ip->seq = 0;
247
}
248
error_info.file = file;
249
error_info.line = line;
250
dp->pz->io = io;
251
252
/*
253
* end the record sequence number list and write it
254
*/
255
256
sfputu(dp->xp, 0);
257
n = sfstrtell(dp->xp);
258
sfstrseek(dp->xp, 0, SEEK_SET);
259
if (sfwrite(op, sfstrbase(dp->xp), n) != n)
260
{
261
if (dp->pz->disc->errorf)
262
(*dp->pz->disc->errorf)(dp->pz, dp->pz->disc, ERROR_SYSTEM|2, "record sequence write error");
263
return -1;
264
}
265
266
/*
267
* done with this window
268
*/
269
270
if (sferror(op))
271
{
272
if (dp->pz->disc->errorf)
273
(*dp->pz->disc->errorf)(dp->pz, dp->pz->disc, ERROR_SYSTEM|2, "write error");
274
return -1;
275
}
276
dtclear(dp->sqs);
277
dp->seq = 0;
278
return 0;
279
bad:
280
error_info.file = file;
281
error_info.line = line;
282
dp->pz->io = io;
283
return -1;
284
}
285
286
/*
287
* deflate
288
*/
289
290
static int
291
deflate(Pz_t* pz, Sfio_t* op)
292
{
293
Pzsplit_t* rp;
294
size_t m;
295
size_t z;
296
Dtdisc_t iddisc;
297
Dtdisc_t sqdisc;
298
char* file;
299
char* s;
300
int line;
301
int i;
302
Id_t* ip;
303
Pzindex_f indexf;
304
Sfoff_t o;
305
Deflate_t def;
306
Pzindex_t index;
307
Sfulong_t extra;
308
char num[16];
309
310
file = error_info.file;
311
line = error_info.line;
312
memset(&iddisc, 0, sizeof(iddisc));
313
iddisc.key = offsetof(Id_t, id);
314
iddisc.link = offsetof(Id_t, byid);
315
iddisc.size = sizeof(unsigned long);
316
#if _ast_intswap
317
iddisc.comparf = byulong;
318
#endif
319
iddisc.freef = freeid;
320
memset(&sqdisc, 0, sizeof(sqdisc));
321
sqdisc.key = offsetof(Id_t, seq);
322
sqdisc.link = offsetof(Id_t, byseq);
323
sqdisc.size = sizeof(int);
324
#if _ast_intswap
325
sqdisc.comparf = byint;
326
#endif
327
memset(&def, 0, sizeof(def));
328
def.pz = pz;
329
if (!(state.buf = sfstropen()) || !(def.xp = sfstropen()))
330
goto nospace;
331
if (!(def.ids = dtopen(&iddisc, Dtoset)) || !(def.sqs = dtopen(&sqdisc, Dtoset)))
332
goto nospace;
333
def.seq = 0;
334
335
/*
336
* write the pzip header
337
*/
338
339
if (pzheadwrite(def.pz, op))
340
goto bad;
341
if (sferror(op))
342
{
343
if (pz->disc->errorf)
344
(*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "magic write error");
345
goto bad;
346
}
347
348
/*
349
* loop on the records and deflate a window at a time
350
*/
351
352
if (indexf = pz->disc->indexf)
353
sfraise(op, SFGZ_GETPOS, &index.block);
354
else
355
index.block = 0;
356
index.offset = extra = 0;
357
m = pz->win - 8;
358
error_info.file = (char*)pz->path;
359
error_info.line = 0;
360
while (rp = (*pz->disc->splitf)(pz, pz->io, pz->disc))
361
{
362
if (rp->record)
363
{
364
z = rp->record;
365
error_info.line++;
366
pz->count.records++;
367
}
368
else
369
z = rp->size;
370
if (!rp->size)
371
continue;
372
if ((index.offset + z) > m)
373
{
374
if (flush(&def, index.offset, op))
375
goto bad;
376
if (indexf)
377
sfraise(op, SFGZ_GETPOS, &index.block);
378
pz->count.uncompressed += index.offset - extra;
379
index.offset = extra = 0;
380
}
381
if (rp->record && indexf && (*indexf)(pz, &index, rp->data, pz->disc) < 0)
382
goto bad;
383
index.offset += rp->size;
384
if (!(ip = (Id_t*)dtmatch(def.ids, &rp->id)))
385
{
386
if (pz->disc->namef)
387
s = (*pz->disc->namef)(pz, rp->id, pz->disc);
388
else
389
sfsprintf(s = num, sizeof(num), "%lu", rp->id);
390
if (!(ip = newof(0, Id_t, 1, strlen(s) + 1)))
391
goto nospace;
392
if (ip->id = rp->id)
393
ip->row = rp->size;
394
ip->name = strcpy((char*)(ip + 1), s);
395
if (!(ip->sp = sfstropen()))
396
{
397
if (pz->disc->errorf)
398
(*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "%s: cannot create tmp stream", ip->name);
399
goto bad;
400
}
401
if ((ip->part = pzpartget(def.pz, ip->name)) && pz->disc->errorf && ip->row && ip->part->row != ip->row)
402
(*pz->disc->errorf)(pz, pz->disc, 1, "%s: partition row %I*u != data row %I*u", ip->name, sizeof(ip->part->row), ip->part->row, sizeof(ip->row), ip->row);
403
dtinsert(def.ids, ip);
404
}
405
else if (!ip->id)
406
ip->total += rp->size;
407
else if (pz->disc->errorf && ip->row != rp->size && (ip->row % rp->size))
408
(*pz->disc->errorf)(pz, pz->disc, 1, "%s: size %I*u not a multiple of %I*u", ip->name, sizeof(rp->size), rp->size, sizeof(ip->row), ip->row);
409
if (!ip->seq)
410
{
411
ip->seq = ++def.seq;
412
dtinsert(def.sqs, ip);
413
}
414
sfputu(def.xp, ip->seq);
415
if (!ip->id)
416
{
417
o = sfstrtell(ip->sp);
418
sfputu(ip->sp, rp->size);
419
o = sfstrtell(ip->sp) - o;
420
index.offset += o;
421
extra += o;
422
}
423
if (sfwrite(ip->sp, rp->data, rp->size) != rp->size)
424
{
425
if (pz->disc->errorf)
426
(*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "%s: %I*u byte write error", ip->name, sizeof(rp->size), rp->size);
427
goto bad;
428
}
429
ip->modules++;
430
pz->count.modules++;
431
}
432
if (index.offset)
433
{
434
if (flush(&def, index.offset, op))
435
goto bad;
436
pz->count.uncompressed += index.offset - extra;
437
}
438
439
/*
440
* done with all the data
441
* a 0 actual window size marks the end of data
442
*/
443
444
sfputu(op, 0);
445
if (sferror(op))
446
{
447
if (pz->disc->errorf)
448
(*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "write error");
449
goto bad;
450
}
451
if ((pz->flags & PZ_DUMP) && pz->disc->errorf)
452
{
453
(*pz->disc->errorf)(pz, pz->disc, 0, "totals");
454
for (ip = (Id_t*)dtfirst(def.ids); ip; ip = (Id_t*)dtnext(def.ids, ip))
455
(*pz->disc->errorf)(pz, pz->disc, 0, "%8I*u %12s %2u %4I*u %4I*u %12I*u %12I*u%s", sizeof(ip->windows), ip->windows, ip->name, !!ip->part, sizeof(ip->used), ip->used, sizeof(ip->row), ip->row, sizeof(ip->total), ip->total ? ip->total : ip->modules * ip->row, sizeof(ip->modules), ip->modules, ip->used && !ip->part ? " GENERATE PARTITION" : "");
456
}
457
i = 0;
458
goto done;
459
nospace:
460
pznospace(pz);
461
bad:
462
i = -1;
463
done:
464
if (state.buf)
465
sfclose(state.buf);
466
if (def.xp)
467
sfclose(def.xp);
468
if (def.ids)
469
dtclose(def.ids);
470
if (def.sqs)
471
dtclose(def.sqs);
472
error_info.file = file;
473
error_info.line = line;
474
return i;
475
}
476
477
/*
478
* inflate
479
*/
480
481
static int
482
inflate(Pz_t* pz, Sfio_t* op)
483
{
484
register char* s;
485
register Id_t* ip;
486
register size_t m;
487
register size_t n;
488
register size_t u;
489
register unsigned char* p;
490
size_t w;
491
size_t i;
492
size_t parts;
493
char* id;
494
int row;
495
int use;
496
Dt_t* ids;
497
Dtdisc_t iddisc;
498
499
register Id_t** tab = 0;
500
size_t tabsiz = 0;
501
char* win = 0;
502
503
memset(&iddisc, 0, sizeof(iddisc));
504
iddisc.key = offsetof(Id_t, name);
505
iddisc.link = offsetof(Id_t, byid);
506
iddisc.size = -1;
507
iddisc.freef = freeid;
508
if (!(ids = dtopen(&iddisc, Dtoset)))
509
goto nospace;
510
if (!(state.buf = sfstropen()))
511
goto nospace;
512
if (!(win = newof(0, char, pz->win, 0)))
513
goto nospace;
514
515
/*
516
* loop on all windows
517
* w is the actual window size
518
* w <= pz->win guaranteed
519
*/
520
521
while ((w = sfgetu(pz->io)) && w <= pz->win)
522
{
523
if ((pz->flags & (PZ_DUMP|PZ_VERBOSE)) && pz->disc->errorf)
524
(*pz->disc->errorf)(pz, pz->disc, 0, "window %I*u", sizeof(w), w);
525
526
/*
527
* read the partition headers
528
*/
529
530
if (pzpartread(pz))
531
goto bad;
532
533
/*
534
* read the number of partitions
535
*/
536
537
parts = sfgetu(pz->io);
538
if (parts > tabsiz)
539
{
540
n = roundof(parts, 64);
541
if (!(tab = newof(tab, Id_t*, n, 0)))
542
goto nospace;
543
tabsiz = n;
544
}
545
546
/*
547
* read the partition table
548
*/
549
550
u = 0;
551
s = win;
552
for (i = 0; i < parts; i++)
553
{
554
row = sfgetu(pz->io);
555
use = sfgetu(pz->io);
556
m = sfgetu(pz->io);
557
id = sfgetr(pz->io, 0, 0);
558
if (!(ip = (Id_t*)dtmatch(ids, id)))
559
{
560
if (!(ip = newof(0, Id_t, 1, sfvalue(pz->io))))
561
goto nospace;
562
ip->name = strcpy((char*)(ip + 1), id);
563
ip->row = row;
564
if ((ip->part = pzpartget(pz, ip->name)) && pz->disc->errorf && ip->row && ip->part->row != ip->row)
565
(*pz->disc->errorf)(pz, pz->disc, 1, "%s: partition row %I*u != data row %I*u", ip->name, sizeof(ip->part->row), ip->part->row, sizeof(ip->row), ip->row);
566
dtinsert(ids, ip);
567
}
568
ip->use = use;
569
ip->used++;
570
tab[i] = ip;
571
if (m >= pz->win || ip->row && m % ip->row)
572
{
573
if (pz->disc->errorf)
574
(*pz->disc->errorf)(pz, pz->disc, 2, "input corrupted [%s partition table size %I*u]", ip->name, sizeof(m), m);
575
goto bad;
576
}
577
ip->size = m;
578
if (ip->use)
579
{
580
ip->bp = s;
581
s += m;
582
}
583
else
584
u += m;
585
if ((pz->flags & PZ_DUMP) && pz->disc->errorf)
586
(*pz->disc->errorf)(pz, pz->disc, 0, "%8d %12s %2d %4I*u %4I*u %12I*u%s", i + 1, ip->name, ip->use, sizeof(ip->used), ip->used, sizeof(ip->row), ip->row, sizeof(ip->size), ip->size, ip->used == 1 ? " NEW" : "");
587
}
588
589
/*
590
* read the pzip partition data
591
*/
592
593
for (i = 0; i < parts; i++)
594
if (tab[i]->use)
595
{
596
sfstrbuf(state.buf, tab[i]->bp, tab[i]->size, 0);
597
if (!pzpartset(pz, tab[i]->part))
598
goto bad;
599
if (pzinflate(pz, state.buf))
600
goto bad;
601
}
602
603
/*
604
* read the remaining partition data
605
* and set up the table buffer pointers
606
*/
607
608
if (sfread(pz->io, s, u) != u)
609
{
610
if (pz->disc->errorf)
611
(*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "cannot read %I*u byte partition data buffer", sizeof(u), u);
612
goto bad;
613
}
614
for (i = 0; i < parts; i++)
615
if (!tab[i]->use)
616
{
617
tab[i]->bp = s;
618
s += tab[i]->size;
619
}
620
621
/*
622
* read the record table indices and reconstruct the records
623
*/
624
625
while (m = sfgetu(pz->io))
626
{
627
if (m > parts)
628
{
629
if (pz->disc->errorf)
630
(*pz->disc->errorf)(pz, pz->disc, 2, "input corrupted [partition record index %I*u > %I*u]", sizeof(m), m, sizeof(parts), parts);
631
goto bad;
632
}
633
ip = tab[m - 1];
634
p = (unsigned char*)ip->bp;
635
if (!(n = ip->row) && ((n = *p++) & SF_MORE))
636
{
637
n &= (SF_MORE - 1);
638
while ((i = *p++) & SF_MORE)
639
n = (n << SF_UBITS) | (i & (SF_MORE - 1));
640
n = (n << SF_UBITS) | i;
641
}
642
#if 0
643
if (s = (char*)sfreserve(op, n, 0)) /* NOTE: investigate how reserve can fail but write work */
644
memcpy(s, p, n);
645
else
646
#endif
647
if (sfwrite(op, p, n) != n)
648
{
649
if (pz->disc->errorf)
650
(*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "%I*u byte write error", sizeof(n), n);
651
goto bad;
652
}
653
ip->bp = (char*)p + n;
654
}
655
}
656
if (w || sfgetc(pz->io) != EOF)
657
{
658
if (pz->disc->errorf)
659
(*pz->disc->errorf)(pz, pz->disc, 2, "%s: input corrupted [EOF expected at %I*u]", pz->path, sftell(pz->io));
660
goto bad;
661
}
662
if (sferror(op))
663
{
664
if (pz->disc->errorf)
665
(*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "write error");
666
goto bad;
667
}
668
i = 0;
669
goto done;
670
nospace:
671
pznospace(pz);
672
bad:
673
i = -1;
674
done:
675
if (state.buf)
676
sfclose(state.buf);
677
if (ids)
678
dtclose(ids);
679
if (tab)
680
free(tab);
681
if (win)
682
free(win);
683
return i;
684
}
685
686
int
687
pzsdeflate(Pz_t* pz, Sfio_t* op)
688
{
689
int r;
690
691
pz->split.flags |= PZ_SPLIT_PART;
692
r = deflate(pz, op);
693
pz->split.flags &= ~PZ_SPLIT_PART;
694
return r;
695
}
696
697
int
698
pzsinflate(Pz_t* pz, Sfio_t* op)
699
{
700
int r;
701
702
pz->split.flags |= PZ_SPLIT_PART;
703
r = inflate(pz, op);
704
pz->split.flags &= ~PZ_SPLIT_PART;
705
return r;
706
}
707
708
int
709
pzssplit(Pz_t* pz)
710
{
711
Pzsplit_t* rp;
712
Dtdisc_t iddisc;
713
char* file;
714
char* s;
715
int line;
716
int i;
717
size_t window;
718
Id_t* ip;
719
Dt_t* ids;
720
char num[16];
721
722
if (!pz->disc->splitf)
723
{
724
if (pz->disc->errorf)
725
(*pz->disc->errorf)(pz, pz->disc, 2, "%s: split discipline library expected", pz->path);
726
return -1;
727
}
728
window = pz->disc->window ? pz->disc->window : PZ_WINDOW;
729
file = error_info.file;
730
line = error_info.line;
731
memset(&iddisc, 0, sizeof(iddisc));
732
iddisc.key = offsetof(Id_t, id);
733
iddisc.link = offsetof(Id_t, byid);
734
iddisc.size = sizeof(unsigned long);
735
#if _ast_intswap
736
iddisc.comparf = byulong;
737
#endif
738
iddisc.freef = freeid;
739
if (!(ids = dtopen(&iddisc, Dtoset)))
740
goto nospace;
741
742
/*
743
* loop on the records and split by id
744
*/
745
746
error_info.file = (char*)pz->path;
747
error_info.line = 0;
748
while (rp = (*pz->disc->splitf)(pz, pz->io, pz->disc))
749
{
750
if (rp->record)
751
{
752
error_info.line++;
753
pz->count.records++;
754
}
755
if (!(ip = (Id_t*)dtmatch(ids, &rp->id)))
756
{
757
if (pz->disc->namef)
758
s = (*pz->disc->namef)(pz, rp->id, pz->disc);
759
else
760
sfsprintf(s = num, sizeof(num), "%lu", rp->id);
761
if (!(ip = newof(0, Id_t, 1, strlen(s) + 1)))
762
goto nospace;
763
if (ip->id = rp->id)
764
ip->row = rp->size;
765
ip->name = strcpy((char*)(ip + 1), s);
766
if (!pz->split.match || strmatch(ip->name, pz->split.match))
767
{
768
if (!(ip->sp = sfopen(NiL, ip->name, (pz->flags & PZ_APPEND) ? "a" : "w")))
769
{
770
if (pz->disc->errorf)
771
(*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "%s: cannot create split stream", ip->name);
772
goto bad;
773
}
774
ip->count = sfsize(ip->sp);
775
}
776
dtinsert(ids, ip);
777
if ((pz->flags & PZ_DUMP) && pz->disc->errorf)
778
(*pz->disc->errorf)(pz, pz->disc, 0, "split %s size %I*u", ip->name, sizeof(ip->row), ip->row);
779
}
780
else if (!ip->id)
781
ip->total += rp->size;
782
else if (pz->disc->errorf && ip->row != rp->size && rp->size && (ip->row % rp->size))
783
(*pz->disc->errorf)(pz, pz->disc, 1, "%s: size %I*u not a multiple of %I*u", ip->name, sizeof(rp->size), rp->size, sizeof(ip->row), ip->row);
784
if (ip->sp)
785
{
786
if (ip->count < window)
787
{
788
if (sfwrite(ip->sp, rp->data, rp->size) != rp->size)
789
{
790
if (pz->disc->errorf)
791
(*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "%s: %I*u byte write error", ip->name, sizeof(rp->size), rp->size);
792
goto bad;
793
}
794
ip->count += rp->size;
795
}
796
ip->modules++;
797
pz->count.modules++;
798
}
799
}
800
if ((pz->flags & PZ_DUMP) && pz->disc->errorf)
801
{
802
(*pz->disc->errorf)(pz, pz->disc, 0, "totals");
803
for (ip = (Id_t*)dtfirst(ids); ip; ip = (Id_t*)dtnext(ids, ip))
804
if (ip->sp)
805
(*pz->disc->errorf)(pz, pz->disc, 0, "%8I*u %12s %2u %4I*u %4I*u %12I*u %12I*u%s", sizeof(ip->windows), ip->windows, ip->name, !!ip->part, sizeof(ip->used), ip->used, sizeof(ip->row), ip->row, sizeof(ip->total), ip->total ? ip->total : ip->modules * ip->row, sizeof(ip->modules), ip->modules, ip->used && !ip->part ? " GENERATE PARTITION" : "");
806
}
807
for (ip = (Id_t*)dtfirst(ids); ip; ip = (Id_t*)dtnext(ids, ip))
808
if (ip->sp && sfclose(ip->sp))
809
{
810
if (pz->disc->errorf)
811
(*pz->disc->errorf)(pz, pz->disc, ERROR_SYSTEM|2, "%s: write error", ip->name);
812
goto bad;
813
}
814
i = 0;
815
goto done;
816
nospace:
817
pznospace(pz);
818
bad:
819
i = -1;
820
done:
821
if (ids)
822
dtclose(ids);
823
error_info.file = file;
824
error_info.line = line;
825
return i;
826
}
827
828