aboutsummaryrefslogtreecommitdiffstats
path: root/fs/udf/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/udf/namei.c')
-rw-r--r--fs/udf/namei.c218
1 files changed, 76 insertions, 142 deletions
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index 112a5fb0b27b..ba5537d4bc15 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -31,6 +31,7 @@
31#include <linux/smp_lock.h> 31#include <linux/smp_lock.h>
32#include <linux/buffer_head.h> 32#include <linux/buffer_head.h>
33#include <linux/sched.h> 33#include <linux/sched.h>
34#include <linux/crc-itu-t.h>
34 35
35static inline int udf_match(int len1, const char *name1, int len2, 36static inline int udf_match(int len1, const char *name1, int len2,
36 const char *name2) 37 const char *name2)
@@ -97,25 +98,23 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
97 memset(fibh->ebh->b_data, 0x00, padlen + offset); 98 memset(fibh->ebh->b_data, 0x00, padlen + offset);
98 } 99 }
99 100
100 crc = udf_crc((uint8_t *)cfi + sizeof(tag), 101 crc = crc_itu_t(0, (uint8_t *)cfi + sizeof(tag),
101 sizeof(struct fileIdentDesc) - sizeof(tag), 0); 102 sizeof(struct fileIdentDesc) - sizeof(tag));
102 103
103 if (fibh->sbh == fibh->ebh) { 104 if (fibh->sbh == fibh->ebh) {
104 crc = udf_crc((uint8_t *)sfi->impUse, 105 crc = crc_itu_t(crc, (uint8_t *)sfi->impUse,
105 crclen + sizeof(tag) - 106 crclen + sizeof(tag) -
106 sizeof(struct fileIdentDesc), crc); 107 sizeof(struct fileIdentDesc));
107 } else if (sizeof(struct fileIdentDesc) >= -fibh->soffset) { 108 } else if (sizeof(struct fileIdentDesc) >= -fibh->soffset) {
108 crc = udf_crc(fibh->ebh->b_data + 109 crc = crc_itu_t(crc, fibh->ebh->b_data +
109 sizeof(struct fileIdentDesc) + 110 sizeof(struct fileIdentDesc) +
110 fibh->soffset, 111 fibh->soffset,
111 crclen + sizeof(tag) - 112 crclen + sizeof(tag) -
112 sizeof(struct fileIdentDesc), 113 sizeof(struct fileIdentDesc));
113 crc);
114 } else { 114 } else {
115 crc = udf_crc((uint8_t *)sfi->impUse, 115 crc = crc_itu_t(crc, (uint8_t *)sfi->impUse,
116 -fibh->soffset - sizeof(struct fileIdentDesc), 116 -fibh->soffset - sizeof(struct fileIdentDesc));
117 crc); 117 crc = crc_itu_t(crc, fibh->ebh->b_data, fibh->eoffset);
118 crc = udf_crc(fibh->ebh->b_data, fibh->eoffset, crc);
119 } 118 }
120 119
121 cfi->descTag.descCRC = cpu_to_le16(crc); 120 cfi->descTag.descCRC = cpu_to_le16(crc);
@@ -149,7 +148,7 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
149 struct fileIdentDesc *fi = NULL; 148 struct fileIdentDesc *fi = NULL;
150 loff_t f_pos; 149 loff_t f_pos;
151 int block, flen; 150 int block, flen;
152 char fname[UDF_NAME_LEN]; 151 char *fname = NULL;
153 char *nameptr; 152 char *nameptr;
154 uint8_t lfi; 153 uint8_t lfi;
155 uint16_t liu; 154 uint16_t liu;
@@ -163,12 +162,12 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
163 size = udf_ext0_offset(dir) + dir->i_size; 162 size = udf_ext0_offset(dir) + dir->i_size;
164 f_pos = udf_ext0_offset(dir); 163 f_pos = udf_ext0_offset(dir);
165 164
165 fibh->sbh = fibh->ebh = NULL;
166 fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1); 166 fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
167 if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) 167 if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
168 fibh->sbh = fibh->ebh = NULL; 168 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, 169 &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30))
170 &epos, &eloc, &elen, &offset) == 170 goto out_err;
171 (EXT_RECORDED_ALLOCATED >> 30)) {
172 block = udf_get_lb_pblock(dir->i_sb, eloc, offset); 171 block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
173 if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { 172 if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
174 if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) 173 if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
@@ -179,25 +178,19 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
179 offset = 0; 178 offset = 0;
180 179
181 fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block); 180 fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
182 if (!fibh->sbh) { 181 if (!fibh->sbh)
183 brelse(epos.bh); 182 goto out_err;
184 return NULL;
185 }
186 } else {
187 brelse(epos.bh);
188 return NULL;
189 } 183 }
190 184
185 fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
186 if (!fname)
187 goto out_err;
188
191 while (f_pos < size) { 189 while (f_pos < size) {
192 fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc, 190 fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc,
193 &elen, &offset); 191 &elen, &offset);
194 if (!fi) { 192 if (!fi)
195 if (fibh->sbh != fibh->ebh) 193 goto out_err;
196 brelse(fibh->ebh);
197 brelse(fibh->sbh);
198 brelse(epos.bh);
199 return NULL;
200 }
201 194
202 liu = le16_to_cpu(cfi->lengthOfImpUse); 195 liu = le16_to_cpu(cfi->lengthOfImpUse);
203 lfi = cfi->lengthFileIdent; 196 lfi = cfi->lengthFileIdent;
@@ -237,53 +230,22 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
237 230
238 flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); 231 flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
239 if (flen && udf_match(flen, fname, dentry->d_name.len, 232 if (flen && udf_match(flen, fname, dentry->d_name.len,
240 dentry->d_name.name)) { 233 dentry->d_name.name))
241 brelse(epos.bh); 234 goto out_ok;
242 return fi;
243 }
244 } 235 }
245 236
237out_err:
238 fi = NULL;
246 if (fibh->sbh != fibh->ebh) 239 if (fibh->sbh != fibh->ebh)
247 brelse(fibh->ebh); 240 brelse(fibh->ebh);
248 brelse(fibh->sbh); 241 brelse(fibh->sbh);
242out_ok:
249 brelse(epos.bh); 243 brelse(epos.bh);
244 kfree(fname);
250 245
251 return NULL; 246 return fi;
252} 247}
253 248
254/*
255 * udf_lookup
256 *
257 * PURPOSE
258 * Look-up the inode for a given name.
259 *
260 * DESCRIPTION
261 * Required - lookup_dentry() will return -ENOTDIR if this routine is not
262 * available for a directory. The filesystem is useless if this routine is
263 * not available for at least the filesystem's root directory.
264 *
265 * This routine is passed an incomplete dentry - it must be completed by
266 * calling d_add(dentry, inode). If the name does not exist, then the
267 * specified inode must be set to null. An error should only be returned
268 * when the lookup fails for a reason other than the name not existing.
269 * Note that the directory inode semaphore is held during the call.
270 *
271 * Refer to lookup_dentry() in fs/namei.c
272 * lookup_dentry() -> lookup() -> real_lookup() -> .
273 *
274 * PRE-CONDITIONS
275 * dir Pointer to inode of parent directory.
276 * dentry Pointer to dentry to complete.
277 * nd Pointer to lookup nameidata
278 *
279 * POST-CONDITIONS
280 * <return> Zero on success.
281 *
282 * HISTORY
283 * July 1, 1997 - Andrew E. Mileski
284 * Written, tested, and released.
285 */
286
287static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry, 249static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
288 struct nameidata *nd) 250 struct nameidata *nd)
289{ 251{
@@ -336,11 +298,9 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
336{ 298{
337 struct super_block *sb = dir->i_sb; 299 struct super_block *sb = dir->i_sb;
338 struct fileIdentDesc *fi = NULL; 300 struct fileIdentDesc *fi = NULL;
339 char name[UDF_NAME_LEN], fname[UDF_NAME_LEN]; 301 char *name = NULL;
340 int namelen; 302 int namelen;
341 loff_t f_pos; 303 loff_t f_pos;
342 int flen;
343 char *nameptr;
344 loff_t size = udf_ext0_offset(dir) + dir->i_size; 304 loff_t size = udf_ext0_offset(dir) + dir->i_size;
345 int nfidlen; 305 int nfidlen;
346 uint8_t lfi; 306 uint8_t lfi;
@@ -352,16 +312,23 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
352 struct extent_position epos = {}; 312 struct extent_position epos = {};
353 struct udf_inode_info *dinfo; 313 struct udf_inode_info *dinfo;
354 314
315 fibh->sbh = fibh->ebh = NULL;
316 name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
317 if (!name) {
318 *err = -ENOMEM;
319 goto out_err;
320 }
321
355 if (dentry) { 322 if (dentry) {
356 if (!dentry->d_name.len) { 323 if (!dentry->d_name.len) {
357 *err = -EINVAL; 324 *err = -EINVAL;
358 return NULL; 325 goto out_err;
359 } 326 }
360 namelen = udf_put_filename(sb, dentry->d_name.name, name, 327 namelen = udf_put_filename(sb, dentry->d_name.name, name,
361 dentry->d_name.len); 328 dentry->d_name.len);
362 if (!namelen) { 329 if (!namelen) {
363 *err = -ENAMETOOLONG; 330 *err = -ENAMETOOLONG;
364 return NULL; 331 goto out_err;
365 } 332 }
366 } else { 333 } else {
367 namelen = 0; 334 namelen = 0;
@@ -373,11 +340,14 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
373 340
374 fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1); 341 fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
375 dinfo = UDF_I(dir); 342 dinfo = UDF_I(dir);
376 if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) 343 if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
377 fibh->sbh = fibh->ebh = NULL; 344 if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos,
378 else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, 345 &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) {
379 &epos, &eloc, &elen, &offset) == 346 block = udf_get_lb_pblock(dir->i_sb,
380 (EXT_RECORDED_ALLOCATED >> 30)) { 347 dinfo->i_location, 0);
348 fibh->soffset = fibh->eoffset = sb->s_blocksize;
349 goto add;
350 }
381 block = udf_get_lb_pblock(dir->i_sb, eloc, offset); 351 block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
382 if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { 352 if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
383 if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) 353 if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
@@ -389,17 +359,11 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
389 359
390 fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block); 360 fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
391 if (!fibh->sbh) { 361 if (!fibh->sbh) {
392 brelse(epos.bh);
393 *err = -EIO; 362 *err = -EIO;
394 return NULL; 363 goto out_err;
395 } 364 }
396 365
397 block = dinfo->i_location.logicalBlockNum; 366 block = dinfo->i_location.logicalBlockNum;
398 } else {
399 block = udf_get_lb_pblock(dir->i_sb, dinfo->i_location, 0);
400 fibh->sbh = fibh->ebh = NULL;
401 fibh->soffset = fibh->eoffset = sb->s_blocksize;
402 goto add;
403 } 367 }
404 368
405 while (f_pos < size) { 369 while (f_pos < size) {
@@ -407,41 +371,16 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
407 &elen, &offset); 371 &elen, &offset);
408 372
409 if (!fi) { 373 if (!fi) {
410 if (fibh->sbh != fibh->ebh)
411 brelse(fibh->ebh);
412 brelse(fibh->sbh);
413 brelse(epos.bh);
414 *err = -EIO; 374 *err = -EIO;
415 return NULL; 375 goto out_err;
416 } 376 }
417 377
418 liu = le16_to_cpu(cfi->lengthOfImpUse); 378 liu = le16_to_cpu(cfi->lengthOfImpUse);
419 lfi = cfi->lengthFileIdent; 379 lfi = cfi->lengthFileIdent;
420 380
421 if (fibh->sbh == fibh->ebh)
422 nameptr = fi->fileIdent + liu;
423 else {
424 int poffset; /* Unpaded ending offset */
425
426 poffset = fibh->soffset + sizeof(struct fileIdentDesc) +
427 liu + lfi;
428
429 if (poffset >= lfi)
430 nameptr = (char *)(fibh->ebh->b_data +
431 poffset - lfi);
432 else {
433 nameptr = fname;
434 memcpy(nameptr, fi->fileIdent + liu,
435 lfi - poffset);
436 memcpy(nameptr + lfi - poffset,
437 fibh->ebh->b_data, poffset);
438 }
439 }
440
441 if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) { 381 if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) {
442 if (((sizeof(struct fileIdentDesc) + 382 if (((sizeof(struct fileIdentDesc) +
443 liu + lfi + 3) & ~3) == nfidlen) { 383 liu + lfi + 3) & ~3) == nfidlen) {
444 brelse(epos.bh);
445 cfi->descTag.tagSerialNum = cpu_to_le16(1); 384 cfi->descTag.tagSerialNum = cpu_to_le16(1);
446 cfi->fileVersionNum = cpu_to_le16(1); 385 cfi->fileVersionNum = cpu_to_le16(1);
447 cfi->fileCharacteristics = 0; 386 cfi->fileCharacteristics = 0;
@@ -449,27 +388,13 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
449 cfi->lengthOfImpUse = cpu_to_le16(0); 388 cfi->lengthOfImpUse = cpu_to_le16(0);
450 if (!udf_write_fi(dir, cfi, fi, fibh, NULL, 389 if (!udf_write_fi(dir, cfi, fi, fibh, NULL,
451 name)) 390 name))
452 return fi; 391 goto out_ok;
453 else { 392 else {
454 *err = -EIO; 393 *err = -EIO;
455 return NULL; 394 goto out_err;
456 } 395 }
457 } 396 }
458 } 397 }
459
460 if (!lfi || !dentry)
461 continue;
462
463 flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
464 if (flen && udf_match(flen, fname, dentry->d_name.len,
465 dentry->d_name.name)) {
466 if (fibh->sbh != fibh->ebh)
467 brelse(fibh->ebh);
468 brelse(fibh->sbh);
469 brelse(epos.bh);
470 *err = -EEXIST;
471 return NULL;
472 }
473 } 398 }
474 399
475add: 400add:
@@ -496,7 +421,7 @@ add:
496 fibh->sbh = fibh->ebh = 421 fibh->sbh = fibh->ebh =
497 udf_expand_dir_adinicb(dir, &block, err); 422 udf_expand_dir_adinicb(dir, &block, err);
498 if (!fibh->sbh) 423 if (!fibh->sbh)
499 return NULL; 424 goto out_err;
500 epos.block = dinfo->i_location; 425 epos.block = dinfo->i_location;
501 epos.offset = udf_file_entry_alloc_offset(dir); 426 epos.offset = udf_file_entry_alloc_offset(dir);
502 /* Load extent udf_expand_dir_adinicb() has created */ 427 /* Load extent udf_expand_dir_adinicb() has created */
@@ -537,11 +462,8 @@ add:
537 dir->i_sb->s_blocksize_bits); 462 dir->i_sb->s_blocksize_bits);
538 fibh->ebh = udf_bread(dir, 463 fibh->ebh = udf_bread(dir,
539 f_pos >> dir->i_sb->s_blocksize_bits, 1, err); 464 f_pos >> dir->i_sb->s_blocksize_bits, 1, err);
540 if (!fibh->ebh) { 465 if (!fibh->ebh)
541 brelse(epos.bh); 466 goto out_err;
542 brelse(fibh->sbh);
543 return NULL;
544 }
545 467
546 if (!fibh->soffset) { 468 if (!fibh->soffset) {
547 if (udf_next_aext(dir, &epos, &eloc, &elen, 1) == 469 if (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
@@ -572,20 +494,25 @@ add:
572 cfi->lengthFileIdent = namelen; 494 cfi->lengthFileIdent = namelen;
573 cfi->lengthOfImpUse = cpu_to_le16(0); 495 cfi->lengthOfImpUse = cpu_to_le16(0);
574 if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) { 496 if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) {
575 brelse(epos.bh);
576 dir->i_size += nfidlen; 497 dir->i_size += nfidlen;
577 if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) 498 if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
578 dinfo->i_lenAlloc += nfidlen; 499 dinfo->i_lenAlloc += nfidlen;
579 mark_inode_dirty(dir); 500 mark_inode_dirty(dir);
580 return fi; 501 goto out_ok;
581 } else { 502 } else {
582 brelse(epos.bh);
583 if (fibh->sbh != fibh->ebh)
584 brelse(fibh->ebh);
585 brelse(fibh->sbh);
586 *err = -EIO; 503 *err = -EIO;
587 return NULL; 504 goto out_err;
588 } 505 }
506
507out_err:
508 fi = NULL;
509 if (fibh->sbh != fibh->ebh)
510 brelse(fibh->ebh);
511 brelse(fibh->sbh);
512out_ok:
513 brelse(epos.bh);
514 kfree(name);
515 return fi;
589} 516}
590 517
591static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi, 518static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi,
@@ -940,7 +867,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
940 char *ea; 867 char *ea;
941 int err; 868 int err;
942 int block; 869 int block;
943 char name[UDF_NAME_LEN]; 870 char *name = NULL;
944 int namelen; 871 int namelen;
945 struct buffer_head *bh; 872 struct buffer_head *bh;
946 struct udf_inode_info *iinfo; 873 struct udf_inode_info *iinfo;
@@ -950,6 +877,12 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
950 if (!inode) 877 if (!inode)
951 goto out; 878 goto out;
952 879
880 name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
881 if (!name) {
882 err = -ENOMEM;
883 goto out_no_entry;
884 }
885
953 iinfo = UDF_I(inode); 886 iinfo = UDF_I(inode);
954 inode->i_mode = S_IFLNK | S_IRWXUGO; 887 inode->i_mode = S_IFLNK | S_IRWXUGO;
955 inode->i_data.a_ops = &udf_symlink_aops; 888 inode->i_data.a_ops = &udf_symlink_aops;
@@ -1089,6 +1022,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
1089 err = 0; 1022 err = 0;
1090 1023
1091out: 1024out:
1025 kfree(name);
1092 unlock_kernel(); 1026 unlock_kernel();
1093 return err; 1027 return err;
1094 1028