FAT: Convert to fshelp.
exFAT doesn't handle "." and ".." correctly, convert it to fshelp to reuse the same logic.
This commit is contained in:
parent
d1d3a60b71
commit
bfb5b33e96
1 changed files with 170 additions and 193 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue