static int do_udf_readdir(struct inode *dir, struct file *filp,
filldir_t filldir, void *dirent)
{
- struct udf_fileident_bh fibh;
+ struct udf_fileident_bh fibh = { .sbh = NULL, .ebh = NULL};
struct fileIdentDesc *fi = NULL;
struct fileIdentDesc cfi;
int block, iblock;
loff_t nf_pos = (filp->f_pos - 1) << 2;
int flen;
- char fname[UDF_NAME_LEN];
+ char *fname = NULL;
char *nameptr;
uint16_t liu;
uint8_t lfi;
kernel_lb_addr eloc;
uint32_t elen;
sector_t offset;
- int i, num;
+ int i, num, ret = 0;
unsigned int dt_type;
struct extent_position epos = { NULL, 0, {0, 0} };
struct udf_inode_info *iinfo;
if (nf_pos >= size)
- return 0;
+ goto out;
+
+ fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
+ if (!fname) {
+ ret = -ENOMEM;
+ goto out;
+ }
if (nf_pos == 0)
nf_pos = udf_ext0_offset(dir);
fibh.soffset = fibh.eoffset = nf_pos & (dir->i_sb->s_blocksize - 1);
iinfo = UDF_I(dir);
- if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
- fibh.sbh = fibh.ebh = NULL;
- } else if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits,
- &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30)) {
+ if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
+ if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits,
+ &epos, &eloc, &elen, &offset)
+ != (EXT_RECORDED_ALLOCATED >> 30)) {
+ ret = -ENOENT;
+ goto out;
+ }
block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
}
if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block))) {
- brelse(epos.bh);
- return -EIO;
+ ret = -EIO;
+ goto out;
}
if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9)) - 1))) {
brelse(bha[i]);
}
}
- } else {
- brelse(epos.bh);
- return -ENOENT;
}
while (nf_pos < size) {
fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc,
&elen, &offset);
- if (!fi) {
- if (fibh.sbh != fibh.ebh)
- brelse(fibh.ebh);
- brelse(fibh.sbh);
- brelse(epos.bh);
- return 0;
- }
+ if (!fi)
+ goto out;
liu = le16_to_cpu(cfi.lengthOfImpUse);
lfi = cfi.lengthFileIdent;
dt_type = DT_UNKNOWN;
}
- if (flen) {
- if (filldir(dirent, fname, flen, filp->f_pos, iblock, dt_type) < 0) {
- if (fibh.sbh != fibh.ebh)
- brelse(fibh.ebh);
- brelse(fibh.sbh);
- brelse(epos.bh);
- return 0;
- }
- }
+ if (flen && filldir(dirent, fname, flen, filp->f_pos,
+ iblock, dt_type) < 0)
+ goto out;
} /* end while */
filp->f_pos = (nf_pos >> 2) + 1;
+out:
if (fibh.sbh != fibh.ebh)
brelse(fibh.ebh);
brelse(fibh.sbh);
brelse(epos.bh);
+ kfree(fname);
- return 0;
+ return ret;
}
static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
struct fileIdentDesc *fi = NULL;
loff_t f_pos;
int block, flen;
- char fname[UDF_NAME_LEN];
+ char *fname = NULL;
char *nameptr;
uint8_t lfi;
uint16_t liu;
size = udf_ext0_offset(dir) + dir->i_size;
f_pos = udf_ext0_offset(dir);
+ fibh->sbh = fibh->ebh = NULL;
fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
- if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
- fibh->sbh = fibh->ebh = NULL;
- else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits,
- &epos, &eloc, &elen, &offset) ==
- (EXT_RECORDED_ALLOCATED >> 30)) {
+ if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
+ if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos,
+ &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30))
+ goto out_err;
block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
offset = 0;
fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
- if (!fibh->sbh) {
- brelse(epos.bh);
- return NULL;
- }
- } else {
- brelse(epos.bh);
- return NULL;
+ if (!fibh->sbh)
+ goto out_err;
}
+ fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
+ if (!fname)
+ goto out_err;
+
while (f_pos < size) {
fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc,
&elen, &offset);
- if (!fi) {
- if (fibh->sbh != fibh->ebh)
- brelse(fibh->ebh);
- brelse(fibh->sbh);
- brelse(epos.bh);
- return NULL;
- }
+ if (!fi)
+ goto out_err;
liu = le16_to_cpu(cfi->lengthOfImpUse);
lfi = cfi->lengthFileIdent;
flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
if (flen && udf_match(flen, fname, dentry->d_name.len,
- dentry->d_name.name)) {
- brelse(epos.bh);
- return fi;
- }
+ dentry->d_name.name))
+ goto out_ok;
}
+out_err:
+ fi = NULL;
if (fibh->sbh != fibh->ebh)
brelse(fibh->ebh);
brelse(fibh->sbh);
+out_ok:
brelse(epos.bh);
+ kfree(fname);
- return NULL;
+ return fi;
}
static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
{
struct super_block *sb = dir->i_sb;
struct fileIdentDesc *fi = NULL;
- char name[UDF_NAME_LEN];
+ char *name = NULL;
int namelen;
loff_t f_pos;
loff_t size = udf_ext0_offset(dir) + dir->i_size;
struct extent_position epos = {};
struct udf_inode_info *dinfo;
+ fibh->sbh = fibh->ebh = NULL;
+ name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
+ if (!name) {
+ *err = -ENOMEM;
+ goto out_err;
+ }
+
if (dentry) {
if (!dentry->d_name.len) {
*err = -EINVAL;
- return NULL;
+ goto out_err;
}
namelen = udf_put_filename(sb, dentry->d_name.name, name,
dentry->d_name.len);
if (!namelen) {
*err = -ENAMETOOLONG;
- return NULL;
+ goto out_err;
}
} else {
namelen = 0;
fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
dinfo = UDF_I(dir);
- if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
- fibh->sbh = fibh->ebh = NULL;
- else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits,
- &epos, &eloc, &elen, &offset) ==
- (EXT_RECORDED_ALLOCATED >> 30)) {
+ if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
+ if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos,
+ &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) {
+ block = udf_get_lb_pblock(dir->i_sb,
+ dinfo->i_location, 0);
+ fibh->soffset = fibh->eoffset = sb->s_blocksize;
+ goto add;
+ }
block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
if (!fibh->sbh) {
- brelse(epos.bh);
*err = -EIO;
- return NULL;
+ goto out_err;
}
block = dinfo->i_location.logicalBlockNum;
- } else {
- block = udf_get_lb_pblock(dir->i_sb, dinfo->i_location, 0);
- fibh->sbh = fibh->ebh = NULL;
- fibh->soffset = fibh->eoffset = sb->s_blocksize;
- goto add;
}
while (f_pos < size) {
&elen, &offset);
if (!fi) {
- if (fibh->sbh != fibh->ebh)
- brelse(fibh->ebh);
- brelse(fibh->sbh);
- brelse(epos.bh);
*err = -EIO;
- return NULL;
+ goto out_err;
}
liu = le16_to_cpu(cfi->lengthOfImpUse);
if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) {
if (((sizeof(struct fileIdentDesc) +
liu + lfi + 3) & ~3) == nfidlen) {
- brelse(epos.bh);
cfi->descTag.tagSerialNum = cpu_to_le16(1);
cfi->fileVersionNum = cpu_to_le16(1);
cfi->fileCharacteristics = 0;
cfi->lengthOfImpUse = cpu_to_le16(0);
if (!udf_write_fi(dir, cfi, fi, fibh, NULL,
name))
- return fi;
+ goto out_ok;
else {
*err = -EIO;
- return NULL;
+ goto out_err;
}
}
}
fibh->sbh = fibh->ebh =
udf_expand_dir_adinicb(dir, &block, err);
if (!fibh->sbh)
- return NULL;
+ goto out_err;
epos.block = dinfo->i_location;
epos.offset = udf_file_entry_alloc_offset(dir);
/* Load extent udf_expand_dir_adinicb() has created */
dir->i_sb->s_blocksize_bits);
fibh->ebh = udf_bread(dir,
f_pos >> dir->i_sb->s_blocksize_bits, 1, err);
- if (!fibh->ebh) {
- brelse(epos.bh);
- brelse(fibh->sbh);
- return NULL;
- }
+ if (!fibh->ebh)
+ goto out_err;
if (!fibh->soffset) {
if (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
cfi->lengthFileIdent = namelen;
cfi->lengthOfImpUse = cpu_to_le16(0);
if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) {
- brelse(epos.bh);
dir->i_size += nfidlen;
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
dinfo->i_lenAlloc += nfidlen;
mark_inode_dirty(dir);
- return fi;
+ goto out_ok;
} else {
- brelse(epos.bh);
- if (fibh->sbh != fibh->ebh)
- brelse(fibh->ebh);
- brelse(fibh->sbh);
*err = -EIO;
- return NULL;
+ goto out_err;
}
+
+out_err:
+ fi = NULL;
+ if (fibh->sbh != fibh->ebh)
+ brelse(fibh->ebh);
+ brelse(fibh->sbh);
+out_ok:
+ brelse(epos.bh);
+ kfree(name);
+ return fi;
}
static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi,
char *ea;
int err;
int block;
- char name[UDF_NAME_LEN];
+ char *name = NULL;
int namelen;
struct buffer_head *bh;
struct udf_inode_info *iinfo;
if (!inode)
goto out;
+ name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
+ if (!name) {
+ err = -ENOMEM;
+ goto out_no_entry;
+ }
+
iinfo = UDF_I(inode);
inode->i_mode = S_IFLNK | S_IRWXUGO;
inode->i_data.a_ops = &udf_symlink_aops;
err = 0;
out:
+ kfree(name);
unlock_kernel();
return err;