FAT: Convert to fshelp.

exFAT doesn't handle "." and ".." correctly, convert it to fshelp to
reuse the same logic.
This commit is contained in:
Vladimir Serbinenko 2015-07-27 12:49:26 +02:00
parent d1d3a60b71
commit bfb5b33e96

View file

@ -31,6 +31,7 @@
#else #else
#include <grub/exfat.h> #include <grub/exfat.h>
#endif #endif
#include <grub/fshelp.h>
#include <grub/i18n.h> #include <grub/i18n.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
@ -173,8 +174,6 @@ struct grub_fat_data
#ifndef MODE_EXFAT #ifndef MODE_EXFAT
grub_uint32_t root_sector; grub_uint32_t root_sector;
grub_uint32_t num_root_sectors; grub_uint32_t num_root_sectors;
#else
int is_contiguous;
#endif #endif
int cluster_bits; int cluster_bits;
@ -182,13 +181,22 @@ struct grub_fat_data
grub_uint32_t cluster_sector; grub_uint32_t cluster_sector;
grub_uint32_t num_clusters; grub_uint32_t num_clusters;
grub_uint32_t uuid;
};
struct grub_fshelp_node {
grub_disk_t disk;
struct grub_fat_data *data;
grub_uint8_t attr; grub_uint8_t attr;
grub_ssize_t file_size; grub_ssize_t file_size;
grub_uint32_t file_cluster; grub_uint32_t file_cluster;
grub_uint32_t cur_cluster_num; grub_uint32_t cur_cluster_num;
grub_uint32_t cur_cluster; grub_uint32_t cur_cluster;
grub_uint32_t uuid; #ifdef MODE_EXFAT
int is_contiguous;
#endif
}; };
static grub_dl_t my_mod; static grub_dl_t my_mod;
@ -427,13 +435,6 @@ grub_fat_mount (grub_disk_t disk)
(void) magic; (void) magic;
#endif #endif
/* Start from the root directory. */
data->file_cluster = data->root_cluster;
data->cur_cluster_num = ~0U;
data->attr = GRUB_FAT_ATTR_DIRECTORY;
#ifdef MODE_EXFAT
data->is_contiguous = 0;
#endif
return data; return data;
fail: fail:
@ -444,7 +445,7 @@ grub_fat_mount (grub_disk_t disk)
} }
static grub_ssize_t static grub_ssize_t
grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data, grub_fat_read_data (grub_disk_t disk, grub_fshelp_node_t node,
grub_disk_read_hook_t read_hook, void *read_hook_data, grub_disk_read_hook_t read_hook, void *read_hook_data,
grub_off_t offset, grub_size_t len, char *buf) grub_off_t offset, grub_size_t len, char *buf)
{ {
@ -457,13 +458,13 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
#ifndef MODE_EXFAT #ifndef MODE_EXFAT
/* This is a special case. FAT12 and FAT16 doesn't have the root directory /* This is a special case. FAT12 and FAT16 doesn't have the root directory
in clusters. */ in clusters. */
if (data->file_cluster == ~0U) if (node->file_cluster == ~0U)
{ {
size = (data->num_root_sectors << GRUB_DISK_SECTOR_BITS) - offset; size = (node->data->num_root_sectors << GRUB_DISK_SECTOR_BITS) - offset;
if (size > len) if (size > len)
size = len; size = len;
if (grub_disk_read (disk, data->root_sector, offset, size, buf)) if (grub_disk_read (disk, node->data->root_sector, offset, size, buf))
return -1; return -1;
return size; return size;
@ -471,12 +472,12 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
#endif #endif
#ifdef MODE_EXFAT #ifdef MODE_EXFAT
if (data->is_contiguous) if (node->is_contiguous)
{ {
/* Read the data here. */ /* Read the data here. */
sector = (data->cluster_sector sector = (node->data->cluster_sector
+ ((data->file_cluster - 2) + ((node->file_cluster - 2)
<< data->cluster_bits)); << node->data->cluster_bits));
disk->read_hook = read_hook; disk->read_hook = read_hook;
disk->read_hook_data = read_hook_data; disk->read_hook_data = read_hook_data;
@ -491,53 +492,53 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
#endif #endif
/* Calculate the logical cluster number and offset. */ /* Calculate the logical cluster number and offset. */
logical_cluster_bits = (data->cluster_bits logical_cluster_bits = (node->data->cluster_bits
+ GRUB_DISK_SECTOR_BITS); + GRUB_DISK_SECTOR_BITS);
logical_cluster = offset >> logical_cluster_bits; logical_cluster = offset >> logical_cluster_bits;
offset &= (1ULL << logical_cluster_bits) - 1; offset &= (1ULL << logical_cluster_bits) - 1;
if (logical_cluster < data->cur_cluster_num) if (logical_cluster < node->cur_cluster_num)
{ {
data->cur_cluster_num = 0; node->cur_cluster_num = 0;
data->cur_cluster = data->file_cluster; node->cur_cluster = node->file_cluster;
} }
while (len) while (len)
{ {
while (logical_cluster > data->cur_cluster_num) while (logical_cluster > node->cur_cluster_num)
{ {
/* Find next cluster. */ /* Find next cluster. */
grub_uint32_t next_cluster; grub_uint32_t next_cluster;
grub_uint32_t fat_offset; grub_uint32_t fat_offset;
switch (data->fat_size) switch (node->data->fat_size)
{ {
case 32: case 32:
fat_offset = data->cur_cluster << 2; fat_offset = node->cur_cluster << 2;
break; break;
case 16: case 16:
fat_offset = data->cur_cluster << 1; fat_offset = node->cur_cluster << 1;
break; break;
default: default:
/* case 12: */ /* case 12: */
fat_offset = data->cur_cluster + (data->cur_cluster >> 1); fat_offset = node->cur_cluster + (node->cur_cluster >> 1);
break; break;
} }
/* Read the FAT. */ /* Read the FAT. */
if (grub_disk_read (disk, data->fat_sector, fat_offset, if (grub_disk_read (disk, node->data->fat_sector, fat_offset,
(data->fat_size + 7) >> 3, (node->data->fat_size + 7) >> 3,
(char *) &next_cluster)) (char *) &next_cluster))
return -1; return -1;
next_cluster = grub_le_to_cpu32 (next_cluster); next_cluster = grub_le_to_cpu32 (next_cluster);
switch (data->fat_size) switch (node->data->fat_size)
{ {
case 16: case 16:
next_cluster &= 0xFFFF; next_cluster &= 0xFFFF;
break; break;
case 12: case 12:
if (data->cur_cluster & 1) if (node->cur_cluster & 1)
next_cluster >>= 4; next_cluster >>= 4;
next_cluster &= 0x0FFF; next_cluster &= 0x0FFF;
@ -545,27 +546,27 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
} }
grub_dprintf ("fat", "fat_size=%d, next_cluster=%u\n", grub_dprintf ("fat", "fat_size=%d, next_cluster=%u\n",
data->fat_size, next_cluster); node->data->fat_size, next_cluster);
/* Check the end. */ /* Check the end. */
if (next_cluster >= data->cluster_eof_mark) if (next_cluster >= node->data->cluster_eof_mark)
return ret; return ret;
if (next_cluster < 2 || next_cluster >= data->num_clusters) if (next_cluster < 2 || next_cluster >= node->data->num_clusters)
{ {
grub_error (GRUB_ERR_BAD_FS, "invalid cluster %u", grub_error (GRUB_ERR_BAD_FS, "invalid cluster %u",
next_cluster); next_cluster);
return -1; return -1;
} }
data->cur_cluster = next_cluster; node->cur_cluster = next_cluster;
data->cur_cluster_num++; node->cur_cluster_num++;
} }
/* Read the data here. */ /* Read the data here. */
sector = (data->cluster_sector sector = (node->data->cluster_sector
+ ((data->cur_cluster - 2) + ((node->cur_cluster - 2)
<< data->cluster_bits)); << node->data->cluster_bits));
size = (1 << logical_cluster_bits) - offset; size = (1 << logical_cluster_bits) - offset;
if (size > len) if (size > len)
size = len; size = len;
@ -631,7 +632,7 @@ grub_fat_iterate_fini (struct grub_fat_iterate_context *ctxt)
#ifdef MODE_EXFAT #ifdef MODE_EXFAT
static grub_err_t static grub_err_t
grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, grub_fat_iterate_dir_next (grub_fshelp_node_t node,
struct grub_fat_iterate_context *ctxt) struct grub_fat_iterate_context *ctxt)
{ {
grub_memset (&ctxt->dir, 0, sizeof (ctxt->dir)); grub_memset (&ctxt->dir, 0, sizeof (ctxt->dir));
@ -641,7 +642,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data,
ctxt->offset += sizeof (dir); ctxt->offset += sizeof (dir);
if (grub_fat_read_data (disk, data, 0, 0, ctxt->offset, sizeof (dir), if (grub_fat_read_data (node->disk, node, 0, 0, ctxt->offset, sizeof (dir),
(char *) &dir) (char *) &dir)
!= sizeof (dir)) != sizeof (dir))
break; break;
@ -663,7 +664,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data,
{ {
struct grub_fat_dir_entry sec; struct grub_fat_dir_entry sec;
ctxt->offset += sizeof (sec); ctxt->offset += sizeof (sec);
if (grub_fat_read_data (disk, data, 0, 0, if (grub_fat_read_data (node->disk, node, 0, 0,
ctxt->offset, sizeof (sec), (char *) &sec) ctxt->offset, sizeof (sec), (char *) &sec)
!= sizeof (sec)) != sizeof (sec))
break; break;
@ -727,7 +728,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data,
#else #else
static grub_err_t static grub_err_t
grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, grub_fat_iterate_dir_next (grub_fshelp_node_t node,
struct grub_fat_iterate_context *ctxt) struct grub_fat_iterate_context *ctxt)
{ {
char *filep = 0; char *filep = 0;
@ -742,7 +743,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data,
ctxt->offset += sizeof (ctxt->dir); ctxt->offset += sizeof (ctxt->dir);
/* Read a directory entry. */ /* Read a directory entry. */
if (grub_fat_read_data (disk, data, 0, 0, if (grub_fat_read_data (node->disk, node, 0, 0,
ctxt->offset, sizeof (ctxt->dir), ctxt->offset, sizeof (ctxt->dir),
(char *) &ctxt->dir) (char *) &ctxt->dir)
!= sizeof (ctxt->dir) || ctxt->dir.name[0] == 0) != sizeof (ctxt->dir) || ctxt->dir.name[0] == 0)
@ -853,84 +854,20 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data,
#endif #endif
/* Find the underlying directory or file in PATH and return the static grub_err_t lookup_file (grub_fshelp_node_t node,
next path. If there is no next path or an error occurs, return NULL. const char *name,
If HOOK is specified, call it with each file name. */ grub_fshelp_node_t *foundnode,
static char * enum grub_fshelp_filetype *foundtype)
grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
const char *path, const char *origpath,
grub_fs_dir_hook_t hook, void *hook_data)
{ {
char *dirname, *dirp;
int call_hook;
int found = 0;
struct grub_fat_iterate_context ctxt;
grub_err_t err; grub_err_t err;
struct grub_fat_iterate_context ctxt;
if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
{
grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
return 0;
}
do
{
/* Extract a directory name. */
while (*path == '/')
path++;
/* Emulate special "." and ".." entries in root directory */
if (data->file_cluster == data->root_cluster)
{
if (*path != '.')
break;
if (!path[1] || path[1] == '/')
{
path++;
continue;
}
if (path[1] == '.' && (!path[2] || path[2] == '/'))
{
path += 2;
continue;
}
}
break;
}
while (1);
dirp = grub_strchr (path, '/');
if (dirp)
{
unsigned len = dirp - path;
dirname = grub_malloc (len + 1);
if (! dirname)
goto fail;
grub_memcpy (dirname, path, len);
dirname[len] = '\0';
}
else
/* This is actually a file. */
dirname = grub_strdup (path);
call_hook = (! dirp && hook);
err = grub_fat_iterate_init (&ctxt); err = grub_fat_iterate_init (&ctxt);
if (err) if (err)
{ return err;
grub_free (dirname);
return 0;
}
while (!(err = grub_fat_iterate_dir_next (disk, data, &ctxt))) while (!(err = grub_fat_iterate_dir_next (node, &ctxt)))
{ {
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
info.dir = !! (ctxt.dir.attr & GRUB_FAT_ATTR_DIRECTORY);
info.case_insensitive = 1;
#ifdef MODE_EXFAT #ifdef MODE_EXFAT
if (!ctxt.dir.have_stream) if (!ctxt.dir.have_stream)
@ -939,36 +876,33 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
if (ctxt.dir.attr & GRUB_FAT_ATTR_VOLUME_ID) if (ctxt.dir.attr & GRUB_FAT_ATTR_VOLUME_ID)
continue; continue;
#endif #endif
if (*dirname == '\0' && call_hook)
{
if (hook (ctxt.filename, &info, hook_data))
break;
else
continue;
}
if (grub_strcasecmp (dirname, ctxt.filename) == 0) if (grub_strcasecmp (name, ctxt.filename) == 0)
{ {
found = 1; *foundnode = grub_malloc (sizeof (struct grub_fshelp_node));
data->attr = ctxt.dir.attr; if (!*foundnode)
return grub_errno;
(*foundnode)->attr = ctxt.dir.attr;
#ifdef MODE_EXFAT #ifdef MODE_EXFAT
data->file_size = ctxt.dir.file_size; (*foundnode)->file_size = ctxt.dir.file_size;
data->file_cluster = ctxt.dir.first_cluster; (*foundnode)->file_cluster = ctxt.dir.first_cluster;
data->is_contiguous = ctxt.dir.is_contiguous; (*foundnode)->is_contiguous = ctxt.dir.is_contiguous;
#else #else
data->file_size = grub_le_to_cpu32 (ctxt.dir.file_size); (*foundnode)->file_size = grub_le_to_cpu32 (ctxt.dir.file_size);
data->file_cluster = ((grub_le_to_cpu16 (ctxt.dir.first_cluster_high) << 16) (*foundnode)->file_cluster = ((grub_le_to_cpu16 (ctxt.dir.first_cluster_high) << 16)
| grub_le_to_cpu16 (ctxt.dir.first_cluster_low)); | grub_le_to_cpu16 (ctxt.dir.first_cluster_low));
/* If directory points to root, starting cluster is 0 */ /* If directory points to root, starting cluster is 0 */
if (!data->file_cluster) if (!(*foundnode)->file_cluster)
data->file_cluster = data->root_cluster; (*foundnode)->file_cluster = node->data->root_cluster;
#endif #endif
data->cur_cluster_num = ~0U; (*foundnode)->cur_cluster_num = ~0U;
(*foundnode)->data = node->data;
(*foundnode)->disk = node->disk;
if (call_hook) *foundtype = ((*foundnode)->attr & GRUB_FAT_ATTR_DIRECTORY) ? GRUB_FSHELP_DIR : GRUB_FSHELP_REG;
hook (ctxt.filename, &info, hook_data);
break; grub_fat_iterate_fini (&ctxt);
return GRUB_ERR_NONE;
} }
} }
@ -976,13 +910,8 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
if (err == GRUB_ERR_EOF) if (err == GRUB_ERR_EOF)
err = 0; err = 0;
if (grub_errno == GRUB_ERR_NONE && ! found && !call_hook) return err;
grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), origpath);
fail:
grub_free (dirname);
return found ? dirp : 0;
} }
static grub_err_t static grub_err_t
@ -991,9 +920,9 @@ grub_fat_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook,
{ {
struct grub_fat_data *data = 0; struct grub_fat_data *data = 0;
grub_disk_t disk = device->disk; grub_disk_t disk = device->disk;
grub_size_t len; grub_fshelp_node_t found = NULL;
char *dirname = 0; grub_err_t err;
char *p; struct grub_fat_iterate_context ctxt;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
@ -1001,27 +930,53 @@ grub_fat_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook,
if (! data) if (! data)
goto fail; goto fail;
/* Make sure that DIRNAME terminates with '/'. */ struct grub_fshelp_node root = {
len = grub_strlen (path); .data = data,
dirname = grub_malloc (len + 1 + 1); .disk = disk,
if (! dirname) .attr = GRUB_FAT_ATTR_DIRECTORY,
goto fail; .file_size = 0,
grub_memcpy (dirname, path, len); .file_cluster = data->root_cluster,
p = dirname + len; .cur_cluster_num = ~0U,
if (path[len - 1] != '/') .cur_cluster = 0,
*p++ = '/'; #ifdef MODE_EXFAT
*p = '\0'; .is_contiguous = 0,
p = dirname; #endif
};
do err = grub_fshelp_find_file_lookup (path, &root, &found, lookup_file, NULL, GRUB_FSHELP_DIR);
if (err)
goto fail;
err = grub_fat_iterate_init (&ctxt);
if (err)
goto fail;
while (!(err = grub_fat_iterate_dir_next (found, &ctxt)))
{ {
p = grub_fat_find_dir (disk, data, p, path, hook, hook_data); struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
info.dir = !! (ctxt.dir.attr & GRUB_FAT_ATTR_DIRECTORY);
info.case_insensitive = 1;
#ifdef MODE_EXFAT
if (!ctxt.dir.have_stream)
continue;
#else
if (ctxt.dir.attr & GRUB_FAT_ATTR_VOLUME_ID)
continue;
#endif
if (hook (ctxt.filename, &info, hook_data))
break;
} }
while (p && grub_errno == GRUB_ERR_NONE); grub_fat_iterate_fini (&ctxt);
if (err == GRUB_ERR_EOF)
err = 0;
fail: fail:
if (found != &root)
grub_free (found);
grub_free (dirname);
grub_free (data); grub_free (data);
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
@ -1033,35 +988,43 @@ static grub_err_t
grub_fat_open (grub_file_t file, const char *name) grub_fat_open (grub_file_t file, const char *name)
{ {
struct grub_fat_data *data = 0; struct grub_fat_data *data = 0;
char *p = (char *) name; grub_fshelp_node_t found = NULL;
grub_err_t err;
grub_disk_t disk = file->device->disk;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
data = grub_fat_mount (file->device->disk); data = grub_fat_mount (disk);
if (! data) if (! data)
goto fail; goto fail;
do struct grub_fshelp_node root = {
{ .data = data,
p = grub_fat_find_dir (file->device->disk, data, p, name, 0, 0); .disk = disk,
if (grub_errno != GRUB_ERR_NONE) .attr = GRUB_FAT_ATTR_DIRECTORY,
goto fail; .file_size = 0,
} .file_cluster = data->root_cluster,
while (p); .cur_cluster_num = ~0U,
.cur_cluster = 0,
#ifdef MODE_EXFAT
.is_contiguous = 0,
#endif
};
if (data->attr & GRUB_FAT_ATTR_DIRECTORY) err = grub_fshelp_find_file_lookup (name, &root, &found, lookup_file, NULL, GRUB_FSHELP_REG);
{ if (err)
grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); goto fail;
goto fail;
}
file->data = data; file->data = found;
file->size = data->file_size; file->size = found->file_size;
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
fail: fail:
if (found != &root)
grub_free (found);
grub_free (data); grub_free (data);
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
@ -1080,7 +1043,10 @@ grub_fat_read (grub_file_t file, char *buf, grub_size_t len)
static grub_err_t static grub_err_t
grub_fat_close (grub_file_t file) grub_fat_close (grub_file_t file)
{ {
grub_free (file->data); grub_fshelp_node_t node = file->data;
grub_free (node->data);
grub_free (node);
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
@ -1093,20 +1059,29 @@ grub_fat_label (grub_device_t device, char **label)
{ {
struct grub_fat_dir_entry dir; struct grub_fat_dir_entry dir;
grub_ssize_t offset = -sizeof(dir); grub_ssize_t offset = -sizeof(dir);
struct grub_fat_data *data;
grub_disk_t disk = device->disk; grub_disk_t disk = device->disk;
struct grub_fshelp_node root = {
.disk = disk,
.attr = GRUB_FAT_ATTR_DIRECTORY,
.file_size = 0,
.cur_cluster_num = ~0U,
.cur_cluster = 0,
.is_contiguous = 0,
};
data = grub_fat_mount (disk); root.data = grub_fat_mount (disk);
if (! data) if (! root.data)
return grub_errno; return grub_errno;
root.file_cluster = root.data->root_cluster;
*label = NULL; *label = NULL;
while (1) while (1)
{ {
offset += sizeof (dir); offset += sizeof (dir);
if (grub_fat_read_data (disk, data, 0, 0, if (grub_fat_read_data (disk, &root, 0, 0,
offset, sizeof (dir), (char *) &dir) offset, sizeof (dir), (char *) &dir)
!= sizeof (dir)) != sizeof (dir))
break; break;
@ -1126,7 +1101,7 @@ grub_fat_label (grub_device_t device, char **label)
* GRUB_MAX_UTF8_PER_UTF16 + 1); * GRUB_MAX_UTF8_PER_UTF16 + 1);
if (!*label) if (!*label)
{ {
grub_free (data); grub_free (root.data);
return grub_errno; return grub_errno;
} }
chc = dir.type_specific.volume_label.character_count; chc = dir.type_specific.volume_label.character_count;
@ -1138,7 +1113,7 @@ grub_fat_label (grub_device_t device, char **label)
} }
} }
grub_free (data); grub_free (root.data);
return grub_errno; return grub_errno;
} }
@ -1147,30 +1122,32 @@ grub_fat_label (grub_device_t device, char **label)
static grub_err_t static grub_err_t
grub_fat_label (grub_device_t device, char **label) grub_fat_label (grub_device_t device, char **label)
{ {
struct grub_fat_data *data;
grub_disk_t disk = device->disk; grub_disk_t disk = device->disk;
grub_err_t err; grub_err_t err;
struct grub_fat_iterate_context ctxt; struct grub_fat_iterate_context ctxt;
struct grub_fshelp_node root = {
.disk = disk,
.attr = GRUB_FAT_ATTR_DIRECTORY,
.file_size = 0,
.cur_cluster_num = ~0U,
.cur_cluster = 0,
};
*label = 0; *label = 0;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
data = grub_fat_mount (disk); root.data = grub_fat_mount (disk);
if (! data) if (! root.data)
goto fail; goto fail;
if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY)) root.file_cluster = root.data->root_cluster;
{
grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
goto fail;
}
err = grub_fat_iterate_init (&ctxt); err = grub_fat_iterate_init (&ctxt);
if (err) if (err)
goto fail; goto fail;
while (!(err = grub_fat_iterate_dir_next (disk, data, &ctxt))) while (!(err = grub_fat_iterate_dir_next (&root, &ctxt)))
if ((ctxt.dir.attr & ~GRUB_FAT_ATTR_ARCHIVE) == GRUB_FAT_ATTR_VOLUME_ID) if ((ctxt.dir.attr & ~GRUB_FAT_ATTR_ARCHIVE) == GRUB_FAT_ATTR_VOLUME_ID)
{ {
*label = grub_strdup (ctxt.filename); *label = grub_strdup (ctxt.filename);
@ -1183,7 +1160,7 @@ grub_fat_label (grub_device_t device, char **label)
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
grub_free (data); grub_free (root.data);
return grub_errno; return grub_errno;
} }