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 <gsf@research.att.com> *
18 * *
19 ***********************************************************************/
20 #pragma prototyped
21 /*
22 * opaque method
23 *
24 * Glenn Fowler
25 * AT&T Research
26 */
27
28 static const char usage[] =
29 "[+DESCRIPTION?The \bdss\b opaque method handles anonymous fixed record "
30 "data. Field names and expressions are not supported.]"
31 "[n:name?The magic header generic data/application name.]:[name]"
32 "[s:size?The fixed record size; must be specified.]#[size]"
33 "[t:type?The magic header specific data type.]:[type]"
34 "[v:version?The magic header version stamp, either \aYYYYMMDD\a or"
35 " \a0xWWXXYYZZ\a.]#[version]"
36 ;
37
38 #include <dsslib.h>
39 #include <magicid.h>
40
41 struct Opaque_s; typedef struct Opaque_s Opaque_t;
42
43 struct Opaque_s
44 {
45 Dssmeth_t meth;
46 Magicid_t magic;
47 };
48
49 extern Dsslib_t dss_lib_opaque;
50
51 /*
52 * identf
53 */
54
55 static int
opaqueident(Dssfile_t * file,void * buf,size_t size,Dssdisc_t * disc)56 opaqueident(Dssfile_t* file, void* buf, size_t size, Dssdisc_t* disc)
57 {
58 register Opaque_t* opaque = (Opaque_t*)file->dss->meth->data;
59 register Magicid_t* magic = (Magicid_t*)buf;
60
61 if (size < opaque->magic.size)
62 return 0;
63 if (opaque->magic.magic)
64 {
65 if (magic->magic != opaque->magic.magic)
66 return 0;
67 if (magic->size != opaque->magic.size)
68 return 0;
69 if (!streq(magic->name, opaque->magic.name))
70 return 0;
71 if (!streq(magic->type, opaque->magic.type))
72 return 0;
73 if (opaque->magic.version && magic->version > opaque->magic.version)
74 return 0;
75 file->skip = opaque->magic.size;
76 }
77 return 1;
78 }
79
80 /*
81 * opaque fopenf
82 */
83
84 static int
opaquefopen(Dssfile_t * file,Dssdisc_t * disc)85 opaquefopen(Dssfile_t* file, Dssdisc_t* disc)
86 {
87 file->data = &((Opaque_t*)file->dss->meth->data)->magic.size;
88 if (file->skip && !sfreserve(file->io, file->skip, 0))
89 {
90 if (disc->errorf)
91 (*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "header read error");
92 return -1;
93 }
94 return 0;
95 }
96
97 /*
98 * opaque fclosef
99 */
100
101 static int
opaquefclose(Dssfile_t * file,Dssdisc_t * disc)102 opaquefclose(Dssfile_t* file, Dssdisc_t* disc)
103 {
104 if (!file)
105 return -1;
106 return 0;
107 }
108
109 /*
110 * opaque readf
111 */
112
113 static int
opaqueread(register Dssfile_t * file,register Dssrecord_t * record,Dssdisc_t * disc)114 opaqueread(register Dssfile_t* file, register Dssrecord_t* record, Dssdisc_t* disc)
115 {
116 record->data = sfreserve(file->io, *((size_t*)file->data), 0);
117 record->size = sfvalue(file->io);
118 if (record->data)
119 return 1;
120 if (record->size && disc->errorf)
121 (*disc->errorf)(NiL, disc, 2, "%slast record truncated -- record ignored", cxlocation(file->dss->cx, record));
122 return 0;
123 }
124
125 /*
126 * opaque writef
127 */
128
129 static int
opaquewrite(Dssfile_t * file,Dssrecord_t * record,Dssdisc_t * disc)130 opaquewrite(Dssfile_t* file, Dssrecord_t* record, Dssdisc_t* disc)
131 {
132 return sfwrite(file->io, record->data, record->size) == record->size ? 0 : -1;
133 }
134
135 static Dssformat_t opaque_format =
136 {
137 "opaque",
138 "opaque format (2010-05-28)",
139 CXH,
140 opaqueident,
141 opaquefopen,
142 opaqueread,
143 opaquewrite,
144 0,
145 opaquefclose,
146 0,
147 0,
148 0
149 };
150
151 /*
152 * methf
153 */
154
155 static Dssmeth_t*
opaquemeth(const char * name,const char * options,const char * schema,Dssdisc_t * disc,Dssmeth_t * meth)156 opaquemeth(const char* name, const char* options, const char* schema, Dssdisc_t* disc, Dssmeth_t* meth)
157 {
158 register Opaque_t* opaque;
159 char* s;
160
161 if (!(opaque = newof(0, Opaque_t, 1, 0)))
162 {
163 if (disc->errorf)
164 (*disc->errorf)(NiL, disc, 2, "out of space");
165 return 0;
166 }
167 opaque->meth = *meth;
168 opaque->meth.data = opaque;
169 if (options)
170 {
171 if (dssoptlib(meth->cx->buf, &dss_lib_opaque, usage, disc))
172 goto drop;
173 s = sfstruse(meth->cx->buf);
174 for (;;)
175 {
176 switch (optstr(options, s))
177 {
178 case 'n':
179 opaque->magic.magic = MAGICID;
180 strncopy(opaque->magic.name, opt_info.arg, sizeof(opaque->magic.name));
181 continue;
182 case 's':
183 opaque->magic.size = opt_info.num;
184 continue;
185 case 't':
186 opaque->magic.magic = MAGICID;
187 strncopy(opaque->magic.type, opt_info.arg, sizeof(opaque->magic.type));
188 continue;
189 case 'v':
190 opaque->magic.magic = MAGICID;
191 opaque->magic.version = opt_info.num;
192 continue;
193 case '?':
194 if (disc->errorf)
195 (*disc->errorf)(NiL, disc, ERROR_USAGE|4, "%s", opt_info.arg);
196 goto drop;
197 case ':':
198 if (disc->errorf)
199 (*disc->errorf)(NiL, disc, 2, "%s", opt_info.arg);
200 goto drop;
201 }
202 break;
203 }
204 }
205 if (!opaque->magic.size)
206 {
207 if (disc->errorf)
208 (*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "data size must be specified");
209 goto drop;
210 }
211 dtinsert(opaque->meth.formats, &opaque_format);
212 return &opaque->meth;
213 drop:
214 free(opaque);
215 return 0;
216 }
217
218 static Dssmeth_t method =
219 {
220 "opaque",
221 "opaque fixed record data with optional magic",
222 CXH,
223 opaquemeth
224 };
225
226 Dsslib_t dss_lib_opaque =
227 {
228 "opaque",
229 "opaque method"
230 "[-1ls5Pp0?\n@(#)$Id: dss opaque method (AT&T Research) 2002-11-22 $\n]"
231 USAGE_LICENSE,
232 CXH,
233 0,
234 &method
235 };
236