diff options
Diffstat (limited to 'fs/isofs/rock.c')
| -rw-r--r-- | fs/isofs/rock.c | 39 | 
1 files changed, 28 insertions, 11 deletions
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c index c0bf42472e40..f488bbae541a 100644 --- a/fs/isofs/rock.c +++ b/fs/isofs/rock.c @@ -288,12 +288,16 @@ eio:  	goto out;  } +#define RR_REGARD_XA 1 +#define RR_RELOC_DE 2 +  static int  parse_rock_ridge_inode_internal(struct iso_directory_record *de, -				struct inode *inode, int regard_xa) +				struct inode *inode, int flags)  {  	int symlink_len = 0;  	int cnt, sig; +	unsigned int reloc_block;  	struct inode *reloc;  	struct rock_ridge *rr;  	int rootflag; @@ -305,7 +309,7 @@ parse_rock_ridge_inode_internal(struct iso_directory_record *de,  	init_rock_state(&rs, inode);  	setup_rock_ridge(de, inode, &rs); -	if (regard_xa) { +	if (flags & RR_REGARD_XA) {  		rs.chr += 14;  		rs.len -= 14;  		if (rs.len < 0) @@ -485,12 +489,22 @@ repeat:  					"relocated directory\n");  			goto out;  		case SIG('C', 'L'): -			ISOFS_I(inode)->i_first_extent = -			    isonum_733(rr->u.CL.location); -			reloc = -			    isofs_iget(inode->i_sb, -				       ISOFS_I(inode)->i_first_extent, -				       0); +			if (flags & RR_RELOC_DE) { +				printk(KERN_ERR +				       "ISOFS: Recursive directory relocation " +				       "is not supported\n"); +				goto eio; +			} +			reloc_block = isonum_733(rr->u.CL.location); +			if (reloc_block == ISOFS_I(inode)->i_iget5_block && +			    ISOFS_I(inode)->i_iget5_offset == 0) { +				printk(KERN_ERR +				       "ISOFS: Directory relocation points to " +				       "itself\n"); +				goto eio; +			} +			ISOFS_I(inode)->i_first_extent = reloc_block; +			reloc = isofs_iget_reloc(inode->i_sb, reloc_block, 0);  			if (IS_ERR(reloc)) {  				ret = PTR_ERR(reloc);  				goto out; @@ -637,9 +651,11 @@ static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)  	return rpnt;  } -int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode) +int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode, +			   int relocated)  { -	int result = parse_rock_ridge_inode_internal(de, inode, 0); +	int flags = relocated ? RR_RELOC_DE : 0; +	int result = parse_rock_ridge_inode_internal(de, inode, flags);  	/*  	 * if rockridge flag was reset and we didn't look for attributes @@ -647,7 +663,8 @@ int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode)  	 */  	if ((ISOFS_SB(inode->i_sb)->s_rock_offset == -1)  	    && (ISOFS_SB(inode->i_sb)->s_rock == 2)) { -		result = parse_rock_ridge_inode_internal(de, inode, 14); +		result = parse_rock_ridge_inode_internal(de, inode, +							 flags | RR_REGARD_XA);  	}  	return result;  }  |