isofs: add support for Rock Ridge deep directories
Change-Id: I723c1365e751683e63b95b642e55d95a41040091
This commit is contained in:
parent
8b8fa23c78
commit
d402f03800
|
|
@ -16,9 +16,6 @@ struct inode_cache {
|
|||
|
||||
struct inode_cache *icache = NULL;
|
||||
|
||||
struct inode* inode_cache_get(ino_t ino_nr);
|
||||
void inode_cache_add(ino_t ino_nr, struct inode *i_node);
|
||||
|
||||
void read_inode_iso9660(struct inode_dir_entry *i,
|
||||
const struct iso9660_dir_record *dir_rec, struct dir_extent *extent,
|
||||
size_t offset, int name_only);
|
||||
|
|
@ -117,6 +114,7 @@ int read_directory(struct inode *dir) {
|
|||
if (cur_entry >= MAX_DIRECTORY_LENGTH)
|
||||
break;
|
||||
|
||||
read_next_inode:
|
||||
memset(&entries[cur_entry], 0, sizeof(struct inode_dir_entry));
|
||||
status = read_inode(&entries[cur_entry], dir->extent, &pos);
|
||||
if (status != OK)
|
||||
|
|
@ -363,6 +361,7 @@ void read_inode_susp(struct inode_dir_entry *i,
|
|||
rrii_data.rdev = NO_DEV;
|
||||
rrii_data.file_id_rrip[0] = '\0';
|
||||
rrii_data.slink_rrip[0] = '\0';
|
||||
rrii_data.reparented_inode = NULL;
|
||||
|
||||
parse_susp_buffer(&rrii_data, b_data(bp)+offset+susp_offset, susp_size);
|
||||
|
||||
|
|
@ -379,6 +378,15 @@ void read_inode_susp(struct inode_dir_entry *i,
|
|||
memcpy(i->i_node->s_name, rrii_data.slink_rrip, name_length);
|
||||
}
|
||||
|
||||
if (rrii_data.reparented_inode) {
|
||||
i->i_node = rrii_data.reparented_inode;
|
||||
return;
|
||||
}
|
||||
|
||||
/* XXX: not the correct way to detect reparented directory holder... */
|
||||
if (strcmp(rrii_data.file_id_rrip, ".rr_moved") == 0)
|
||||
i->i_node->skip = 1;
|
||||
|
||||
if (name_only == TRUE)
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ struct rrii_dir_record {
|
|||
|
||||
char file_id_rrip[ISO9660_RRIP_MAX_FILE_ID_LEN]; /* file name */
|
||||
char slink_rrip[ISO9660_RRIP_MAX_FILE_ID_LEN]; /* symbolic link */
|
||||
|
||||
struct inode *reparented_inode;
|
||||
} ;
|
||||
|
||||
struct dir_extent {
|
||||
|
|
@ -63,6 +65,7 @@ struct inode {
|
|||
struct inode_dir_entry *dir_contents; /* contents of directory */
|
||||
size_t dir_size; /* number of inodes in this directory */
|
||||
char *s_name; /* Rock Ridge symbolic link */
|
||||
int skip; /* skip inode because of reparenting */
|
||||
} ;
|
||||
|
||||
struct opt {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@ int read_directory(struct inode *dir);
|
|||
int read_inode(struct inode_dir_entry *dir_entry, struct dir_extent *extent,
|
||||
size_t *offset);
|
||||
|
||||
struct inode* inode_cache_get(ino_t ino_nr);
|
||||
void inode_cache_add(ino_t ino_nr, struct inode *i_node);
|
||||
|
||||
int check_inodes(void);
|
||||
|
||||
/* link.c */
|
||||
|
|
|
|||
|
|
@ -8,6 +8,42 @@
|
|||
|
||||
#ifdef ISO9660_OPTION_ROCKRIDGE
|
||||
|
||||
void parse_susp_rock_ridge_plcl(struct rrii_dir_record *dir, u32_t block) {
|
||||
struct inode *rep_inode;
|
||||
struct buf *bp;
|
||||
struct iso9660_dir_record *dir_rec;
|
||||
struct dir_extent extent;
|
||||
struct inode_dir_entry dummy_dir_entry;
|
||||
size_t dummy_offset = 0;
|
||||
|
||||
/* Check if inode wasn't already parsed. */
|
||||
rep_inode = inode_cache_get(block);
|
||||
if (rep_inode != NULL) {
|
||||
rep_inode->i_refcount++;
|
||||
dir->reparented_inode = rep_inode;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Peek ahead to build extent for read_inode. */
|
||||
bp = lmfs_get_block(fs_dev, block, NORMAL);
|
||||
if (!bp)
|
||||
return;
|
||||
|
||||
dir_rec = (struct iso9660_dir_record*)b_data(bp);
|
||||
|
||||
extent.location = block;
|
||||
extent.length = dir_rec->data_length_l / v_pri.logical_block_size_l;
|
||||
if (dir_rec->data_length_l % v_pri.logical_block_size_l)
|
||||
extent.length++;
|
||||
extent.next = NULL;
|
||||
lmfs_put_block(bp, FULL_DATA_BLOCK);
|
||||
|
||||
memset(&dummy_dir_entry, 0, sizeof(struct inode_dir_entry));
|
||||
read_inode(&dummy_dir_entry, &extent, &dummy_offset);
|
||||
free(dummy_dir_entry.r_name);
|
||||
dir->reparented_inode = dummy_dir_entry.i_node;
|
||||
}
|
||||
|
||||
void parse_susp_rock_ridge_sl(struct rrii_dir_record *dir, char *buffer, int length)
|
||||
{
|
||||
/* Parse a Rock Ridge SUSP symbolic link entry (SL). */
|
||||
|
|
@ -108,6 +144,7 @@ int parse_susp_rock_ridge(struct rrii_dir_record *dir, char *buffer)
|
|||
u32_t rrii_pn_rdev_major;
|
||||
u32_t rrii_pn_rdev_minor;
|
||||
mode_t rrii_px_posix_mode;
|
||||
u32_t rrii_pcl_block;
|
||||
|
||||
susp_signature[0] = buffer[0];
|
||||
susp_signature[1] = buffer[1];
|
||||
|
|
@ -166,16 +203,25 @@ int parse_susp_rock_ridge(struct rrii_dir_record *dir, char *buffer)
|
|||
|
||||
return OK;
|
||||
}
|
||||
else if ((susp_signature[0] == 'C') && (susp_signature[1] == 'L')) {
|
||||
/* Ignored, skip. */
|
||||
else if ((susp_signature[0] == 'P') && (susp_signature[1] == 'L') &&
|
||||
(susp_length >= 12) && (susp_version >= 1)) {
|
||||
/* Reparenting ".." directory entry. */
|
||||
rrii_pcl_block = *((u32_t*)(buffer + 4));
|
||||
parse_susp_rock_ridge_plcl(dir, rrii_pcl_block);
|
||||
|
||||
return OK;
|
||||
}
|
||||
else if ((susp_signature[0] == 'P') && (susp_signature[1] == 'L')) {
|
||||
/* Ignored, skip. */
|
||||
else if ((susp_signature[0] == 'C') && (susp_signature[1] == 'L') &&
|
||||
(susp_length >= 12) && (susp_version >= 1)) {
|
||||
/* Reorganize deep directory entry. */
|
||||
rrii_pcl_block = *((u32_t*)(buffer + 4));
|
||||
parse_susp_rock_ridge_plcl(dir, rrii_pcl_block);
|
||||
|
||||
return OK;
|
||||
}
|
||||
else if ((susp_signature[0] == 'R') && (susp_signature[1] == 'E')) {
|
||||
/* Ignored, skip. */
|
||||
|
||||
return OK;
|
||||
}
|
||||
else if ((susp_signature[0] == 'T') && (susp_signature[1] == 'F') &&
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user