Virtual ISO: Delegate Rock Ridge name trimming to fill_dir_record, saving memory
This commit is contained in:
@@ -42,7 +42,7 @@
|
|||||||
memset(p, 0x00, n); \
|
memset(p, 0x00, n); \
|
||||||
p += n; \
|
p += n; \
|
||||||
}
|
}
|
||||||
#define VISO_TIME_VALID(t) (((t) -1) < ((time_t) -2))
|
#define VISO_TIME_VALID(t) ((t) > 0)
|
||||||
|
|
||||||
/* ISO 9660 defines "both endian" data formats, which
|
/* ISO 9660 defines "both endian" data formats, which
|
||||||
are stored as little endian followed by big endian. */
|
are stored as little endian followed by big endian. */
|
||||||
@@ -80,8 +80,8 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _viso_entry_ {
|
typedef struct _viso_entry_ {
|
||||||
char name_short[13], name_rr[257]; /* name_rr size limited by at least Linux */
|
char name_short[13];
|
||||||
union { /* save some memory */
|
union { /* save some memory */
|
||||||
uint64_t pt_offsets[4];
|
uint64_t pt_offsets[4];
|
||||||
FILE *file;
|
FILE *file;
|
||||||
};
|
};
|
||||||
@@ -90,13 +90,13 @@ typedef struct _viso_entry_ {
|
|||||||
uint64_t data_offset;
|
uint64_t data_offset;
|
||||||
};
|
};
|
||||||
uint16_t name_joliet[111], pt_idx; /* name_joliet size limited by maximum directory record size */
|
uint16_t name_joliet[111], pt_idx; /* name_joliet size limited by maximum directory record size */
|
||||||
uint8_t name_rr_len, name_joliet_len;
|
uint8_t name_joliet_len;
|
||||||
|
|
||||||
struct stat stats;
|
struct stat stats;
|
||||||
|
|
||||||
struct _viso_entry_ *parent, *next, *next_dir, *first_child;
|
struct _viso_entry_ *parent, *next, *next_dir, *first_child;
|
||||||
|
|
||||||
char path[];
|
char *basename, path[];
|
||||||
} viso_entry_t;
|
} viso_entry_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -355,7 +355,7 @@ viso_fill_time(uint8_t *data, time_t time, int longform)
|
|||||||
static int
|
static int
|
||||||
viso_fill_dir_record(uint8_t *data, viso_entry_t *entry, int type)
|
viso_fill_dir_record(uint8_t *data, viso_entry_t *entry, int type)
|
||||||
{
|
{
|
||||||
uint8_t *p = data, *q;
|
uint8_t *p = data, *q, *r;
|
||||||
|
|
||||||
*p++ = 0; /* size (filled in later) */
|
*p++ = 0; /* size (filled in later) */
|
||||||
*p++ = 0; /* extended attribute length */
|
*p++ = 0; /* extended attribute length */
|
||||||
@@ -470,29 +470,38 @@ viso_fill_dir_record(uint8_t *data, viso_entry_t *entry, int type)
|
|||||||
p += viso_fill_time(p, entry->stats.st_ctime, 0); /* attributes */
|
p += viso_fill_time(p, entry->stats.st_ctime, 0); /* attributes */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Trim Rock Ridge name to fit available space. */
|
|
||||||
int max_len = 254 - (p - data) - 5;
|
|
||||||
if (entry->name_rr_len > max_len) {
|
|
||||||
/* Relocate extension if this is a file whose name exceeds the maximum length. */
|
|
||||||
if (!S_ISDIR(entry->stats.st_mode)) {
|
|
||||||
char *ext = strrchr(entry->name_rr, '.');
|
|
||||||
if (ext) {
|
|
||||||
entry->name_rr_len = strlen(ext);
|
|
||||||
memmove(entry->name_rr + (max_len - entry->name_rr_len), ext, entry->name_rr_len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
entry->name_rr_len = max_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
*q |= 0x08; /* NM = alternate name */
|
*q |= 0x08; /* NM = alternate name */
|
||||||
*p++ = 'N';
|
*p++ = 'N';
|
||||||
*p++ = 'M';
|
*p++ = 'M';
|
||||||
*p++ = 5 + entry->name_rr_len; /* length */
|
r = p++; /* save location of the length for later */
|
||||||
*p++ = 1; /* version */
|
*r = 5; /* length */
|
||||||
|
*p++ = 1; /* version */
|
||||||
|
|
||||||
*p++ = 0; /* flags */
|
*p++ = 0; /* flags */
|
||||||
memcpy(p, entry->name_rr, entry->name_rr_len); /* name */
|
|
||||||
p += entry->name_rr_len;
|
/* Trim Rock Ridge name to fit available space. */
|
||||||
|
size_t len = strlen(entry->basename),
|
||||||
|
max_len = 254 - (p - data);
|
||||||
|
if (len > max_len) {
|
||||||
|
*r += max_len;
|
||||||
|
viso_write_string(p, entry->basename, max_len, VISO_CHARSET_FN);
|
||||||
|
p += max_len;
|
||||||
|
|
||||||
|
/* Relocate extension if this is a file whose name exceeds the maximum length. */
|
||||||
|
if (!S_ISDIR(entry->stats.st_mode)) {
|
||||||
|
char *ext = strrchr(entry->basename, '.');
|
||||||
|
if (ext > entry->basename) {
|
||||||
|
len = strlen(ext);
|
||||||
|
if (len >= max_len)
|
||||||
|
len = max_len - 1; /* avoid creating a dotfile where there isn't one */
|
||||||
|
viso_write_string(p - len, ext, len, VISO_CHARSET_FN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*r += len;
|
||||||
|
viso_write_string(p, entry->basename, len, VISO_CHARSET_FN);
|
||||||
|
p += len;
|
||||||
|
}
|
||||||
pad_susp:
|
pad_susp:
|
||||||
if ((p - data) & 1) /* padding for odd SUSP section lengths */
|
if ((p - data) & 1) /* padding for odd SUSP section lengths */
|
||||||
*p++ = 0;
|
*p++ = 0;
|
||||||
@@ -699,7 +708,6 @@ viso_init(const char *dirname, int *error)
|
|||||||
|
|
||||||
/* Set short and long filenames. */
|
/* Set short and long filenames. */
|
||||||
strcpy(last_entry->name_short, i ? ".." : ".");
|
strcpy(last_entry->name_short, i ? ".." : ".");
|
||||||
strcpy(last_entry->name_rr, i ? ".." : ".");
|
|
||||||
wcscpy(last_entry->name_joliet, i ? L".." : L".");
|
wcscpy(last_entry->name_joliet, i ? L".." : L".");
|
||||||
|
|
||||||
cdrom_image_viso_log("[%08X] %s => %s\n", last_entry, dir->path, last_entry->name_short);
|
cdrom_image_viso_log("[%08X] %s => %s\n", last_entry, dir->path, last_entry->name_short);
|
||||||
@@ -720,7 +728,8 @@ viso_init(const char *dirname, int *error)
|
|||||||
last_entry->parent = dir;
|
last_entry->parent = dir;
|
||||||
strcpy(last_entry->path, dir->path);
|
strcpy(last_entry->path, dir->path);
|
||||||
plat_path_slash(&last_entry->path[dir_path_len]);
|
plat_path_slash(&last_entry->path[dir_path_len]);
|
||||||
strcpy(&last_entry->path[dir_path_len + 1], readdir_entry->d_name);
|
last_entry->basename = &last_entry->path[dir_path_len + 1];
|
||||||
|
strcpy(last_entry->basename, readdir_entry->d_name);
|
||||||
|
|
||||||
/* Stat this child. */
|
/* Stat this child. */
|
||||||
if (stat(last_entry->path, &last_entry->stats) != 0) {
|
if (stat(last_entry->path, &last_entry->stats) != 0) {
|
||||||
@@ -748,12 +757,6 @@ viso_init(const char *dirname, int *error)
|
|||||||
if (viso_get_short_filename(dir, last_entry->name_short, readdir_entry->d_name))
|
if (viso_get_short_filename(dir, last_entry->name_short, readdir_entry->d_name))
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
/* Set Rock Ridge long filename. */
|
|
||||||
len = MIN(name_len, sizeof(last_entry->name_rr) - 1);
|
|
||||||
viso_write_string((uint8_t *) last_entry->name_rr, readdir_entry->d_name, len, VISO_CHARSET_FN);
|
|
||||||
last_entry->name_rr[len] = '\0';
|
|
||||||
last_entry->name_rr_len = len;
|
|
||||||
|
|
||||||
/* Set Joliet long filename. */
|
/* Set Joliet long filename. */
|
||||||
if (wtemp_len < (name_len + 1)) { /* grow wchar buffer if needed */
|
if (wtemp_len < (name_len + 1)) { /* grow wchar buffer if needed */
|
||||||
wtemp_len = name_len + 1;
|
wtemp_len = name_len + 1;
|
||||||
@@ -776,7 +779,7 @@ viso_init(const char *dirname, int *error)
|
|||||||
last_entry->name_joliet[len] = '\0';
|
last_entry->name_joliet[len] = '\0';
|
||||||
last_entry->name_joliet_len = len;
|
last_entry->name_joliet_len = len;
|
||||||
|
|
||||||
cdrom_image_viso_log("[%08X] %s => [%-12s] %s\n", last_entry, dir->path, last_entry->name_short, last_entry->name_rr);
|
cdrom_image_viso_log("[%08X] %s => [%-12s] %s\n", last_entry, dir->path, last_entry->name_short, last_entry->basename);
|
||||||
|
|
||||||
/* If this is a directory, add it to the traversal list. */
|
/* If this is a directory, add it to the traversal list. */
|
||||||
if (S_ISDIR(last_entry->stats.st_mode)) {
|
if (S_ISDIR(last_entry->stats.st_mode)) {
|
||||||
@@ -1048,7 +1051,7 @@ next_dir:
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
cdrom_image_viso_log("[%08X] %s => %s\n", dir, dir->path, (i & 2) ? dir->name_rr : dir->name_short);
|
cdrom_image_viso_log("[%08X] %s => %s\n", dir, dir->path, (i & 2) ? dir->basename : dir->name_short);
|
||||||
|
|
||||||
/* Save this directory's path table index and offset. */
|
/* Save this directory's path table index and offset. */
|
||||||
dir->pt_idx = pt_idx;
|
dir->pt_idx = pt_idx;
|
||||||
@@ -1107,7 +1110,7 @@ next_dir:
|
|||||||
cdrom_image_viso_log("VISO: Generating directory record set #%d:\n", i);
|
cdrom_image_viso_log("VISO: Generating directory record set #%d:\n", i);
|
||||||
|
|
||||||
/* Go through directories. */
|
/* Go through directories. */
|
||||||
dir = viso->root_dir;
|
dir = viso->root_dir;
|
||||||
while (dir) {
|
while (dir) {
|
||||||
/* Pad to the next sector if required. */
|
/* Pad to the next sector if required. */
|
||||||
write = ftello64(viso->tf.file) % viso->sector_size;
|
write = ftello64(viso->tf.file) % viso->sector_size;
|
||||||
@@ -1142,7 +1145,7 @@ next_dir:
|
|||||||
|
|
||||||
cdrom_image_viso_log("[%08X] %s => %s\n", entry,
|
cdrom_image_viso_log("[%08X] %s => %s\n", entry,
|
||||||
entry->path ? entry->path : ((dir_type == VISO_DIR_PARENT) ? dir->parent->path : dir->path),
|
entry->path ? entry->path : ((dir_type == VISO_DIR_PARENT) ? dir->parent->path : dir->path),
|
||||||
i ? entry->name_rr : entry->name_short);
|
i ? entry->basename : entry->name_short);
|
||||||
|
|
||||||
/* Fill directory record. */
|
/* Fill directory record. */
|
||||||
viso_fill_dir_record(data, entry, dir_type);
|
viso_fill_dir_record(data, entry, dir_type);
|
||||||
|
|||||||
Reference in New Issue
Block a user