diff options
-rw-r--r-- | fs/fat/dir.c | 42 |
1 files changed, 26 insertions, 16 deletions
diff --git a/fs/fat/dir.c b/fs/fat/dir.c index a4410740627f..96a1cad30da4 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c | |||
@@ -325,6 +325,19 @@ parse_long: | |||
325 | } | 325 | } |
326 | 326 | ||
327 | /* | 327 | /* |
328 | * Maximum buffer size of short name. | ||
329 | * [(MSDOS_NAME + '.') * max one char + nul] | ||
330 | * For msdos style, ['.' (hidden) + MSDOS_NAME + '.' + nul] | ||
331 | */ | ||
332 | #define FAT_MAX_SHORT_SIZE ((MSDOS_NAME + 1) * NLS_MAX_CHARSET_SIZE + 1) | ||
333 | /* | ||
334 | * Maximum buffer size of unicode chars from slots. | ||
335 | * [(max longname slots * 13 (size in a slot) + nul) * sizeof(wchar_t)] | ||
336 | */ | ||
337 | #define FAT_MAX_UNI_CHARS ((MSDOS_SLOTS - 1) * 13 + 1) | ||
338 | #define FAT_MAX_UNI_SIZE (FAT_MAX_UNI_CHARS * sizeof(wchar_t)) | ||
339 | |||
340 | /* | ||
328 | * Return values: negative -> error, 0 -> not found, positive -> found, | 341 | * Return values: negative -> error, 0 -> not found, positive -> found, |
329 | * value is the total amount of slots, including the shortname entry. | 342 | * value is the total amount of slots, including the shortname entry. |
330 | */ | 343 | */ |
@@ -340,15 +353,11 @@ int fat_search_long(struct inode *inode, const unsigned char *name, | |||
340 | wchar_t bufuname[14]; | 353 | wchar_t bufuname[14]; |
341 | wchar_t *unicode = NULL; | 354 | wchar_t *unicode = NULL; |
342 | unsigned char work[MSDOS_NAME]; | 355 | unsigned char work[MSDOS_NAME]; |
343 | unsigned char *bufname = NULL; | 356 | unsigned char bufname[FAT_MAX_SHORT_SIZE]; |
344 | unsigned short opt_shortname = sbi->options.shortname; | 357 | unsigned short opt_shortname = sbi->options.shortname; |
345 | loff_t cpos = 0; | 358 | loff_t cpos = 0; |
346 | int chl, i, j, last_u, err, len; | 359 | int chl, i, j, last_u, err, len; |
347 | 360 | ||
348 | bufname = __getname(); | ||
349 | if (!bufname) | ||
350 | return -ENOMEM; | ||
351 | |||
352 | err = -ENOENT; | 361 | err = -ENOENT; |
353 | while (1) { | 362 | while (1) { |
354 | if (fat_get_entry(inode, &cpos, &bh, &de) == -1) | 363 | if (fat_get_entry(inode, &cpos, &bh, &de) == -1) |
@@ -414,14 +423,17 @@ parse_record: | |||
414 | 423 | ||
415 | /* Compare shortname */ | 424 | /* Compare shortname */ |
416 | bufuname[last_u] = 0x0000; | 425 | bufuname[last_u] = 0x0000; |
417 | len = fat_uni_to_x8(sbi, bufuname, bufname, PATH_MAX); | 426 | len = fat_uni_to_x8(sbi, bufuname, bufname, sizeof(bufname)); |
418 | if (fat_name_match(sbi, name, name_len, bufname, len)) | 427 | if (fat_name_match(sbi, name, name_len, bufname, len)) |
419 | goto found; | 428 | goto found; |
420 | 429 | ||
421 | if (nr_slots) { | 430 | if (nr_slots) { |
431 | void *longname = unicode + FAT_MAX_UNI_CHARS; | ||
432 | int size = PATH_MAX - FAT_MAX_UNI_SIZE; | ||
433 | |||
422 | /* Compare longname */ | 434 | /* Compare longname */ |
423 | len = fat_uni_to_x8(sbi, unicode, bufname, PATH_MAX); | 435 | len = fat_uni_to_x8(sbi, unicode, longname, size); |
424 | if (fat_name_match(sbi, name, name_len, bufname, len)) | 436 | if (fat_name_match(sbi, name, name_len, longname, len)) |
425 | goto found; | 437 | goto found; |
426 | } | 438 | } |
427 | } | 439 | } |
@@ -435,8 +447,6 @@ found: | |||
435 | sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de); | 447 | sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de); |
436 | err = 0; | 448 | err = 0; |
437 | end_of_dir: | 449 | end_of_dir: |
438 | if (bufname) | ||
439 | __putname(bufname); | ||
440 | if (unicode) | 450 | if (unicode) |
441 | __putname(unicode); | 451 | __putname(unicode); |
442 | 452 | ||
@@ -466,7 +476,8 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent, | |||
466 | unsigned char nr_slots; | 476 | unsigned char nr_slots; |
467 | wchar_t bufuname[14]; | 477 | wchar_t bufuname[14]; |
468 | wchar_t *unicode = NULL; | 478 | wchar_t *unicode = NULL; |
469 | unsigned char c, work[MSDOS_NAME], bufname[56], *ptname = bufname; | 479 | unsigned char c, work[MSDOS_NAME]; |
480 | unsigned char bufname[FAT_MAX_SHORT_SIZE], *ptname = bufname; | ||
470 | unsigned short opt_shortname = sbi->options.shortname; | 481 | unsigned short opt_shortname = sbi->options.shortname; |
471 | int isvfat = sbi->options.isvfat; | 482 | int isvfat = sbi->options.isvfat; |
472 | int nocase = sbi->options.nocase; | 483 | int nocase = sbi->options.nocase; |
@@ -620,11 +631,10 @@ parse_record: | |||
620 | fill_name = bufname; | 631 | fill_name = bufname; |
621 | fill_len = i; | 632 | fill_len = i; |
622 | if (!short_only && nr_slots) { | 633 | if (!short_only && nr_slots) { |
623 | /* convert the unicode long name. 261 is maximum size | 634 | void *longname = unicode + FAT_MAX_UNI_CHARS; |
624 | * of unicode buffer. (13 * slots + nul) */ | 635 | int long_len, size = PATH_MAX - FAT_MAX_UNI_SIZE; |
625 | void *longname = unicode + 261; | 636 | |
626 | int buf_size = PATH_MAX - (261 * sizeof(unicode[0])); | 637 | long_len = fat_uni_to_x8(sbi, unicode, longname, size); |
627 | int long_len = fat_uni_to_x8(sbi, unicode, longname, buf_size); | ||
628 | 638 | ||
629 | if (!both) { | 639 | if (!both) { |
630 | fill_name = longname; | 640 | fill_name = longname; |