-
Notifications
You must be signed in to change notification settings - Fork 10
/
libopk.c
120 lines (100 loc) · 2.24 KB
/
libopk.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include <errno.h>
#include <ini.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// Public interface.
#pragma GCC visibility push(default)
#include "opk.h"
#pragma GCC visibility pop
// Internal interfaces.
#include "unsqfs.h"
#define HEADER "Desktop Entry"
struct OPK {
struct PkgData *pdata;
void *buf;
struct INI *ini;
};
struct OPK *opk_open(const char *opk_filename)
{
struct OPK *opk = malloc(sizeof(*opk));
if (!opk)
return NULL;
opk->pdata = opk_sqfs_open(opk_filename);
if (!opk->pdata) {
free(opk);
return NULL;
}
opk->buf = NULL;
return opk;
}
int opk_read_pair(struct OPK *opk,
const char **key_chars, size_t *key_size,
const char **val_chars, size_t *val_size)
{
return ini_read_pair(opk->ini,
key_chars, key_size, val_chars, val_size);
}
int opk_open_metadata(struct OPK *opk, const char **filename)
{
/* Free previous meta-data information */
if (opk->buf) {
ini_close(opk->ini);
free(opk->buf);
}
opk->buf = NULL;
/* Get the name of the next .desktop */
const char *name;
int err = opk_sqfs_get_metadata(opk->pdata, &name);
if (err <= 0)
return err;
/* Extract the meta-data from the OD package */
void *buf;
size_t buf_size;
err = opk_sqfs_extract_file(opk->pdata, name, &buf, &buf_size);
if (err)
return err;
struct INI *ini = ini_open_mem(buf, buf_size);
if (!ini) {
err = -ENOMEM;
goto err_free_buf;
}
const char *section;
size_t section_len;
int has_section = ini_next_section(ini, §ion, §ion_len);
if (has_section < 0) {
err = has_section;
goto error_ini_close;
}
/* The [Desktop Entry] section must be the first section of the
* .desktop file. */
if (!has_section || strncmp(HEADER, section, section_len)) {
fprintf(stderr, "%s: not a proper desktop entry file\n", name);
err = -EIO;
goto error_ini_close;
}
opk->buf = buf;
opk->ini = ini;
if (filename)
*filename = name;
return 1;
error_ini_close:
ini_close(ini);
err_free_buf:
free(buf);
return err;
}
void opk_close(struct OPK *opk)
{
opk_sqfs_close(opk->pdata);
if (opk->buf) {
ini_close(opk->ini);
free(opk->buf);
}
free(opk);
}
int opk_extract_file(struct OPK *opk,
const char *name, void **data, size_t *size)
{
return opk_sqfs_extract_file(opk->pdata, name, data, size);
}