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:
phcoder 2009-04-05 15:34:30 +00:00
parent 04186a9ce2
commit 8a7e1a145f
2 changed files with 129 additions and 121 deletions

View file

@ -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
View file

@ -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: