aboutsummaryrefslogtreecommitdiffstats
path: root/fs/udf
diff options
context:
space:
mode:
Diffstat (limited to 'fs/udf')
-rw-r--r--fs/udf/dir.c57
-rw-r--r--fs/udf/namei.c128
2 files changed, 93 insertions, 92 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 @@
39static int do_udf_readdir(struct inode *dir, struct file *filp, 39static 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
178out:
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
191static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir) 188static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index e9f587201e17..68686b79650a 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -149,7 +149,7 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
149 struct fileIdentDesc *fi = NULL; 149 struct fileIdentDesc *fi = NULL;
150 loff_t f_pos; 150 loff_t f_pos;
151 int block, flen; 151 int block, flen;
152 char fname[UDF_NAME_LEN]; 152 char *fname = NULL;
153 char *nameptr; 153 char *nameptr;
154 uint8_t lfi; 154 uint8_t lfi;
155 uint16_t liu; 155 uint16_t liu;
@@ -163,12 +163,12 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
163 size = udf_ext0_offset(dir) + dir->i_size; 163 size = udf_ext0_offset(dir) + dir->i_size;
164 f_pos = udf_ext0_offset(dir); 164 f_pos = udf_ext0_offset(dir);
165 165
166 fibh->sbh = fibh->ebh = NULL;
166 fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1); 167 fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
167 if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) 168 if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
168 fibh->sbh = fibh->ebh = NULL; 169 if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos,
169 else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, 170 &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30))
170 &epos, &eloc, &elen, &offset) == 171 goto out_err;
171 (EXT_RECORDED_ALLOCATED >> 30)) {
172 block = udf_get_lb_pblock(dir->i_sb, eloc, offset); 172 block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
173 if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { 173 if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
174 if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) 174 if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
@@ -179,25 +179,19 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
179 offset = 0; 179 offset = 0;
180 180
181 fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block); 181 fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
182 if (!fibh->sbh) { 182 if (!fibh->sbh)
183 brelse(epos.bh); 183 goto out_err;
184 return NULL;
185 }
186 } else {
187 brelse(epos.bh);
188 return NULL;
189 } 184 }
190 185
186 fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
187 if (!fname)
188 goto out_err;
189
191 while (f_pos < size) { 190 while (f_pos < size) {
192 fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc, 191 fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc,
193 &elen, &offset); 192 &elen, &offset);
194 if (!fi) { 193 if (!fi)
195 if (fibh->sbh != fibh->ebh) 194 goto out_err;
196 brelse(fibh->ebh);
197 brelse(fibh->sbh);
198 brelse(epos.bh);
199 return NULL;
200 }
201 195
202 liu = le16_to_cpu(cfi->lengthOfImpUse); 196 liu = le16_to_cpu(cfi->lengthOfImpUse);
203 lfi = cfi->lengthFileIdent; 197 lfi = cfi->lengthFileIdent;
@@ -237,18 +231,20 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
237 231
238 flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); 232 flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
239 if (flen && udf_match(flen, fname, dentry->d_name.len, 233 if (flen && udf_match(flen, fname, dentry->d_name.len,
240 dentry->d_name.name)) { 234 dentry->d_name.name))
241 brelse(epos.bh); 235 goto out_ok;
242 return fi;
243 }
244 } 236 }
245 237
238out_err:
239 fi = NULL;
246 if (fibh->sbh != fibh->ebh) 240 if (fibh->sbh != fibh->ebh)
247 brelse(fibh->ebh); 241 brelse(fibh->ebh);
248 brelse(fibh->sbh); 242 brelse(fibh->sbh);
243out_ok:
249 brelse(epos.bh); 244 brelse(epos.bh);
245 kfree(fname);
250 246
251 return NULL; 247 return fi;
252} 248}
253 249
254static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry, 250static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
@@ -303,7 +299,7 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
303{ 299{
304 struct super_block *sb = dir->i_sb; 300 struct super_block *sb = dir->i_sb;
305 struct fileIdentDesc *fi = NULL; 301 struct fileIdentDesc *fi = NULL;
306 char name[UDF_NAME_LEN]; 302 char *name = NULL;
307 int namelen; 303 int namelen;
308 loff_t f_pos; 304 loff_t f_pos;
309 loff_t size = udf_ext0_offset(dir) + dir->i_size; 305 loff_t size = udf_ext0_offset(dir) + dir->i_size;
@@ -317,16 +313,23 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
317 struct extent_position epos = {}; 313 struct extent_position epos = {};
318 struct udf_inode_info *dinfo; 314 struct udf_inode_info *dinfo;
319 315
316 fibh->sbh = fibh->ebh = NULL;
317 name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
318 if (!name) {
319 *err = -ENOMEM;
320 goto out_err;
321 }
322
320 if (dentry) { 323 if (dentry) {
321 if (!dentry->d_name.len) { 324 if (!dentry->d_name.len) {
322 *err = -EINVAL; 325 *err = -EINVAL;
323 return NULL; 326 goto out_err;
324 } 327 }
325 namelen = udf_put_filename(sb, dentry->d_name.name, name, 328 namelen = udf_put_filename(sb, dentry->d_name.name, name,
326 dentry->d_name.len); 329 dentry->d_name.len);
327 if (!namelen) { 330 if (!namelen) {
328 *err = -ENAMETOOLONG; 331 *err = -ENAMETOOLONG;
329 return NULL; 332 goto out_err;
330 } 333 }
331 } else { 334 } else {
332 namelen = 0; 335 namelen = 0;
@@ -338,11 +341,14 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
338 341
339 fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1); 342 fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
340 dinfo = UDF_I(dir); 343 dinfo = UDF_I(dir);
341 if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) 344 if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
342 fibh->sbh = fibh->ebh = NULL; 345 if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos,
343 else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, 346 &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) {
344 &epos, &eloc, &elen, &offset) == 347 block = udf_get_lb_pblock(dir->i_sb,
345 (EXT_RECORDED_ALLOCATED >> 30)) { 348 dinfo->i_location, 0);
349 fibh->soffset = fibh->eoffset = sb->s_blocksize;
350 goto add;
351 }
346 block = udf_get_lb_pblock(dir->i_sb, eloc, offset); 352 block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
347 if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { 353 if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
348 if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) 354 if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
@@ -354,17 +360,11 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
354 360
355 fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block); 361 fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
356 if (!fibh->sbh) { 362 if (!fibh->sbh) {
357 brelse(epos.bh);
358 *err = -EIO; 363 *err = -EIO;
359 return NULL; 364 goto out_err;
360 } 365 }
361 366
362 block = dinfo->i_location.logicalBlockNum; 367 block = dinfo->i_location.logicalBlockNum;
363 } else {
364 block = udf_get_lb_pblock(dir->i_sb, dinfo->i_location, 0);
365 fibh->sbh = fibh->ebh = NULL;
366 fibh->soffset = fibh->eoffset = sb->s_blocksize;
367 goto add;
368 } 368 }
369 369
370 while (f_pos < size) { 370 while (f_pos < size) {
@@ -372,12 +372,8 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
372 &elen, &offset); 372 &elen, &offset);
373 373
374 if (!fi) { 374 if (!fi) {
375 if (fibh->sbh != fibh->ebh)
376 brelse(fibh->ebh);
377 brelse(fibh->sbh);
378 brelse(epos.bh);
379 *err = -EIO; 375 *err = -EIO;
380 return NULL; 376 goto out_err;
381 } 377 }
382 378
383 liu = le16_to_cpu(cfi->lengthOfImpUse); 379 liu = le16_to_cpu(cfi->lengthOfImpUse);
@@ -386,7 +382,6 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
386 if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) { 382 if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) {
387 if (((sizeof(struct fileIdentDesc) + 383 if (((sizeof(struct fileIdentDesc) +
388 liu + lfi + 3) & ~3) == nfidlen) { 384 liu + lfi + 3) & ~3) == nfidlen) {
389 brelse(epos.bh);
390 cfi->descTag.tagSerialNum = cpu_to_le16(1); 385 cfi->descTag.tagSerialNum = cpu_to_le16(1);
391 cfi->fileVersionNum = cpu_to_le16(1); 386 cfi->fileVersionNum = cpu_to_le16(1);
392 cfi->fileCharacteristics = 0; 387 cfi->fileCharacteristics = 0;
@@ -394,10 +389,10 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
394 cfi->lengthOfImpUse = cpu_to_le16(0); 389 cfi->lengthOfImpUse = cpu_to_le16(0);
395 if (!udf_write_fi(dir, cfi, fi, fibh, NULL, 390 if (!udf_write_fi(dir, cfi, fi, fibh, NULL,
396 name)) 391 name))
397 return fi; 392 goto out_ok;
398 else { 393 else {
399 *err = -EIO; 394 *err = -EIO;
400 return NULL; 395 goto out_err;
401 } 396 }
402 } 397 }
403 } 398 }
@@ -427,7 +422,7 @@ add:
427 fibh->sbh = fibh->ebh = 422 fibh->sbh = fibh->ebh =
428 udf_expand_dir_adinicb(dir, &block, err); 423 udf_expand_dir_adinicb(dir, &block, err);
429 if (!fibh->sbh) 424 if (!fibh->sbh)
430 return NULL; 425 goto out_err;
431 epos.block = dinfo->i_location; 426 epos.block = dinfo->i_location;
432 epos.offset = udf_file_entry_alloc_offset(dir); 427 epos.offset = udf_file_entry_alloc_offset(dir);
433 /* Load extent udf_expand_dir_adinicb() has created */ 428 /* Load extent udf_expand_dir_adinicb() has created */
@@ -468,11 +463,8 @@ add:
468 dir->i_sb->s_blocksize_bits); 463 dir->i_sb->s_blocksize_bits);
469 fibh->ebh = udf_bread(dir, 464 fibh->ebh = udf_bread(dir,
470 f_pos >> dir->i_sb->s_blocksize_bits, 1, err); 465 f_pos >> dir->i_sb->s_blocksize_bits, 1, err);
471 if (!fibh->ebh) { 466 if (!fibh->ebh)
472 brelse(epos.bh); 467 goto out_err;
473 brelse(fibh->sbh);
474 return NULL;
475 }
476 468
477 if (!fibh->soffset) { 469 if (!fibh->soffset) {
478 if (udf_next_aext(dir, &epos, &eloc, &elen, 1) == 470 if (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
@@ -503,20 +495,25 @@ add:
503 cfi->lengthFileIdent = namelen; 495 cfi->lengthFileIdent = namelen;
504 cfi->lengthOfImpUse = cpu_to_le16(0); 496 cfi->lengthOfImpUse = cpu_to_le16(0);
505 if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) { 497 if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) {
506 brelse(epos.bh);
507 dir->i_size += nfidlen; 498 dir->i_size += nfidlen;
508 if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) 499 if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
509 dinfo->i_lenAlloc += nfidlen; 500 dinfo->i_lenAlloc += nfidlen;
510 mark_inode_dirty(dir); 501 mark_inode_dirty(dir);
511 return fi; 502 goto out_ok;
512 } else { 503 } else {
513 brelse(epos.bh);
514 if (fibh->sbh != fibh->ebh)
515 brelse(fibh->ebh);
516 brelse(fibh->sbh);
517 *err = -EIO; 504 *err = -EIO;
518 return NULL; 505 goto out_err;
519 } 506 }
507
508out_err:
509 fi = NULL;
510 if (fibh->sbh != fibh->ebh)
511 brelse(fibh->ebh);
512 brelse(fibh->sbh);
513out_ok:
514 brelse(epos.bh);
515 kfree(name);
516 return fi;
520} 517}
521 518
522static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi, 519static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi,
@@ -871,7 +868,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
871 char *ea; 868 char *ea;
872 int err; 869 int err;
873 int block; 870 int block;
874 char name[UDF_NAME_LEN]; 871 char *name = NULL;
875 int namelen; 872 int namelen;
876 struct buffer_head *bh; 873 struct buffer_head *bh;
877 struct udf_inode_info *iinfo; 874 struct udf_inode_info *iinfo;
@@ -881,6 +878,12 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
881 if (!inode) 878 if (!inode)
882 goto out; 879 goto out;
883 880
881 name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
882 if (!name) {
883 err = -ENOMEM;
884 goto out_no_entry;
885 }
886
884 iinfo = UDF_I(inode); 887 iinfo = UDF_I(inode);
885 inode->i_mode = S_IFLNK | S_IRWXUGO; 888 inode->i_mode = S_IFLNK | S_IRWXUGO;
886 inode->i_data.a_ops = &udf_symlink_aops; 889 inode->i_data.a_ops = &udf_symlink_aops;
@@ -1020,6 +1023,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
1020 err = 0; 1023 err = 0;
1021 1024
1022out: 1025out:
1026 kfree(name);
1023 unlock_kernel(); 1027 unlock_kernel();
1024 return err; 1028 return err;
1025 1029