+ if (buf1[0] != b2[0])
+ return 1;
+ if (buf1[1] != b2[1])
+ return 1;
+ if (buf1[2] != b2[2])
+ return 1;
+ if (buf1[3] != b2[3])
+ return 1;
+ return 0;
+}
+
+static int read_atom_header(unsigned char *buf, uint64_t *subsize, unsigned char type[5])
+{
+ int i;
+ uint64_t size = (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3];
+
+ memcpy(type, buf + 4, 4);
+ type[4] = '\0';
+
+ PARA_DEBUG_LOG("size: %llu, type: %s\n", (long long unsigned)size, type);
+ if (size != 1) {
+ *subsize = size;
+ return 8;
+ }
+ buf += 4;
+ size = 0;
+ for (i = 0; i < 8; i++)
+ size |= ((uint64_t)buf[i]) << ((7 - i) * 8);
+ *subsize = size;
+ return 16;
+}
+
+static char *get_tag(unsigned char *p, int size)
+{
+ char *buf;
+
+ assert(size > 0);
+ buf = para_malloc(size + 1);
+
+ memcpy(buf, p, size);
+ buf[size] = '\0';
+ PARA_DEBUG_LOG("size: %d: %s\n", size, buf);
+ return buf;
+}
+
+static char *read_tags(unsigned char *buf, size_t buflen)
+{
+ unsigned char *p = buf;
+ char *title = NULL, *artist = NULL, *album = NULL, *year = NULL,
+ *comment = NULL, *result;
+
+ while (p + 32 < buf + buflen) {
+ unsigned char *q, type1[5], type2[5];
+ uint64_t size1, size2;
+ int ret, ret2;
+
+ ret = read_atom_header(p, &size1, type1);
+ ret2 = read_atom_header(p + ret, &size2, type2);
+
+ if (size2 <= 16 || atom_cmp(type2, "data")) {
+ p += size1;
+ continue;
+ }
+ size2 -= 16;
+ q = p + ret + ret2 + 8;
+ if (q + size2 > buf + buflen)