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);
139 memmove(buf, buf+len+5, nbuf);
149 for (unsigned i = 0; i < index; i++)
150 free(pkg->priv->names[i].name);
151 free(pkg->priv->names);
155 static int pkg_init_exports(struct upkg *pkg)
157 size_t rc, len, nbuf = 0;
158 unsigned long index = 0;
161 if (fseek(pkg->priv->f, pkg->priv->export_offset, SEEK_SET) != 0)
164 pkg->priv->exports = malloc(pkg->export_count * sizeof *pkg->priv->exports);
165 if (!pkg->priv->exports)
168 while (index < pkg->export_count) {
169 struct upkg_export *export = &pkg->priv->exports[index];
172 /* Read some data into buffer. */
173 if (!feof(pkg->priv->f)) {
174 rc = fread(buf+nbuf, 1, sizeof buf-nbuf, pkg->priv->f);
181 rc = decode_index(&export->class, buf+len, nbuf-len);
182 if (rc == 0) goto err;
185 rc = decode_index(&export->super, buf+len, nbuf-len);
186 if (rc == 0) goto err;
189 if (nbuf-len < 4) goto err;
190 export->package = unpack_32_le(buf+len);
193 rc = decode_index(&tmp, buf+len, nbuf-len);
194 if (rc == 0 || tmp < 0 || tmp >= pkg->name_count) goto err;
195 export->name = pkg->priv->names[tmp].name;
198 if (nbuf-len < 4) goto err;
199 export->flags = unpack_32_le(buf+len);
202 rc = decode_index(&export->size, buf+len, nbuf-len);
203 if (rc == 0) goto err;
207 rc = decode_index(&export->offset, buf+len, nbuf-len);
208 if (rc == 0) goto err;
213 memmove(buf, buf+len, nbuf);
219 free(pkg->priv->exports);
223 static int pkg_init_imports(struct upkg *pkg)
225 size_t rc, len, nbuf = 0;
226 unsigned long index = 0;
229 if (fseek(pkg->priv->f, pkg->priv->import_offset, SEEK_SET) != 0)
232 pkg->priv->imports = malloc(pkg->import_count * sizeof *pkg->priv->imports);
233 if (!pkg->priv->imports)
236 while (index < pkg->import_count) {
237 struct upkg_import *import = &pkg->priv->imports[index];
240 /* Read some data into buffer. */
241 if (!feof(pkg->priv->f)) {
242 rc = fread(buf+nbuf, 1, sizeof buf-nbuf, pkg->priv->f);
249 rc = decode_index(&tmp, buf+len, nbuf-len);
250 if (rc == 0 || len < 0 || len >= pkg->name_count) goto err;
251 import->class_package = pkg->priv->names[tmp].name;
254 rc = decode_index(&tmp, buf+len, nbuf-len);
255 if (rc == 0 || len < 0 || len >= pkg->name_count) goto err;
256 import->class_name = pkg->priv->names[tmp].name;
259 if (nbuf-len < 4) goto err;
260 import->package = unpack_32_le(buf+len);
263 rc = decode_index(&tmp, buf+len, nbuf-len);
264 if (rc == 0 || len < 0 || len >= pkg->name_count) goto err;
265 import->object_name = pkg->priv->names[tmp].name;
269 memmove(buf, buf+len, nbuf);
275 free(pkg->priv->imports);
279 struct upkg *upkg_fopen(const char *path)
281 unsigned char hdr_buf[UPKG_HDR_SIZE];
285 if (!(f = fopen(path, "rb"))) {
288 if (fread(hdr_buf, sizeof hdr_buf, 1, f) != 1) {
291 if (unpack_32_le(hdr_buf) != UPKG_HDR_MAGIC) {
295 /* Initialize package structure. */
296 pkg = init_upkg(hdr_buf);
302 if (pkg_init_names(pkg) != 0) {
306 if (pkg_init_exports(pkg) != 0) {
310 if (pkg_init_imports(pkg) != 0) {
316 free(pkg->priv->exports);
318 for (unsigned i = 0; i < pkg->name_count; i++)
319 free(pkg->priv->names[i].name);
320 free(pkg->priv->names);
329 int upkg_close(struct upkg *pkg)
334 rc = fclose(pkg->priv->f);
336 for (unsigned i = 0; i < pkg->name_count; i++) {
337 free(pkg->priv->names[i].name);
341 free(pkg->priv->imports);
342 free(pkg->priv->exports);
343 free(pkg->priv->names);
350 const char *upkg_get_name(struct upkg *pkg, unsigned long idx)
352 if (idx >= pkg->name_count)
354 return pkg->priv->names[idx].name;