Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/pax/pax-mime.c
1808 views
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 <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
22
/*
23
* pax mime format
24
*/
25
26
#include "format.h"
27
28
#define MIME_HEADER 1024
29
30
typedef struct Mime_s
31
{
32
size_t fill; /* last member filler size */
33
size_t length; /* separator magic length */
34
char magic[1]; /* separator magic */
35
} Mime_t;
36
37
static int
38
mime_getprologue(Pax_t* pax, Format_t* fp, register Archive_t* ap, File_t* f, unsigned char* buf, size_t size)
39
{
40
register Mime_t* mime;
41
char* s;
42
char* t;
43
size_t n;
44
45
s = state.tmp.buffer;
46
if (paxread(pax, ap, s, (off_t)0, (off_t)MIME_HEADER, 0) <= 0)
47
return 0;
48
paxunread(pax, ap, s, MIME_HEADER);
49
if (s[0] != '-' || s[1] != '-' || !(t = (char*)memchr(s, '\n', MIME_HEADER - 2)) || (t - s + 8) >= MIME_HEADER || strncasecmp(t + 1, "Content", 7))
50
return 0;
51
n = t - s + 1;
52
if (t > s && *(t - 1) == '\r')
53
t--;
54
n = t - s;
55
if (!(mime = newof(0, Mime_t, 1, n)))
56
{
57
nospace();
58
return -1;
59
}
60
ap->data = mime;
61
mime->length = n;
62
memcpy(mime->magic, s, mime->length);
63
message((-1, "mime magic `%s'", mime->magic));
64
paxread(pax, ap, NiL, (off_t)0, n, 0);
65
return 1;
66
}
67
68
static int
69
mime_done(Pax_t* pax, register Archive_t* ap)
70
{
71
if (ap->data)
72
{
73
free(ap->data);
74
ap->data = 0;
75
}
76
return 0;
77
}
78
79
static int
80
mime_getheader(Pax_t* pax, Archive_t* ap, register File_t* f)
81
{
82
register Mime_t* mime = (Mime_t*)ap->data;
83
register char* s;
84
register char* t;
85
register char* v;
86
off_t m;
87
off_t b;
88
size_t n;
89
int loop;
90
91
if (paxread(pax, ap, s = state.tmp.buffer, mime->length + 2, mime->length + 2, 1) <= 0 || memcmp(s, mime->magic, mime->length))
92
error(3, "%s: corrupt %s format member header -- separator not found", ap->name, ap->format->name);
93
else if (*(s += mime->length) == '-' && *(s + 1) == '-')
94
{
95
while (paxread(pax, ap, s, 1, 1, 1) > 0 && *s != '\n');
96
return 0;
97
}
98
else if (*s == '\n')
99
paxunread(pax, ap, s + 1, 1);
100
else if (*s != '\r' && *(s + 1) != '\n')
101
error(3, "%s: corrupt %s format member header -- separator line not found", ap->name, ap->format->name);
102
f->name = 0;
103
for (;;)
104
{
105
for (t = (s = state.tmp.buffer) + state.buffersize - 1; s < t; s++)
106
if (paxread(pax, ap, s, 1, 1, 1) <= 0)
107
error(3, "%s: unexpected %s format EOF", ap->name, ap->format->name);
108
else if (*s == '\n')
109
{
110
if (s > state.tmp.buffer && *(s - 1) == '\r')
111
s--;
112
*s = 0;
113
break;
114
}
115
s = state.tmp.buffer;
116
if (!*s)
117
break;
118
if (strncasecmp(s, "content-", 8))
119
error(3, "%s: corrupt %s format member header", ap->name, ap->format->name);
120
if (t = strchr(s, ':'))
121
s = t + 1;
122
while (isspace(*s))
123
s++;
124
for (;;)
125
{
126
for (t = s; *s && *s != ';' && *s != '='; s++);
127
if (!(n = s - t))
128
break;
129
if (*s == '=')
130
{
131
if (*++s == '"')
132
for (v = ++s; *s && *s != '"'; s++);
133
else
134
for (v = s; *s && *s != ';'; s++);
135
}
136
else
137
v = s;
138
m = s - v;
139
if (*s)
140
*s++ = 0;
141
for (; *s == ';' || isspace(*s); s++);
142
if (!f->name && n == 4 && !strncasecmp(t, "name", 4) || n == 8 && !strncasecmp(t, "filename", 8))
143
f->name = paxstash(pax, &ap->stash.head, v, m);
144
}
145
}
146
if (!f->name)
147
{
148
if (s = strrchr(ap->name, '/'))
149
s++;
150
else
151
s = ap->name;
152
f->name = paxstash(pax, &ap->stash.head, s, strlen(s) + 16);
153
sfsprintf(f->name, ap->stash.head.size, "%s-%d", s, ap->entries + 1);
154
}
155
if (!ap->io->seekable)
156
seekable(ap);
157
f->st->st_size = 0;
158
loop = 0;
159
b = paxseek(pax, ap, 0, SEEK_CUR, 0);
160
while (s = paxget(pax, ap, 0, &m))
161
{
162
if (m < mime->length)
163
{
164
if (loop++)
165
error(3, "%s: corrupt %s format member header [too short]", ap->name, ap->format->name);
166
paxseek(pax, ap, -m, SEEK_CUR, 0);
167
paxsync(pax, ap, 0);
168
continue;
169
}
170
v = s;
171
for (t = s + m - mime->length; s = memchr(s, '-', t - s); s++)
172
if (!memcmp(s, mime->magic, mime->length))
173
{
174
paxseek(pax, ap, b, SEEK_CUR, 0);
175
paxsync(pax, ap, 0);
176
if (s > v && *(s - 1) == '\n')
177
{
178
mime->fill++;
179
if (s > (v + 1) && *(s - 2) == '\r')
180
mime->fill++;
181
}
182
f->st->st_size += (s - v) - mime->fill;
183
f->st->st_mtime = NOW;
184
f->st->st_mode = X_IFREG|X_IRUSR|X_IRGRP|X_IROTH;
185
f->st->st_uid = state.uid;
186
f->st->st_gid = state.gid;
187
f->st->st_dev = 0;
188
f->st->st_ino = 0;
189
f->st->st_nlink = 1;
190
IDEVICE(f->st, 0);
191
f->linktype = NOLINK;
192
f->linkpath = 0;
193
f->uidname = 0;
194
f->gidname = 0;
195
return 1;
196
}
197
paxseek(pax, ap, -(off_t)mime->length, SEEK_CUR, 0);
198
paxsync(pax, ap, 0);
199
f->st->st_size += m;
200
}
201
return 0;
202
}
203
204
Format_t pax_mime_format =
205
{
206
"mime",
207
0,
208
"encapsulated mime",
209
0,
210
ARCHIVE|DOS|NOHARDLINKS|IN,
211
DEFBUFFER,
212
DEFBLOCKS,
213
0,
214
PAXNEXT(mime),
215
0,
216
mime_done,
217
mime_getprologue,
218
mime_getheader,
219
};
220
221
PAXLIB(mime)
222
223