From: Vladimir Serbinenko Date: Sun, 27 Oct 2013 16:24:35 +0000 (+0100) Subject: More efficient retrieval of file size X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fheads%2Fphcoder%2Ffilesize;p=thirdparty%2Fgrub.git More efficient retrieval of file size --- diff --git a/grub-core/commands/ls.c b/grub-core/commands/ls.c index 0eaf83652..6ba85f462 100644 --- a/grub-core/commands/ls.c +++ b/grub-core/commands/ls.c @@ -116,35 +116,11 @@ print_files_long (const char *filename, const struct grub_dirhook_info *info, if (! info->dir) { - grub_file_t file; - char *pathname; - - if (ctx->dirname[grub_strlen (ctx->dirname) - 1] == '/') - pathname = grub_xasprintf ("%s%s", ctx->dirname, filename); - else - pathname = grub_xasprintf ("%s/%s", ctx->dirname, filename); - - if (!pathname) - return 1; - - /* XXX: For ext2fs symlinks are detected as files while they - should be reported as directories. */ - grub_file_filter_disable_compression (); - file = grub_file_open (pathname); - if (! file) - { - grub_errno = 0; - grub_free (pathname); - return 0; - } - if (! ctx->human) - grub_printf ("%-12llu", (unsigned long long) file->size); + grub_printf ("%-12llu", (unsigned long long) info->size); else - grub_printf ("%-12s", grub_get_human_size (file->size, - GRUB_HUMAN_SIZE_SHORT)); - grub_file_close (file); - grub_free (pathname); + grub_printf ("%-12s", grub_get_human_size (info->size, + GRUB_HUMAN_SIZE_SHORT)); } else grub_printf ("%-12s", _("DIR")); diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c index 15f7d9dc6..15e64d26b 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -565,6 +565,7 @@ grub_affs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); info.mtimeset = 1; info.mtime = aftime2ctime (&node->di.mtime); + info.size = grub_be_to_cpu32 (node->di.size); grub_free (node); return ctx->hook (filename, &info, ctx->hook_data); } diff --git a/grub-core/fs/archelp.c b/grub-core/fs/archelp.c index 4a7ace117..73a05b2b4 100644 --- a/grub-core/fs/archelp.c +++ b/grub-core/fs/archelp.c @@ -155,9 +155,10 @@ grub_archelp_dir (struct grub_archelp_data *data, { grub_int32_t mtime; grub_uint32_t mode; + grub_uint64_t size; grub_err_t err; - if (arcops->find_file (data, &name, &mtime, &mode)) + if (arcops->find_file (data, &name, &mtime, &mode, &size)) goto fail; if (mode == GRUB_ARCHELP_ATTR_END) @@ -189,6 +190,7 @@ grub_archelp_dir (struct grub_archelp_data *data, info.mtime = mtime; info.mtimeset = 1; } + info.size = size; if (hook (n, &info, hook_data)) { grub_free (name); @@ -248,8 +250,9 @@ grub_archelp_open (struct grub_archelp_data *data, { grub_uint32_t mode; int restart; + grub_uint64_t size; - if (arcops->find_file (data, &fn, NULL, &mode)) + if (arcops->find_file (data, &fn, NULL, &mode, &size)) goto fail; if (mode == GRUB_ARCHELP_ATTR_END) diff --git a/grub-core/fs/bfs.c b/grub-core/fs/bfs.c index 36b01efc8..22acd50a0 100644 --- a/grub-core/fs/bfs.c +++ b/grub-core/fs/bfs.c @@ -889,6 +889,7 @@ grub_bfs_dir_iter (const char *name, grub_uint64_t value, info.mtime = grub_bfs_to_cpu64 (ino.mtime) >> 16; #endif info.dir = ((grub_bfs_to_cpu32 (ino.mode) & ATTR_TYPE) == ATTR_DIR); + info.size = grub_bfs_to_cpu64 (ino.size); return ctx->hook (name, &info, ctx->hook_data); } diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index 196f3017c..ee0c8fde6 100644 --- a/grub-core/fs/btrfs.c +++ b/grub-core/fs/btrfs.c @@ -1580,6 +1580,7 @@ grub_btrfs_dir (grub_device_t device, const char *path, else { info.mtime = grub_le_to_cpu64 (inode.mtime.sec); + info.size = grub_le_to_cpu64 (inode.size); info.mtimeset = 1; } c = cdirel->name[grub_le_to_cpu16 (cdirel->n)]; diff --git a/grub-core/fs/cbfs.c b/grub-core/fs/cbfs.c index c79ec433a..efc29d568 100644 --- a/grub-core/fs/cbfs.c +++ b/grub-core/fs/cbfs.c @@ -44,7 +44,8 @@ struct grub_archelp_data static grub_err_t grub_cbfs_find_file (struct grub_archelp_data *data, char **name, grub_int32_t *mtime, - grub_uint32_t *mode) + grub_uint32_t *mode, + grub_uint64_t *size) { grub_size_t offset; for (;; @@ -71,6 +72,7 @@ grub_cbfs_find_file (struct grub_archelp_data *data, char **name, return GRUB_ERR_NONE; } data->size = grub_be_to_cpu32 (hd.len); + *size = grub_be_to_cpu32 (hd.len); (void) mtime; offset = grub_be_to_cpu32 (hd.offset); diff --git a/grub-core/fs/cpio_common.c b/grub-core/fs/cpio_common.c index b0ae9f445..eedc18ef6 100644 --- a/grub-core/fs/cpio_common.c +++ b/grub-core/fs/cpio_common.c @@ -38,7 +38,8 @@ struct grub_archelp_data static grub_err_t grub_cpio_find_file (struct grub_archelp_data *data, char **name, - grub_int32_t *mtime, grub_uint32_t *mode) + grub_int32_t *mtime, grub_uint32_t *mode, + grub_uint64_t *size) { struct head hd; grub_size_t namesize; @@ -86,6 +87,7 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name, data->dofs = data->hofs + ALIGN_CPIO (sizeof (hd) + namesize); data->next_hofs = data->dofs + ALIGN_CPIO (data->size); + *size = data->size; return GRUB_ERR_NONE; } diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c index 46fb76f55..7107ef77d 100644 --- a/grub-core/fs/ext2.c +++ b/grub-core/fs/ext2.c @@ -884,6 +884,8 @@ grub_ext2_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, { info.mtimeset = 1; info.mtime = grub_le_to_cpu32 (node->inode.mtime); + info.size = grub_le_to_cpu32 (node->inode.size); + info.size |= ((grub_off_t) grub_le_to_cpu32 (node->inode.size_high)) << 32; } info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c index e84f6c672..49c4ba11b 100644 --- a/grub-core/fs/fat.c +++ b/grub-core/fs/fat.c @@ -938,6 +938,8 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, #endif data->cur_cluster_num = ~0U; + info.size = data->file_size; + if (call_hook) hook (ctxt.filename, &info, hook_data); diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c index 25414a5c5..c16d7101a 100644 --- a/grub-core/fs/hfs.c +++ b/grub-core/fs/hfs.c @@ -1237,6 +1237,7 @@ grub_hfs_dir_hook (struct grub_hfs_record *rec, void *hook_arg) info.dir = 0; info.mtimeset = 1; info.mtime = grub_be_to_cpu32 (frec->mtime) - 2082844800; + info.size = grub_be_to_cpu32 (frec->size); return ctx->hook (fname, &info, ctx->hook_data); } diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c index 790562450..a2110ef90 100644 --- a/grub-core/fs/hfsplus.c +++ b/grub-core/fs/hfsplus.c @@ -917,6 +917,7 @@ grub_hfsplus_dir_iter (const char *filename, info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); info.mtimeset = 1; info.mtime = node->mtime; + info.size = node->size; info.case_insensitive = !! (filetype & GRUB_FSHELP_CASE_INSENSITIVE); grub_free (node); return ctx->hook (filename, &info, ctx->hook_data); diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c index 69e61ca02..9240a4db9 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -861,7 +861,7 @@ grub_iso9660_dir_iter (const char *filename, grub_memset (&info, 0, sizeof (info)); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); info.mtimeset = !!iso9660_to_unixtime2 (&node->dirents[0].mtime, &info.mtime); - + info.size = get_node_size (node); grub_free (node); return ctx->hook (filename, &info, ctx->hook_data); } diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c index 26d771647..af457442f 100644 --- a/grub-core/fs/jfs.c +++ b/grub-core/fs/jfs.c @@ -778,6 +778,7 @@ grub_jfs_dir (grub_device_t device, const char *path, & GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_DIR; info.mtimeset = 1; info.mtime = grub_le_to_cpu32 (inode.mtime.sec); + info.size = grub_le_to_cpu64 (inode.size); if (hook (diro->name, &info, hook_data)) goto fail; } diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index 98e1b71ec..30a02a88a 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -576,6 +576,7 @@ grub_minix_dir (grub_device_t device, const char *path, & GRUB_MINIX_IFDIR) == GRUB_MINIX_IFDIR); info.mtimeset = 1; info.mtime = grub_minix_to_cpu32 (data->inode.mtime); + info.size = GRUB_MINIX_INODE_SIZE (data); if (hook (filename, &info, hook_data) ? 1 : 0) break; diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c index 1318f2140..0332992d5 100644 --- a/grub-core/fs/nilfs2.c +++ b/grub-core/fs/nilfs2.c @@ -1066,6 +1066,7 @@ grub_nilfs2_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, { info.mtimeset = 1; info.mtime = grub_le_to_cpu64 (node->inode.i_mtime); + info.size = grub_le_to_cpu64 (node->inode.i_size); } info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c index a0ae44200..fd1ae54f6 100644 --- a/grub-core/fs/ntfs.c +++ b/grub-core/fs/ntfs.c @@ -981,10 +981,13 @@ grub_ntfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, grub_memset (&info, 0, sizeof (info)); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + init_file (node, node->ino); info.mtimeset = 1; info.mtime = grub_divmod64 (node->mtime, 10000000, 0) - 86400ULL * 365 * (1970 - 1601) - 86400ULL * ((1970 - 1601) / 4) + 86400ULL * ((1970 - 1601) / 100); + info.mtime = node->size; + free_file (node); grub_free (node); return ctx->hook (filename, &info, ctx->hook_data); } diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c index eaa7adead..0ff3d33c2 100644 --- a/grub-core/fs/reiserfs.c +++ b/grub-core/fs/reiserfs.c @@ -1271,6 +1271,7 @@ grub_reiserfs_dir_iter (const char *filename, info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); info.mtimeset = 1; info.mtime = node->mtime; + info.size = node->size; grub_free (node); return ctx->hook (filename, &info, ctx->hook_data); } diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c index 2e3544408..4d2d9fd15 100644 --- a/grub-core/fs/romfs.c +++ b/grub-core/fs/romfs.c @@ -331,6 +331,7 @@ grub_romfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, grub_memset (&info, 0, sizeof (info)); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.size = grub_be_to_cpu32 (node->file.size); grub_free (node); return ctx->hook (filename, &info, ctx->hook_data); } diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c index e7d2f72f3..9780b42c6 100644 --- a/grub-core/fs/sfs.c +++ b/grub-core/fs/sfs.c @@ -671,6 +671,7 @@ grub_sfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); info.mtime = node->mtime + 8 * 365 * 86400 + 86400 * 2; info.mtimeset = 1; + info.size = node->size; grub_free (node->cache); grub_free (node); return ctx->hook (filename, &info, ctx->hook_data); diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index cb3cc3a6e..0cda4f611 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -656,6 +656,15 @@ grub_squash_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); info.mtimeset = 1; info.mtime = grub_le_to_cpu32 (node->ino.mtime); + switch (node->ino.type) + { + case grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR): + info.size = grub_le_to_cpu64 (node->ino.long_file.size); + break; + case grub_cpu_to_le16_compile_time (SQUASH_TYPE_REGULAR): + info.size = grub_le_to_cpu32 (node->ino.file.size); + break; + } grub_free (node); return ctx->hook (filename, &info, ctx->hook_data); } diff --git a/grub-core/fs/tar.c b/grub-core/fs/tar.c index 85382974c..e63e3c01c 100644 --- a/grub-core/fs/tar.c +++ b/grub-core/fs/tar.c @@ -72,7 +72,8 @@ struct grub_archelp_data static grub_err_t grub_cpio_find_file (struct grub_archelp_data *data, char **name, grub_int32_t *mtime, - grub_uint32_t *mode) + grub_uint32_t *mode, + grub_uint64_t *size) { struct head hd; int reread = 0, have_longname = 0, have_longlink = 0; @@ -200,6 +201,7 @@ grub_cpio_find_file (struct grub_archelp_data *data, char **name, grub_memcpy (data->linkname, hd.linkname, sizeof (hd.linkname)); data->linkname[100] = 0; } + *size = data->size; return GRUB_ERR_NONE; } return GRUB_ERR_NONE; diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c index 60ce92830..c80bd587f 100644 --- a/grub-core/fs/udf.c +++ b/grub-core/fs/udf.c @@ -1072,6 +1072,7 @@ grub_udf_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, info.mtimeset = !!grub_datetime2unixtime (&datetime, &info.mtime); info.mtime -= 60 * tz; + info.size = U64 (node->block.fe.file_size); } grub_free (node); return ctx->hook (filename, &info, ctx->hook_data); diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c index c9c2556d1..fabed017e 100644 --- a/grub-core/fs/ufs.c +++ b/grub-core/fs/ufs.c @@ -711,6 +711,8 @@ grub_ufs_dir (grub_device_t device, const char *path, #endif info.mtimeset = 1; + info.size = grub_ufs_to_cpu64 (inode.size); + if (hook (filename, &info, hook_data)) { grub_free (filename); diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index 7cd3e07bf..b611e41cd 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -732,6 +732,7 @@ grub_xfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, { info.mtimeset = 1; info.mtime = grub_be_to_cpu32 (node->inode.mtime.sec); + info.size = grub_be_to_cpu64 (node->inode.size); } info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); grub_free (node); diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 52314040f..06c6198e2 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -3999,6 +3999,8 @@ iterate_zap (const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx) info.mtimeset = 1; info.mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian); info.case_insensitive = ctx->data->subvol.case_insensitive; + info.size = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET), dn.endian); + } if (dn.dn.dn_bonustype == DMU_OT_ZNODE) @@ -4006,6 +4008,7 @@ iterate_zap (const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx) info.mtimeset = 1; info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], dn.endian); + info.size = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_size, dn.endian); } info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS); grub_dprintf ("zfs", "type=%d, name=%s\n", diff --git a/include/grub/archelp.h b/include/grub/archelp.h index 2611d7f45..7129ec561 100644 --- a/include/grub/archelp.h +++ b/include/grub/archelp.h @@ -40,7 +40,8 @@ struct grub_archelp_ops grub_err_t (*find_file) (struct grub_archelp_data *data, char **name, grub_int32_t *mtime, - grub_archelp_mode_t *mode); + grub_archelp_mode_t *mode, + grub_uint64_t *size); char * (*get_link_target) (struct grub_archelp_data *data); diff --git a/include/grub/fs.h b/include/grub/fs.h index e4517972b..66d84cab4 100644 --- a/include/grub/fs.h +++ b/include/grub/fs.h @@ -39,6 +39,7 @@ struct grub_dirhook_info unsigned mtimeset:1; unsigned case_insensitive:1; grub_int32_t mtime; + grub_off_t size; }; typedef int (*grub_fs_dir_hook_t) (const char *filename,