aboutsummaryrefslogtreecommitdiffstats
path: root/fs/udf/namei.c
diff options
context:
space:
mode:
authorFabian Frederick <fabf@skynet.be>2015-04-08 15:23:58 -0400
committerJan Kara <jack@suse.cz>2015-05-18 05:23:07 -0400
commit231473f6ddcef9c01993e0bfe36acc6f8e425c31 (patch)
tree8f756c6d7ddbd6ffffd90f35ccdc3746e0cc8f9c /fs/udf/namei.c
parent6ce638367382ea8015cf64619e9bca4e207ef36f (diff)
udf: Return error from udf_find_entry()
Return appropriate error from udf_find_entry() instead of just NULL. That way we can distinguish the fact that some error happened when looking up filename (and return error to userspace) from the fact that we just didn't find the filename. Also update callers of udf_find_entry() accordingly. [JK: Improved udf_find_entry() documentation] Suggested-by: Jan Kara <jack@suse.cz> Signed-off-by: Fabian Frederick <fabf@skynet.be> Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/udf/namei.c')
-rw-r--r--fs/udf/namei.c91
1 files changed, 71 insertions, 20 deletions
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index 51b1c31b55c8..6abbb649c28a 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -138,6 +138,25 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
138 return 0; 138 return 0;
139} 139}
140 140
141/**
142 * udf_find_entry - find entry in given directory.
143 *
144 * @dir: directory inode to search in
145 * @child: qstr of the name
146 * @fibh: buffer head / inode with file identifier descriptor we found
147 * @cfi: found file identifier descriptor with given name
148 *
149 * This function searches in the directory @dir for a file name @child. When
150 * found, @fibh points to the buffer head(s) (bh is NULL for in ICB
151 * directories) containing the file identifier descriptor (FID). In that case
152 * the function returns pointer to the FID in the buffer or inode - but note
153 * that FID may be split among two buffers (blocks) so accessing it via that
154 * pointer isn't easily possible. This pointer can be used only as an iterator
155 * for other directory manipulation functions. For inspection of the FID @cfi
156 * can be used - the found FID is copied there.
157 *
158 * Returns pointer to FID, NULL when nothing found, or error code.
159 */
141static struct fileIdentDesc *udf_find_entry(struct inode *dir, 160static struct fileIdentDesc *udf_find_entry(struct inode *dir,
142 const struct qstr *child, 161 const struct qstr *child,
143 struct udf_fileident_bh *fibh, 162 struct udf_fileident_bh *fibh,
@@ -167,8 +186,11 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
167 fibh->soffset = fibh->eoffset = f_pos & (sb->s_blocksize - 1); 186 fibh->soffset = fibh->eoffset = f_pos & (sb->s_blocksize - 1);
168 if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { 187 if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
169 if (inode_bmap(dir, f_pos >> sb->s_blocksize_bits, &epos, 188 if (inode_bmap(dir, f_pos >> sb->s_blocksize_bits, &epos,
170 &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) 189 &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) {
190 fi = ERR_PTR(-EIO);
171 goto out_err; 191 goto out_err;
192 }
193
172 block = udf_get_lb_pblock(sb, &eloc, offset); 194 block = udf_get_lb_pblock(sb, &eloc, offset);
173 if ((++offset << sb->s_blocksize_bits) < elen) { 195 if ((++offset << sb->s_blocksize_bits) < elen) {
174 if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) 196 if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
@@ -179,19 +201,25 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
179 offset = 0; 201 offset = 0;
180 202
181 fibh->sbh = fibh->ebh = udf_tread(sb, block); 203 fibh->sbh = fibh->ebh = udf_tread(sb, block);
182 if (!fibh->sbh) 204 if (!fibh->sbh) {
205 fi = ERR_PTR(-EIO);
183 goto out_err; 206 goto out_err;
207 }
184 } 208 }
185 209
186 fname = kmalloc(UDF_NAME_LEN, GFP_NOFS); 210 fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
187 if (!fname) 211 if (!fname) {
212 fi = ERR_PTR(-ENOMEM);
188 goto out_err; 213 goto out_err;
214 }
189 215
190 while (f_pos < size) { 216 while (f_pos < size) {
191 fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc, 217 fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc,
192 &elen, &offset); 218 &elen, &offset);
193 if (!fi) 219 if (!fi) {
220 fi = ERR_PTR(-EIO);
194 goto out_err; 221 goto out_err;
222 }
195 223
196 liu = le16_to_cpu(cfi->lengthOfImpUse); 224 liu = le16_to_cpu(cfi->lengthOfImpUse);
197 lfi = cfi->lengthFileIdent; 225 lfi = cfi->lengthFileIdent;
@@ -234,12 +262,17 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
234 continue; 262 continue;
235 263
236 flen = udf_get_filename(sb, nameptr, lfi, fname, UDF_NAME_LEN); 264 flen = udf_get_filename(sb, nameptr, lfi, fname, UDF_NAME_LEN);
237 if (flen > 0 && udf_match(flen, fname, child->len, child->name)) 265 if (flen < 0) {
266 fi = ERR_PTR(flen);
267 goto out_err;
268 }
269
270 if (udf_match(flen, fname, child->len, child->name))
238 goto out_ok; 271 goto out_ok;
239 } 272 }
240 273
241out_err:
242 fi = NULL; 274 fi = NULL;
275out_err:
243 if (fibh->sbh != fibh->ebh) 276 if (fibh->sbh != fibh->ebh)
244 brelse(fibh->ebh); 277 brelse(fibh->ebh);
245 brelse(fibh->sbh); 278 brelse(fibh->sbh);
@@ -256,6 +289,7 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
256 struct inode *inode = NULL; 289 struct inode *inode = NULL;
257 struct fileIdentDesc cfi; 290 struct fileIdentDesc cfi;
258 struct udf_fileident_bh fibh; 291 struct udf_fileident_bh fibh;
292 struct fileIdentDesc *fi;
259 293
260 if (dentry->d_name.len > UDF_NAME_LEN - 2) 294 if (dentry->d_name.len > UDF_NAME_LEN - 2)
261 return ERR_PTR(-ENAMETOOLONG); 295 return ERR_PTR(-ENAMETOOLONG);
@@ -275,7 +309,11 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
275 } else 309 } else
276#endif /* UDF_RECOVERY */ 310#endif /* UDF_RECOVERY */
277 311
278 if (udf_find_entry(dir, &dentry->d_name, &fibh, &cfi)) { 312 fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi);
313 if (IS_ERR(fi))
314 return ERR_CAST(fi);
315
316 if (fi) {
279 struct kernel_lb_addr loc; 317 struct kernel_lb_addr loc;
280 318
281 if (fibh.sbh != fibh.ebh) 319 if (fibh.sbh != fibh.ebh)
@@ -774,8 +812,11 @@ static int udf_rmdir(struct inode *dir, struct dentry *dentry)
774 812
775 retval = -ENOENT; 813 retval = -ENOENT;
776 fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi); 814 fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi);
777 if (!fi) 815 if (IS_ERR_OR_NULL(fi)) {
816 if (fi)
817 retval = PTR_ERR(fi);
778 goto out; 818 goto out;
819 }
779 820
780 retval = -EIO; 821 retval = -EIO;
781 tloc = lelb_to_cpu(cfi.icb.extLocation); 822 tloc = lelb_to_cpu(cfi.icb.extLocation);
@@ -817,8 +858,12 @@ static int udf_unlink(struct inode *dir, struct dentry *dentry)
817 858
818 retval = -ENOENT; 859 retval = -ENOENT;
819 fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi); 860 fi = udf_find_entry(dir, &dentry->d_name, &fibh, &cfi);
820 if (!fi) 861
862 if (IS_ERR_OR_NULL(fi)) {
863 if (fi)
864 retval = PTR_ERR(fi);
821 goto out; 865 goto out;
866 }
822 867
823 retval = -EIO; 868 retval = -EIO;
824 tloc = lelb_to_cpu(cfi.icb.extLocation); 869 tloc = lelb_to_cpu(cfi.icb.extLocation);
@@ -1049,24 +1094,30 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry,
1049 struct udf_inode_info *old_iinfo = UDF_I(old_inode); 1094 struct udf_inode_info *old_iinfo = UDF_I(old_inode);
1050 1095
1051 ofi = udf_find_entry(old_dir, &old_dentry->d_name, &ofibh, &ocfi); 1096 ofi = udf_find_entry(old_dir, &old_dentry->d_name, &ofibh, &ocfi);
1052 if (ofi) { 1097 if (IS_ERR(ofi)) {
1053 if (ofibh.sbh != ofibh.ebh) 1098 retval = PTR_ERR(ofi);
1054 brelse(ofibh.ebh); 1099 goto end_rename;
1055 brelse(ofibh.sbh);
1056 } 1100 }
1101
1102 if (ofibh.sbh != ofibh.ebh)
1103 brelse(ofibh.ebh);
1104
1105 brelse(ofibh.sbh);
1057 tloc = lelb_to_cpu(ocfi.icb.extLocation); 1106 tloc = lelb_to_cpu(ocfi.icb.extLocation);
1058 if (!ofi || udf_get_lb_pblock(old_dir->i_sb, &tloc, 0) 1107 if (!ofi || udf_get_lb_pblock(old_dir->i_sb, &tloc, 0)
1059 != old_inode->i_ino) 1108 != old_inode->i_ino)
1060 goto end_rename; 1109 goto end_rename;
1061 1110
1062 nfi = udf_find_entry(new_dir, &new_dentry->d_name, &nfibh, &ncfi); 1111 nfi = udf_find_entry(new_dir, &new_dentry->d_name, &nfibh, &ncfi);
1063 if (nfi) { 1112 if (IS_ERR(nfi)) {
1064 if (!new_inode) { 1113 retval = PTR_ERR(nfi);
1065 if (nfibh.sbh != nfibh.ebh) 1114 goto end_rename;
1066 brelse(nfibh.ebh); 1115 }
1067 brelse(nfibh.sbh); 1116 if (nfi && !new_inode) {
1068 nfi = NULL; 1117 if (nfibh.sbh != nfibh.ebh)
1069 } 1118 brelse(nfibh.ebh);
1119 brelse(nfibh.sbh);
1120 nfi = NULL;
1070 } 1121 }
1071 if (S_ISDIR(old_inode->i_mode)) { 1122 if (S_ISDIR(old_inode->i_mode)) {
1072 int offset = udf_ext0_offset(old_inode); 1123 int offset = udf_ext0_offset(old_inode);