Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
210 changes: 135 additions & 75 deletions backends/cdda/cdda.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,10 @@
#include "odfs/cache.h"
#include "odfs/log.h"
#include "odfs/error.h"
#include "odfs/printf.h"
#include "odfs/string.h"

#include <string.h>
#include <inttypes.h>
#include <stdarg.h>

#define CDDA_CDDB_NAME "CDDB.txt"
#define CDDA_CDDB_NODE_ID 0x43444442u
Expand Down Expand Up @@ -168,26 +166,81 @@ static void cdda_set_album_volume_name(cdda_context_t *ctx)
ctx->volume_name[i] = '\0';
}

static int cdda_appendf(char *buf, size_t buf_size, size_t *used,
const char *fmt, ...)
static int cdda_append_bytes(char *buf, size_t buf_size, size_t *used,
const char *src, size_t len)
{
va_list ap;
int wrote;

if (*used >= buf_size)
if (!buf || !used || !src || *used >= buf_size ||
len >= buf_size - *used)
return 0;

va_start(ap, fmt);
wrote = odfs_vsnprintf(buf + *used, buf_size - *used, fmt, ap);
va_end(ap);
memcpy(buf + *used, src, len);
*used += len;
buf[*used] = '\0';
return 1;
}

if (wrote < 0 || (size_t)wrote >= buf_size - *used)
return 0;
static int cdda_append_string(char *buf, size_t buf_size, size_t *used,
const char *str)
{
const char *end = str;

while (*end != '\0')
end++;
return cdda_append_bytes(buf, buf_size, used, str, (size_t)(end - str));
}

static int cdda_append_line(char *buf, size_t buf_size, size_t *used,
const char *value)
{
return cdda_append_string(buf, buf_size, used, value) &&
cdda_append_string(buf, buf_size, used, "\n");
}

static int cdda_append_u32(char *buf, size_t buf_size, size_t *used,
uint32_t value, unsigned int min_width)
{
char digits[10];
size_t count = 0;
char zero = '0';

do {
digits[count++] = (char)('0' + value % 10u);
value /= 10u;
} while (value != 0);

while (count < min_width) {
if (!cdda_append_bytes(buf, buf_size, used, &zero, 1))
return 0;
min_width--;
}

while (count != 0) {
if (!cdda_append_bytes(buf, buf_size, used, &digits[--count], 1))
return 0;
}

*used += (size_t)wrote;
return 1;
}

/* Write a complete key=value line without the general printf formatter. */
static int cdda_append_u32_field(char *buf, size_t buf_size, size_t *used,
const char *key, uint32_t value)
{
return cdda_append_string(buf, buf_size, used, key) &&
cdda_append_string(buf, buf_size, used, "=") &&
cdda_append_u32(buf, buf_size, used, value, 0) &&
cdda_append_string(buf, buf_size, used, "\n");
}

static int cdda_append_hex32(char *buf, size_t buf_size, size_t *used,
uint32_t value)
{
char digits[9];

cdda_format_hex32(digits, value);
return cdda_append_bytes(buf, buf_size, used, digits, 8);
}

