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