diff options
Diffstat (limited to 'fs/udf/dir.c')
-rw-r--r-- | fs/udf/dir.c | 57 |
1 files changed, 27 insertions, 30 deletions
diff --git a/fs/udf/dir.c b/fs/udf/dir.c index 31feef916fb7..62dc270c69d1 100644 --- a/fs/udf/dir.c +++ b/fs/udf/dir.c | |||
@@ -39,13 +39,13 @@ | |||
39 | static int do_udf_readdir(struct inode *dir, struct file *filp, | 39 | static int do_udf_readdir(struct inode *dir, struct file *filp, |
40 | filldir_t filldir, void *dirent) | 40 | filldir_t filldir, void *dirent) |
41 | { | 41 | { |
42 | struct udf_fileident_bh fibh; | 42 | struct udf_fileident_bh fibh = { .sbh = NULL, .ebh = NULL}; |
43 | struct fileIdentDesc *fi = NULL; | 43 | struct fileIdentDesc *fi = NULL; |
44 | struct fileIdentDesc cfi; | 44 | struct fileIdentDesc cfi; |
45 | int block, iblock; | 45 | int block, iblock; |
46 | loff_t nf_pos = (filp->f_pos - 1) << 2; | 46 | loff_t nf_pos = (filp->f_pos - 1) << 2; |
47 | int flen; | 47 | int flen; |
48 | char fname[UDF_NAME_LEN]; | 48 | char *fname = NULL; |
49 | char *nameptr; | 49 | char *nameptr; |
50 | uint16_t liu; | 50 | uint16_t liu; |
51 | uint8_t lfi; | 51 | uint8_t lfi; |
@@ -54,23 +54,32 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, | |||
54 | kernel_lb_addr eloc; | 54 | kernel_lb_addr eloc; |
55 | uint32_t elen; | 55 | uint32_t elen; |
56 | sector_t offset; | 56 | sector_t offset; |
57 | int i, num; | 57 | int i, num, ret = 0; |
58 | unsigned int dt_type; | 58 | unsigned int dt_type; |
59 | struct extent_position epos = { NULL, 0, {0, 0} }; | 59 | struct extent_position epos = { NULL, 0, {0, 0} }; |
60 | struct udf_inode_info *iinfo; | 60 | struct udf_inode_info *iinfo; |
61 | 61 | ||
62 | if (nf_pos >= size) | 62 | if (nf_pos >= size) |
63 | return 0; | 63 | goto out; |
64 | |||
65 | fname = kmalloc(UDF_NAME_LEN, GFP_NOFS); | ||
66 | if (!fname) { | ||
67 | ret = -ENOMEM; | ||
68 | goto out; | ||
69 | } | ||
64 | 70 | ||
65 | if (nf_pos == 0) | 71 | if (nf_pos == 0) |
66 | nf_pos = udf_ext0_offset(dir); | 72 | nf_pos = udf_ext0_offset(dir); |
67 | 73 | ||
68 | fibh.soffset = fibh.eoffset = nf_pos & (dir->i_sb->s_blocksize - 1); | 74 | fibh.soffset = fibh.eoffset = nf_pos & (dir->i_sb->s_blocksize - 1); |
69 | iinfo = UDF_I(dir); | 75 | iinfo = UDF_I(dir); |
70 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { | 76 | if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { |
71 | fibh.sbh = fibh.ebh = NULL; | 77 | if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits, |
72 | } else if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits, | 78 | &epos, &eloc, &elen, &offset) |
73 | &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30)) { | 79 | != (EXT_RECORDED_ALLOCATED >> 30)) { |
80 | ret = -ENOENT; | ||
81 | goto out; | ||
82 | } | ||
74 | block = udf_get_lb_pblock(dir->i_sb, eloc, offset); | 83 | block = udf_get_lb_pblock(dir->i_sb, eloc, offset); |
75 | if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { | 84 | if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { |
76 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) | 85 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
@@ -83,8 +92,8 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, | |||
83 | } | 92 | } |
84 | 93 | ||
85 | if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block))) { | 94 | if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block))) { |
86 | brelse(epos.bh); | 95 | ret = -EIO; |
87 | return -EIO; | 96 | goto out; |
88 | } | 97 | } |
89 | 98 | ||
90 | if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9)) - 1))) { | 99 | if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9)) - 1))) { |
@@ -105,9 +114,6 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, | |||
105 | brelse(bha[i]); | 114 | brelse(bha[i]); |
106 | } | 115 | } |
107 | } | 116 | } |
108 | } else { | ||
109 | brelse(epos.bh); | ||
110 | return -ENOENT; | ||
111 | } | 117 | } |
112 | 118 | ||
113 | while (nf_pos < size) { | 119 | while (nf_pos < size) { |
@@ -115,13 +121,8 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, | |||
115 | 121 | ||
116 | fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc, | 122 | fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc, |
117 | &elen, &offset); | 123 | &elen, &offset); |
118 | if (!fi) { | 124 | if (!fi) |
119 | if (fibh.sbh != fibh.ebh) | 125 | goto out; |
120 | brelse(fibh.ebh); | ||
121 | brelse(fibh.sbh); | ||
122 | brelse(epos.bh); | ||
123 | return 0; | ||
124 | } | ||
125 | 126 | ||
126 | liu = le16_to_cpu(cfi.lengthOfImpUse); | 127 | liu = le16_to_cpu(cfi.lengthOfImpUse); |
127 | lfi = cfi.lengthFileIdent; | 128 | lfi = cfi.lengthFileIdent; |
@@ -167,25 +168,21 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, | |||
167 | dt_type = DT_UNKNOWN; | 168 | dt_type = DT_UNKNOWN; |
168 | } | 169 | } |
169 | 170 | ||
170 | if (flen) { | 171 | if (flen && filldir(dirent, fname, flen, filp->f_pos, |
171 | if (filldir(dirent, fname, flen, filp->f_pos, iblock, dt_type) < 0) { | 172 | iblock, dt_type) < 0) |
172 | if (fibh.sbh != fibh.ebh) | 173 | goto out; |
173 | brelse(fibh.ebh); | ||
174 | brelse(fibh.sbh); | ||
175 | brelse(epos.bh); | ||
176 | return 0; | ||
177 | } | ||
178 | } | ||
179 | } /* end while */ | 174 | } /* end while */ |
180 | 175 | ||
181 | filp->f_pos = (nf_pos >> 2) + 1; | 176 | filp->f_pos = (nf_pos >> 2) + 1; |
182 | 177 | ||
178 | out: | ||
183 | if (fibh.sbh != fibh.ebh) | 179 | if (fibh.sbh != fibh.ebh) |
184 | brelse(fibh.ebh); | 180 | brelse(fibh.ebh); |
185 | brelse(fibh.sbh); | 181 | brelse(fibh.sbh); |
186 | brelse(epos.bh); | 182 | brelse(epos.bh); |
183 | kfree(fname); | ||
187 | 184 | ||
188 | return 0; | 185 | return ret; |
189 | } | 186 | } |
190 | 187 | ||
191 | static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir) | 188 | static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir) |