Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/vczip/vczip.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 2003-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
* Phong Vo <[email protected]> *
18
* Glenn Fowler <[email protected]> *
19
* *
20
***********************************************************************/
21
/* Command to encode and decode with Vcodex methods.
22
**
23
** Written by Kiem-Phong Vo (09/06/2003 - ILNGUYEN)
24
*/
25
26
#if _PACKAGE_ast
27
28
#define UNZIP ((char*)0)
29
#define DISABLED ((char*)disabled)
30
#define DFLTZIP "delta,huffgroup"
31
#define ALIASES "lib/vcodex/aliases"
32
#define VCZIPRC ".vcziprc"
33
#define VCZIP "vczip"
34
35
static const char usage[] =
36
"[-?\n@(#)$Id: vczip (AT&T Research) 2009-10-01 $\n]"
37
USAGE_LICENSE
38
"[+NAME?vczip - vcodex method encode/decode filter]"
39
"[+DESCRIPTION?\bvczip\b is a filter that decodes the standard input "
40
"and/or encodes the standard output. The \b--method\b option specifies "
41
"the encoding. The default encoding is \b--method=" DFLTZIP "\b. The "
42
"method is automatically determined when decoding.]"
43
"[+?For delta methods the \asource\a operand optionally specifies the "
44
"file to delta against. If \asource\a is omitted then the input file is "
45
"simply compressed. Delta-encoded data must be decoded with the same "
46
"\asource\a.]"
47
"[+?Method aliases may be defined in \b../" ALIASES "\b in one of the "
48
"directories on \b$PATH\b, or in \b$HOME/" VCZIPRC "\b, searched in "
49
"order. Each alias is a \aname=value\a pair where \avalue\a is a "
50
"\b--method\b option value, described below. Method names are searched "
51
"before alias names.]"
52
"[i:input?Input data is read from \afile\a instead of the standard "
53
"input.]:[file]"
54
"[m:method|encode?Set the transformation method from the \b,\b (or \b^\b) "
55
"separated list of \amethod\a[.\aarg\a]] elements, where \amethod\a is "
56
"a method alias or primitive method, \aarg\a is an optional method "
57
"specific argument, and \b-\b denotes the default argument. Parenthesized "
58
"values are implementation details. The \alibvcodex\a (\b-catalog\b) "
59
"denotes a method supplied by the default library. Otherwise the method "
60
"is a separate plugin; that plugin will be required to decode any "
61
"encoded data. The primitive methods and method aliases "
62
"are:]:[method[.arg]][,method[.arg]]...]]:=" DFLTZIP "]"
63
"{\fvcodex\f[vcdiff|ietf?Encode as defined in IETF RFC3284.]}"
64
"[o:output?Output data is written to \afile\a instead of the standard "
65
"output.]:[file]"
66
"[p:plain?Do not encode transformation information in the data. This means "
67
"the transform must be explicitly supplied to decode.]"
68
"[q:identify?Identify the standard input encoding and write the "
69
"\b--method\b transformation string on the standard output. "
70
"If the standard input is not vczip encoded then nothing is "
71
"printed.]"
72
"[t:transform?Apply the \bcodex\b(3) data transform around the "
73
"\bvcodex\b(3) transform. A codex transform is a catenation of the "
74
"following methods, each method prefixed by \b<\b to decode the input or "
75
"\b>\b to encode the output. Method arguments, if any, must be prefixed "
76
"by \b-\b. The method are:]:[[<>]]method[-arg...]]...]"
77
"{\fcodex\f}"
78
"[u:undo|decode?Decode data.]"
79
"[v:verbose?List the compresses size on the standard error.]"
80
"[w:window?Set the data partition window size to \awindow\a. "
81
"\amethod\a specifies an optional window matching "
82
"method. The window methods are:]:[window[,method]]]"
83
"{\fwindows\f}"
84
"[d:vcdiff|ietf?Encode as defined in IETF RFC3284. Obsolete -- use "
85
"--method=ietf.]"
86
"[D:debug?Set the debug trace level to \alevel\a. Higher levels produce "
87
"more output.]:[level]"
88
"[M:move?Use sfmove() for io.]"
89
"[P:pause?Debug: print the pid and sleep(10); then continue processing.]"
90
91
"\n"
92
"\n[ source ] < input > output\n"
93
"\n"
94
95
"[+FILES]"
96
"{"
97
"[+../" ALIASES "?\b--method\b \aname=value\a alias file, found "
98
"on \b$PATH\b.]"
99
"}"
100
"[+SEE ALSO?\bcodex\b(1), \bcodex\b(3), \bvcodex\b(3)]"
101
;
102
103
#include <ast.h>
104
#include <error.h>
105
#include <ccode.h>
106
#include <ctype.h>
107
#include <vcodex.h>
108
#include <codex.h>
109
110
static const char disabled[] = "disabled";
111
112
static int
113
optmethod(Void_t* obj, char* name, char* desc, Void_t* handle)
114
{
115
Sfio_t* sp = (Sfio_t*)handle;
116
Vcmethod_t* mt = (Vcmethod_t*)obj;
117
int i;
118
119
sfprintf(sp, "[+%s?", name);
120
optesc(sp, desc, 0);
121
if(mt->args)
122
{ sfprintf(sp, " The arguments are:]{");
123
for(i = 0; mt->args[i].desc; i++)
124
{ sfprintf(sp, "[+%s?", mt->args[i].name ? mt->args[i].name : "-");
125
if(mt->args[i].desc)
126
optesc(sp, mt->args[i].desc, 0);
127
sfputc(sp, ']');
128
if(!mt->args[i].name)
129
break;
130
}
131
}
132
else
133
sfputc(sp, ']');
134
if(mt->about)
135
{ if(!mt->args)
136
sfputc(sp, '{');
137
sfprintf(sp, "%s}", mt->about);
138
}
139
else if(mt->args)
140
sfputc(sp, '}');
141
return 0;
142
}
143
144
static int
145
optalias(Void_t* obj, char* name, char* desc, Void_t* handle)
146
{
147
Sfio_t* sp = (Sfio_t*)handle;
148
149
sfprintf(sp, "[+%s?Equivalent to \b%s\b.]", name, desc);
150
return 0;
151
}
152
153
static int
154
optwindow(Void_t* obj, char* name, char* desc, Void_t* handle)
155
{
156
Sfio_t* sp = (Sfio_t*)handle;
157
158
sfprintf(sp, "[+%s?", name);
159
optesc(sp, desc, 0);
160
sfprintf(sp, "]");
161
return 0;
162
}
163
164
/*
165
* optget() info discipline function
166
*/
167
168
static int
169
optinfo(Opt_t* op, Sfio_t* sp, const char* s, Optdisc_t* dp)
170
{
171
register Codexmeth_t* meth;
172
register const char* p;
173
register int c;
174
175
switch (*s)
176
{
177
case 'c':
178
/* codex methods */
179
for (meth = codexlist(NiL); meth; meth = codexlist(meth))
180
{
181
sfprintf(sp, "[+%s\b", meth->name);
182
p = " (";
183
if (meth->identf)
184
{
185
sfprintf(sp, "%sident", p);
186
p = ",";
187
}
188
if (!(meth->flags & CODEX_ENCODE))
189
{
190
sfprintf(sp, "%sdecode", p);
191
p = ",";
192
}
193
if (*p == ',')
194
sfputc(sp, ')');
195
sfputc(sp, '?');
196
p = meth->description;
197
while (c = *p++)
198
{
199
if (c == ']')
200
sfputc(sp, c);
201
sfputc(sp, c);
202
}
203
sfputc(sp, ']');
204
if ((p = meth->options) || meth->optionsf)
205
{
206
sfprintf(sp, "{\n");
207
if (meth->optionsf)
208
(*meth->optionsf)(meth, sp);
209
if (p)
210
sfprintf(sp, "%s", p);
211
sfprintf(sp, "\n}");
212
}
213
}
214
break;
215
case 'v':
216
/* vcodex methods */
217
vcwalkmeth(optmethod, sp);
218
/* aliases */
219
vcwalkalias(optalias, sp);
220
break;
221
case 'w':
222
/* vcodex window methods */
223
vcwwalkmeth(optwindow, sp);
224
break;
225
}
226
return 0;
227
}
228
229
static void
230
vcsferror(const char* mesg)
231
{
232
error(2, "%s", mesg);
233
}
234
235
/*
236
* apply the codex and/or vcodex transforms to a single input/output pair
237
*/
238
239
static void
240
apply(int action, const char* vt, Vcsfdata_t* vcodexdisc, const char* ct, Codexdisc_t* codexdisc, const char* input, const char* source, const char* output, void* buf, size_t bufsize, Sfoff_t donez, Sfoff_t lastz)
241
{
242
Sfio_t* ip;
243
Sfio_t* op;
244
ssize_t n;
245
246
/*
247
* set up the sfio input stream
248
*/
249
250
if (!input || !*input || streq(input, "-") || streq(input, "/dev/stdin") || streq(input, "/dev/fd/0"))
251
{
252
input = "/dev/stdin";
253
ip = sfstdin;
254
sfset(ip, SF_SHARE, 0);
255
sfopen(ip, NiL, "rb");
256
}
257
else if (!(ip = sfopen(NiL, input, "rb")))
258
{
259
error(ERROR_SYSTEM|2, "%s: cannot read", input);
260
return;
261
}
262
263
/*
264
* set up the sfio output stream
265
*/
266
267
if (!action)
268
{
269
sfprintf(sfstdout, "%s: ", input);
270
output = "/dev/null";
271
codexdisc->identify = sfstdout;
272
}
273
if (!output || !*output || streq(output, "-") || streq(output, "/dev/stdout") || streq(output, "/dev/fd/1"))
274
{
275
output = "/dev/stdout";
276
op = sfstdout;
277
sfset(op, SF_SHARE, 0);
278
sfopen(op, NiL, "wb");
279
}
280
else if (!(op = sfopen(NiL, output, "wb")))
281
{
282
error(ERROR_SYSTEM|2, "%s: cannot write", output);
283
if (ip != sfstdin)
284
sfclose(ip);
285
return;
286
}
287
288
/*
289
* check codex sfio discipline
290
*/
291
292
error(-1, "AHA action=%s input=%s source=%s output=%s vt=%s ct=%s", action == VC_ENCODE ? "encode" : "decode", input, source, output, vt, ct);
293
if (ct != DISABLED)
294
{
295
if ((n = codex(ip, op, ct, action == VC_ENCODE ? CODEX_ENCODE : CODEX_DECODE, codexdisc, NiL)) < 0)
296
error(3, "%s: cannot push codex io stream discipline", input);
297
if (!action && n > 0)
298
sfprintf(sfstdout, ",");
299
}
300
301
/*
302
* check vcodex sfio discipline
303
*/
304
305
if (vt != DISABLED)
306
{
307
vcodexdisc->trans = (char*)vt;
308
vcodexdisc->source = (char*)source;
309
if (!vcsfio(action == VC_ENCODE ? op : ip, vcodexdisc, action))
310
error(3, "%s: cannot push vcodex io stream discipline", input);
311
else if (!action)
312
sfprintf(sfstdout, "%s", vcodexdisc->trans);
313
}
314
315
/*
316
* copy from ip to op
317
*/
318
319
if (action)
320
{
321
if (buf)
322
for (;;)
323
{
324
if ((n = sfread(ip, buf, bufsize)) <= 0)
325
{
326
if (n < 0)
327
error(ERROR_SYSTEM|2, "%s: read error", input);
328
break;
329
}
330
if (donez >= 0) /* verbose mode */
331
{
332
if (donez >= lastz + 64 * (bufsize > 1024*1024 ? bufsize : 1024*1024))
333
{
334
sfprintf(sfstderr, "done %10I*d %s\n", sizeof(donez), donez, output);
335
lastz = donez;
336
}
337
donez += n;
338
}
339
if ((n = sfwrite(op, buf, n)) < 0)
340
{
341
error(ERROR_SYSTEM|2, "%s: write error", output);
342
break;
343
}
344
}
345
else
346
{
347
sfmove(ip, op, SF_UNBOUND, -1);
348
if (!sfeof(ip))
349
error(ERROR_SYSTEM|2, "%s: read error", input);
350
else if (sfsync(op) || sferror(op))
351
error(ERROR_SYSTEM|2, "%s: write error", output);
352
}
353
}
354
else
355
sfprintf(sfstdout, "\n");
356
if (ip != sfstdin)
357
sfclose(ip);
358
if (op != sfstdout)
359
sfclose(op);
360
}
361
362
int
363
main(int argc, char** argv)
364
{
365
Vcchar_t *buf;
366
size_t bufsize;
367
int action; /* default is encoding */
368
int move = 0; /* sfmove() */
369
int vczip; /* are we vczip? */
370
int c;
371
char* vt; /* vcodex transform */
372
char* ct; /* codex transform */
373
Sfio_t* cs; /* codex transform buf */
374
Sfoff_t donez = -1, lastz = -1; /* amount processed */
375
Optdisc_t optdisc; /* optget() dscipline */
376
char name[256]; /* method name buffer */
377
378
/* NOTE: disciplines may be accessed after main() returns */
379
380
static Vcsfdata_t vcodexdisc; /* vcodex discipline */
381
static Codexdisc_t codexdisc; /* codex discipline */
382
383
error_info.id = (ct = strrchr(argv[0], '/')) ? (ct + 1) : argv[0];
384
if (!(cs = sfstropen()))
385
error(ERROR_SYSTEM|3, "out of space");
386
action = VC_ENCODE;
387
ct = error_info.id;
388
vt = name;
389
while (vt < &name[sizeof(name)-1] && (c = tolower(*ct++)))
390
if (c == 'u' && tolower(*ct) == 'n')
391
{ action = VC_DECODE;
392
ct++;
393
}
394
else
395
*vt++ = c;
396
*vt = 0;
397
vczip = streq(name, VCZIP);
398
if (!vczip && codexmeth(name))
399
{
400
vt = DISABLED;
401
sfprintf(cs, "%c%s", action == VC_DECODE ? '<' : '>', name);
402
}
403
else if (action == VC_DECODE)
404
vt = UNZIP;
405
else
406
vt = DFLTZIP;
407
memset(&vcodexdisc, 0, sizeof(vcodexdisc));
408
vcodexdisc.errorf = vcsferror;
409
codexinit(&codexdisc, errorf);
410
optinit(&optdisc, optinfo);
411
for (;;)
412
{
413
switch (optget(argv, usage))
414
{
415
case 'd':
416
vcodexdisc.type = VCSF_VCDIFF;
417
continue;
418
case 'i':
419
if (sfopen(sfstdin, opt_info.arg, "r") != sfstdin)
420
error(ERROR_SYSTEM|3, "%s: cannot read", opt_info.arg);
421
continue;
422
case 'm':
423
if (streq(opt_info.arg, "ietf") || streq(opt_info.arg, "vcdiff"))
424
vcodexdisc.type = VCSF_VCDIFF;
425
else if (streq(opt_info.arg, "-"))
426
vt = DISABLED;
427
else
428
vt = opt_info.arg;
429
continue;
430
case 'o':
431
if (sfopen(sfstdout, opt_info.arg, "w") != sfstdout)
432
error(ERROR_SYSTEM|3, "%s: cannot write", opt_info.arg);
433
continue;
434
case 'p':
435
vcodexdisc.type = VCSF_PLAIN;
436
continue;
437
case 'q':
438
action = 0;
439
continue;
440
case 't':
441
if (*opt_info.arg != '<' && *opt_info.arg != '>')
442
sfprintf(cs, "%c", action == VC_DECODE ? '<' : '>');
443
sfprintf(cs, "%s", opt_info.arg);
444
continue;
445
case 'u':
446
action = VC_DECODE;
447
if (vt)
448
vt = UNZIP;
449
continue;
450
case 'v':
451
donez = lastz = 0;
452
continue;
453
case 'w':
454
vcodexdisc.window = opt_info.arg;
455
continue;
456
case 'D':
457
error_info.trace = -(int)opt_info.num;
458
continue;
459
case 'M':
460
move = 1;
461
continue;
462
case 'P':
463
error(1, "pid %d", getpid());
464
sleep(10);
465
continue;
466
case ':':
467
error(2, "%s", opt_info.arg);
468
continue;
469
case '?':
470
error(ERROR_USAGE|4, "%s", opt_info.arg);
471
continue;
472
}
473
break;
474
}
475
argv += opt_info.index;
476
if (error_info.errors || argv[0] && argv[1])
477
error(ERROR_USAGE|4, "%s", optusage(NiL));
478
buf = 0;
479
if (!move)
480
for (bufsize = 1024*1024; bufsize > 0; bufsize /= 2)
481
if (buf = malloc(bufsize))
482
break;
483
if (!(ct = sfstruse(cs)))
484
error(ERROR_SYSTEM|3, "out of space");
485
if (streq(ct+1, "-"))
486
ct = DISABLED;
487
else if (!*(ct+1))
488
ct = UNZIP;
489
apply(action, vt, &vcodexdisc, ct, &codexdisc, NiL, *argv, NiL, buf, bufsize, donez, lastz);
490
return error_info.errors != 0;
491
}
492
493
#else
494
495
#include "vchdr.h"
496
497
#define PR_METHOD ((Void_t*)1)
498
#define PR_ALIAS ((Void_t*)2)
499
500
#define DFLTZIP "sieve.delta,bwt,mtf,rle.0,huffgroup"
501
502
static char *Mesg[] =
503
{
504
"vczip [-Arguments] [SourceFile] < Input > Output\n",
505
506
"\nBelow are the standard 'Arguments':\n",
507
"-?: This prints this message.\n",
508
"-i[InputFile]: This redefines the standard 'Input' to be 'InputFile'.\n",
509
"-o[OutputFile]: This redefines the standard 'Output' to be 'OutputFile'.\n",
510
"-w[size[.alg]]: This argument is ignored during decoding (i.e., -u).\n",
511
" On encoding, it defines the window processing for a large input file.\n",
512
" 'size' is the window size, i.e., the size to break the input file into\n",
513
" chunks for processing. Units 'k' and 'm' mean kilo and megabytes.\n",
514
" 'alg' selects a windowing matching algorithm for delta compression:\n",
515
" p: matching windows by a prefix matching method (default) or\n",
516
" m: matching windows by simply mirroring file positions.\n",
517
"-E[type]: This translates between EBCDIC and ASCII during encoding or\n",
518
" decoding via the given 'type'. See also the 'map' transform below.\n",
519
"-vcdiff: This encodes data as defined in IETF RFC3284.\n",
520
"-plain: This means that the transformed data will not have information\n",
521
" about the transformation used for encoding. So, that information\n",
522
" will have to be supplied explicitly on decoding.\n",
523
"-u[transformation]: This decodes some previously encoded data.\n",
524
" If 'transformation' is not empty, it is the transformation used\n",
525
" to encode data. The data to be decoded will be treated as if it\n",
526
" was encoded with '-plain'. That is, '-utransformation' is the same\n",
527
" as '-u -plain -mtransformation'.\n",
528
"-m[transformation]: A 'transformation' is defined as a comma-separated list:\n",
529
" transform1[.arg11.arg12...],transform2[.arg21.arg22],...'\n",
530
" For example, '-mbwt,mtf,rle.0,huffgroup' defines a transformation that\n"
531
" compresses data based on the Burrows-Wheeler transform. When the first\n",
532
" transform in a transformation is a delta compressor such as 'delta' or\n",
533
" 'sieve', a 'SourceFile' can help enhancing compression. In that case,\n"
534
" the same source file must be given on both encoding and decoding.\n",
535
0
536
};
537
538
static char *Program; /* name of executable */
539
540
static void error(const char* mesg, ...)
541
{
542
va_list args;
543
va_start(args, mesg);
544
sfprintf(sfstderr,"%s: ",Program);
545
sfvprintf(sfstderr,mesg,args);
546
sfprintf(sfstderr,"\n");
547
va_end(args);
548
exit(1);
549
}
550
551
static void vcsferror(const char* mesg)
552
{ sfprintf(sfstderr,"%s: %s\n", Program, mesg);
553
}
554
555
static int printdesc(Void_t* obj, char* name, char* value, Void_t* type)
556
{
557
Vcmtarg_t *arg;
558
559
if(type == PR_METHOD)
560
{ if(!obj)
561
return -1;
562
sfprintf(sfstderr,"%s: %s.\n", name, value);
563
for(arg = ((Vcmethod_t*)obj)->args; arg && arg->name; ++arg)
564
sfprintf(sfstderr, " %12s: %s.\n", arg->name, arg->desc);
565
if(arg && !arg->name && arg->desc)
566
sfprintf(sfstderr, " %12s: %s.\n", "None", arg->desc);
567
}
568
else if(type == PR_ALIAS)
569
sfprintf(sfstderr, "-%s: %s.\n", name, value);
570
else return -1;
571
572
return 0;
573
}
574
575
static void printmesg()
576
{
577
int i;
578
579
for(i = 0; Mesg[i]; ++i)
580
sfprintf(sfstderr,"%s", Mesg[i]);
581
582
sfprintf(sfstderr, "\nThe default transformation is %s.\n", DFLTZIP);
583
sfprintf(sfstderr, "Below are short-hands for common transformations:\n");
584
vcwalkalias(printdesc, PR_ALIAS);
585
586
/* print the set of primitive methods */
587
sfprintf(sfstderr, "\nBelow are the available transforms and their arguments:\n");
588
vcwalkmeth(printdesc, PR_METHOD);
589
}
590
591
int
592
main(int argc, char** argv)
593
{
594
Vcchar_t *data, *dt;
595
ssize_t dtsz, n;
596
char buf[1024];
597
Vcsfdata_t sfdt; /* data passed to vcsf */
598
Vcsfio_t *sfio = NIL(Vcsfio_t*); /* IO handle */
599
Vcodex_t *eavc = NIL(Vcodex_t*); /* ebcdic <-> ascii */
600
int action = VC_ENCODE; /* default is encoding */
601
int type = 0; /* type of processing */
602
char *trans = DFLTZIP; /* transformation spec */
603
char *window = NIL(char*); /* window specification */
604
ssize_t donez = -1, lastz = -1; /* amount processed */
605
606
/* get program name */
607
for(Program = argv[0]+strlen(argv[0]); Program > argv[0]; --Program)
608
if(Program[-1] == '/')
609
break;
610
611
/* make list of default aliases */
612
vcaddalias(Dfltalias);
613
614
for(; argc > 1 && argv[1][0] == '-'; argc--, argv++)
615
{ switch(argv[1][1])
616
{
617
case '?':
618
printmesg();
619
return 0;
620
case 'o':
621
case 'i':
622
case 'S':
623
if(argv[1][1] == 'S')
624
; /* state file has been made obsolete */
625
else if(argv[1][2] == 0)
626
error("No file was given for %s.", argv[1]);
627
else if(argv[1][1] == 'i')
628
{ if(sfopen(sfstdin, argv[1]+2, "r") != sfstdin)
629
error("Can't open input file '%s'.", argv[1]+2);
630
}
631
else
632
{ if(sfopen(sfstdout, argv[1]+2, "w") != sfstdout)
633
error("Can't open output file '%s'.", argv[1]+2);
634
}
635
break;
636
case 'w':
637
window = argv[1]+2;
638
break;
639
case 'E': /* ebcdic <-> ascii translation */
640
if(eavc)
641
vcclose(eavc);
642
if(!(eavc = vcopen(0, Vcmap, argv[1]+2, 0, VC_ENCODE)) )
643
error("'%s' specifies bad translation mode.", argv[1]);
644
break;
645
case 'v':
646
if(strcmp(argv[1]+1,"vcdiff") == 0)
647
type = VCSF_VCDIFF;
648
else goto dflt_arg;
649
break;
650
case 'p':
651
if(strcmp(argv[1]+1,"plain") == 0)
652
type = VCSF_PLAIN;
653
else goto dflt_arg;
654
break;
655
case 'u':
656
action = VC_DECODE;
657
if(argv[1][2])
658
{ type = VCSF_PLAIN;
659
trans = argv[1]+2;
660
}
661
break;
662
case 'm':
663
trans = argv[1]+2;
664
break;
665
case 'V':
666
donez = lastz = 0;
667
break;
668
default:
669
dflt_arg:
670
trans = vcgetalias(argv[1]+1, buf, sizeof(buf));
671
if(!trans || trans == argv[1]+1)
672
error("'%s' is invalid. Use '-?' for help.", argv[1]);
673
}
674
}
675
676
if(strcmp(Program, "vcunzip") == 0)
677
action = VC_DECODE;
678
else if(strncmp(Program, "vczip", 5) != 0 )
679
error("Program name should be vczip or vcunzip");
680
681
if(sfsize(sfstdin) == 0) /* a potentially empty data stream */
682
{ Void_t *data;
683
684
/* see if this is just a pipe showing up initially empty */
685
if(!(data = sfreserve(sfstdin, -1, SF_LOCKR)) || sfvalue(sfstdin) == 0 )
686
return 0; /* empty data transforms to empty output */
687
else sfread(sfstdin, data, 0); /* reset stream for normal transformation */
688
}
689
690
/* turn off share mode to avoid peeking on unseekable devices */
691
sfset(sfstdin, SF_SHARE, 0);
692
sfset(sfstdout, SF_SHARE, 0);
693
694
#if _WIN32 /* on Windows systems, use binary mode for file I/O */
695
setmode(0, O_BINARY);
696
setmode(1, O_BINARY);
697
#endif
698
699
/* open stream for data processing */
700
sfdt.type = type;
701
sfdt.trans = trans;
702
sfdt.source = argc == 2 ? argv[1] : NIL(char*);
703
sfdt.window = window;
704
sfdt.errorf = vcsferror;
705
if(!(sfio = vcsfio(action == VC_ENCODE ? sfstdout : sfstdin, &sfdt, action)) )
706
error("Can't set up stream to encode or decode data.");
707
708
/* get buffer for IO */
709
data = NIL(Void_t*);
710
for(dtsz = 1024*1024; dtsz > 0; dtsz /= 2)
711
if((data = (Void_t*)malloc(dtsz)) )
712
break;
713
if(!data)
714
error("Can't allocate I/O buffer.");
715
716
for(;;)
717
{ if(action == VC_DECODE) /* get a chunk of data */
718
n = vcsfread(sfio, data, dtsz);
719
else n = sfread(sfstdin, data, dtsz);
720
if(n <= 0)
721
break;
722
723
if(donez >= 0) /* verbose mode */
724
{ if(donez >= lastz + 64*(dtsz > 1024*1024 ? dtsz : 1024*1024))
725
{ sfprintf(sfstderr, "Done %d\n", donez);
726
lastz = donez;
727
}
728
donez += n;
729
}
730
731
if(!eavc) /* do any ascii <-> ebcdic mapping required */
732
dt = data;
733
else if((n = vcapply(eavc, data, n, &dt)) <= 0)
734
error("Byte mapping failed.");
735
736
if(action == VC_DECODE) /* write out the data */
737
n = sfwrite(sfstdout, dt, n);
738
else n = vcsfwrite(sfio, dt, n);
739
if(n <= 0)
740
error("Error writing out data.");
741
}
742
vcsfclose(sfio);
743
744
return 0;
745
}
746
747
#endif
748
749