Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libardir/ardir.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
/*
24
* archive scan/touch/extract implementation
25
*/
26
27
#include <ardirlib.h>
28
29
Ardir_t*
30
ardiropen(const char* file, Ardirmeth_t* meth, int flags)
31
{
32
Ardir_t* ar;
33
char* skip;
34
off_t pos;
35
ssize_t n = 0;
36
char buf[1024];
37
38
if (!(ar = newof(0, Ardir_t, 1, strlen(file) + 1)))
39
return 0;
40
strcpy(ar->path = (char*)(ar + 1), file);
41
ar->flags = flags;
42
if (((ar->fd = open(file, (flags & ARDIR_CREATE) ? (O_CREAT|O_TRUNC|O_RDWR|O_BINARY|O_cloexec) : (flags & ARDIR_UPDATE) ? (O_RDWR|O_BINARY|O_cloexec) : (O_RDONLY|O_BINARY|O_cloexec))) < 0 || fstat(ar->fd, &ar->st) || !S_ISREG(ar->st.st_mode)) && (!meth || !(flags & ARDIR_FORCE)))
43
{
44
ardirclose(ar);
45
return 0;
46
}
47
if (ar->fd >= 0 && ((pos = lseek(ar->fd, (off_t)0, SEEK_CUR)) < 0 || (n = read(ar->fd, buf, sizeof(buf))) < 0 || lseek(ar->fd, pos, SEEK_SET) != pos))
48
{
49
ardirclose(ar);
50
return 0;
51
}
52
if (!(ar->meth = meth))
53
{
54
skip = getenv("_AST_DEBUG_ARDIR_SKIP");
55
for (meth = ar_first_method; ar->meth = meth; meth = meth->next)
56
if ((!skip || !strmatch(meth->name, skip)) && !(*meth->openf)(ar, buf, n))
57
break;
58
if (!(ar->meth = meth))
59
{
60
ardirclose(ar);
61
return 0;
62
}
63
}
64
else if ((*meth->openf)(ar, buf, n))
65
{
66
ardirclose(ar);
67
return 0;
68
}
69
return ar;
70
}
71
72
Ardirent_t*
73
ardirnext(Ardir_t* ar)
74
{
75
return (ar->meth && ar->meth->nextf) ? (*ar->meth->nextf)(ar) : (Ardirent_t*)0;
76
}
77
78
off_t
79
ardircopy(Ardir_t* ar, Ardirent_t* ent, int fd)
80
{
81
ssize_t n;
82
size_t m;
83
off_t z;
84
off_t pos;
85
char buf[1024 * 16];
86
87
if (ent->offset < 0)
88
{
89
ar->error = ENOSYS;
90
return -1;
91
}
92
pos = lseek(ar->fd, (off_t)0, SEEK_CUR);
93
if (lseek(ar->fd, ent->offset, SEEK_SET) != ent->offset)
94
return -1;
95
z = ent->size;
96
while (z > 0)
97
{
98
m = z > sizeof(buf) ? sizeof(buf) : z;
99
if ((n = read(ar->fd, buf, m)) < 0)
100
{
101
ar->error = errno;
102
break;
103
}
104
if (n == 0)
105
break;
106
if (write(fd, buf, n) != n)
107
{
108
ar->error = errno;
109
break;
110
}
111
z -= n;
112
}
113
lseek(ar->fd, pos, SEEK_SET);
114
if (z)
115
{
116
errno = EIO;
117
z = -z;
118
}
119
else
120
z = ent->size;
121
return z;
122
}
123
124
int
125
ardirchange(Ardir_t* ar, Ardirent_t* ent)
126
{
127
if (!ar->meth || !ar->meth->changef)
128
{
129
ar->error = EINVAL;
130
return -1;
131
}
132
return (*ar->meth->changef)(ar, ent);
133
}
134
135
int
136
ardirinsert(Ardir_t* ar, const char* name, int flags)
137
{
138
if (!ar->meth || !ar->meth->insertf)
139
{
140
ar->error = EINVAL;
141
return -1;
142
}
143
return (*ar->meth->insertf)(ar, name, flags);
144
}
145
146
const char*
147
ardirspecial(Ardir_t* ar)
148
{
149
if (!ar->meth || !ar->meth->specialf)
150
{
151
ar->error = EINVAL;
152
return 0;
153
}
154
return (*ar->meth->specialf)(ar);
155
}
156
157
int
158
ardirclose(Ardir_t* ar)
159
{
160
int r;
161
162
if (!ar)
163
return -1;
164
r = (ar->meth && ar->meth->closef) ? (*ar->meth->closef)(ar) : -1;
165
if (ar->error)
166
r = -1;
167
if (ar->fd >= 0)
168
close(ar->fd);
169
free(ar);
170
return r;
171
}
172
173
Ardirmeth_t*
174
ardirmeth(const char* name)
175
{
176
Ardirmeth_t* meth;
177
178
for (meth = ar_first_method; meth; meth = meth->next)
179
if (!strcasecmp(name, meth->name))
180
return meth;
181
return 0;
182
}
183
184
Ardirmeth_t*
185
ardirlist(Ardirmeth_t* meth)
186
{
187
return meth ? meth->next : ar_first_method;
188
}
189
190