static void cdda_generate_cddb(cdda_context_t *ctx)
{
char *text;
Expand All @@ -207,47 +260,54 @@ static void cdda_generate_cddb(cdda_context_t *ctx)
disc_id = cdda_disc_id(ctx);
total_seconds = cdda_total_seconds(ctx);

if (!cdda_appendf(text, text_size, &used,
"# Generated by ODFileSystem from disc TOC\n"
"DISCID=%08" PRIx32 "\n"
"TRACKS=%d\n"
"TOTAL_SECONDS=%" PRIu32 "\n"
"TOTAL_FRAMES=%" PRIu32 "\n",
disc_id, ctx->track_count,
total_seconds,
total_seconds * CDDA_FRAMES_PER_SEC)) {
if (!cdda_append_string(text, text_size, &used,
"# Generated by ODFileSystem from disc TOC\n"
"DISCID=") ||
!cdda_append_hex32(text, text_size, &used, disc_id) ||
!cdda_append_string(text, text_size, &used, "\n") ||
!cdda_append_u32_field(text, text_size, &used, "TRACKS",
(uint32_t)ctx->track_count) ||
!cdda_append_u32_field(text, text_size, &used, "TOTAL_SECONDS",
total_seconds) ||
!cdda_append_u32_field(text, text_size, &used, "TOTAL_FRAMES",
total_seconds * CDDA_FRAMES_PER_SEC)) {
odfs_free(text);
return;
}

for (int i = 0; i < ctx->track_count; i++) {
if (!cdda_appendf(text, text_size, &used,
"OFFSET%02d=%" PRIu32 "\n",
i + 1,
cdda_track_offset_frames(&ctx->tracks[i]))) {
if (!cdda_append_string(text, text_size, &used, "OFFSET") ||
!cdda_append_u32(text, text_size, &used, (uint32_t)(i + 1), 2) ||
!cdda_append_string(text, text_size, &used, "=") ||
!cdda_append_u32(text, text_size, &used,
cdda_track_offset_frames(&ctx->tracks[i]), 0) ||
!cdda_append_string(text, text_size, &used, "\n")) {
odfs_free(text);
return;
}
}

if (!cdda_appendf(text, text_size, &used,
"QUERY=cddb query %08" PRIx32 " %d",
disc_id, ctx->track_count)) {
if (!cdda_append_string(text, text_size, &used, "QUERY=cddb query ") ||
!cdda_append_hex32(text, text_size, &used, disc_id) ||
!cdda_append_string(text, text_size, &used, " ") ||
!cdda_append_u32(text, text_size, &used,
(uint32_t)ctx->track_count, 0)) {
odfs_free(text);
return;
}

for (int i = 0; i < ctx->track_count; i++) {
if (!cdda_appendf(text, text_size, &used,
" %" PRIu32,
cdda_track_offset_frames(&ctx->tracks[i]))) {
if (!cdda_append_string(text, text_size, &used, " ") ||
!cdda_append_u32(text, text_size, &used,
cdda_track_offset_frames(&ctx->tracks[i]), 0)) {
odfs_free(text);
return;
}
}

if (!cdda_appendf(text, text_size, &used, " %" PRIu32 "\n",
total_seconds)) {
if (!cdda_append_string(text, text_size, &used, " ") ||
!cdda_append_u32(text, text_size, &used, total_seconds, 0) ||
!cdda_append_string(text, text_size, &used, "\n")) {
odfs_free(text);
return;
}
Expand Down Expand Up @@ -346,6 +406,31 @@ static size_t cdda_hex_encode(char *dst, size_t dst_size,
return used;
}

/* A CD-Text key is [BLOCKnn.]DISC.TYPE= or [BLOCKnn.]TRACKnn.TYPE=. */
static int cdda_append_cdtext_key(char *buf, size_t buf_size, size_t *used,
uint8_t type, uint32_t track, uint8_t block)
{
if (block != 0 &&
(!cdda_append_string(buf, buf_size, used, "BLOCK") ||
!cdda_append_u32(buf, buf_size, used, block, 2) ||
!cdda_append_string(buf, buf_size, used, ".")))
return 0;

if (track == 0) {
if (!cdda_append_string(buf, buf_size, used, "DISC."))
return 0;
} else {
if (!cdda_append_string(buf, buf_size, used, "TRACK") ||
!cdda_append_u32(buf, buf_size, used, track, 2) ||
!cdda_append_string(buf, buf_size, used, "."))
return 0;
}

return cdda_append_string(buf, buf_size, used,
cdda_cdtext_type_name(type, (uint8_t)track)) &&
cdda_append_string(buf, buf_size, used, "=");
}

static int cdda_append_cdtext_record(char *buf, size_t buf_size, size_t *used,
uint8_t type, uint8_t track, uint8_t block,
int is_dbcs, const uint8_t *data,
Expand All @@ -355,27 +440,11 @@ static int cdda_append_cdtext_record(char *buf, size_t buf_size, size_t *used,
size_t start = 0;
int value_count = 0;

if (track == 0) {
if (block != 0) {
if (!cdda_appendf(buf, buf_size, used, "BLOCK%02u.", block))
return 0;
}
if (!cdda_appendf(buf, buf_size, used, "DISC.%s=",
cdda_cdtext_type_name(type, track)))
return 0;
} else {
if (block != 0) {
if (!cdda_appendf(buf, buf_size, used, "BLOCK%02u.", block))
return 0;
}
if (!cdda_appendf(buf, buf_size, used, "TRACK%02u.%s=",
track, cdda_cdtext_type_name(type, track)))
return 0;
}
if (!cdda_append_cdtext_key(buf, buf_size, used, type, track, block))
return 0;

if (is_dbcs) {
return cdda_appendf(buf, buf_size, used, "<DBCS>\n");
}
if (is_dbcs)
return cdda_append_string(buf, buf_size, used, "<DBCS>\n");

if (type >= 0x80 && type <= 0x85) {
while (start < data_size) {
Expand All @@ -384,27 +453,27 @@ static int cdda_append_cdtext_record(char *buf, size_t buf_size, size_t *used,
end++;
if (end > start) {
if (value_count > 0) {
if (!cdda_appendf(buf, buf_size, used, "; "))
if (!cdda_append_string(buf, buf_size, used, "; "))
return 0;
}
cdda_sanitize_ascii(value, sizeof(value),
data + start, end - start);
if (!cdda_appendf(buf, buf_size, used, "%s", value))
if (!cdda_append_string(buf, buf_size, used, value))
return 0;
value_count++;
}
start = end + 1;
}
return cdda_appendf(buf, buf_size, used, "\n");
return cdda_append_string(buf, buf_size, used, "\n");
}

if (type == 0x8e) {
cdda_sanitize_ascii(value, sizeof(value), data, data_size);
return cdda_appendf(buf, buf_size, used, "%s\n", value);
return cdda_append_line(buf, buf_size, used, value);
}

cdda_hex_encode(value, sizeof(value), data, data_size);
return cdda_appendf(buf, buf_size, used, "%s\n", value);
return cdda_append_line(buf, buf_size, used, value);
}

static void cdda_store_track_title(cdda_context_t *ctx, int track,
Expand Down Expand Up @@ -560,20 +629,10 @@ static int cdda_render_cdtext_strings(const uint8_t *raw, size_t pack_count,
if (!skip_current && cur_len != 0) {
cdda_sanitize_ascii(clean, sizeof(clean),
(const uint8_t *)cur, cur_len);
if (block != 0 &&
!cdda_appendf(buf, buf_size, used, "BLOCK%02u.", block))
if (!cdda_append_cdtext_key(buf, buf_size, used, type,
(uint32_t)cur_track, block) ||
!cdda_append_line(buf, buf_size, used, clean))
return 0;
if (cur_track == 0) {
if (!cdda_appendf(buf, buf_size, used, "DISC.%s=%s\n",
cdda_cdtext_type_name(type, 0), clean))
return 0;
} else if (!cdda_appendf(buf, buf_size, used,
"TRACK%02u.%s=%s\n", cur_track,
cdda_cdtext_type_name(type,
(uint8_t)cur_track),
clean)) {
return 0;
}
}
cur_track++;
cur_len = 0;
Expand Down Expand Up @@ -625,8 +684,9 @@ static void cdda_generate_cdtext(cdda_context_t *ctx)
return;
}

if (!cdda_appendf(text, 128u + raw_size * 4u, &used,
"# Generated by ODFileSystem from CD-Text packs\n")) {
if (!cdda_append_string(
text, 128u + raw_size * 4u, &used,
"# Generated by ODFileSystem from CD-Text packs\n")) {
odfs_free(field_buf);
odfs_free(text);
odfs_free(raw);
Expand Down
4 changes: 2 additions & 2 deletions backends/iso9660/iso9660.c
Original file line number Diff line number Diff line change
Expand Up @@ -942,8 +942,8 @@ odfs_err_t odfs_iso_merge_multi_extent(odfs_cache_t *cache,
}

/* synthesize the minimal node needed to enumerate a directory extent */
odfs_node_t odfs_iso_dir_stub(odfs_backend_type_t backend,
uint32_t lba, uint32_t size)
static odfs_node_t odfs_iso_dir_stub(odfs_backend_type_t backend,
uint32_t lba, uint32_t size)
{
odfs_node_t n;
memset(&n, 0, sizeof(n));
Expand Down
4 changes: 0 additions & 4 deletions backends/iso9660/iso9660.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,6 @@ odfs_err_t odfs_iso_read_parent_extent(odfs_cache_t *cache,
uint32_t *parent_lba_out,
uint32_t *parent_size_out);

/* synthesize the minimal directory node needed to enumerate an extent */
odfs_node_t odfs_iso_dir_stub(odfs_backend_type_t backend,
uint32_t lba, uint32_t size);

/*
* Merge the continuation records of a multi-extent file (ISO 9660 Level 3,
* ECMA-119 6.5.1). Called after parsing a directory record whose
Expand Down
4 changes: 4 additions & 0 deletions core/cache_block.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ void odfs_cache_destroy(odfs_cache_t *cache)
memset(cache, 0, sizeof(*cache));
}

#if !defined(AMIGA)
void odfs_cache_flush(odfs_cache_t *cache)
{
if (!cache || !cache->entries)
Expand All @@ -293,6 +294,7 @@ void odfs_cache_flush(odfs_cache_t *cache)
cache->valid_count = 0;
cache_reset_indices(cache);
}
#endif

static int32_t cache_reserve(const odfs_cache_t *cache)
{
Expand Down Expand Up @@ -568,7 +570,9 @@ odfs_err_t odfs_cache_read_bytes(odfs_cache_t *cache,
return ODFS_OK;
}

#if !defined(AMIGA)
const odfs_cache_stats_t *odfs_cache_get_stats(const odfs_cache_t *cache)
{
return &cache->stats;
}
#endif
2 changes: 2 additions & 0 deletions core/charset.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ odfs_err_t odfs_iso_name_to_display(const char *src, size_t src_len,
return ODFS_OK;
}

#if !defined(AMIGA)
void odfs_sanitize_name(char *name, size_t len, char replacement)
{
for (size_t i = 0; i < len && name[i] != '\0'; i++) {
Expand All @@ -160,6 +161,7 @@ void odfs_sanitize_name(char *name, size_t len, char replacement)
name[i] = replacement;
}
}
#endif

#define ODFS_PATH_MAX_COMPONENTS 32

Expand Down
Loading
Loading