Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libdss/dssfile.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 2002-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
* dss file support
23
*
24
* Glenn Fowler
25
* AT&T Research
26
*/
27
28
#include "dsshdr.h"
29
30
#include <ls.h>
31
#include <pzip.h>
32
33
/*
34
* not open for read
35
*/
36
37
static int
38
noreadf(Dssfile_t* file, Dssrecord_t* record, Dssdisc_t* disc)
39
{
40
if (disc->errorf)
41
(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "%s: not open for read", file->path);
42
return -1;
43
}
44
45
/*
46
* empty input
47
*/
48
49
static int
50
nullreadf(Dssfile_t* file, Dssrecord_t* record, Dssdisc_t* disc)
51
{
52
return 0;
53
}
54
55
/*
56
* not open for write
57
*/
58
59
static int
60
nowritef(Dssfile_t* file, Dssrecord_t* record, Dssdisc_t* disc)
61
{
62
if (disc->errorf)
63
(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "%s: not open for write", file->path);
64
return -1;
65
}
66
67
/*
68
* file open
69
*/
70
71
Dssfile_t*
72
dssfopen(Dss_t* dss, const char* path, Sfio_t* io, Dssflags_t flags, Dssformat_t* format)
73
{
74
Dssfile_t* file;
75
Vmalloc_t* vm;
76
char* s;
77
size_t n;
78
int i;
79
struct stat st;
80
Sfdisc_t top;
81
char buf[PATH_MAX];
82
83
if (flags & DSS_FILE_WRITE)
84
{
85
if (io)
86
{
87
memset(&top, 0, sizeof(top));
88
if (sfdisc(io, &top))
89
{
90
n = top.disc == &dss->state->compress_preferred;
91
sfdisc(io, SF_POPDISC);
92
if (n)
93
{
94
sfdisc(io, SF_POPDISC);
95
sfdczip(io, path, dss->meth->compress ? dss->meth->compress : "gzip", dss->disc->errorf);
96
}
97
}
98
}
99
if (dss->flags & DSS_APPEND)
100
flags |= DSS_FILE_APPEND;
101
}
102
if (!path || !*path || streq(path, "-"))
103
{
104
if (flags & DSS_FILE_WRITE)
105
{
106
if (io)
107
path = "output-stream";
108
else
109
{
110
path = "/dev/stdout";
111
io = sfstdout;
112
}
113
}
114
else if (io)
115
path = "input-stream";
116
else
117
{
118
path = "/dev/stdin";
119
io = sfstdin;
120
}
121
flags |= DSS_FILE_KEEP;
122
}
123
else if (io)
124
flags |= DSS_FILE_KEEP;
125
else if (flags & DSS_FILE_WRITE)
126
{
127
if (!(io = sfopen(NiL, path, (flags & DSS_FILE_APPEND) ? "a" : "w")))
128
{
129
if (dss->disc->errorf)
130
(*dss->disc->errorf)(NiL, dss->disc, ERROR_SYSTEM|2, "%s: cannot open", path);
131
return 0;
132
}
133
}
134
else if (!(io = dssfind(path, NiL, DSS_VERBOSE, buf, sizeof(buf), dss->disc)))
135
return 0;
136
else
137
path = (const char*)buf;
138
if (!(vm = vmopen(Vmdcheap, Vmbest, 0)))
139
{
140
if (dss->disc->errorf)
141
(*dss->disc->errorf)(NiL, dss->disc, ERROR_SYSTEM|2, "out of space");
142
return 0;
143
}
144
if (!(file = vmnewof(vm, 0, Dssfile_t, 1, strlen(path) + 1)))
145
{
146
if (dss->disc->errorf)
147
(*dss->disc->errorf)(NiL, dss->disc, ERROR_SYSTEM|2, "out of space");
148
if (!(flags & DSS_FILE_KEEP))
149
sfclose(io);
150
vmclose(vm);
151
return 0;
152
}
153
strcpy(file->path = (char*)(file + 1), path);
154
file->dss = dss;
155
file->vm = vm;
156
file->io = io;
157
file->flags = flags;
158
if (flags & DSS_FILE_WRITE)
159
{
160
if (!(file->format = format) && !(file->format = dss->format))
161
{
162
if (dss->disc->errorf)
163
(*dss->disc->errorf)(NiL, dss->disc, 2, "output method format must be specified");
164
if (!(flags & DSS_FILE_KEEP))
165
sfclose(io);
166
return 0;
167
}
168
file->readf = noreadf;
169
file->writef = file->format->writef;
170
}
171
else
172
{
173
if (sfsize(file->io) || !fstat(sffileno(file->io), &st) && (S_ISFIFO(st.st_mode)
174
#ifdef S_ISSOCK
175
|| S_ISSOCK(st.st_mode)
176
#endif
177
))
178
{
179
if (sfdczip(file->io, file->path, NiL, dss->disc->errorf) < 0)
180
{
181
if (dss->disc->errorf)
182
(*dss->disc->errorf)(NiL, dss->disc, ERROR_SYSTEM|2, "%s: inflate error", file->path);
183
dssfclose(file);
184
return 0;
185
}
186
s = sfreserve(file->io, SF_UNBOUND, SF_LOCKR);
187
n = sfvalue(file->io);
188
if (!s)
189
{
190
if (n && dss->disc->errorf)
191
(*dss->disc->errorf)(NiL, dss->disc, ERROR_SYSTEM|2, "%s: cannot peek", file->path);
192
dssfclose(file);
193
return 0;
194
}
195
for (file->format = (Dssformat_t*)dtfirst(dss->meth->formats); file->format && !(i = (*file->format->identf)(file, s, n, dss->disc)); file->format = (Dssformat_t*)dtnext(dss->meth->formats, file->format));
196
sfread(file->io, s, 0);
197
if (!file->format)
198
{
199
if (dss->disc->errorf)
200
(*dss->disc->errorf)(NiL, dss->disc, 2, "%s: unknown %s format", file->path, dss->meth->name);
201
dssfclose(file);
202
return 0;
203
}
204
if (i < 0)
205
return 0;
206
if (format && format != file->format)
207
{
208
if (dss->disc->errorf)
209
(*dss->disc->errorf)(NiL, dss->disc, 2, "%s: %s file format %s incompatible with %s", file->path, dss->meth->name, file->format->name, format->name);
210
dssfclose(file);
211
return 0;
212
}
213
if ((dss->flags & DSS_VERBOSE) && dss->disc->errorf)
214
(*dss->disc->errorf)(dss, dss->disc, 1, "%s: %s method %s format", file->path, dss->meth->name, file->format->name);
215
file->readf = file->format->readf;
216
}
217
else
218
{
219
file->format = format ? format : dss->format ? dss->format : (Dssformat_t*)dtfirst(dss->meth->formats);
220
file->readf = nullreadf;
221
}
222
file->writef = nowritef;
223
if (!dss->format)
224
dss->format = file->format;
225
}
226
if (!file->format)
227
{
228
if (dss->disc->errorf)
229
(*dss->disc->errorf)(NiL, dss->disc, 2, "%s: %s method did not set file format", file->path, dss->meth->name);
230
dssfclose(file);
231
return 0;
232
}
233
file->record.file = file;
234
if ((*file->format->openf)(file, dss->disc))
235
{
236
dssfclose(file);
237
return 0;
238
}
239
return file;
240
}
241
242
/*
243
* file close
244
*/
245
246
int
247
dssfclose(Dssfile_t* file)
248
{
249
int r;
250
Dss_t* dss;
251
252
if (!file)
253
return -1;
254
dss = file->dss;
255
if (!file->io)
256
r = -1;
257
else
258
{
259
r = file->format ? (*file->format->closef)(file, dss->disc) : 0;
260
if ((file->flags & DSS_FILE_WRITE) && sfsync(file->io))
261
{
262
if (dss->disc->errorf)
263
(*dss->disc->errorf)(NiL, dss->disc, ERROR_SYSTEM|2, "%s: write error", file->path);
264
r = -1;
265
}
266
if (!(file->flags & DSS_FILE_KEEP))
267
sfclose(file->io);
268
if (!r && (file->flags & DSS_FILE_ERROR))
269
r = -1;
270
}
271
vmclose(file->vm);
272
return r;
273
}
274
275
/*
276
* file read
277
*/
278
279
Dssrecord_t*
280
dssfread(Dssfile_t* file)
281
{
282
int r;
283
284
file->count++;
285
file->offset += file->length;
286
if ((r = (*file->readf)(file, &file->record, file->dss->disc)) <= 0)
287
{
288
if (r < 0)
289
file->flags |= DSS_FILE_ERROR;
290
file->count--;
291
return 0;
292
}
293
file->length = sftell(file->io) - file->offset;
294
return &file->record;
295
}
296
297
/*
298
* file write
299
*/
300
301
int
302
dssfwrite(Dssfile_t* file, Dssrecord_t* record)
303
{
304
return (*file->writef)(file, record, file->dss->disc);
305
}
306
307
/*
308
* file tell
309
*/
310
311
Sfoff_t
312
dssftell(Dssfile_t* file)
313
{
314
return file->seekf ? (*file->seekf)(file, DSS_TELL, file->dss->disc) : file->offset;
315
}
316
317
/*
318
* file seek
319
*/
320
321
int
322
dssfseek(Dssfile_t* file, Sfoff_t offset)
323
{
324
return (file->seekf ? (*file->seekf)(file, offset, file->dss->disc) : sfseek(file->io, offset, SEEK_SET)) == offset ? 0 : -1;
325
}
326
327
/*
328
* save record state
329
*/
330
331
Dssrecord_t*
332
dsssave(Dssrecord_t* record)
333
{
334
return record->file->format->savef ? (*record->file->format->savef)(record->file, record, record->file->dss->disc) : (Dssrecord_t*)0;
335
}
336
337
/*
338
* drop saved record
339
*/
340
341
int
342
dssdrop(Dssrecord_t* record)
343
{
344
return record->file->format->dropf ? (*record->file->format->dropf)(record->file, record, record->file->dss->disc) : -1;
345
}
346
347
/*
348
* common diagnostics
349
*/
350
351
Dssrecord_t*
352
dss_no_fread(Dssfile_t* file, Dssrecord_t* record, Dssdisc_t* disc)
353
{
354
if (disc->errorf)
355
(*disc->errorf)(NiL, disc, 2, "%s: %s file format %s read not implemented", file->path, file->dss->meth->name, file->format->name);
356
return 0;
357
}
358
359
int
360
dss_no_fwrite(Dssfile_t* file, Dssrecord_t* record, Dssdisc_t* disc)
361
{
362
if (disc->errorf)
363
(*disc->errorf)(NiL, disc, 2, "%s: %s file format %s write not implemented", file->path, file->dss->meth->name, file->format->name);
364
return -1;
365
}
366
367
Sfoff_t
368
dss_no_fseek(Dssfile_t* file, Sfoff_t offset, Dssdisc_t* disc)
369
{
370
if (disc->errorf)
371
(*disc->errorf)(NiL, disc, 2, "%s: %s file format %s seek not implemented", file->path, file->dss->meth->name, file->format->name);
372
return -1;
373
}
374
375