8 #define MIN(a, b) ((a) < (b) ? (a) : (b))
18 long package, class, super;
20 unsigned long size, offset;
24 const char *class_package, *class_name, *object_name;
31 struct upkg_name *names;
32 struct upkg_export *exports;
33 struct upkg_import *imports;
35 unsigned long name_offset, export_offset, import_offset;
36 unsigned char guid[16];
40 * Decode the compact index format from the upkg. This format is fucked.
41 * Stores the result in *val and returns the number of input bytes read (or 0
42 * if the input is invalid, in which case *val is undefined).
44 static size_t decode_index(long *val, unsigned char *bytes, size_t n)
49 while (i < MIN(n, 5)) {
51 * Least significant bytes are first, so we need to do this
54 long tmp = bytes[i] & (i == 0 ? 0x3f : 0x7f);
57 if (i > 1) tmp <<= 7*(i-1);
60 if (!(bytes[i] & (i == 0 ? 0x40 : 0x80))) {
68 if (i > MIN(n, 5) || n == 0)
75 static struct upkg *init_upkg(unsigned char hdr[static UPKG_HDR_SIZE])
79 pkg = malloc(sizeof *pkg);
84 pkg->priv = malloc(sizeof *pkg->priv);
90 pkg->version = unpack_16_le(hdr+4);
91 pkg->license = unpack_16_le(hdr+6);
92 pkg->flags = unpack_32_le(hdr+8);
93 pkg->name_count = unpack_32_le(hdr+12);
94 pkg->export_count = unpack_32_le(hdr+20);
95 pkg->import_count = unpack_32_le(hdr+28);
97 pkg->priv->name_offset = unpack_32_le(hdr+16);
98 pkg->priv->export_offset = unpack_32_le(hdr+24);
99 pkg->priv->import_offset = unpack_32_le(hdr+32);
104 static int pkg_init_names(struct upkg *pkg)
106 size_t rc, len, nbuf = 0;
107 unsigned long index = 0;
110 if (fseek(pkg->priv->f, pkg->priv->name_offset, SEEK_SET) != 0)
113 pkg->priv->names = malloc(pkg->name_count * sizeof *pkg->priv->names);
114 if (!pkg->priv->names)
117 while (index < pkg->name_count) {
118 struct upkg_name *name = &pkg->priv->names[index];
120 /* Read some data into buffer. */
121 if (!feof(pkg->priv->f)) {
122 rc = fread(buf+nbuf, 1, sizeof buf-nbuf, pkg->priv->f);
128 if (pkg->version >= 64) {
130 if (nbuf <= len + 4 || buf[len])
132 name->name = malloc(len);
135 memcpy(name->name, buf+1, len);
136 name->flags = unpack_32_le(buf+len+1);
140 memmove(buf, buf+len+1, nbuf);
143 char *c = memchr(buf, 0, nbuf);
144 if (!c || nbuf <= c - buf + 5)
147 name->name = malloc(len);
150 memcpy(name->name, buf, len);
151 name->flags = unpack_32_le(buf+len);
155 memmove(buf, buf+len, nbuf);
162 for (unsigned i = 0; i < index; i++)
163 free(pkg->priv->names[i].name);
164 free(pkg->priv->names);
168 static int pkg_init_exports(struct upkg *pkg)
170 size_t rc, len, nbuf = 0;
171 unsigned long index = 0;
174 if (fseek(pkg->priv->f, pkg->priv->export_offset, SEEK_SET) != 0)
177 pkg->priv->exports = malloc(pkg->export_count * sizeof *pkg->priv->exports);
178 if (!pkg->priv->exports)
181 while (index < pkg->export_count) {
182 struct upkg_export *export = &pkg->priv->exports[index];
185 /* Read some data into buffer. */
186 if (!feof(pkg->priv->f)) {
187 rc = fread(buf+nbuf, 1, sizeof buf-nbuf, pkg->priv->f);
194 rc = decode_index(&export->class, buf+len, nbuf-len);
195 if (rc == 0) goto err;
198 rc = decode_index(&export->super, buf+len, nbuf-len);
199 if (rc == 0) goto err;
202 if (nbuf-len < 4) goto err;
203 export->package = unpack_32_le(buf+len);
206 rc = decode_index(&tmp, buf+len, nbuf-len);
207 if (rc == 0 || tmp < 0 || tmp >= pkg->name_count) goto err;
208 export->name = pkg->priv->names[tmp].name;
211 if (nbuf-len < 4) goto err;
212 export->flags = unpack_32_le(buf+len);
215 rc = decode_index(&export->size, buf+len, nbuf-len);
216 if (rc == 0) goto err;
220 rc = decode_index(&export->offset, buf+len, nbuf-len);
221 if (rc == 0) goto err;
226 memmove(buf, buf+len, nbuf);
232 free(pkg->priv->exports);
236 static int pkg_init_imports(struct upkg *pkg)
238 size_t rc, len, nbuf = 0;
239 unsigned long index = 0;
242 if (fseek(pkg->priv->f, pkg->priv->import_offset, SEEK_SET) != 0)
245 pkg->priv->imports = malloc(pkg->import_count * sizeof *pkg->priv->imports);
246 if (!pkg->priv->imports)
249 while (index < pkg->import_count) {
250 struct upkg_import *import = &pkg->priv->imports[index];
253 /* Read some data into buffer. */
254 if (!feof(pkg->priv->f)) {
255 rc = fread(buf+nbuf, 1, sizeof buf-nbuf, pkg->priv->f);
262 rc = decode_index(&tmp, buf+len, nbuf-len);
263 if (rc == 0 || len < 0 || len >= pkg->name_count) goto err;
264 import->class_package = pkg->priv->names[tmp].name;
267 rc = decode_index(&tmp, buf+len, nbuf-len);
268 if (rc == 0 || len < 0 || len >= pkg->name_count) goto err;
269 import->class_name = pkg->priv->names[tmp].name;
272 if (nbuf-len < 4) goto err;
273 import->package = unpack_32_le(buf+len);
276 rc = decode_index(&tmp, buf+len, nbuf-len);
277 if (rc == 0 || len < 0 || len >= pkg->name_count) goto err;
278 import->object_name = pkg->priv->names[tmp].name;
282 memmove(buf, buf+len, nbuf);
288 free(pkg->priv->imports);
292 struct upkg *upkg_fopen(const char *path)
294 unsigned char hdr_buf[UPKG_HDR_SIZE];
298 if (!(f = fopen(path, "rb"))) {
301 if (fread(hdr_buf, sizeof hdr_buf, 1, f) != 1) {
304 if (unpack_32_le(hdr_buf) != UPKG_HDR_MAGIC) {
308 /* Initialize package structure. */
309 pkg = init_upkg(hdr_buf);
315 if (pkg_init_names(pkg) != 0) {
319 if (pkg_init_exports(pkg) != 0) {
323 if (pkg_init_imports(pkg) != 0) {
329 free(pkg->priv->exports);
331 for (unsigned i = 0; i < pkg->name_count; i++)
332 free(pkg->priv->names[i].name);
333 free(pkg->priv->names);
342 int upkg_close(struct upkg *pkg)
347 rc = fclose(pkg->priv->f);
349 for (unsigned i = 0; i < pkg->name_count; i++) {
350 free(pkg->priv->names[i].name);
354 free(pkg->priv->imports);
355 free(pkg->priv->exports);
356 free(pkg->priv->names);
363 const char *upkg_get_name(struct upkg *pkg, unsigned long idx)
365 if (idx >= pkg->name_count)
367 return pkg->priv->names[idx].name;