2009-04-05 Vladimir Serbinenko <phcoder@gmail.com>
Trim trailing spaces in FAT label and support mtools-like labels * fs/fat.c (grub_fat_iterate_dir): New function based on grub_fat_find_dir (grub_fat_find_dir): use grub_fat_iterate_dir (grub_fat_label): likewise
This commit is contained in:
parent
04186a9ce2
commit
8a7e1a145f
2 changed files with 129 additions and 121 deletions
|
@ -1,3 +1,12 @@
|
||||||
|
2009-04-05 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
|
Trim trailing spaces in FAT label and support mtools-like labels
|
||||||
|
|
||||||
|
* fs/fat.c (grub_fat_iterate_dir): New function based
|
||||||
|
on grub_fat_find_dir
|
||||||
|
(grub_fat_find_dir): use grub_fat_iterate_dir
|
||||||
|
(grub_fat_label): likewise
|
||||||
|
|
||||||
2009-04-04 Vladimir Serbinenko <phcoder@gmail.com>
|
2009-04-04 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
* conf/powerpc-ieee1275.rmk (kernel_elf_HEADERS): add list.h
|
* conf/powerpc-ieee1275.rmk (kernel_elf_HEADERS): add list.h
|
||||||
|
|
209
fs/fat.c
209
fs/fat.c
|
@ -45,7 +45,8 @@
|
||||||
| GRUB_FAT_ATTR_HIDDEN \
|
| GRUB_FAT_ATTR_HIDDEN \
|
||||||
| GRUB_FAT_ATTR_SYSTEM \
|
| GRUB_FAT_ATTR_SYSTEM \
|
||||||
| GRUB_FAT_ATTR_DIRECTORY \
|
| GRUB_FAT_ATTR_DIRECTORY \
|
||||||
| GRUB_FAT_ATTR_ARCHIVE)
|
| GRUB_FAT_ATTR_ARCHIVE \
|
||||||
|
| GRUB_FAT_ATTR_VOLUME_ID)
|
||||||
|
|
||||||
struct grub_fat_bpb
|
struct grub_fat_bpb
|
||||||
{
|
{
|
||||||
|
@ -467,50 +468,20 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the underlying directory or file in PATH and return the
|
static grub_err_t
|
||||||
next path. If there is no next path or an error occurs, return NULL.
|
grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data,
|
||||||
If HOOK is specified, call it with each file name. */
|
int (*hook) (const char *filename,
|
||||||
static char *
|
struct grub_fat_dir_entry *dir))
|
||||||
grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
|
|
||||||
const char *path,
|
|
||||||
int (*hook) (const char *filename, int dir))
|
|
||||||
{
|
{
|
||||||
struct grub_fat_dir_entry dir;
|
struct grub_fat_dir_entry dir;
|
||||||
char *dirname, *dirp;
|
|
||||||
char *filename, *filep = 0;
|
char *filename, *filep = 0;
|
||||||
grub_uint16_t *unibuf;
|
grub_uint16_t *unibuf;
|
||||||
int slot = -1, slots = -1;
|
int slot = -1, slots = -1;
|
||||||
int checksum = -1;
|
int checksum = -1;
|
||||||
grub_ssize_t offset = -sizeof(dir);
|
grub_ssize_t offset = -sizeof(dir);
|
||||||
int call_hook;
|
|
||||||
|
|
||||||
if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
|
if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
|
||||||
{
|
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
|
||||||
grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Extract a directory name. */
|
|
||||||
while (*path == '/')
|
|
||||||
path++;
|
|
||||||
|
|
||||||
dirp = grub_strchr (path, '/');
|
|
||||||
if (dirp)
|
|
||||||
{
|
|
||||||
unsigned len = dirp - path;
|
|
||||||
|
|
||||||
dirname = grub_malloc (len + 1);
|
|
||||||
if (! dirname)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
grub_memcpy (dirname, path, len);
|
|
||||||
dirname[len] = '\0';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* This is actually a file. */
|
|
||||||
dirname = grub_strdup (path);
|
|
||||||
|
|
||||||
call_hook = (! dirp && hook);
|
|
||||||
|
|
||||||
/* Allocate space enough to hold a long name. */
|
/* Allocate space enough to hold a long name. */
|
||||||
filename = grub_malloc (0x40 * 13 * 4 + 1);
|
filename = grub_malloc (0x40 * 13 * 4 + 1);
|
||||||
|
@ -519,7 +490,6 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
|
||||||
{
|
{
|
||||||
grub_free (filename);
|
grub_free (filename);
|
||||||
grub_free (unibuf);
|
grub_free (unibuf);
|
||||||
grub_free (dirname);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -533,15 +503,8 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
|
||||||
/* Read a directory entry. */
|
/* Read a directory entry. */
|
||||||
if ((grub_fat_read_data (disk, data, 0,
|
if ((grub_fat_read_data (disk, data, 0,
|
||||||
offset, sizeof (dir), (char *) &dir)
|
offset, sizeof (dir), (char *) &dir)
|
||||||
!= sizeof (dir))
|
!= sizeof (dir) || dir.name[0] == 0))
|
||||||
|| dir.name[0] == 0)
|
|
||||||
{
|
|
||||||
if (grub_errno == GRUB_ERR_NONE && ! call_hook)
|
|
||||||
grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle long name entries. */
|
/* Handle long name entries. */
|
||||||
if (dir.attr == GRUB_FAT_ATTR_LONG_NAME)
|
if (dir.attr == GRUB_FAT_ATTR_LONG_NAME)
|
||||||
{
|
{
|
||||||
|
@ -594,30 +557,26 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
|
||||||
*grub_utf16_to_utf8 ((grub_uint8_t *) filename, unibuf,
|
*grub_utf16_to_utf8 ((grub_uint8_t *) filename, unibuf,
|
||||||
slots * 13) = '\0';
|
slots * 13) = '\0';
|
||||||
|
|
||||||
if (*dirname == '\0' && call_hook)
|
if (hook (filename, &dir))
|
||||||
{
|
|
||||||
if (hook (filename, dir.attr & GRUB_FAT_ATTR_DIRECTORY))
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
checksum = -1;
|
checksum = -1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (grub_strcmp (dirname, filename) == 0)
|
|
||||||
{
|
|
||||||
if (call_hook)
|
|
||||||
hook (filename, dir.attr & GRUB_FAT_ATTR_DIRECTORY);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
checksum = -1;
|
checksum = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert the 8.3 file name. */
|
/* Convert the 8.3 file name. */
|
||||||
filep = filename;
|
filep = filename;
|
||||||
|
if (dir.attr & GRUB_FAT_ATTR_VOLUME_ID)
|
||||||
|
{
|
||||||
|
for (i = 0; i < sizeof (dir.name) && dir.name[i]
|
||||||
|
&& ! grub_isspace (dir.name[i]); i++)
|
||||||
|
*filep++ = dir.name[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
for (i = 0; i < 8 && dir.name[i] && ! grub_isspace (dir.name[i]); i++)
|
for (i = 0; i < 8 && dir.name[i] && ! grub_isspace (dir.name[i]); i++)
|
||||||
*filep++ = grub_tolower (dir.name[i]);
|
*filep++ = grub_tolower (dir.name[i]);
|
||||||
|
|
||||||
|
@ -628,33 +587,91 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
|
||||||
|
|
||||||
if (*filep != '.')
|
if (*filep != '.')
|
||||||
filep++;
|
filep++;
|
||||||
|
}
|
||||||
*filep = '\0';
|
*filep = '\0';
|
||||||
|
|
||||||
if (*dirname == '\0' && call_hook)
|
if (hook (filename, &dir))
|
||||||
{
|
|
||||||
if (hook (filename, dir.attr & GRUB_FAT_ATTR_DIRECTORY))
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (grub_strncasecmp (dirname, filename, GRUB_FAT_MAXFILE) == 0)
|
|
||||||
{
|
|
||||||
if (call_hook)
|
|
||||||
hook (filename, dir.attr & GRUB_FAT_ATTR_DIRECTORY);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
grub_free (filename);
|
grub_free (filename);
|
||||||
grub_free (dirname);
|
|
||||||
|
|
||||||
data->attr = dir.attr;
|
return grub_errno;
|
||||||
data->file_size = grub_le_to_cpu32 (dir.file_size);
|
}
|
||||||
data->file_cluster = ((grub_le_to_cpu16 (dir.first_cluster_high) << 16)
|
|
||||||
| grub_le_to_cpu16 (dir.first_cluster_low));
|
|
||||||
|
/* Find the underlying directory or file in PATH and return the
|
||||||
|
next path. If there is no next path or an error occurs, return NULL.
|
||||||
|
If HOOK is specified, call it with each file name. */
|
||||||
|
static char *
|
||||||
|
grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
|
||||||
|
const char *path,
|
||||||
|
int (*hook) (const char *filename, int dir))
|
||||||
|
{
|
||||||
|
char *dirname, *dirp;
|
||||||
|
int call_hook;
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
|
auto int iter_hook (const char *filename, struct grub_fat_dir_entry *dir);
|
||||||
|
int iter_hook (const char *filename, struct grub_fat_dir_entry *dir)
|
||||||
|
{
|
||||||
|
if (dir->attr & GRUB_FAT_ATTR_VOLUME_ID)
|
||||||
|
return 0;
|
||||||
|
if (*dirname == '\0' && call_hook)
|
||||||
|
return hook (filename, dir->attr & GRUB_FAT_ATTR_DIRECTORY);
|
||||||
|
|
||||||
|
if (grub_strcasecmp (dirname, filename) == 0)
|
||||||
|
{
|
||||||
|
found = 1;
|
||||||
|
data->attr = dir->attr;
|
||||||
|
data->file_size = grub_le_to_cpu32 (dir->file_size);
|
||||||
|
data->file_cluster = ((grub_le_to_cpu16 (dir->first_cluster_high) << 16)
|
||||||
|
| grub_le_to_cpu16 (dir->first_cluster_low));
|
||||||
data->cur_cluster_num = ~0U;
|
data->cur_cluster_num = ~0U;
|
||||||
|
|
||||||
return dirp;
|
if (call_hook)
|
||||||
|
hook (filename, dir->attr & GRUB_FAT_ATTR_DIRECTORY);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Extract a directory name. */
|
||||||
|
while (*path == '/')
|
||||||
|
path++;
|
||||||
|
|
||||||
|
dirp = grub_strchr (path, '/');
|
||||||
|
if (dirp)
|
||||||
|
{
|
||||||
|
unsigned len = dirp - path;
|
||||||
|
|
||||||
|
dirname = grub_malloc (len + 1);
|
||||||
|
if (! dirname)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
grub_memcpy (dirname, path, len);
|
||||||
|
dirname[len] = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* This is actually a file. */
|
||||||
|
dirname = grub_strdup (path);
|
||||||
|
|
||||||
|
call_hook = (! dirp && hook);
|
||||||
|
|
||||||
|
grub_fat_iterate_dir (disk, data, iter_hook);
|
||||||
|
if (grub_errno == GRUB_ERR_NONE && ! found && !call_hook)
|
||||||
|
grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
|
||||||
|
|
||||||
|
grub_free (dirname);
|
||||||
|
|
||||||
|
return found ? dirp : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
|
@ -773,8 +790,17 @@ grub_fat_label (grub_device_t device, char **label)
|
||||||
{
|
{
|
||||||
struct grub_fat_data *data;
|
struct grub_fat_data *data;
|
||||||
grub_disk_t disk = device->disk;
|
grub_disk_t disk = device->disk;
|
||||||
grub_ssize_t offset = -sizeof(struct grub_fat_dir_entry);
|
|
||||||
|
|
||||||
|
auto int iter_hook (const char *filename, struct grub_fat_dir_entry *dir);
|
||||||
|
int iter_hook (const char *filename, struct grub_fat_dir_entry *dir)
|
||||||
|
{
|
||||||
|
if (dir->attr == GRUB_FAT_ATTR_VOLUME_ID)
|
||||||
|
{
|
||||||
|
*label = grub_strdup (filename);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef GRUB_UTIL
|
#ifndef GRUB_UTIL
|
||||||
grub_dl_ref (my_mod);
|
grub_dl_ref (my_mod);
|
||||||
|
@ -790,36 +816,9 @@ grub_fat_label (grub_device_t device, char **label)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
struct grub_fat_dir_entry dir;
|
|
||||||
|
|
||||||
/* Adjust the offset. */
|
|
||||||
offset += sizeof (dir);
|
|
||||||
|
|
||||||
/* Read a directory entry. */
|
|
||||||
if ((grub_fat_read_data (disk, data, 0,
|
|
||||||
offset, sizeof (dir), (char *) &dir)
|
|
||||||
!= sizeof (dir))
|
|
||||||
|| dir.name[0] == 0)
|
|
||||||
{
|
|
||||||
if (grub_errno != GRUB_ERR_NONE)
|
|
||||||
goto fail;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*label = 0;
|
*label = 0;
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dir.attr == GRUB_FAT_ATTR_VOLUME_ID)
|
grub_fat_iterate_dir (disk, data, iter_hook);
|
||||||
{
|
|
||||||
*label = grub_strndup ((char *) dir.name, 11);
|
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*label = 0;
|
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue