diff options
author | Thomas Schmitt <scdbackup@gmx.net> | 2013-03-31 14:37:20 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2013-03-31 14:37:20 -0700 |
commit | c2e07a22ea9749d4ac591b992f378e188b8afc40 (patch) | |
tree | 741d84c0c41834c53411b9c176108116cb0c2471 | |
parent | e40ba6059aa9c6b5cefd01e277eafbe60c7752fd (diff) | |
download | syslinux-c2e07a22ea9749d4ac591b992f378e188b8afc40.tar.gz syslinux-c2e07a22ea9749d4ac591b992f378e188b8afc40.tar.xz syslinux-c2e07a22ea9749d4ac591b992f378e188b8afc40.zip |
iso9660: support for Rock Ridge filenamesobsolete-20130331
Add support for parsing SUSP and RRIP records and Rock Ridge long
filenames. This also avoids the naming and character set limitations
of plain iso9660.
-rw-r--r-- | core/fs/iso9660/iso9660.c | 41 | ||||
-rw-r--r-- | core/fs/iso9660/iso9660_fs.h | 5 | ||||
-rw-r--r-- | core/fs/iso9660/susp_rr.c | 533 | ||||
-rw-r--r-- | core/fs/iso9660/susp_rr.h | 84 |
4 files changed, 659 insertions, 4 deletions
diff --git a/core/fs/iso9660/iso9660.c b/core/fs/iso9660/iso9660.c index 3cd3ac46..5d61d5f9 100644 --- a/core/fs/iso9660/iso9660.c +++ b/core/fs/iso9660/iso9660.c @@ -7,6 +7,7 @@ #include <disk.h> #include <fs.h> #include "iso9660_fs.h" +#include "susp_rr.h" /* Convert to lower case string */ static inline char iso_tolower(char c) @@ -99,9 +100,10 @@ iso_find_entry(const char *dname, struct inode *inode) block_t dir_block = PVT(inode)->lba; int i = 0, offset = 0; const char *de_name; - int de_name_len, de_len; + int de_name_len, de_len, rr_name_len, ret; const struct iso_dir_entry *de; const char *data = NULL; + char *rr_name = NULL; dprintf("iso_find_entry: \"%s\"\n", dname); @@ -130,10 +132,24 @@ iso_find_entry(const char *dname, struct inode *inode) continue; } + /* Try to get Rock Ridge name */ + ret = susp_rr_get_nm(fs, (char *) de, &rr_name, &rr_name_len); + if (ret > 0) { + if (strcmp(rr_name, dname) == 0) { + dprintf("Found (by RR name).\n"); + free(rr_name); + return de; + } + free(rr_name); + rr_name = NULL; + continue; /* Rock Ridge was valid and did not match */ + } + + /* Fall back to ISO name */ de_name_len = de->name_len; de_name = de->name; if (iso_compare_name(de_name, de_name_len, dname)) { - dprintf("Found.\n"); + dprintf("Found (by ISO name).\n"); return de; } } @@ -193,6 +209,8 @@ static int iso_readdir(struct file *file, struct dirent *dirent) struct inode *inode = file->inode; const struct iso_dir_entry *de; const char *data = NULL; + char *rr_name = NULL; + int name_len, ret; while (1) { size_t offset = file->offset & (BLOCK_SIZE(fs) - 1); @@ -217,8 +235,18 @@ static int iso_readdir(struct file *file, struct dirent *dirent) dirent->d_ino = 0; /* Inode number is invalid to ISO fs */ dirent->d_off = file->offset; dirent->d_type = get_inode_mode(de->flags); - dirent->d_reclen = offsetof(struct dirent, d_name) + 1 + - iso_convert_name(dirent->d_name, de->name, de->name_len); + + /* Try to get Rock Ridge name */ + ret = susp_rr_get_nm(fs, (char *) de, &rr_name, &name_len); + if (ret > 0) { + memcpy(dirent->d_name, rr_name, name_len); + free(rr_name); + rr_name = NULL; + } else { + name_len = iso_convert_name(dirent->d_name, de->name, de->name_len); + } + + dirent->d_reclen = offsetof(struct dirent, d_name) + 1 + name_len; file->offset += de->length; /* Update for next reading */ @@ -281,6 +309,11 @@ static int iso_fs_init(struct fs_info *fs) /* Initialize the cache */ cache_init(fs->fs_dev, fs->block_shift); + /* Check for SP and ER in the first directory record of the root directory. + Set sbi->susp_skip and enable sbi->do_rr as appropriate. + */ + susp_rr_check_signatures(fs, 1); + return fs->block_shift; } diff --git a/core/fs/iso9660/iso9660_fs.h b/core/fs/iso9660/iso9660_fs.h index a365fa1a..40265642 100644 --- a/core/fs/iso9660/iso9660_fs.h +++ b/core/fs/iso9660/iso9660_fs.h @@ -37,6 +37,11 @@ struct iso_dir_entry { struct iso_sb_info { struct iso_dir_entry root; + + int do_rr; /* 1 , 2 = try to process Rock Ridge info , 0 = do not. + 2 indicates that the id of RRIP 1.12 was found. + */ + int susp_skip; /* Skip length from SUSP entry SP */ }; /* diff --git a/core/fs/iso9660/susp_rr.c b/core/fs/iso9660/susp_rr.c new file mode 100644 index 00000000..f609f7ff --- /dev/null +++ b/core/fs/iso9660/susp_rr.c @@ -0,0 +1,533 @@ +/* Reader for SUSP and Rock Ridge information. + + Copyright (c) 2013 Thomas Schmitt <scdbackup@gmx.net> + Provided under GNU General Public License version 2 or later. + + Based on: + SUSP 1.12 (entries CE , PD , SP , ST , ER , ES) + ftp://ftp.ymi.com/pub/rockridge/susp112.ps + RRIP 1.12 (entries PX , PN , SL , NM , CL , PL , RE , TF , SF) + ftp://ftp.ymi.com/pub/rockridge/rrip112.ps + ECMA-119 aka ISO 9660 + http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-119.pdf + + Shortcommings / Future improvements: + (XXX): Avoid memcpy() with Continuation Areas wich span over more than one + block ? (Will then need memcpy() with entries which are hit by a + block boundary.) (Questionable whether the effort is worth it.) + (XXX): Take into respect ES entries ? (Hardly anybody does this.) + +*/ + +#ifndef Isolinux_rockridge_in_libisofS + +/* Mindlessly copied from core/fs/iso9660/iso9660.c */ +#include <dprintf.h> +#include <stdio.h> +#include <string.h> +#include <sys/dirent.h> +#include <core.h> +#include <cache.h> +#include <disk.h> +#include <fs.h> +#include "iso9660_fs.h" + +#else /* ! Isolinux_rockridge_in_libisofS */ + +/* ====== Test mock-up of definitions which should come from syslinux ====== */ + +/* With defined Isolinux_rockridge_in_libisofS this source file can be included + into libisofs/fs_image.c and the outcome of its public functions can be + compared with the perception of libisofs when loading an ISO image. + + Test results look ok with 50 ISO images when read by xorriso underneath + valgrind. +*/ + +typedef uint32_t block_t; + +#define dprintf printf + +struct device { + IsoDataSource *src; +}; + + +struct susp_rr_dir_rec_wrap { + char data[256]; +}; + +struct iso_sb_info { + struct susp_rr_dir_rec_wrap root; + + int do_rr; /* 1 = try to process Rock Ridge info , 0 = do not */ + int susp_skip; /* Skip length from SUSP enntry SP */ +}; + +struct fs_info { + struct device *fs_dev; + struct iso_sb_info *fs_info; +}; + +#define get_cache dummy_get_cache + +static char *dummy_get_cache(struct device *fs_dev, block_t lba) +{ + static uint8_t buf[2048]; + int ret; + + ret = fs_dev->src->read_block(fs_dev->src, lba, buf); + if (ret < 0) + return NULL; + return (char *) buf; +} + +/* =========================== End of test mock-up ========================= */ + +#endif /* ! Isolinux_rockridge_for_reaL */ + + +static int susp_rr_is_out_of_mem(void *pt) +{ + if (pt != NULL) + return 0; + dprintf("susp_rr.c: Out of memory !\n"); + + /* XXX : Should one abort on global level ? */ + + return 1; +} + + +/* XXX: Is there already a reader for 32-bit MSB or LSB in the syslinux code ? + (iso9660.c seems to flatly assume that it runs on little-endian int.) +*/ +static uint32_t susp_rr_read_msb(uint8_t *buf, int bytes) +{ + int i; + uint32_t ret = 0; + + for (i = 0; i < bytes; i++) { + ret += ((uint32_t) buf[bytes - i - 1]) << (i * 8); + } + return ret; +} + + +/* State of iteration over SUSP entries. + + This would be quite trivial if there was not the possibility of Continuation + Areas announced by the CE entry. In general they are quite rare, because + often all Rock Ridge entries fit into the ISO 9660 directory record. + So it seems unwise to invest much complexity into optimization of + Continuation Areas. + (I found 35 CE in a backup of mine which contains 63000 files, 2 CE in + a Debian netinst ISO, 2 CE in a Fedora live CD.) +*/ +struct susp_rr_iter { + struct fs_info *fs; /* From where to read Continuation Area data */ + char *dir_rec; /* ISO 9660 directory record */ + int in_ce; /* 0= still reading dir_rec, 1= reading ce_data */ + char *ce_data; /* Loaded Continuation Area data */ + int ce_allocated; /* 0= do not free ce_data, 1= do free */ + size_t read_pos; /* Current read offset in dir_rec or ce_data */ + size_t read_end; /* Current first invalid read_pos */ + + block_t next_lba; /* Block number of start of next Continuation Area */ + size_t next_offset; /* Byte offset within the next_lba block */ + size_t next_length; /* Number of valid bytes in next Cont. Area */ +}; + + +static int susp_rr_iter_new(struct susp_rr_iter **iter, + struct fs_info *fs, char *dir_rec) +{ + struct iso_sb_info *sbi = fs->fs_info; + struct susp_rr_iter *o; + uint8_t len_fi; + int read_pos, read_end; + + len_fi = ((uint8_t *) dir_rec)[32]; + read_pos = 33 + len_fi + !(len_fi % 2) + sbi->susp_skip; + read_end = ((uint8_t *) dir_rec)[0]; + if (read_pos + 4 > read_end) + return 0; /* Not enough System Use data present for SUSP */ + if (dir_rec[read_pos + 3] != 1) + return 0; /* Not SUSP version 1 */ + + o= *iter= malloc(sizeof(struct susp_rr_iter)); + if (susp_rr_is_out_of_mem(o)) + return -1; + o->fs = fs; + o->dir_rec= dir_rec; + o->in_ce= 0; + o->read_pos = read_pos; + o->read_end = read_end; + o->next_lba = 0; + o->next_offset = o->next_length = 0; + o->ce_data = NULL; + o->ce_allocated = 0; + return 1; +} + + +static int susp_rr_iter_destroy(struct susp_rr_iter **iter) +{ + struct susp_rr_iter *o; + + o = *iter; + if (o == NULL) + return 0; + if (o->ce_data != NULL && o->ce_allocated) + free(o->ce_data); + free(o); + *iter = NULL; + return 1; +} + + +/* Switch to next Continuation Area. +*/ +static int susp_rr_switch_to_ca(struct susp_rr_iter *iter) +{ + block_t num_blocks, i; + const char *data = NULL; + + num_blocks = (iter->next_offset + iter->next_length + 2047) / 2048; + + if (iter->ce_data != NULL && iter->ce_allocated) + free(iter->ce_data); + iter->ce_data = NULL; + iter->ce_allocated = 0; + if (num_blocks > 1) { + /* The blocks are expected contiguously. Need to consolidate them. */ + iter->ce_data = malloc(num_blocks * 2048); + if (susp_rr_is_out_of_mem(iter->ce_data)) + return -1; + iter->ce_allocated = 1; + for (i = 0; i < num_blocks; i++) { + data = get_cache(iter->fs->fs_dev, iter->next_lba + i); + if (data == NULL) { + dprintf("susp_rr.c: Failure to read block %lu\n", + (unsigned long) iter->next_lba + i); + return -1; + } + memcpy(iter->ce_data + i * 2048, data, 2048); + } + } else { + /* Avoiding malloc() and memcpy() in the single block case */ + data = get_cache(iter->fs->fs_dev, iter->next_lba); + if (data == NULL) { + dprintf("susp_rr.c: Failure to read block %lu\n", + (unsigned long) iter->next_lba); + return -1; + } + iter->ce_data = (char *) data; + } + + iter->in_ce = 1; + iter->read_pos = iter->next_offset; + iter->read_end = iter->next_offset + iter->next_length; + iter->next_lba = 0; + iter->next_offset = iter->next_length = 0; + return 1; +} + + +/* Obtain the next SUSP entry. +*/ +static int susp_rr_iterate(struct susp_rr_iter *iter, char **pos_pt) +{ + char *entries; + uint8_t susp_len, *u_entry; + int ret; + + if (iter->in_ce) { + entries = iter->ce_data + iter->read_pos; + } else { + entries = iter->dir_rec + iter->read_pos; + } + if (iter->read_pos + 4 <= iter->read_end) + if (entries[3] != 1) { + /* Not SUSP version 1 */ + dprintf("susp_rr.c: Chain of SUSP entries broken\n"); + return -1; + } + if (iter->read_pos + 4 > iter->read_end || + (entries[0] == 'S' && entries[1] == 'T')) { + /* This part of the SU area is done */ + if (iter->next_length == 0) { + /* No further CE entry was encountered. Iteration ends now. */ + return 0; + } + ret = susp_rr_switch_to_ca(iter); + if (ret <= 0) + return ret; + entries = iter->ce_data + iter->read_pos; + } + + if (entries[0] == 'C' && entries[1] == 'E') { + if (iter->next_length > 0) { + dprintf("susp_rr.c: Surplus CE entry detected\n"); + return -1; + } + /* Register address data of next Continuation Area */ + u_entry = (uint8_t *) entries; + iter->next_lba = susp_rr_read_msb(u_entry + 8, 4); + iter->next_offset = susp_rr_read_msb(u_entry + 16, 4); + iter->next_length = susp_rr_read_msb(u_entry + 24, 4); + } + + *pos_pt = entries; + susp_len = ((uint8_t *) entries)[2]; + iter->read_pos += susp_len; + return 1; +} + + +/* Check for SP entry at position try_skip in the System Use area. +*/ +static int susp_rr_check_sp(struct fs_info *fs, char *dir_rec, int try_skip) +{ + struct iso_sb_info *sbi = fs->fs_info; + int read_pos, read_end, len_fi; + uint8_t *sua; + + len_fi = ((uint8_t *) dir_rec)[32]; + read_pos = 33 + len_fi + !(len_fi % 2) + try_skip; + read_end = ((uint8_t *) dir_rec)[0]; + if (read_end - read_pos < 7) + return 0; + sua = (uint8_t *) (dir_rec + read_pos); + if (sua[0] != 'S' || sua[1] != 'P' || sua[2] != 7 || sua[3] != 1 || + sua[4] != 0xbe || sua[5] != 0xef) + return 0; + dprintf("susp_rr.c: SUSP signature detected\n"); + sbi->susp_skip = ((uint8_t *) dir_rec)[6]; + if (sbi->susp_skip > 0 && sbi->susp_skip != try_skip) + dprintf("susp_rr.c: Unusual: Non-zero skip length in SP entry\n"); + return 1; +} + + +/* Public function. See susp_rr.h + + Rock Ridge specific knowledge about NM and SL has been integrated here, + because this saves one malloc and memcpy for the file name. +*/ +int susp_rr_get_entries(struct fs_info *fs, char *dir_rec, char *sig, + char **data, int *len_data, int flag) +{ + int count = 0, ret = 0, head_skip = 4, nmsp_flags = -1, is_done = 0; + char *pos_pt, *new_data; + uint8_t pay_len; + struct susp_rr_iter *iter = NULL; + struct iso_sb_info *sbi = fs->fs_info; + + *data = NULL; + *len_data = 0; + + if (!sbi->do_rr) + return 0; /* Rock Ridge is not enabled */ + + if (flag & 1) + head_skip = 5; + + ret = susp_rr_iter_new(&iter, fs, dir_rec); + if (ret <= 0) + goto ex; + while (!is_done) { + ret = susp_rr_iterate(iter, &pos_pt); + if (ret < 0) + goto ex; + if (ret == 0) + break; /* End SUSP iteration */ + if (sig[0] != pos_pt[0] || sig[1] != pos_pt[1]) + continue; /* Next SUSP iteration */ + + pay_len = ((uint8_t *) pos_pt)[2]; + if (pay_len < head_skip) { + dprintf("susp_rr.c: Short NM entry encountered.\n"); + ret = -1; + goto ex; + } + pay_len -= head_skip; + if ((flag & 1)) { + if (nmsp_flags < 0) + nmsp_flags = ((uint8_t *) pos_pt)[4]; + if (!(pos_pt[4] & 1)) /* No CONTINUE bit */ + is_done = 1; /* This is the last iteration cycle */ + } + count += pay_len; + if (count > 102400) { + dprintf("susp_rr.c: More than 100 KB in '%c%c' entries.\n", + sig[0], sig[1]); + ret = -1; + goto ex; + } + new_data = malloc(count + 1); + if (susp_rr_is_out_of_mem(new_data)) { + ret = -1; + goto ex; + } + if (*data != NULL) { + /* This case should be rare. An extra iteration pass to predict + the needed data size would hardly pay off. + */ + memcpy(new_data, *data, *len_data); + free(*data); + } + new_data[count] = 0; + *data = new_data; + memcpy(*data + *len_data, pos_pt + head_skip, pay_len); + *len_data += pay_len; + } + if (*data == NULL) { + ret = 0; + } else if (flag & 1) { + ret = 0x100 | nmsp_flags; + } else { + ret = 1; + } +ex:; + susp_rr_iter_destroy(&iter); + if (ret <= 0 && *data != NULL) { + free(*data); + *data = NULL; + } + return ret; +} + + +/* Public function. See susp_rr.h +*/ +int susp_rr_get_nm(struct fs_info *fs, char *dir_rec, + char **name, int *len_name) +{ + int ret; + + ret = susp_rr_get_entries(fs, dir_rec, "NM", name, len_name, 1); + if (ret <= 0) + return ret; + + /* Interpret flags */ + if (ret & 0x6) { + if (*name != NULL) + free(*name); + *len_name = 0; + *name = strdup(ret & 0x2 ? "." : ".."); + if (susp_rr_is_out_of_mem(*name)) { + return -1; + } + *len_name = strlen(*name); + } + if (*len_name >= 256) { + dprintf("susp_rr.c: Rock Ridge name longer than 255 characters.\n"); + free(*name); + *name = NULL; + *len_name = 0; + return -1; + } + return 1; +} + + +/* Public function. See susp_rr.h +*/ +int susp_rr_check_signatures(struct fs_info *fs, int flag) +{ + struct iso_sb_info *sbi = fs->fs_info; + char *dir_rec; + char *data = NULL; + uint8_t *u_data; + block_t lba; + int len_data, i, len_er = 0, len_id, ret; + int rrip_112 = 0; + + sbi->do_rr = 1; /* provisory for the time of examination */ + sbi->susp_skip = 0; + +#ifndef Isolinux_rockridge_in_libisofS +/* (There is a name collision with libisofs BLOCK_SIZE. On the other hand, + libisofs has hardcoded blocksize 2048.) */ + + /* For now this works only with 2 KB blocks */ + if (BLOCK_SIZE(fs) != 2048) { + dprintf("susp_rr.c: Block size is not 2048. Rock Ridge disabled.\n"); + goto no_susp; + } + +#endif /* Isolinux_rockridge_in_libisofS */ + + /* Obtain first dir_rec of root directory */ + lba = susp_rr_read_msb(((uint8_t *) &(sbi->root)) + 6, 4); + dir_rec = (char *) get_cache(fs->fs_dev, lba); + if (dir_rec == NULL) + goto no_susp; + + /* First System Use entry must be SP */ + ret = susp_rr_check_sp(fs, dir_rec, 0); + if (ret == 0) { + /* SUSP 1.12 prescribes that on CD-ROM XA discs the SP entry is at + offset 14 of the System Use area. + How to detect a CD-ROM XA disc here ? + (libisofs ignores this prescription and lives well with that. + /usr/src/linux/fs/isofs/ makes a blind try with 14.) + */ + ret = susp_rr_check_sp(fs, dir_rec, 14); + } + if (ret <= 0) + goto no_susp; + + if (!(flag & 1)) { + ret = 1; + goto ex; + } + + /* Look for ER entries */ + ret = susp_rr_get_entries(fs, dir_rec, "ER", &data, &len_data, 0); + if (ret <= 0 || len_data < 8) + goto no_rr; + u_data = (uint8_t *) data; + for (i = 0; i < len_data; i += len_er) { + len_id = u_data[0]; + len_er = 4 + len_id + u_data[1] + u_data[2]; + if (i + len_er > len_data) { + dprintf("susp_rr.c: Error with field lengths in ER entry\n"); + goto no_rr; + } + if (len_id == 10 && strncmp(data + 4, "RRIP_1991A", len_id) == 0) { + dprintf("susp_rr.c: Signature of Rock Ridge 1.10 detected\n"); + break; + } else if ((len_id == 10 && + strncmp(data + 4, "IEEE_P1282", len_id) == 0) || + (len_id == 9 && + strncmp(data + 4, "IEEE_1282", len_id) == 0)) { + dprintf("susp_rr.c: Signature of Rock Ridge 1.12 detected\n"); + rrip_112 = 1; + break; + } + } + if (i >= len_data) + goto no_rr; + + sbi->do_rr = 1 + rrip_112; + ret = 2 + rrip_112; + goto ex; + +no_susp:; + dprintf("susp_rr.c: No SUSP signature detected\n"); + ret = 0; + goto ex; + +no_rr:; + dprintf("susp_rr.c: No Rock Ridge signature detected\n"); + ret = 0; + +ex:; + if (ret <= 0) + sbi->do_rr = 0; + if (data != NULL) + free(data); + return ret; +} diff --git a/core/fs/iso9660/susp_rr.h b/core/fs/iso9660/susp_rr.h new file mode 100644 index 00000000..16732df3 --- /dev/null +++ b/core/fs/iso9660/susp_rr.h @@ -0,0 +1,84 @@ +#ifndef ISO9660_SUSP_H +#define ISO9660_SUSP_H 1 + +/* Public functions of susp_rr.c, a reader for SUSP and Rock Ridge information. +*/ + +/* Inspect the ISO 9660 filesystem whether it bears the signatures of + SUSP and Rock Ridge. + Set the parameters fs->fs_info->do_rr and fs->fs_info->susp_skip. + To be called at the end of iso_fs_init(). + + SUSP demands an SP entry as first entry in the System Use area of + the first directory record in the root directory. + Rock Ridge prescribes at the same directory record an ER entry with + id field content "RRIP_1991A", or "IEEE_P1282", or "IEEE_1282". + + @param fs The filesystem to inspect + @param flag Bitfield for control purposes: + bit0= Demand a Rock Ridge ER entry + @return 0 No valid SUSP signature found. + 1 Yes, signature of SUSP found. No ER was demanded. + 2 ER of RRIP 1.10 found. + 3 ER of RRIP 1.12 found. +*/ +int susp_rr_check_signatures(struct fs_info *fs, int flag); + + +/* Obtain the payload bytes of all SUSP entries with the given signature. + + @param fs The filesystem from which to read CE blocks. + fs->fs_info->do_rr must be non-zero or else this function + will always return 0 (i.e. no payload found). + @param dir_rec Memory containing the whole ISO 9660 directory record. + @param sig Two characters of SUSP signature. E.g. "NM", "ER", ... + @param data Returns allocated memory with the payload. + A trailing 0-byte is added for convenience with strings. + If data is returned != NULL, then it has to be disposed + by free() when it is no longer needed. + @param len_data Returns the number of valid bytes in *data. + Not included in this count is the convenience 0-byte. + @param flag Bitfield for control purposes: + bit0= NM/SL mode: + Skip 5 header bytes rather than 4. + End after first matching entry without CONTINUE bit. + Return 0x100 | byte[4] (FLAGS) of first entry. + @return >0 Success. + *data and *len_data are valid. + Only in this case, *data is returned != NULL. + 0 Desired signature not found. + -1 Error. + Something is wrong with the ISO 9660 or SUSP data in + the image. +*/ +int susp_rr_get_entries(struct fs_info *fs, char *dir_rec, char *sig, + char **data, int *len_data, int flag); + + +/* Obtain the Rock Ridge name of a directory record. + If the found content of NM entries is longer than 255 characters, + then this function will not return it, but rather indicate an error. + + @param fs The filesystem from which to read CE blocks. + fs->fs_info->do_rr must be non-zero or else this function + will always return 0 (i.e. no Rock Ridge name found). + @param dir_rec Memory containing the whole ISO 9660 directory record. + @param name Returns allocated memory with the name and a trailing + 0-byte. name might contain any byte values. + If name is returned != NULL, then it has to be disposed + by free() when it is no longer needed. + @param len_name Returns the number of valid bytes in *name. + Not included in this count is the 0-byte after the name. + @return >0 Success. + *name and *len_name are valid. + Only in this case, *data is returned != NULL. + 0 No NM entry found. No Rock Ridge name defined. + -1 Error. + Something is wrong with the ISO 9660 or SUSP data in + the image. +*/ +int susp_rr_get_nm(struct fs_info *fs, char *dir_rec, + char **name, int *len_name); + + +#endif /* ! ISO9660_SUSP_H */ |