58
tag_add_item_n(tag, type, value, value_length);
56
const char *end = value + value_length;
58
/* multiple values are separated by null bytes */
59
const char *n = memchr(value, 0, end - value);
62
tag_add_item_n(tag, type, value, n - value);
66
tag_add_item_n(tag, type, value, end - value);
79
tag_ape_callback(unsigned long flags, const char *key,
80
const char *value, size_t value_length, void *_ctx)
82
struct tag_ape_ctx *ctx = _ctx;
84
ctx->tag = tag_ape_import_item(ctx->tag, flags, key,
64
90
tag_ape_load(const char *file)
66
struct tag *ret = NULL;
81
unsigned char flags[4];
82
unsigned char reserved[8];
85
fp = fopen(file, "r");
89
/* determine if file has an apeV2 tag */
90
if (fseek(fp, 0, SEEK_END))
92
size = (size_t)ftell(fp);
93
if (fseek(fp, size - sizeof(footer), SEEK_SET))
95
if (fread(&footer, 1, sizeof(footer), fp) != sizeof(footer))
97
if (memcmp(footer.id, "APETAGEX", sizeof(footer.id)) != 0)
99
if (GUINT32_FROM_LE(footer.version) != 2000)
102
/* find beginning of ape tag */
103
tagLen = GUINT32_FROM_LE(footer.length);
104
if (tagLen <= sizeof(footer) + 10)
106
if (tagLen > 1024 * 1024)
107
/* refuse to load more than one megabyte of tag data */
109
if (fseek(fp, size - tagLen, SEEK_SET))
112
/* read tag into buffer */
113
tagLen -= sizeof(footer);
116
buffer = g_malloc(tagLen);
117
if (fread(buffer, 1, tagLen, fp) != tagLen)
121
tagCount = GUINT32_FROM_LE(footer.tagCount);
123
while (tagCount-- && tagLen > 10) {
124
size = GUINT32_FROM_LE(*(const uint32_t *)p);
127
flags = GUINT32_FROM_LE(*(const uint32_t *)p);
133
while (tagLen > size && *p != '\0') {
144
ret = tag_ape_import_item(ret, flags, key, p, size);
92
struct tag_ape_ctx ctx = { .tag = NULL };
94
tag_ape_scan(file, tag_ape_callback, &ctx);