Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libardir/ar-omf.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 2002-2012 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
* David Korn <[email protected]> *
19
* *
20
***********************************************************************/
21
#pragma prototyped
22
/*
23
* omf archive format method
24
*/
25
26
#include <ardirlib.h>
27
#include <cdt.h>
28
#include <omf.h>
29
30
#ifndef EILSEQ
31
#define EILSEQ EINVAL
32
#endif
33
34
#define FILENAME "U_w_i_n.o"
35
36
typedef struct _arfile_
37
{
38
Ardirent_t st;
39
char *alias;
40
Dtlink_t link;
41
int flags;
42
size_t toffset;
43
char suffix[4];
44
} Arfile_t;
45
46
typedef struct State_s /* method state */
47
{
48
Dt_t *dict;
49
void *addr;
50
Arfile_t lib;
51
Arfile_t *next;
52
int state;
53
} State_t;
54
55
struct Table
56
{
57
struct Table *next;
58
size_t offset;
59
size_t disp;
60
};
61
62
static int namcomp(Dt_t *dp, Void_t *left, Void_t *right, Dtdisc_t *dsp)
63
{
64
char *l= (char*)left;
65
char *r= (char*)right;
66
char *suffix;
67
if(suffix=strrchr(l,'.'))
68
return(memcmp(l,r,suffix+1-l));
69
return(strcmp(l,r));
70
}
71
72
static int offcomp(Dt_t *dp, Void_t *left, Void_t *right, Dtdisc_t *dsp)
73
{
74
off_t l= *((off_t*)left);
75
off_t r= *((off_t*)right);
76
if (l < r)
77
return -1;
78
if (l > r)
79
return 1;
80
return 0;
81
}
82
83
static Dtdisc_t namdisc =
84
{
85
offsetof(Arfile_t,st.name),-1, offsetof(Arfile_t,link), 0, 0, namcomp
86
};
87
88
static Dtdisc_t offdisc =
89
{
90
offsetof(Arfile_t,st.offset), sizeof(off_t), offsetof(Arfile_t,link), 0, 0, offcomp
91
};
92
93
static unsigned char *readint(unsigned char *cp,int *i, int big)
94
{
95
if(big)
96
{
97
*i = (*cp) | (cp[1]<<8) | (cp[2]<<16) | (cp[3]<<24);
98
return(cp+4);
99
}
100
*i = (*cp) | (cp[1]<<8);
101
return(cp+2);
102
}
103
104
static unsigned char *readindex(unsigned char *cp, int *size)
105
{
106
if(*cp&0x80)
107
{
108
*size = (*cp&0xf7)<<8 | cp[1];
109
return(cp+2);
110
}
111
*size = *cp++;
112
return(cp);
113
}
114
115
#define round(a,b) (((a)+(b)-1) &~ ((b)-1))
116
117
static unsigned int is_omf(int fd)
118
{
119
unsigned char buff[4];
120
if(read(fd,buff,4) != 4)
121
return(0);
122
if(*buff==OMF_THEADR)
123
return(buff[3]);
124
lseek(fd,(off_t)-4,SEEK_CUR);
125
errno = EILSEQ;
126
return(0);
127
}
128
129
static Arfile_t *ar_getnode(Ardir_t *ar, const char *name)
130
{
131
const char *cp;
132
Arfile_t *fp;
133
Dt_t *dp = ((State_t*)ar->data)->dict;
134
if(cp = strrchr(name,'/'))
135
name = cp+1;
136
fp = (Arfile_t*)dtmatch(dp,(void*)name);
137
if(!fp)
138
{
139
size_t len = strlen(name)+5;
140
if(!(fp = newof(0,Arfile_t,1,len)))
141
return(0);
142
fp->st.name = (char*)(fp+1);
143
memcpy((char*)fp->st.name,name,len);
144
if(!strrchr(fp->st.name,'.'))
145
{
146
fp->st.name[len-5] = '.';
147
fp->st.name[len-4] = 0;
148
}
149
fp->suffix[0] = 'o';
150
fp->suffix[1] = 0;
151
fp->st.mtime = ar->st.st_mtime;
152
fp->st.mode = ar->st.st_mode&(S_IRWXU|S_IRWXG|S_IRWXO);
153
fp->st.uid = ar->st.st_uid;
154
fp->st.gid = ar->st.st_gid;
155
dtinsert(dp,fp);
156
}
157
return(fp);
158
}
159
160
/*
161
* closef
162
*/
163
164
static int
165
omfclose(Ardir_t* ar)
166
{
167
State_t *sp = (State_t*)ar->data;
168
Dt_t *dp = sp?sp->dict:0;
169
if(sp && dp && sp->state)
170
{
171
/* update modification times */
172
Arfile_t *fp;
173
for(fp=(Arfile_t*)dtfirst(dp); fp; fp = (Arfile_t*)dtnext(dp,fp))
174
{
175
if(fp->flags && fp->toffset>0 && lseek(ar->fd,(off_t)fp->toffset,SEEK_SET)>0)
176
{
177
write(ar->fd,(void*)&fp->st.mtime,sizeof(time_t));
178
}
179
}
180
}
181
if (sp && sp->addr)
182
free(sp->addr);
183
if (dp)
184
dtclose(dp);
185
if(sp)
186
free(sp);
187
return 0;
188
}
189
190
static size_t displacement(struct Table *tp,size_t addr)
191
{
192
size_t disp = 0;
193
while(tp)
194
{
195
disp = tp->disp;
196
if(addr>tp->offset)
197
break;
198
tp = tp->next;
199
}
200
return(disp);
201
}
202
203
static void omfload(Ardir_t *ar,unsigned char *base, unsigned char *last, struct Table *tp, int dmars)
204
{
205
State_t *sp = (State_t*)ar->data;
206
unsigned char *cp=base, *end=last;
207
int *ip;
208
Arfile_t *fp;
209
int len;
210
struct Table *tpnext;
211
if(dmars)
212
{
213
/* string table at the top */
214
while(*cp)
215
cp += strlen((char*)cp)+1;
216
while(cp[4]==0)
217
cp++;
218
}
219
else
220
{
221
readint(cp,&len,1);
222
end = base + len;
223
}
224
for(ip=(int*)cp; (unsigned char*)(ip+6) < end; ip+=7)
225
{
226
if(dmars)
227
len = *ip;
228
else
229
readint((unsigned char*)ip,&len,1);
230
if(base+len >= last)
231
break;
232
if(!(fp = ar_getnode(ar,(char*)base+len)))
233
return;
234
fp->st.mtime = (time_t)ip[1];
235
fp->st.mode = (mode_t)ip[2];
236
fp->st.uid = (uid_t)ip[3];
237
fp->st.gid = (gid_t)ip[4];
238
memcpy(fp->suffix,&ip[5],sizeof(fp->suffix));
239
fp->toffset = ((char*)&ip[1])-(char*)(sp->addr);
240
fp->toffset += displacement(tp,((unsigned char*)&ip[1])-base);
241
if(ip[6])
242
fp->alias = (char*)base+ip[6];
243
244
}
245
while(tp)
246
{
247
tpnext = tp->next;
248
free((void*)tp);
249
tp = tpnext;
250
}
251
}
252
/*
253
* openf
254
*/
255
256
static int
257
omfopen(Ardir_t* ar, char* buf, size_t size)
258
{
259
State_t* state;
260
int pagesize;
261
unsigned char *addr, *addrstart, *addrmax, *begin,*cp, *base=0, *last;
262
char name[PATH_MAX];
263
Arfile_t *fp;
264
struct Table *tp=0, *tpnew;
265
int dmars=0,n,type,special=0,len;
266
267
if (ar->fd>=0 && (size<=0 || *((unsigned char*)buf) != OMF_LIBHDR))
268
return -1;
269
if(!(state = newof(0,State_t,1,0)))
270
return -1;
271
ar->data = (void*)state;
272
if(!(state->dict = dtopen(&namdisc,Dtoset)))
273
goto nope;
274
if(ar->fd<0)
275
return 0;
276
size = (size_t)ar->st.st_size;
277
if(!(addr = (unsigned char*)malloc(size)))
278
goto nope;
279
addrstart = addr;
280
state->addr = (void*)addr;
281
if(lseek(ar->fd,(off_t)0, SEEK_SET)<0)
282
goto nope;
283
if(read(ar->fd,(void*)addr,size) < 0)
284
goto nope;
285
addrmax=addr+size;
286
addr = readint(addr+1,&n,0);
287
pagesize = n+3;
288
while((addr+=n) < addrmax)
289
{
290
if(*addr==OMF_LIBDHD)
291
return(0);
292
cp = addr;
293
type = *addr;
294
addr = readint(addr+1,&n,0);
295
if((type&~1)==OMF_MODEND)
296
{
297
if(special)
298
{
299
if(base)
300
omfload(ar,base,last,tp,dmars);
301
special = 0;
302
}
303
else
304
{
305
if(!(fp = ar_getnode(ar,name)))
306
return(0);
307
fp->st.offset = begin-addrstart;
308
fp->st.size = addr+n-begin;
309
}
310
addr +=n;
311
addr = addrstart + round(addr-addrstart,pagesize);
312
n = 0;
313
}
314
else if(type==OMF_THEADR)
315
{
316
if(memcmp(addr+1,FILENAME,sizeof(FILENAME)-2))
317
{
318
begin = addr+1;
319
len = *addr;
320
if(addr[1]=='.' && addr[2]=='\\')
321
{
322
len -=2;
323
begin +=2;
324
}
325
memcpy(name,begin,len);
326
name[len] = 0;
327
begin = cp;
328
}
329
else
330
special = 1;
331
}
332
else if((type&~1)==OMF_LEDATA && special)
333
{
334
int offset;
335
cp = readindex(addr,&len);
336
cp= readint(cp,&offset,type&1);
337
dmars = (type&1);
338
len = (n-1) - (cp-addr);
339
if(!(tpnew = newof(0,struct Table,1,0)))
340
return(0);
341
tpnew->next = tp;
342
tp = tpnew;
343
if(!base)
344
base = last = cp;
345
else
346
{
347
tp->disp = cp - (base+offset);
348
memcpy(base+offset,cp,len);
349
}
350
tp->offset = offset;
351
last += len;
352
}
353
}
354
nope:
355
omfclose(ar);
356
return -1;
357
}
358
359
/*
360
* nextf
361
*/
362
363
static Ardirent_t*
364
omfnext(Ardir_t* ar)
365
{
366
State_t *ap = (State_t*)ar->data;
367
Arfile_t *fp;
368
if(ap->next)
369
ap->next = (Arfile_t*)dtnext(ap->dict,ap->next);
370
else
371
{
372
dtdisc(ap->dict, &offdisc, 0);
373
ap->next = (Arfile_t*)dtfirst(ap->dict);
374
}
375
if(!(fp = ap->next))
376
return(0);
377
if(*fp->suffix)
378
{
379
char *last = strrchr(fp->st.name,'.');
380
if(last)
381
last++;
382
else
383
last = fp->st.name+strlen(fp->st.name);
384
memcpy((void*)last,(void*)fp->suffix,sizeof(fp->suffix));
385
}
386
if(!(ar->flags&ARDIR_FORCE) && fp->alias)
387
fp->st.name = fp->alias;
388
return(&fp->st);
389
}
390
391
392
/*
393
* returns -1 for error
394
* returns 0 for ignore
395
* returns ARDIR_CREATE add
396
* returns ARDIR_REPLACE replace
397
* returns ARDIR_DELETE delete
398
*/
399
int omfinsert(Ardir_t *ar, const char *name, int op)
400
{
401
char *suffix,fname[256];
402
Dt_t *dp = ((State_t*)ar->data)->dict;
403
int m,n,fd;
404
Arfile_t *fp;
405
struct stat statb;
406
int ret = -1;
407
if(suffix=strrchr(name,'.'))
408
n = (const char*)++suffix - name;
409
else
410
n = strlen(name);
411
if((fd=open(name,O_RDONLY|O_cloexec))>=0)
412
{
413
if(fstat(fd,&statb)>=0 && (m=is_omf(fd)))
414
{
415
read(fd,(void*)fname,m);
416
fname[m] = 0;
417
m = memcmp((void*)fname,(void*)name,n);
418
ret = ARDIR_CREATE;
419
}
420
close(fd);
421
}
422
fp = (Arfile_t*)dtmatch(dp,(void*)fname);
423
if(ret<0 && !((op&ARDIR_DELETE) && fp))
424
return -1;
425
if(fp)
426
{
427
if(op&ARDIR_DELETE)
428
{
429
dtdelete(dp,(Void_t*)fp);
430
return ARDIR_DELETE;
431
}
432
if(fp->st.mtime>= statb.st_mtime && (op&ARDIR_NEWER))
433
return 0 ;
434
ret = ARDIR_REPLACE;
435
}
436
else
437
{
438
if(op&ARDIR_DELETE)
439
return -1 ;
440
if(!(fp = (Arfile_t*)ar_getnode(ar,fname)))
441
return -1 ;
442
}
443
fp->st.mode = statb.st_mode&(S_IRWXU|S_IRWXG|S_IRWXO);
444
fp->st.uid = statb.st_uid;
445
fp->st.gid = statb.st_gid;
446
fp->st.mtime = statb.st_mtime;
447
fp->st.size = (size_t)statb.st_size;
448
fp->st.offset = ++ar->st.st_size;
449
if(m)
450
fp->alias = (char*)name;
451
if(suffix)
452
memcpy(fp->suffix,suffix,sizeof(fp->suffix));
453
return(ret);
454
}
455
456
const char *omfspecial(Ardir_t *ar)
457
{
458
return(FILENAME);
459
}
460
461
/*
462
* changef
463
*/
464
465
static int
466
omfchange(Ardir_t* ar, Ardirent_t* ent)
467
{
468
State_t *sp = (State_t*)ar->data;
469
Arfile_t *fp = (Arfile_t*)ent;
470
fp->flags = 1;
471
sp->state = 1;
472
return 0;
473
}
474
475
Ardirmeth_t ar_omf =
476
{
477
"omf",
478
"omf archive",
479
omfopen,
480
omfnext,
481
omfchange,
482
omfinsert,
483
omfspecial,
484
omfclose,
485
ar_omf_next
486
};
487
488