DArray * da_read (FILE *file) { DArray *d = NULL; TrieIndex n; /* check signature */ if (!file_read_int32 (file, &n) || DA_SIGNATURE != (uint32) n) return NULL; d = (DArray *) malloc (sizeof (DArray)); if (!d) return NULL; /* read number of cells */ file_read_int32 (file, &d->num_cells); d->cells = (DACell *) malloc (d->num_cells * sizeof (DACell)); if (!d->cells) goto exit_da_created; d->cells[0].base = DA_SIGNATURE; d->cells[0].check= d->num_cells; for (n = 1; n < d->num_cells; n++) { file_read_int32 (file, &d->cells[n].base); file_read_int32 (file, &d->cells[n].check); } return d; exit_da_created: free (d); return NULL; }
Tail * tail_read (FILE *file) { long save_pos; Tail *t; TrieIndex i; uint32 sig; /* check signature */ save_pos = ftell (file); if (!file_read_int32 (file, (int32 *) &sig) || TAIL_SIGNATURE != sig) goto exit_file_read; if (NULL == (t = (Tail *) malloc (sizeof (Tail)))) goto exit_file_read; if (!file_read_int32 (file, &t->first_free) || !file_read_int32 (file, &t->num_tails)) { goto exit_tail_created; } if (t->num_tails > SIZE_MAX / sizeof (TailBlock)) goto exit_tail_created; t->tails = (TailBlock *) malloc (t->num_tails * sizeof (TailBlock)); if (!t->tails) goto exit_tail_created; for (i = 0; i < t->num_tails; i++) { int16 length; if (!file_read_int32 (file, &t->tails[i].next_free) || !file_read_int32 (file, &t->tails[i].data) || !file_read_int16 (file, &length)) { goto exit_in_loop; } t->tails[i].suffix = (TrieChar *) malloc (length + 1); if (length > 0) { if (!file_read_chars (file, (char *)t->tails[i].suffix, length)) { free (t->tails[i].suffix); goto exit_in_loop; } } t->tails[i].suffix[length] = '\0'; } return t; exit_in_loop: while (i > 0) { free (t->tails[--i].suffix); } free (t->tails); exit_tail_created: free (t); exit_file_read: fseek (file, save_pos, SEEK_SET); return NULL; }
/** * @brief Read double-array data from file * * @param file : the file to read * * @return a pointer to the openned double-array, NULL on failure * * Read double-array data from the opened file, starting from the current * file pointer until the end of double array data block. On return, the * file pointer is left at the position after the read block. */ DArray * da_fread (FILE *file) { long save_pos; DArray *d = NULL; TrieIndex n; /* check signature */ save_pos = ftell (file); if (!file_read_int32 (file, &n) || DA_SIGNATURE != (uint32) n) goto exit_file_read; if (NULL == (d = (DArray *) malloc (sizeof (DArray)))) goto exit_file_read; /* read number of cells */ if (!file_read_int32 (file, &d->num_cells)) goto exit_da_created; if (d->num_cells > SIZE_MAX / sizeof (DACell)) goto exit_da_created; d->cells = (DACell *) malloc (d->num_cells * sizeof (DACell)); if (!d->cells) goto exit_da_created; d->cells[0].base = DA_SIGNATURE; d->cells[0].check= d->num_cells; for (n = 1; n < d->num_cells; n++) { if (!file_read_int32 (file, &d->cells[n].base) || !file_read_int32 (file, &d->cells[n].check)) { goto exit_da_cells_created; } } return d; exit_da_cells_created: free (d->cells); exit_da_created: free (d); exit_file_read: fseek (file, save_pos, SEEK_SET); return NULL; }
AlphaMap * alpha_map_fread_bin (FILE *file) { long save_pos; uint32 sig; int32 total, i; AlphaMap *alpha_map; /* check signature */ save_pos = ftell (file); if (!file_read_int32 (file, (int32 *) &sig) || ALPHAMAP_SIGNATURE != sig) goto exit_file_read; alpha_map = alpha_map_new (); if (UNLIKELY (!alpha_map)) goto exit_file_read; /* read number of ranges */ if (!file_read_int32 (file, &total)) goto exit_map_created; /* read character ranges */ for (i = 0; i < total; i++) { int32 b, e; if (!file_read_int32 (file, &b) || !file_read_int32 (file, &e)) goto exit_map_created; alpha_map_add_range_only (alpha_map, b, e); } /* work area */ if (UNLIKELY (alpha_map_recalc_work_area (alpha_map) != 0)) goto exit_map_created; return alpha_map; exit_map_created: alpha_map_free (alpha_map); exit_file_read: fseek (file, save_pos, SEEK_SET); return NULL; }
/* Read the items in a Vorbis comment packet. For Ogg files, the file must * be located on a page start, for other files, the beginning of the comment * data (i.e., the vendor string length). Returns total size of the * comments, or 0 if there was a read error. */ long read_vorbis_tags(int fd, struct mp3entry *id3, long tag_remaining) { struct file file; char *buf = id3->id3v2buf; int32_t comment_count; int32_t len; long comment_size = 0; int buf_remaining = sizeof(id3->id3v2buf) + sizeof(id3->id3v1buf); int i; if (!file_init(&file, fd, id3->codectype, tag_remaining)) { return 0; } /* Skip vendor string */ if (!file_read_int32(&file, &len) || (file_read(&file, NULL, len) < 0)) { return 0; } if (!file_read_int32(&file, &comment_count)) { return 0; } comment_size += 4 + len + 4; for (i = 0; i < comment_count && file.packet_remaining > 0; i++) { char name[TAG_NAME_LENGTH]; int32_t read_len; if (!file_read_int32(&file, &len)) { return 0; } comment_size += 4 + len; read_len = file_read_string(&file, name, sizeof(name), '=', len); if (read_len < 0) { return 0; } len -= read_len; read_len = file_read_string(&file, id3->path, sizeof(id3->path), -1, len); if (read_len < 0) { return 0; } logf("Vorbis comment %d: %s=%s", i, name, id3->path); /* Is it an embedded cuesheet? */ if (!strcasecmp(name, "CUESHEET")) { id3->has_embedded_cuesheet = true; id3->embedded_cuesheet.pos = lseek(file.fd, 0, SEEK_CUR) - read_len; id3->embedded_cuesheet.size = len; id3->embedded_cuesheet.encoding = CHAR_ENC_UTF_8; } else { len = parse_tag(name, id3->path, id3, buf, buf_remaining, TAGTYPE_VORBIS); } buf += len; buf_remaining -= len; } /* Skip to the end of the block (needed by FLAC) */ if (file.packet_remaining) { if (file_read(&file, NULL, file.packet_remaining) < 0) { return 0; } } return comment_size; }