diff options
Diffstat (limited to 'fs/exfat/namei.c')
-rw-r--r-- | fs/exfat/namei.c | 120 |
1 files changed, 47 insertions, 73 deletions
diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c index 0b12033e1577..b966b9120c9c 100644 --- a/fs/exfat/namei.c +++ b/fs/exfat/namei.c @@ -604,6 +604,8 @@ static int exfat_find(struct inode *dir, struct qstr *qname, struct super_block *sb = dir->i_sb; struct exfat_sb_info *sbi = EXFAT_SB(sb); struct exfat_inode_info *ei = EXFAT_I(dir); + struct exfat_dentry *ep, *ep2; + struct exfat_entry_set_cache *es; if (qname->len == 0) return -ENOENT; @@ -629,91 +631,63 @@ static int exfat_find(struct inode *dir, struct qstr *qname, dentry = exfat_find_dir_entry(sb, ei, &cdir, &uni_name, num_entries, TYPE_ALL); - if ((dentry < 0) && (dentry != -EEXIST)) + if (dentry < 0) return dentry; /* -error value */ memcpy(&info->dir, &cdir.dir, sizeof(struct exfat_chain)); info->entry = dentry; info->num_subdirs = 0; - /* root directory itself */ - if (unlikely(dentry == -EEXIST)) { - int num_clu = 0; + es = exfat_get_dentry_set(sb, &cdir, dentry, ES_2_ENTRIES); + if (!es) + return -EIO; + ep = exfat_get_dentry_cached(es, 0); + ep2 = exfat_get_dentry_cached(es, 1); + + info->type = exfat_get_entry_type(ep); + info->attr = le16_to_cpu(ep->dentry.file.attr); + info->size = le64_to_cpu(ep2->dentry.stream.valid_size); + if ((info->type == TYPE_FILE) && (info->size == 0)) { + info->flags = ALLOC_NO_FAT_CHAIN; + info->start_clu = EXFAT_EOF_CLUSTER; + } else { + info->flags = ep2->dentry.stream.flags; + info->start_clu = + le32_to_cpu(ep2->dentry.stream.start_clu); + } - info->type = TYPE_DIR; - info->attr = ATTR_SUBDIR; - info->flags = ALLOC_FAT_CHAIN; - info->start_clu = sbi->root_dir; - memset(&info->crtime, 0, sizeof(info->crtime)); - memset(&info->mtime, 0, sizeof(info->mtime)); - memset(&info->atime, 0, sizeof(info->atime)); - - exfat_chain_set(&cdir, sbi->root_dir, 0, ALLOC_FAT_CHAIN); - if (exfat_count_num_clusters(sb, &cdir, &num_clu)) - return -EIO; - info->size = num_clu << sbi->cluster_size_bits; + exfat_get_entry_time(sbi, &info->crtime, + ep->dentry.file.create_tz, + ep->dentry.file.create_time, + ep->dentry.file.create_date, + ep->dentry.file.create_time_cs); + exfat_get_entry_time(sbi, &info->mtime, + ep->dentry.file.modify_tz, + ep->dentry.file.modify_time, + ep->dentry.file.modify_date, + ep->dentry.file.modify_time_cs); + exfat_get_entry_time(sbi, &info->atime, + ep->dentry.file.access_tz, + ep->dentry.file.access_time, + ep->dentry.file.access_date, + 0); + exfat_free_dentry_set(es, false); + + if (ei->start_clu == EXFAT_FREE_CLUSTER) { + exfat_fs_error(sb, + "non-zero size file starts with zero cluster (size : %llu, p_dir : %u, entry : 0x%08x)", + i_size_read(dir), ei->dir.dir, ei->entry); + return -EIO; + } + if (info->type == TYPE_DIR) { + exfat_chain_set(&cdir, info->start_clu, + EXFAT_B_TO_CLU(info->size, sbi), info->flags); count = exfat_count_dir_entries(sb, &cdir); if (count < 0) return -EIO; - info->num_subdirs = count; - } else { - struct exfat_dentry *ep, *ep2; - struct exfat_entry_set_cache *es; - - es = exfat_get_dentry_set(sb, &cdir, dentry, ES_2_ENTRIES); - if (!es) - return -EIO; - ep = exfat_get_dentry_cached(es, 0); - ep2 = exfat_get_dentry_cached(es, 1); - - info->type = exfat_get_entry_type(ep); - info->attr = le16_to_cpu(ep->dentry.file.attr); - info->size = le64_to_cpu(ep2->dentry.stream.valid_size); - if ((info->type == TYPE_FILE) && (info->size == 0)) { - info->flags = ALLOC_NO_FAT_CHAIN; - info->start_clu = EXFAT_EOF_CLUSTER; - } else { - info->flags = ep2->dentry.stream.flags; - info->start_clu = - le32_to_cpu(ep2->dentry.stream.start_clu); - } - - if (ei->start_clu == EXFAT_FREE_CLUSTER) { - exfat_fs_error(sb, - "non-zero size file starts with zero cluster (size : %llu, p_dir : %u, entry : 0x%08x)", - i_size_read(dir), ei->dir.dir, ei->entry); - exfat_free_dentry_set(es, false); - return -EIO; - } - - exfat_get_entry_time(sbi, &info->crtime, - ep->dentry.file.create_tz, - ep->dentry.file.create_time, - ep->dentry.file.create_date, - ep->dentry.file.create_time_cs); - exfat_get_entry_time(sbi, &info->mtime, - ep->dentry.file.modify_tz, - ep->dentry.file.modify_time, - ep->dentry.file.modify_date, - ep->dentry.file.modify_time_cs); - exfat_get_entry_time(sbi, &info->atime, - ep->dentry.file.access_tz, - ep->dentry.file.access_time, - ep->dentry.file.access_date, - 0); - exfat_free_dentry_set(es, false); - - if (info->type == TYPE_DIR) { - exfat_chain_set(&cdir, info->start_clu, - EXFAT_B_TO_CLU(info->size, sbi), info->flags); - count = exfat_count_dir_entries(sb, &cdir); - if (count < 0) - return -EIO; - - info->num_subdirs = count + EXFAT_MIN_SUBDIR; - } + info->num_subdirs = count + EXFAT_MIN_SUBDIR; } return 0; } |