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 <glenn.s.fowler@gmail.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