8 #define MIN(a, b) ((a) < (b) ? (a) : (b))
16 long class, super, name;
17 unsigned long package, flags;
18 unsigned long size, offset;
24 struct upkg_name *names;
25 struct upkg_export *exports;
27 unsigned long name_offset, export_offset, import_offset;
28 unsigned char guid[16];
32 * Decode the compact index format from the upkg. This format is fucked.
33 * Stores the result in *val and returns the number of input bytes read (or 0
34 * if the input is invalid, in which case *val is undefined).
36 static size_t decode_index(long *val, unsigned char *bytes, size_t n)
41 while (i < MIN(n, 5)) {
43 * Least significant bytes are first, so we need to do this
46 long tmp = bytes[i] & (i == 0 ? 0x3f : 0x7f);
49 if (i > 1) tmp <<= 7*(i-1);
52 if (!(bytes[i] & (i == 0 ? 0x40 : 0x80))) {
60 if (i > MIN(n, 5) || n == 0)
67 static struct upkg *init_upkg(unsigned char hdr[static UPKG_HDR_SIZE])
71 pkg = malloc(sizeof *pkg);
76 pkg->priv = malloc(sizeof *pkg->priv);
82 pkg->version = unpack_16_le(hdr+4);
83 pkg->license = unpack_16_le(hdr+6);
84 pkg->flags = unpack_32_le(hdr+8);
85 pkg->name_count = unpack_32_le(hdr+12);
86 pkg->export_count = unpack_32_le(hdr+20);
87 pkg->import_count = unpack_32_le(hdr+28);
89 pkg->priv->name_offset = unpack_32_le(hdr+16);
90 pkg->priv->export_offset = unpack_32_le(hdr+24);
91 pkg->priv->import_offset = unpack_32_le(hdr+32);
96 static int pkg_init_names(struct upkg *pkg)
98 size_t rc, len, nbuf = 0;
99 unsigned long index = 0;
102 if (fseek(pkg->priv->f, pkg->priv->name_offset, SEEK_SET) != 0)
105 pkg->priv->names = malloc(pkg->name_count * sizeof *pkg->priv->names);
106 if (!pkg->priv->names)
109 while (index < pkg->name_count) {
110 struct upkg_name *name = &pkg->priv->names[index];
112 /* Read some data into buffer. */
113 if (!feof(pkg->priv->f)) {
114 rc = fread(buf+nbuf, 1, sizeof buf-nbuf, pkg->priv->f);
120 if (pkg->version >= 64) {
122 if (nbuf <= len + 4 || buf[len])
124 name->name = malloc(len);
127 memcpy(name->name, buf+1, len);
128 name->flags = unpack_32_le(buf+len+1);
131 memmove(buf, buf+len+5, nbuf);
141 for (unsigned i = 0; i < index; i++)
142 free(pkg->priv->names[i].name);
143 free(pkg->priv->names);
147 static int pkg_init_exports(struct upkg *pkg)
149 size_t rc, len, nbuf = 0;
150 unsigned long index = 0;
153 if (fseek(pkg->priv->f, pkg->priv->export_offset, SEEK_SET) != 0)
156 pkg->priv->exports = malloc(pkg->export_count * sizeof *pkg->priv->exports);
157 if (!pkg->priv->exports)
160 while (index < pkg->export_count) {
161 struct upkg_export *export = &pkg->priv->exports[index];
163 /* Read some data into buffer. */
164 if (!feof(pkg->priv->f)) {
165 rc = fread(buf+nbuf, 1, sizeof buf-nbuf, pkg->priv->f);
172 rc = decode_index(&export->class, buf+len, nbuf-len);
173 if (rc == 0) goto err;
176 rc = decode_index(&export->super, buf+len, nbuf-len);
177 if (rc == 0) goto err;
180 if (nbuf-len < 4) goto err;
181 export->package = unpack_32_le(buf+len);
184 rc = decode_index(&export->name, buf+len, nbuf-len);
185 if (rc == 0) goto err;
188 if (nbuf-len < 4) goto err;
189 export->flags = unpack_32_le(buf+len);
192 rc = decode_index(&export->size, buf+len, nbuf-len);
193 if (rc == 0) goto err;
197 rc = decode_index(&export->offset, buf+len, nbuf-len);
198 if (rc == 0) goto err;
203 memmove(buf, buf+len, nbuf);
209 free(pkg->priv->exports);
213 struct upkg *upkg_fopen(const char *path)
215 unsigned char hdr_buf[UPKG_HDR_SIZE];
219 if (!(f = fopen(path, "rb"))) {
222 if (fread(hdr_buf, sizeof hdr_buf, 1, f) != 1) {
225 if (unpack_32_le(hdr_buf) != UPKG_HDR_MAGIC) {
229 /* Initialize package structure. */
230 pkg = init_upkg(hdr_buf);
236 if (pkg_init_exports(pkg) != 0) {
240 if (pkg_init_names(pkg) != 0) {
246 free(pkg->priv->exports);
255 int upkg_close(struct upkg *pkg)
260 rc = fclose(pkg->priv->f);
262 for (unsigned i = 0; i < pkg->name_count; i++) {
263 free(pkg->priv->names[i].name);
267 free(pkg->priv->exports);
268 free(pkg->priv->names);
275 const char *upkg_get_name(struct upkg *pkg, unsigned long idx)
277 if (idx >= pkg->name_count)
279 return pkg->priv->names[idx].name;