isofs: add support for Rock Ridge deep directories
This commit is contained in:
parent
e2b37bcf44
commit
d34477d549
|
|
@ -16,9 +16,6 @@ struct inode_cache {
|
||||||
|
|
||||||
struct inode_cache *icache = NULL;
|
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,
|
void read_inode_iso9660(struct inode_dir_entry *i,
|
||||||
const struct iso9660_dir_record *dir_rec, struct dir_extent *extent,
|
const struct iso9660_dir_record *dir_rec, struct dir_extent *extent,
|
||||||
size_t offset, int name_only);
|
size_t offset, int name_only);
|
||||||
|
|
@ -117,6 +114,7 @@ int read_directory(struct inode *dir) {
|
||||||
if (cur_entry >= MAX_DIRECTORY_LENGTH)
|
if (cur_entry >= MAX_DIRECTORY_LENGTH)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
read_next_inode:
|
||||||
memset(&entries[cur_entry], 0, sizeof(struct inode_dir_entry));
|
memset(&entries[cur_entry], 0, sizeof(struct inode_dir_entry));
|
||||||
status = read_inode(&entries[cur_entry], dir->extent, &pos);
|
status = read_inode(&entries[cur_entry], dir->extent, &pos);
|
||||||
if (status != OK)
|
if (status != OK)
|
||||||
|
|
@ -363,6 +361,7 @@ void read_inode_susp(struct inode_dir_entry *i,
|
||||||
rrii_data.rdev = NO_DEV;
|
rrii_data.rdev = NO_DEV;
|
||||||
rrii_data.file_id_rrip[0] = '\0';
|
rrii_data.file_id_rrip[0] = '\0';
|
||||||
rrii_data.slink_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);
|
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);
|
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)
|
if (name_only == TRUE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,8 @@ struct rrii_dir_record {
|
||||||
|
|
||||||
char file_id_rrip[ISO9660_RRIP_MAX_FILE_ID_LEN]; /* file name */
|
char file_id_rrip[ISO9660_RRIP_MAX_FILE_ID_LEN]; /* file name */
|
||||||
char slink_rrip[ISO9660_RRIP_MAX_FILE_ID_LEN]; /* symbolic link */
|
char slink_rrip[ISO9660_RRIP_MAX_FILE_ID_LEN]; /* symbolic link */
|
||||||
|
|
||||||
|
struct inode *reparented_inode;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
struct dir_extent {
|
struct dir_extent {
|
||||||
|
|
@ -63,6 +65,7 @@ struct inode {
|
||||||
struct inode_dir_entry *dir_contents; /* contents of directory */
|
struct inode_dir_entry *dir_contents; /* contents of directory */
|
||||||
size_t dir_size; /* number of inodes in this directory */
|
size_t dir_size; /* number of inodes in this directory */
|
||||||
char *s_name; /* Rock Ridge symbolic link */
|
char *s_name; /* Rock Ridge symbolic link */
|
||||||
|
int skip; /* skip inode because of reparenting */
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
struct opt {
|
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,
|
int read_inode(struct inode_dir_entry *dir_entry, struct dir_extent *extent,
|
||||||
size_t *offset);
|
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);
|
int check_inodes(void);
|
||||||
|
|
||||||
/* link.c */
|
/* link.c */
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,42 @@
|
||||||
|
|
||||||
#ifdef ISO9660_OPTION_ROCKRIDGE
|
#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)
|
void parse_susp_rock_ridge_sl(struct rrii_dir_record *dir, char *buffer, int length)
|
||||||
{
|
{
|
||||||
/* Parse a Rock Ridge SUSP symbolic link entry (SL). */
|
/* 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_major;
|
||||||
u32_t rrii_pn_rdev_minor;
|
u32_t rrii_pn_rdev_minor;
|
||||||
mode_t rrii_px_posix_mode;
|
mode_t rrii_px_posix_mode;
|
||||||
|
u32_t rrii_pcl_block;
|
||||||
|
|
||||||
susp_signature[0] = buffer[0];
|
susp_signature[0] = buffer[0];
|
||||||
susp_signature[1] = buffer[1];
|
susp_signature[1] = buffer[1];
|
||||||
|
|
@ -166,16 +203,25 @@ int parse_susp_rock_ridge(struct rrii_dir_record *dir, char *buffer)
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
else if ((susp_signature[0] == 'C') && (susp_signature[1] == 'L')) {
|
else if ((susp_signature[0] == 'P') && (susp_signature[1] == 'L') &&
|
||||||
/* Ignored, skip. */
|
(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;
|
return OK;
|
||||||
}
|
}
|
||||||
else if ((susp_signature[0] == 'P') && (susp_signature[1] == 'L')) {
|
else if ((susp_signature[0] == 'C') && (susp_signature[1] == 'L') &&
|
||||||
/* Ignored, skip. */
|
(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;
|
return OK;
|
||||||
}
|
}
|
||||||
else if ((susp_signature[0] == 'R') && (susp_signature[1] == 'E')) {
|
else if ((susp_signature[0] == 'R') && (susp_signature[1] == 'E')) {
|
||||||
/* Ignored, skip. */
|
/* Ignored, skip. */
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
else if ((susp_signature[0] == 'T') && (susp_signature[1] == 'F') &&
|
else if ((susp_signature[0] == 'T') && (susp_signature[1] == 'F') &&
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user