Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libvcodex/vcsfio.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
* *
19
***********************************************************************/
20
#include "vchdr.h"
21
22
/* Sfio discipline to run Vcodex methods for compression.
23
**
24
** Written by Kiem-Phong Vo, [email protected].
25
*/
26
27
#define VCSF_BUFSIZE (256*1024) /* decoding buffer */
28
#define VCSF_BUFMIN (64*1024) /* surely affordable! */
29
#define VCSF_WSIZE (4*1024*1024) /* dflt encoding window */
30
#define VCSF_SLACK (16*sizeof(size_t)) /* for extra coding */
31
#define VCSFDTSZ(sz) ((((sz) / 1024) + 2) * 1024)
32
33
#define VCSFERROR(dc,m) ((dc)->sfdt->errorf ? ((*(dc)->sfdt->errorf)(m), -1) : -1 )
34
35
/* these bits are in sfdc->flags and must be outside VC_FLAGS */
36
#define VCSF_DONEHEAD 01000 /* header was already output */
37
#define VCSF_KEEPSFDC 02000 /* do not free the Sfdc struct */
38
39
typedef struct _sfdc_s
40
{ Sfdisc_t disc; /* Sfio discipline must be 1st */
41
Sfio_t* sf; /* stream to do IO with */
42
43
Vcsfdata_t* sfdt; /* initialization parameters */
44
45
unsigned int flags; /* states of the handle */
46
47
Sfoff_t pos; /* current stream position */
48
Vcwdisc_t vcwdc; /* windowing discipline */
49
Vcwindow_t* vcw; /* to match delta-comp windows */
50
51
Vcdisc_t vcdc; /* encoding/decoding discipline */
52
Vcodex_t* vc; /* Vcodex handle for de/coding */
53
54
Vcio_t* io; /* to write integers, etc. */
55
56
Vcchar_t* data; /* data buffer for external use */
57
ssize_t dtsz;
58
Vcchar_t* endd; /* end of data buffer */
59
Vcchar_t* next; /* where to read/write */
60
61
Vcchar_t* base; /* buffer for encoded data */
62
ssize_t bssz;
63
Vcchar_t* endb; /* end of base buffer */
64
65
Vcchar_t* code; /* space to be used by coder */
66
ssize_t cdsz;
67
} Sfdc_t;
68
69
#ifndef SKIPVCDX /* deal with the ancient VCDX header that uses method numbers */
70
71
#ifndef elementsof
72
#define elementsof(x) (sizeof(x)/sizeof(x[0]))
73
#endif
74
75
typedef struct _map_s /* to map an old method number to a transform */
76
{ const char* name; /* new method name */
77
int mtid; /* old method number */
78
Vcmethod_t* meth; /* corresponding method */
79
} Map_t;
80
81
typedef struct _meth_s /* keep method data for reverse construction */
82
{ Vcmethod_t* meth;
83
ssize_t size;
84
Vcchar_t* data;
85
} Meth_t;
86
87
static Map_t Map[] =
88
{ { "delta", 0 },
89
{ "huffman", 1 },
90
{ "huffgroup", 2 },
91
{ "arith", 3 },
92
{ "bwt", 4 },
93
{ "rle", 5 },
94
{ "mtf", 6 },
95
{ "transpose", 7 },
96
{ "table", 8 },
97
{ "huffpart", 9 },
98
{ "map", 50 },
99
{ "ama", 100 },
100
{ "ss7", 101 },
101
};
102
103
#if __STD_C
104
static ssize_t hdrvcdx(Vcchar_t** datap, ssize_t dtsz, Vcchar_t* code, ssize_t cdsz)
105
#else
106
static ssize_t hdrvcdx(datap, dtsz, code, cdsz)
107
Vcchar_t** datap; /* old header data */
108
ssize_t dtsz;
109
Vcchar_t* code; /* space for new code */
110
ssize_t cdsz;
111
#endif
112
{
113
ssize_t k, n, id, sz;
114
Vcchar_t *dt, buf[1024];
115
Vcio_t io;
116
Meth_t meth[2*elementsof(Map)]; /* should not exceed this */
117
118
/* parse old header into list of transforms */
119
vcioinit(&io, *datap, dtsz);
120
for(n = 0; n < elementsof(meth) && vciomore(&io) > 0; ++n)
121
{ id = vciogetc(&io);
122
for(k = 0; k < elementsof(Map); ++k)
123
if(Map[k].mtid == id)
124
break;
125
if(k >= elementsof(Map)) /* not matching any transform */
126
return dtsz; /* must be new header format */
127
128
if(!Map[k].meth && !(Map[k].meth = vcgetmeth((char*)Map[k].name, 1)))
129
{ Map[k].mtid = -1;
130
return dtsz;
131
}
132
meth[n].meth = Map[k].meth;
133
134
if(vciomore(&io) <= 0 || /* no or bad argument code */
135
(sz = (ssize_t)vciogetu(&io)) < 0 || sz > vciomore(&io) )
136
return dtsz; /* must be new header format */
137
138
meth[n].size = sz;
139
meth[n].data = vcionext(&io);
140
vcioskip(&io, sz);
141
}
142
143
if(vciomore(&io) > 0) /* too many transforms */
144
return dtsz; /* must be new header */
145
146
/* construct new header in reverse order */
147
vcioinit(&io, code, cdsz);
148
for(n -= 1; n >= 0; --n)
149
{ /* get and write out the method id string */
150
if(!(dt = (unsigned char*)vcgetident(meth[n].meth, (char*)buf, sizeof(buf))) )
151
return -1; /* error, no id string for method? */
152
if((sz = strlen((char*)dt)+1) > vciomore(&io)) /* too long */
153
return dtsz; /* must be new header format */
154
vcioputs(&io, dt, sz);
155
156
sz = meth[n].size; dt = meth[n].data;
157
if((sz + vcsizeu(sz)) > vciomore(&io))
158
return dtsz;
159
160
if(sz == 0)
161
vcioputu(&io, 0);
162
else if(meth[n].meth == Vcrle || meth[n].meth == Vcmtf)
163
{ if(*dt == 0) /* coding rle.0 or mtf.0 */
164
{ vcstrcode("0", (char*)buf, sizeof(buf));
165
vcioputu(&io, 1);
166
vcioputc(&io, buf[0]);
167
}
168
else vcioputu(&io, 0);
169
}
170
else /* let us pray for the right coding! */
171
{ vcioputu(&io, sz);
172
vcioputs(&io, dt, sz);
173
}
174
}
175
176
*datap = code; /* set to return new code string */
177
return vciosize(&io);
178
}
179
#endif /* SKIPVCDX */
180
181
/* dealing with RFC3284 Vcdiff header */
182
#if __STD_C
183
static ssize_t hdrvcdiff(Vcio_t* iodt, int indi, Vcchar_t* code, ssize_t cdsz)
184
#else
185
static ssize_t hdrvcdiff(iodt, indi, code, cdsz)
186
Vcio_t* iodt; /* data to be decoded */
187
int indi; /* indicator byte */
188
Vcchar_t* code; /* code buffer */
189
ssize_t cdsz; /* size of code buffer */
190
#endif
191
{
192
Vcio_t io;
193
char *ident, buf[1024];
194
195
if(indi&VCD_COMPRESSOR) /* no secondary compressor */
196
return -1;
197
198
vcioinit(&io, code, cdsz);
199
200
/* write out the method identification string */
201
if(!(ident = vcgetident(Vcdelta, buf, sizeof(buf))) )
202
return -1;
203
if((cdsz = strlen(ident)+1) > vciomore(&io))
204
return -1;
205
vcioputs(&io, ident, cdsz);
206
207
if(indi&VCD_CODETABLE)
208
{ if((cdsz = vciogetu(iodt)) < 0 )
209
return -1;
210
211
if(vciomore(&io) < vcsizeu(cdsz))
212
return -1;
213
vcioputu(&io, cdsz);
214
215
if(vciomore(&io) < cdsz)
216
return -1;
217
vciomove(iodt, &io, cdsz);
218
}
219
else
220
{ if(vciomore(&io) <= 0)
221
return -1;
222
vcioputu(&io, 0);
223
}
224
225
return vciosize(&io);
226
}
227
228
#if __STD_C
229
static int putheader(Sfdc_t* sfdc)
230
#else
231
static int putheader(sfdc)
232
Sfdc_t* sfdc;
233
#endif
234
{
235
Vcchar_t *code;
236
ssize_t sz;
237
238
/* header should be done at most once */
239
if((sfdc->flags&VCSF_DONEHEAD) )
240
return 0;
241
sfdc->flags |= VCSF_DONEHEAD;
242
243
/* header not wanted */
244
if(sfdc->sfdt->type&VCSF_PLAIN)
245
return 0;
246
247
/* get the string that codes the methods */
248
if((sz = vcextract(sfdc->vc, (Void_t**)&code)) <= 0 )
249
return VCSFERROR(sfdc, "Transform data not encodable.");
250
if((4+1+vcsizeu(sz)+sz) > vciomore(sfdc->io))
251
return VCSFERROR(sfdc, "Transform data abnormally large.");
252
253
/* output standard header bytes */
254
vcioputc(sfdc->io, VC_HEADER0);
255
vcioputc(sfdc->io, VC_HEADER1);
256
vcioputc(sfdc->io, VC_HEADER2);
257
vcioputc(sfdc->io, (sfdc->sfdt->type&VCSF_VCDIFF) ? 0 : VC_HEADER3);
258
259
/* output indicator byte - see also compatibility with RFC3284 */
260
vcioputc(sfdc->io, 0);
261
262
/* output data encoding the methods used */
263
if(!(sfdc->sfdt->type&VCSF_VCDIFF) )
264
{ vcioputu(sfdc->io, sz);
265
vcioputs(sfdc->io, code, sz);
266
}
267
268
return 0;
269
}
270
271
#if __STD_C
272
static int makebuf(Sfdc_t* sfdc, ssize_t size)
273
#else
274
static int makebuf(sfdc, size)
275
Sfdc_t* sfdc;
276
ssize_t size;
277
#endif
278
{
279
Vcchar_t *base, *oldbase;
280
281
size = ((size + VCSF_BUFMIN - 1)/VCSF_BUFMIN)*VCSF_BUFMIN;
282
if(sfdc->bssz >= size)
283
return 0;
284
285
oldbase = sfdc->base;
286
if(!(base = (Vcchar_t*)malloc(size)) )
287
return -1;
288
289
memcpy(base, oldbase, sfdc->endb - oldbase);
290
sfdc->endb = base + (sfdc->endb - oldbase);
291
sfdc->code = base + (sfdc->code - oldbase);
292
sfdc->base = base;
293
sfdc->bssz = size;
294
free(oldbase);
295
296
return 0;
297
}
298
299
#if __STD_C
300
static ssize_t fillbuf(Sfdc_t* sfdc, Sfio_t* f, Sfdisc_t* disc)
301
#else
302
static ssize_t fillbuf(sfdc, f, disc)
303
Sfdc_t* sfdc;
304
Sfio_t* f;
305
Sfdisc_t* disc;
306
#endif
307
{
308
ssize_t sz, n;
309
310
if((sz = sfdc->endb - sfdc->code) <= 0 )
311
{ sfdc->endb = sfdc->code = sfdc->base;
312
sz = 0;
313
}
314
else if(sfdc->code > sfdc->base)
315
{ memcpy(sfdc->base, sfdc->code, sz);
316
sfdc->endb = (sfdc->code = sfdc->base) + sz;
317
}
318
for(; sz < sfdc->bssz; sz += n, sfdc->endb += n)
319
{ if(!disc) /* plain read if no discipline set yet */
320
n = sfread(f, sfdc->endb, sfdc->bssz-sz);
321
else n = sfrd(f, sfdc->endb, sfdc->bssz-sz, disc);
322
if(n <= 0)
323
break;
324
}
325
326
return sz;
327
}
328
329
static int
330
#if _STD_C
331
extend(char** pc, char** pb, char** pe, int n)
332
#else
333
extend(pc, pb, pe, n)
334
char** pc;
335
char** pb;
336
char** pe;
337
int n;
338
#endif
339
{
340
int x;
341
int o;
342
343
o = *pc - *pb;
344
x = (*pe - *pb + 1);
345
if (x < n)
346
x = n;
347
x *= 2;
348
if (!(*pb = malloc(x)))
349
return -1;
350
*pe = *pb + x - 1;
351
*pc = * pb + o;
352
return 0;
353
}
354
355
#if __STD_C
356
static ssize_t ident(Sfdc_t* sfdc, Void_t* data, size_t dtsz)
357
#else
358
static ssize_t ident(sfdc, data, dtsz)
359
Sfdc_t* sfdc;
360
Void_t* data;
361
size_t dtsz;
362
#endif
363
{
364
ssize_t sz, k;
365
char *mt;
366
char *id, *buf, *end;
367
unsigned char *dt;
368
int x;
369
Vcio_t io;
370
371
static char hex[] = "0123456789ABCDEF";
372
373
if(!data || dtsz <= 0 )
374
return -1;
375
x = 256;
376
if(!(buf = malloc(x)))
377
return -1;
378
id = buf;
379
end = buf + x - 1;
380
vcioinit(&io, data, dtsz);
381
id = buf;
382
while(vciomore(&io) > 0)
383
{
384
if(id > buf)
385
{ if(id >= end && extend(&id, &buf, &end, 1))
386
return -1;
387
*id++ = VC_METHSEP;
388
}
389
mt = (char*)vcionext(&io);
390
for(sz = vciomore(&io), k = 0; k < sz; ++k)
391
{ if(id >= end && extend(&id, &buf, &end, 1))
392
return -1;
393
if(mt[k] == 0)
394
break;
395
*id++ = mt[k];
396
}
397
if(k >= sz)
398
return -1;
399
vcioskip(&io, k+1);
400
401
/* get the initialization data, if any */
402
if((sz = (ssize_t)vciogetu(&io)) < 0 || sz > vciomore(&io))
403
return -1;
404
if(sz)
405
{ dt = (unsigned char*)vcionext(&io);
406
vcioskip(&io, sz);
407
k - 2 * sz + 1;
408
if((id +k) >= end && extend(&id, &buf, &end, k))
409
return -1;
410
*id++ = '=';
411
for(k = 0; k < sz; k++)
412
{ x = dt[k];
413
*id++ = hex[(x>>4)&0xf];
414
*id++ = hex[x&0xf];
415
}
416
}
417
}
418
*id = 0;
419
sfdc->sfdt->trans = buf;
420
return 1;
421
}
422
423
#if __STD_C
424
static ssize_t getheader(Sfdc_t* sfdc, Sfio_t* f, int init, int identify)
425
#else
426
static ssize_t getheader(sfdc, f, init, identify)
427
Sfdc_t* sfdc;
428
Sfio_t* f;
429
int init; /* initial call */
430
int identify;
431
#endif
432
{
433
ssize_t cdsz, sz;
434
Vcchar_t *code, cdbuf[4*1024];
435
int indi, head, loop;
436
Vcio_t io;
437
438
if(identify)
439
{ /* verify header magic -- ignore if no magic */
440
if(!(code = sfreserve(f, 4, SF_LOCKR)))
441
return 0;
442
memcpy(cdbuf, code, 4);
443
sfread(f, code, 0);
444
if(cdbuf[0]!=VC_HEADER0 || cdbuf[1]!=VC_HEADER1 || cdbuf[2]!=VC_HEADER2 || cdbuf[3]!=VC_HEADER3 && cdbuf[3]!=0)
445
return 0;
446
}
447
448
for(loop = 0;; ++loop)
449
{
450
/* buffer was too small for header data */
451
if(loop > 0 && (sfdc->endb - sfdc->base) >= sfdc->bssz &&
452
makebuf(sfdc, sfdc->bssz+VCSF_BUFMIN) < 0)
453
return VCSFERROR(sfdc, "Failure in allocating memory");
454
455
/* read header data as necessary */
456
sz = sfdc->endb - sfdc->code;
457
if(loop > 0 || sz <= 0)
458
{ if(fillbuf(sfdc, f, sfdc->vc ? &sfdc->disc : NIL(Sfdisc_t*)) <= 0 ||
459
(sz = sfdc->endb - sfdc->code) <= 0 )
460
return identify ? 0 : init ? VCSFERROR(sfdc, "Bad header data") : -1;
461
}
462
463
vcioinit(&io, sfdc->code, sz);
464
465
if(vciomore(&io) < 5) /* need 4-byte header + indicator byte */
466
continue;
467
468
if(vciogetc(&io) != VC_HEADER0 ||
469
vciogetc(&io) != VC_HEADER1 ||
470
vciogetc(&io) != VC_HEADER2 ||
471
((head = vciogetc(&io)) != 0 /* RFC3284 Vcdiff header */ &&
472
head != VC_HEADER3 /* normal Vcodex header */ ) )
473
return identify ? 0 : VCSFERROR(sfdc, "Unknown header data");
474
475
if((indi = vciogetc(&io)) & VC_EXTRAHEADER )
476
{ if((sz = vciogetu(&io)) < 0) /* skip app-specific data */
477
continue;
478
vcioskip(&io, sz);
479
}
480
481
if(head == 0) /* RFC3284 Vcdiff format */
482
{ if((cdsz = hdrvcdiff(&io, indi, cdbuf, sizeof(cdbuf))) < 0)
483
return VCSFERROR(sfdc, "Corrupted Vcdiff header data");
484
else if(cdsz == 0)
485
continue;
486
else code = cdbuf;
487
}
488
else /* Vcodex encoding */
489
{ if((cdsz = vciogetu(&io)) < 0 )
490
continue;
491
else if(cdsz == 0)
492
return VCSFERROR(sfdc, "Corrupted Vcodex header data");
493
if(vciomore(&io) < cdsz)
494
continue;
495
code = vcionext(&io);
496
vcioskip(&io, cdsz);
497
498
#ifndef SKIPVCDX /* deal with old headers that use method numbers instead of names */
499
cdsz = hdrvcdx(&code, cdsz, cdbuf, sizeof(cdbuf));
500
#endif
501
}
502
503
/* successfully read the header data */
504
sfdc->code = vcionext(&io);
505
break;
506
}
507
if(cdsz <= 0 )
508
return identify ? 0 : VCSFERROR(sfdc, "Failure in obtaining header data");
509
else if(identify)
510
return ident(sfdc, code, cdsz);
511
else
512
{ if(sfdc->vc)
513
vcclose(sfdc->vc);
514
if(!(sfdc->vc = vcrestore(code, cdsz)) )
515
return VCSFERROR(sfdc, "Failure in initializing data transforms");
516
else if(sfdc->sfdt->type & VCSF_TRANS)
517
return ident(sfdc, code, cdsz);
518
else return 0;
519
}
520
}
521
522
#if __STD_C
523
static ssize_t encode(Sfdc_t* sfdc, Vcchar_t* data, size_t dtsz)
524
#else
525
static ssize_t encode(sfdc, data, dtsz)
526
Sfdc_t* sfdc;
527
Vcchar_t* data;
528
size_t dtsz;
529
#endif
530
{
531
Vcchar_t *code, ctrl, *dt;
532
ssize_t cdsz, size, sz, bssz, dosz;
533
Vcchar_t *base;
534
Vcwmatch_t *wm;
535
Vcio_t io;
536
537
vcioinit(&io, sfdc->base, sfdc->bssz);
538
sfdc->io = &io;
539
540
if(!(sfdc->flags&VCSF_DONEHEAD) && putheader(sfdc) < 0)
541
return VCSFERROR(sfdc, "Failure in encoding transforms");
542
543
sfdc->code = NIL(Vcchar_t*); sfdc->cdsz = 0;
544
545
for(size = 0, dosz = dtsz, dt = data; size < dtsz; )
546
{ /* control data */
547
ctrl = 0;
548
sfdc->vcdc.data = NIL(Void_t*);
549
sfdc->vcdc.size = 0;
550
551
/* compute a matching window to enhance compression */
552
wm = NIL(Vcwmatch_t*);
553
if(sfdc->vcw)
554
wm = vcwapply(sfdc->vcw, dt, dosz, sfdc->pos);
555
if(wm)
556
{ /**/DEBUG_ASSERT(wm->msize <= dosz);
557
if(wm->wsize > 0 && wm->wpos >= 0)
558
{ sfdc->vcdc.data = wm->wdata;
559
sfdc->vcdc.size = wm->wsize;
560
}
561
562
ctrl = wm->type & (VCD_SOURCEFILE|VCD_TARGETFILE);
563
dosz = wm->msize; /* amount doable now */
564
/**/ DEBUG_PRINT(2,"dtpos=%d ", sfdc->pos);
565
/**/ DEBUG_PRINT(2,"dtsz=%d ", dosz);
566
/**/ DEBUG_PRINT(2,"wpos=%d ", wm->wpos);
567
/**/ DEBUG_PRINT(2,"wsz=%d ", wm->wsize);
568
/**/ DEBUG_PRINT(2,"mtsz=%d\n", wm->msize);
569
}
570
if(sfdc->vcw) /* set window data */
571
vcdisc(sfdc->vc, &sfdc->vcdc);
572
573
vcbuffer(sfdc->vc, NIL(Vcchar_t*), -1, -1); /* free buffers */
574
if((cdsz = vcapply(sfdc->vc, dt, dosz, &code)) <= 0 ||
575
(sz = vcundone(sfdc->vc)) >= dosz )
576
{ if(cdsz < 0)
577
VCSFERROR(sfdc, "Error in transforming data");
578
ctrl = VC_RAW; /* coder failed, output raw data */
579
code = dt;
580
cdsz = dosz;
581
}
582
else
583
{ dosz -= (sz > 0 ? sz : 0); /* true processed amount */
584
if(sfdc->vcw) /* tell window matcher compressed result */
585
vcwfeedback(sfdc->vcw, cdsz);
586
}
587
588
vcioputc(&io, ctrl);
589
if(ctrl&(VCD_SOURCEFILE|VCD_TARGETFILE) )
590
{ vcioputu(&io, wm->wsize);
591
vcioputu(&io, wm->wpos);
592
}
593
vcioputu(&io, cdsz);
594
if(vciomore(&io) < cdsz) /* buffer too small */
595
{ sz = vciosize(&io);
596
bssz = ((cdsz+sz+1023)/1024)*1024;
597
if(!(base = (Vcchar_t*)malloc(bssz)) )
598
return -1;
599
memcpy(base, sfdc->base, vciosize(&io));
600
if(sfdc->base)
601
free(sfdc->base);
602
sfdc->base = base;
603
sfdc->bssz = bssz;
604
605
vcioinit(&io, sfdc->base, sfdc->bssz);
606
vcioskip(&io, sz);
607
}
608
vcioputs(&io, code, cdsz);
609
610
sfdc->pos += dosz; /* advance by amount consumed */
611
dt += dosz;
612
size += dosz;
613
614
if((dosz = dtsz-size) > 0 )
615
{ if(wm && wm->more) /* more subwindows to do */
616
continue;
617
else /* need fresh data */
618
{ if(data == sfdc->data) /* shift undone data */
619
{ memcpy(data, data+size, dosz);
620
sfdc->next = data + dosz;
621
}
622
break;
623
}
624
}
625
}
626
627
sfdc->code = sfdc->base; sfdc->cdsz = vciosize(&io);
628
629
return size; /* return amount processed */
630
}
631
632
/* read data from the filter */
633
#if __STD_C
634
static ssize_t vcsfdcread(Sfio_t* f, Void_t* buf, size_t n, Sfdisc_t* disc)
635
#else
636
static ssize_t vcsfdcread(f, buf, n, disc)
637
Sfio_t* f; /* stream reading from */
638
Void_t* buf; /* buffer to read data into */
639
size_t n; /* number of bytes requested */
640
Sfdisc_t* disc; /* discipline structure */
641
#endif
642
{
643
Vcchar_t *dt, *text;
644
int ctrl;
645
ssize_t sz, r, d, m;
646
Sfoff_t pos;
647
Vcwmatch_t *wm;
648
Vcio_t io;
649
Sfdc_t *sfdc = (Sfdc_t*)disc;
650
651
if(!(sfdc->flags&VC_DECODE) )
652
return VCSFERROR(sfdc, "Handle not created for decoding data");
653
654
for(sz = 0, dt = (Vcchar_t*)buf; sz < n; sz += r, dt += r)
655
{ /* copy already decoded data */
656
if((r = sfdc->endd - sfdc->next) > 0 )
657
{ r = r > (n-sz) ? (n-sz) : r;
658
memcpy(dt, sfdc->next, r);
659
sfdc->next += r;
660
}
661
else /* need to decode a new batch of data */
662
{
663
if((d = (sfdc->endb - sfdc->code)) < 2*sizeof(size_t))
664
{ if(fillbuf(sfdc, f, disc) <= 0 )
665
break;
666
d = sfdc->endb - sfdc->code;
667
}
668
669
vcioinit(&io, sfdc->code, d);
670
671
sfdc->vcdc.data = NIL(Void_t*);
672
sfdc->vcdc.size = 0;
673
674
/* get the control byte */
675
ctrl = vciogetc(&io);
676
677
/* let upper level write and flush first */
678
if((ctrl&VCD_TARGETFILE) && sz > 0)
679
break;
680
681
if(ctrl & (VCD_SOURCEFILE|VCD_TARGETFILE) )
682
{ if(!sfdc->vcw ||
683
(d = (ssize_t)vciogetu(&io)) < 0 ||
684
(pos = (Sfoff_t)vciogetu(&io)) < 0 ||
685
!(wm = vcwapply(sfdc->vcw, TYPECAST(Void_t*, ctrl), d, pos)) )
686
{ VCSFERROR(sfdc, "Error in obtaining source window data while decoding");
687
BREAK;
688
}
689
sfdc->vcdc.data = wm->wdata;
690
sfdc->vcdc.size = wm->wsize;
691
}
692
else if(ctrl == VC_EOF) /* a new decoding context */
693
{ sfdc->code = vcionext(&io);
694
if(vciomore(&io) > 0 && *sfdc->code == VC_EOF)
695
continue; /* skip a sequence of VC_EOF's */
696
if(getheader(sfdc, f, 0, 0) < 0 )
697
break;
698
else continue;
699
}
700
else if(ctrl != 0 && ctrl != VC_RAW)
701
{ VCSFERROR(sfdc, "Data stream appeared to be corrupted");
702
BREAK;
703
}
704
705
if(sfdc->vcw)
706
vcdisc(sfdc->vc, &sfdc->vcdc);
707
708
/* size of coded data */
709
if((d = vciogetu(&io)) <= 0)
710
{ VCSFERROR(sfdc, "Error in getting size of coded data");
711
BREAK;
712
}
713
714
/* make sure all the data is available */
715
if((vcionext(&io) + d) > sfdc->endb)
716
{ sfdc->code = vcionext(&io);
717
if((m = d+VCSF_SLACK) > sfdc->bssz &&
718
makebuf(sfdc, m) < 0 )
719
return VCSFERROR(sfdc, "Failure to allocate buffer");
720
if(fillbuf(sfdc, f, disc) <= 0 ||
721
(m = sfdc->endb - sfdc->code) < d )
722
return VCSFERROR(sfdc, "Failure to read coded data");
723
vcioinit(&io, sfdc->code, m);
724
}
725
726
/* decode data */
727
sfdc->code = vcionext(&io);
728
if(ctrl == VC_RAW)
729
{ text = sfdc->code;
730
m = d;
731
}
732
else
733
{ vcbuffer(sfdc->vc, NIL(Vcchar_t*), -1, -1);
734
if((m = vcapply(sfdc->vc, sfdc->code, d, &text)) <= 0)
735
{ VCSFERROR(sfdc, "Failure in decoding data");
736
BREAK;
737
}
738
}
739
740
sfdc->code += d; /* advance passed processed data */
741
742
/* set plaintext data buffer */
743
sfdc->data = sfdc->next = text;
744
sfdc->endd = text+m;
745
sfdc->dtsz = m;
746
}
747
}
748
749
return sz;
750
}
751
752
#if __STD_C
753
static ssize_t vcsfdcwrite(Sfio_t* f, const Void_t* buf, size_t n, Sfdisc_t* disc)
754
#else
755
static ssize_t vcsfdcwrite(f, buf, n, disc)
756
Sfio_t* f; /* stream writing to */
757
Void_t* buf; /* buffer of data to write out */
758
size_t n; /* number of bytes requested */
759
Sfdisc_t* disc; /* discipline structure */
760
#endif
761
{
762
Vcchar_t *dt;
763
ssize_t sz, w;
764
Sfdc_t *sfdc = (Sfdc_t*)disc;
765
766
if(!(sfdc->flags & VC_ENCODE) )
767
return VCSFERROR(sfdc, "Handle was not created to encode data");
768
769
for(sz = 0, dt = (Vcchar_t*)buf; sz < n; sz += w, dt += w)
770
{ if(buf == (Void_t*)sfdc->data)
771
{ /* final flush */
772
w = sfdc->next - sfdc->data;
773
sfdc->next = sfdc->data;
774
775
if((w = encode(sfdc, sfdc->data, w)) < 0 )
776
{ VCSFERROR(sfdc, "Error encoding data");
777
break;
778
}
779
else sz += w;
780
781
if(sfwr(f, sfdc->code, sfdc->cdsz, disc) != sfdc->cdsz)
782
{ VCSFERROR(sfdc, "Error writing encoded data");
783
break;
784
}
785
786
if(sfdc->next > sfdc->data) /* not done yet */
787
{ w = 0; /* so for(;;) won't add to sz, dt */
788
continue; /* back to flushing */
789
}
790
else break;
791
}
792
793
if((w = sfdc->endd - sfdc->next) == 0)
794
{ /* flush a full buffer */
795
sfdc->next = sfdc->data;
796
if((w = encode(sfdc, sfdc->data, sfdc->dtsz)) < 0)
797
{ VCSFERROR(sfdc, "Error in encoding data");
798
break;
799
}
800
if(sfwr(f, sfdc->code, sfdc->cdsz, disc) != sfdc->cdsz)
801
{ VCSFERROR(sfdc, "Error in writing encoded data");
802
break;
803
}
804
805
w = sfdc->endd - sfdc->next; /* bufferable space */
806
}
807
808
/* process data directly if buffer is empty and data is large */
809
if(w == sfdc->dtsz && (n-sz) >= w)
810
{ if((w = encode(sfdc, dt, n-sz)) < 0)
811
{ VCSFERROR(sfdc, "Error in encoding");
812
break;
813
}
814
if(sfwr(f, sfdc->code, sfdc->cdsz, disc) != sfdc->cdsz)
815
{ VCSFERROR(sfdc, "Error in writing data");
816
break;
817
}
818
}
819
else /* accumulating data into buffer */
820
{ w = w > (n-sz) ? (n-sz) : w;
821
memcpy(sfdc->next, dt, w);
822
sfdc->next += w;
823
}
824
}
825
826
return sz;
827
}
828
829
/* for the duration of this discipline, the stream is unseekable */
830
#if __STD_C
831
static Sfoff_t vcsfdcseek(Sfio_t* f, Sfoff_t addr, int offset, Sfdisc_t* disc)
832
#else
833
static Sfoff_t vcsfdcseek(f, addr, offset, disc)
834
Sfio_t* f;
835
Sfoff_t addr;
836
int offset;
837
Sfdisc_t* disc;
838
#endif
839
{
840
return (Sfoff_t)(-1);
841
}
842
843
/* on close, remove the discipline */
844
#if __STD_C
845
static int vcsfdcexcept(Sfio_t* f, int type, Void_t* data, Sfdisc_t* disc)
846
#else
847
static int vcsfdcexcept(f,type,data,disc)
848
Sfio_t* f;
849
int type;
850
Void_t* data;
851
Sfdisc_t* disc;
852
#endif
853
{
854
ssize_t sz;
855
Sfdc_t *sfdc = (Sfdc_t*)disc;
856
857
switch(type)
858
{
859
case VCSF_DISC: /* get the discipline */
860
if(data)
861
*((Sfdc_t**)data) = sfdc;
862
return VCSF_DISC;
863
case SF_SYNC:
864
case SF_DPOP:
865
case SF_CLOSING:
866
case SF_ATEXIT:
867
if(sfdc->flags & VC_ENCODE)
868
{ if((sz = sfdc->next - sfdc->data) > 0 )
869
{
870
#if _SFIO_H == 1 /* Sfio: this will wind up calling vcsfdcwrite() */
871
sfset(f, SF_IOCHECK, 0);
872
if(sfwr(f, sfdc->data, sz, disc) != sz)
873
return VCSFERROR(sfdc, "Error in writing coded data");
874
sfset(f, SF_IOCHECK, 1);
875
876
#else /* Stdio: must call vcsfdcwrite() directly to encode */
877
if(vcsfdcwrite(f, sfdc->data, sz, disc) != sz)
878
return VCSFERROR(sfdc, "Error in writing coded data");
879
#endif
880
sfdc->next = sfdc->data;
881
}
882
883
if(type == SF_CLOSING || type == SF_ATEXIT)
884
{ Vcio_t io;
885
886
/* back to plain text mode */
887
sfdc->flags |= VCSF_KEEPSFDC;
888
sfdisc(f, NIL(Sfdisc_t*));
889
sfdc->flags &= ~VCSF_KEEPSFDC;
890
891
vcioinit(&io, sfdc->base, sfdc->bssz);
892
if(!(sfdc->flags&VCSF_DONEHEAD))
893
{ sfdc->io = &io;
894
if(putheader(sfdc) < 0 )
895
return VCSFERROR(sfdc, "Error writing header");
896
vcioputu(&io,0);
897
}
898
if(!(sfdc->sfdt->type&VCSF_PLAIN) )
899
vcioputc(&io, VC_EOF); /* write the eof marker */
900
901
sz = vciosize(&io); /* output to stream */
902
if(sz > 0 && sfwr(f, sfdc->base, sz, NIL(Sfdisc_t*)) != sz)
903
return VCSFERROR(sfdc, "Error in writing coded data");
904
}
905
}
906
907
if(!(sfdc->flags&VCSF_KEEPSFDC) && (type == SF_CLOSING || type == SF_DPOP) )
908
{ if(sfdc->vc)
909
vcclose(sfdc->vc);
910
if(sfdc->vcwdc.srcf)
911
sfclose(sfdc->vcwdc.srcf);
912
if(sfdc->vcwdc.tarf)
913
sfclose(sfdc->vcwdc.tarf);
914
if(sfdc->vcw )
915
vcwclose(sfdc->vcw);
916
if((sfdc->flags&VC_ENCODE) && sfdc->data)
917
free(sfdc->data);
918
if(sfdc->base)
919
free(sfdc->base);
920
if(sfdc->sfdt->type&VCSF_FREE)
921
free(sfdc->sfdt);
922
free(sfdc);
923
}
924
925
break;
926
}
927
928
return 0;
929
}
930
931
932
/* syntax for window size is "[0-9]+[mMkK]" */
933
#if __STD_C
934
static ssize_t getwindow(char* spec, Vcwmethod_t** vcwmt)
935
#else
936
static ssize_t getwindow(spec, vcwmt)
937
char* spec; /* window/size specification */
938
Vcwmethod_t** vcwmt; /* return windowing method */
939
#endif
940
{
941
ssize_t wsize;
942
Vcwmethod_t *wmeth = NIL(Vcwmethod_t*);
943
944
if(!spec)
945
spec = "";
946
947
wsize = (ssize_t)vcatoi(spec);
948
while(isdigit(*spec))
949
spec += 1;
950
if(*spec == 'k' || *spec == 'K') /* kilobyte */
951
wsize *= 1024;
952
else if(*spec == 'm' || *spec == 'M') /* megabyte */
953
wsize *= 1024*1024;
954
955
if(vcwmt)
956
{ while(*spec && *spec != VC_ARGSEP)
957
spec += 1;
958
if(*spec == VC_ARGSEP)
959
wmeth = vcwgetmeth(spec+1);
960
*vcwmt = wmeth ? wmeth : Vcwprefix;
961
}
962
963
return wsize;
964
}
965
966
#if __STD_C
967
Vcsfio_t* vcsfio(Sfio_t* sf, Vcsfdata_t* sfdt, int type)
968
#else
969
Vcsfio_t* vcsfio(sf, data, type)
970
Sfio_t* sf; /* stream to be conditioned */
971
Vcsfdata_t* sfdt; /* data to initialize stream */
972
int type; /* VC_ENCODE or VC_DECODE or 0 */
973
#endif
974
{
975
char *trans;
976
ssize_t wsize;
977
Vcwmethod_t *wmeth;
978
Sfdc_t *sfdc = NIL(Sfdc_t*);
979
Vcsfdata_t dflt; /* default decoding data */
980
981
if(!sfdt && type == VC_DECODE)
982
{ sfdt = &dflt; /* assuming coded header data */
983
memset(sfdt, 0, sizeof(Vcsfdata_t));
984
}
985
986
if(!sf || !sfdt )
987
return NIL(Vcsfio_t*);
988
if(type != VC_ENCODE && type != VC_DECODE && type)
989
return NIL(Vcsfio_t*);
990
991
if(sfdt->type & VCSF_VCDIFF) /* special case for RFC3284 header */
992
{ sfdt->type &= ~VCSF_PLAIN;
993
trans = "delta";
994
}
995
else trans = sfdt->trans;
996
997
/* local error processing function */
998
#define errorsfio(s) do { if(sfdt->errorf) (*sfdt->errorf)(s); goto error; } while(0)
999
1000
if(!(sfdc = (Sfdc_t*)calloc(1,sizeof(Sfdc_t) + (sfdt == &dflt ? sizeof(dflt) : 0))) )
1001
{ if(!type)
1002
sfdt->type = -1;
1003
errorsfio("Out of memory for transformation structure");
1004
}
1005
1006
#if _SFIO_H == 1 /* initialize Sfio discipline */
1007
sfdc->disc.readf = vcsfdcread;
1008
sfdc->disc.writef = vcsfdcwrite;
1009
sfdc->disc.seekf = vcsfdcseek;
1010
sfdc->disc.exceptf = vcsfdcexcept;
1011
#endif
1012
1013
sfdc->sf = sf; /* stream to do IO on */
1014
if(sfdt == &dflt)
1015
{ sfdt = (Vcsfdata_t*)(sfdc + 1);
1016
*sfdt = dflt;
1017
}
1018
sfdc->sfdt = sfdt; /* init parameters */
1019
1020
wsize = getwindow(sfdt->window, &wmeth);
1021
1022
if((sfdc->flags = type) == VC_ENCODE)
1023
{ /* creat handle for transformation */
1024
if(!trans || !(sfdc->vc = vcmake(trans, VC_ENCODE)) )
1025
errorsfio("Ill-defined transformation for encoding.");
1026
1027
/* create windowing handle if needed */
1028
if((sfdc->vc->meth->type & VC_MTSOURCE) && sfdt->source)
1029
{ if(!(sfdc->vcwdc.srcf = sfopen(0,sfdt->source,"rb")) )
1030
errorsfio("Non-existing or unreadable source file.");
1031
sfdc->vcw = vcwopen(&sfdc->vcwdc, wmeth);
1032
if(!sfdc->vcw)
1033
errorsfio("Windowing not possible");
1034
}
1035
1036
/* buffer to accumulate data before encoding */
1037
sfdc->dtsz = wsize > 0 ? wsize :
1038
sfdc->vc->meth->window > 0 ? sfdc->vc->meth->window : VCSF_WSIZE;
1039
if(!(sfdc->data = (Vcchar_t*)malloc(sfdc->dtsz)) )
1040
errorsfio("Out of memory for data buffer");
1041
sfdc->next = sfdc->data;
1042
sfdc->endd = sfdc->data + sfdc->dtsz;
1043
1044
/* buffer for the encoder to output results */
1045
sfdc->bssz = VCSFDTSZ(sfdc->dtsz);
1046
if(!(sfdc->base = (Vcchar_t*)malloc(sfdc->bssz)) )
1047
errorsfio("Out of memory for output buffer");
1048
}
1049
else /* VC_DECODE */
1050
{ /* make output buffer */
1051
if((sfdc->bssz = wsize) <= 0)
1052
sfdc->bssz = VCSF_BUFSIZE;
1053
else if(sfdc->bssz < VCSF_BUFMIN)
1054
sfdc->bssz = VCSF_BUFMIN;
1055
if(!(sfdc->base = (Vcchar_t*)malloc(sfdc->bssz)) )
1056
{ if(!type)
1057
sfdt->type = -1;
1058
errorsfio("Out of memory for output buffer");
1059
}
1060
sfdc->code = sfdc->endb = sfdc->base;
1061
1062
/* reconstruct handle to decode data */
1063
if(sfdt->type & VCSF_PLAIN)
1064
{ if(!trans)
1065
errorsfio("No transform specified for decoding.");
1066
if(!(sfdc->vc = vcmake(trans, VC_DECODE)) )
1067
errorsfio("Ill-defined transformation for decoding.");
1068
}
1069
else
1070
{ if(!type)
1071
sfdt->type |= VCSF_TRANS;
1072
if(getheader(sfdc, sf, 1, !type) < 0 )
1073
{ if(!type)
1074
{ sfdt->type = 0;
1075
return NIL(Vcsfio_t*);
1076
}
1077
errorsfio("Badly encoded data, decoding not possible.");
1078
}
1079
if(!type)
1080
{
1081
free(sfdc->base);
1082
free(sfdc);
1083
sfdt->type = 1;
1084
return (Vcsfio_t*)sf;
1085
}
1086
}
1087
1088
/* construct window handle to get data for delta-decoding */
1089
if((sfdc->vc->meth->type & VC_MTSOURCE) && sfdt->source)
1090
{ if(!(sfdc->vcwdc.srcf = sfopen(0,sfdt->source,"rb")) )
1091
errorsfio("Non-existing or unreadable source file.");
1092
if(!(sfdc->vcw = vcwopen(&sfdc->vcwdc, NIL(Vcwmethod_t*))) )
1093
errorsfio("Windowing not possible");
1094
}
1095
}
1096
1097
if(sfdisc(sf, &sfdc->disc) != &sfdc->disc)
1098
errorsfio("Stream not initializable");
1099
1100
#if _SFIO_H == 1
1101
sfset(sf, SF_IOCHECK, 1); /* so that sfsync() will call vcsfdcexcept() */
1102
sfclrerr(sf);
1103
return (Vcsfio_t*)sf;
1104
#else
1105
return (Vcsfio_t*)sfdc;
1106
#endif
1107
1108
error:
1109
if(sfdc)
1110
{ if(sfdc->vc)
1111
vcclose(sfdc->vc);
1112
if(sfdc->vcwdc.srcf)
1113
sfclose(sfdc->vcwdc.srcf);
1114
if(sfdc->vcwdc.tarf)
1115
sfclose(sfdc->vcwdc.tarf);
1116
if(sfdc->vcw)
1117
vcwclose(sfdc->vcw);
1118
if((sfdc->flags&VC_ENCODE) && sfdc->data)
1119
free(sfdc->data);
1120
if(sfdc->base)
1121
free(sfdc->base);
1122
free(sfdc);
1123
}
1124
1125
return NIL(Vcsfio_t*);
1126
}
1127
1128
#if _SFIO_H != 1
1129
1130
typedef struct _rsrv_s Rsrv_t;
1131
struct _rsrv_s
1132
{ Rsrv_t* next;
1133
Sfio_t* f; /* file stream for I/O */
1134
Void_t* data; /* reserved data */
1135
ssize_t dtsz; /* amount of data */
1136
ssize_t size; /* allocated buf size */
1137
};
1138
1139
#if __STD_C
1140
static Rsrv_t* vcsfrsrv(Sfio_t* f, ssize_t n)
1141
#else
1142
static Rsrv_t* vcsfrsrv(f, n)
1143
Sfio_t* f; /* stream to to create reserve buffer */
1144
ssize_t n; /* <0: remove, 0: find, >0: buffer size */
1145
#endif
1146
{
1147
Rsrv_t *p, *r;
1148
static Rsrv_t *Rsrv; /* linked list */
1149
1150
for(p = NIL(Rsrv_t*), r = Rsrv; r; p = r, r = r->next)
1151
if(r->f == f)
1152
break;
1153
1154
if(!r) /* create a new reserve structure if requested */
1155
{ if(n <= 0)
1156
return NIL(Rsrv_t*);
1157
if(!(r = (Rsrv_t*)calloc(1,sizeof(Rsrv_t))) )
1158
return NIL(Rsrv_t*);
1159
r->f = f;
1160
}
1161
else
1162
{ if(p) /* remove from list */
1163
p->next = r->next;
1164
else Rsrv = r->next;
1165
1166
if(n < 0) /* remove all together */
1167
{ if(r->data && r->size > 0)
1168
free(r->data);
1169
free(r);
1170
return NIL(Rsrv_t*);
1171
}
1172
}
1173
1174
if(n > r->size) /* allocate buffer as necessary */
1175
{ if(r->data)
1176
free(r->data);
1177
r->size = r->dtsz = 0;
1178
if(!(r->data = malloc(n)) )
1179
{ free(r);
1180
return NIL(Rsrv_t*);
1181
}
1182
else r->size = n;
1183
}
1184
1185
r->next = Rsrv; Rsrv = r;
1186
return r;
1187
}
1188
1189
#if __STD_C
1190
Void_t* sfreserve(Sfio_t* f, ssize_t n, int type)
1191
#else
1192
Void_t* sfreserve(f, n, type)
1193
Sfio_t* f;
1194
ssize_t n;
1195
int type;
1196
#endif
1197
{
1198
Rsrv_t *r;
1199
Sfoff_t here = 0;
1200
1201
n = n < 0 ? -n : n;
1202
1203
if(type == SF_LASTR)
1204
return (!(r = vcsfrsrv(f,0)) || r->dtsz <= 0 ) ? NIL(Void_t*) : r->data;
1205
1206
if(!(r = vcsfrsrv(f, n)) ) /* find/create reserve structure */
1207
return NIL(Void_t*);
1208
1209
if(type == SF_LOCKR)
1210
if((here = sfseek(f, (Sfoff_t)0, 1)) < 0 )
1211
return NIL(Void_t*);
1212
1213
if((r->dtsz = sfread(f, r->data, n)) > 0 )
1214
if(type == SF_LOCKR)
1215
sfseek(f, here, 0);
1216
1217
return r->dtsz >= n ? r->data : NIL(Void_t*);
1218
}
1219
1220
#if __STD_C
1221
ssize_t sfvalue(Sfio_t* f)
1222
#else
1223
ssize_t sfvalue(f)
1224
Sfio_t* f;
1225
#endif
1226
{
1227
Rsrv_t *r;
1228
return (r = vcsfrsrv(f, 0)) ? r->dtsz : (Sfoff_t)(-1);
1229
}
1230
1231
#if __STD_C
1232
char* sfgetr(Sfio_t* f, int nl, int type)
1233
#else
1234
char* sfgetr(f, nl, type)
1235
Sfio_t* f;
1236
int nl;
1237
int type;
1238
#endif
1239
{
1240
Rsrv_t *r;
1241
1242
if(!(r = vcsfrsrv(f, 1024)) )
1243
return NIL(char*);
1244
if(!fgets(r->data, 1024, f) )
1245
return NIL(char*);
1246
if(type > 0)
1247
{ nl = strlen(r->data);
1248
((char*)r->data)[nl-1] = 0;
1249
}
1250
return (char*)r->data;
1251
}
1252
1253
#if __STD_C
1254
int sfclose(Sfio_t* f)
1255
#else
1256
int sfclose(f)
1257
Sfio_t* f;
1258
#endif
1259
{ vcsfrsrv(f, -1);
1260
fclose(f);
1261
return 0;
1262
}
1263
1264
#if __STD_C
1265
Sfoff_t sfsize(Sfio_t* f)
1266
#else
1267
Sfoff_t sfsize(f)
1268
Sfio_t* f;
1269
#endif
1270
{
1271
Sfoff_t pos, siz;
1272
if(fseek(f, (long)0, 1) < 0 )
1273
return -1;
1274
pos = (Sfoff_t)ftell(f);
1275
fseek(f, (long)0, 2);
1276
siz = (Sfoff_t)ftell(f);
1277
fseek(f, (long)pos, 0);
1278
return siz;
1279
}
1280
1281
#if __STD_C
1282
ssize_t vcsfread(Vcsfio_t* vcf, Void_t* buf, size_t n)
1283
#else
1284
ssize_t vcsfread(vcf, buf, n)
1285
Vcsfio_t* vcf;
1286
Void_t* buf;
1287
size_t n;
1288
#endif
1289
{
1290
return vcsfdcread(((Sfdc_t*)vcf)->sf, buf, n, (Sfdisc_t*)vcf);
1291
}
1292
1293
#if __STD_C
1294
ssize_t vcsfwrite(Vcsfio_t* vcf, const Void_t* buf, size_t n)
1295
#else
1296
ssize_t vcsfwrite(vcf, buf, n)
1297
Vcsfio_t* vcf;
1298
Void_t* buf;
1299
size_t n;
1300
#endif
1301
{
1302
return vcsfdcwrite(((Sfdc_t*)vcf)->sf, buf, n, (Sfdisc_t*)vcf);
1303
}
1304
1305
#if __STD_C
1306
int vcsfsync(Vcsfio_t* vcf)
1307
#else
1308
int vcsfsync(vcf)
1309
Vcsfio_t* vcf;
1310
#endif
1311
{
1312
return vcsfdcexcept(((Sfdc_t*)vcf)->sf, SF_SYNC, 0, (Sfdisc_t*)vcf);
1313
}
1314
1315
#if __STD_C
1316
int vcsfclose(Vcsfio_t* vcf)
1317
#else
1318
int vcsfclose(vcf)
1319
Vcsfio_t* vcf;
1320
#endif
1321
{
1322
Sfio_t *sf = ((Sfdc_t*)vcf)->sf;
1323
1324
if(vcsfdcexcept(sf, SF_CLOSING, 0, (Sfdisc_t*)vcf) < 0)
1325
return -1;
1326
if(sfclose(sf) != 0)
1327
return -1;
1328
return 0;
1329
}
1330
1331
#endif /*!SFIO_H*/
1332
1333