1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1987-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  * Glenn Fowler
23  *
24  * pax pax external library support
25  */
26 
27 #include "pax.h"
28 
29 #undef	paxchecksum
30 #undef	paxcorrupt
31 #undef	paxdata
32 #undef	paxget
33 #undef	paxnext
34 #undef	paxnospace
35 #undef	paxpart
36 #undef	paxput
37 #undef	paxread
38 #undef	paxseek
39 #undef	paxstash
40 #undef	paxsync
41 #undef	paxunread
42 #undef	paxwrite
43 
44 static const char	null[] = "";
45 static const char	sep[] = ": ";
46 
47 #define TXT(s,m)	(s)?sep:null,(s)?(m):null
48 
49 static int
paxdata(Pax_t * pax,Paxarchive_t * ap,Paxfile_t * f,int fd,void * b,off_t n)50 paxdata(Pax_t* pax, Paxarchive_t* ap, Paxfile_t* f, int fd, void* b, off_t n)
51 {
52 	return holewrite(fd, b, n) == n ? 0 : -1;
53 }
54 
55 static void*
paxget(Pax_t * pax,Paxarchive_t * ap,off_t n,off_t * p)56 paxget(Pax_t* pax, Paxarchive_t* ap, off_t n, off_t* p)
57 {
58 	return bget(ap, n, p);
59 }
60 
61 static int
paxput(Pax_t * pax,Paxarchive_t * ap,off_t n)62 paxput(Pax_t* pax, Paxarchive_t* ap, off_t n)
63 {
64 	bput(ap, n);
65 	return 0;
66 }
67 
68 static off_t
paxread(Pax_t * pax,Paxarchive_t * ap,void * b,off_t n,off_t m,int must)69 paxread(Pax_t* pax, Paxarchive_t* ap, void* b, off_t n, off_t m, int must)
70 {
71 	return bread(ap, b, n, m, must);
72 }
73 
74 static off_t
paxseek(Pax_t * pax,Paxarchive_t * ap,off_t pos,int op,int hard)75 paxseek(Pax_t* pax, Paxarchive_t* ap, off_t pos, int op, int hard)
76 {
77 	return bseek(ap, pos, op, hard);
78 }
79 
80 static char*
paxstash(Pax_t * pax,Value_t * v,const char * s,size_t z)81 paxstash(Pax_t* pax, Value_t* v, const char* s, size_t z)
82 {
83 	return stash(v, s, z);
84 }
85 
86 static int
paxsync(Pax_t * pax,Paxarchive_t * ap,int hard)87 paxsync(Pax_t* pax, Paxarchive_t* ap, int hard)
88 {
89 	if (ap->io->mode == O_RDONLY)
90 		bflushin(ap, hard);
91 	else
92 		bflushout(ap);
93 	return 0;
94 }
95 
96 static int
paxunread(Pax_t * pax,Paxarchive_t * ap,void * b,off_t n)97 paxunread(Pax_t* pax, Paxarchive_t* ap, void* b, off_t n)
98 {
99 	bunread(ap, b, n);
100 	return 0;
101 }
102 
103 static int
paxwrite(Pax_t * pax,Paxarchive_t * ap,const void * b,off_t n)104 paxwrite(Pax_t* pax, Paxarchive_t* ap, const void* b, off_t n)
105 {
106 	bwrite(ap, (void*)b, n);
107 	return 0;
108 }
109 
110 static int
paxnext(Pax_t * pax,Paxarchive_t * ap,size_t c,size_t n)111 paxnext(Pax_t* pax, Paxarchive_t* ap, size_t c, size_t n)
112 {
113 	newio(ap, c, n);
114 	return 0;
115 }
116 
117 static int
paxcorrupt(Pax_t * pax,Paxarchive_t * ap,Paxfile_t * f,const char * msg)118 paxcorrupt(Pax_t* pax, Paxarchive_t* ap, Paxfile_t* f, const char* msg)
119 {
120 	(*pax->errorf)(NiL, pax, 2, "%s%s%s: %s archive corrupt at %I*u%s%s", ap->name, TXT(f, f->name), ap->format->name, sizeof(off_t), paxseek(pax, ap, 0, SEEK_CUR, 0), TXT(msg, msg));
121 	return -1;
122 }
123 
124 static int
paxchecksum(Pax_t * pax,Paxarchive_t * ap,Paxfile_t * f,unsigned long expected,unsigned long value)125 paxchecksum(Pax_t* pax, Paxarchive_t* ap, Paxfile_t* f, unsigned long expected, unsigned long value)
126 {
127 	int	z;
128 
129 	if (expected != value)
130 	{
131 		z = ((expected | value) & 0xffff0000) ? 8 : 4;
132 		(*pax->errorf)(NiL, pax, 2, "%s%s%s: %s archive checksum error -- expected %0*lx != %0*lx", ap->name, TXT(f, f->name), ap->format->name, z, expected, z, value);
133 		return -1;
134 	}
135 	return 0;
136 }
137 
138 static int
paxnospace(Pax_t * pax)139 paxnospace(Pax_t* pax)
140 {
141 	(*pax->errorf)(NiL, pax, 2, "out of space");
142 	return -1;
143 }
144 
145 /*
146  * archive part sfio discipline
147  */
148 
149 static ssize_t
part_read(Sfio_t * sp,void * buf,size_t n,Sfdisc_t * disc)150 part_read(Sfio_t* sp, void* buf, size_t n, Sfdisc_t* disc)
151 {
152 	register Part_t*	part = (Part_t*)disc;
153 	ssize_t			r;
154 
155 	if (part->n <= 0)
156 		return part->n;
157 	if (n > part->n)
158 		n = part->n;
159 	if ((r = paxread(part->pax, part->ap, buf, n, 0, 0)) > 0)
160 		part->n -= r;
161 	return r;
162 }
163 
164 static ssize_t
part_write(Sfio_t * sp,const void * buf,size_t n,Sfdisc_t * disc)165 part_write(Sfio_t* sp, const void* buf, size_t n, Sfdisc_t* disc)
166 {
167 	register Part_t*	part = (Part_t*)disc;
168 	ssize_t			r;
169 
170 	if ((r = paxwrite(part->pax, part->ap, buf, n)) > 0)
171 		part->n += r;
172 	return r;
173 }
174 
175 static Sfio_t*
paxpart(Pax_t * pax,Paxarchive_t * ap,off_t n)176 paxpart(Pax_t* pax, Paxarchive_t* ap, off_t n)
177 {
178 	register Part_t*	part;
179 
180 	static int		fd = -1;
181 
182 	if (!(part = ap->partio))
183 	{
184 		if (!(part = newof(0, Part_t, 1, 0)) || !(part->sp = sfstropen()))
185 		{
186 			paxnospace(pax);
187 			return 0;
188 		}
189 		part->sp->_flags &= ~(SF_READ|SF_WRITE|SF_STRING);
190 		if (ap->flags & PAX_IN)
191 			part->sp->_flags |= SF_READ;
192 		else
193 			part->sp->_flags |= SF_WRITE;
194 		if (fd < 0)
195 			fd = open("/dev/null", O_RDWR);
196 		part->sp->_file = fd;
197 		part->disc.readf = part_read;
198 		part->disc.writef = part_write;
199 		if (sfdisc(part->sp, &part->disc) != &part->disc)
200 		{
201 			sfclose(part->sp);
202 			free(part);
203 			return 0;
204 		}
205 		part->pax = pax;
206 		part->ap = ap;
207 		ap->partio = part;
208 	}
209 	part->n = n;
210 	return part->sp;
211 }
212 
213 /*
214  * initialize the external library callbacks
215  */
216 
217 void
paxinit(register Pax_t * pax,const char * id)218 paxinit(register Pax_t* pax, const char* id)
219 {
220 	pax->id = id;
221 	pax->errorf = errorf;
222 
223 	pax->dataf = paxdata;
224 	pax->getf = paxget;
225 	pax->partf = paxpart;
226 	pax->putf = paxput;
227 	pax->readf = paxread;
228 	pax->seekf = paxseek;
229 	pax->stashf = paxstash;
230 	pax->syncf = paxsync;
231 	pax->unreadf = paxunread;
232 	pax->writef = paxwrite;
233 
234 	pax->corruptf = paxcorrupt;
235 	pax->checksumf = paxchecksum;
236 	pax->nospacef = paxnospace;
237 
238 	pax->nextf = paxnext;
239 }
240