* grub-core/fs/bfs.c: Remove variable length arrays. Reduces afs.mod and

bfs.mod size by 556 resp 740 bytes (288 resp 334 compressed).
	* include/grub/types.h (grub_unaligned_uint64_t): New type.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2013-10-20 13:11:40 +02:00
parent e89c2d48a9
commit d28e1163c3
3 changed files with 240 additions and 244 deletions

View file

@ -1,3 +1,9 @@
2013-10-20 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/fs/bfs.c: Remove variable length arrays. Reduces afs.mod and
bfs.mod size by 556 resp 740 bytes (288 resp 334 compressed).
* include/grub/types.h (grub_unaligned_uint64_t): New type.
2013-10-19 Vladimir Serbinenko <phcoder@gmail.com> 2013-10-19 Vladimir Serbinenko <phcoder@gmail.com>
Lift 255x255 erminal sie restriction to 65535x65535. Also change from Lift 255x255 erminal sie restriction to 65535x65535. Also change from

View file

@ -170,7 +170,7 @@ struct grub_bfs_btree_node
struct grub_bfs_data struct grub_bfs_data
{ {
struct grub_bfs_superblock sb; struct grub_bfs_superblock sb;
struct grub_bfs_inode ino[0]; struct grub_bfs_inode ino;
}; };
/* Context for grub_bfs_dir. */ /* Context for grub_bfs_dir. */
@ -419,6 +419,63 @@ read_bfs_file (grub_disk_t disk,
} }
} }
static grub_err_t
read_b_node (grub_disk_t disk,
const struct grub_bfs_superblock *sb,
const struct grub_bfs_inode *ino,
grub_uint64_t node_off,
struct grub_bfs_btree_node **node,
char **key_data, grub_uint16_t **keylen_idx,
grub_unaligned_uint64_t **key_values)
{
void *ret;
struct grub_bfs_btree_node node_head;
grub_size_t total_size;
grub_err_t err;
*node = NULL;
*key_data = NULL;
*keylen_idx = NULL;
*key_values = NULL;
err = read_bfs_file (disk, sb, ino, node_off, &node_head, sizeof (node_head),
0, 0);
if (err)
return err;
total_size = ALIGN_UP (sizeof (node_head) +
grub_bfs_to_cpu_treehead
(node_head.total_key_len),
BTREE_ALIGN) +
grub_bfs_to_cpu_treehead (node_head.count_keys) *
sizeof (grub_uint16_t)
+ grub_bfs_to_cpu_treehead (node_head.count_keys) *
sizeof (grub_uint64_t);
ret = grub_malloc (total_size);
if (!ret)
return grub_errno;
err = read_bfs_file (disk, sb, ino, node_off, ret, total_size, 0, 0);
if (err)
{
grub_free (ret);
return err;
}
*node = ret;
*key_data = (char *) ret + sizeof (node_head);
*keylen_idx = (grub_uint16_t *) ret
+ ALIGN_UP (sizeof (node_head) +
grub_bfs_to_cpu_treehead (node_head.total_key_len),
BTREE_ALIGN) / 2;
*key_values = (grub_unaligned_uint64_t *)
(*keylen_idx +
grub_bfs_to_cpu_treehead (node_head.count_keys));
return GRUB_ERR_NONE;
}
static int static int
iterate_in_b_tree (grub_disk_t disk, iterate_in_b_tree (grub_disk_t disk,
const struct grub_bfs_superblock *sb, const struct grub_bfs_superblock *sb,
@ -462,70 +519,52 @@ iterate_in_b_tree (grub_disk_t disk,
while (1) while (1)
{ {
struct grub_bfs_btree_node node; struct grub_bfs_btree_node *node;
err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), char *key_data;
0, 0); grub_uint16_t *keylen_idx;
if (err) grub_unaligned_uint64_t *key_values;
return 0;
{
char key_data[grub_bfs_to_cpu_treehead (node.total_key_len) + 1];
grub_uint16_t keylen_idx[grub_bfs_to_cpu_treehead (node.count_keys)];
grub_uint64_t key_values[grub_bfs_to_cpu_treehead (node.count_keys)];
unsigned i; unsigned i;
grub_uint16_t start = 0, end = 0; grub_uint16_t start = 0, end = 0;
err = err = read_b_node (disk, sb, ino,
read_bfs_file (disk, sb, ino, node_off + sizeof (node), key_data, node_off,
grub_bfs_to_cpu_treehead (node.total_key_len), 0, 0); &node,
if (err) &key_data,
return 0; &keylen_idx,
key_data[grub_bfs_to_cpu_treehead (node.total_key_len)] = 0; &key_values);
err = read_bfs_file (disk, sb, ino, node_off
+ ALIGN_UP (sizeof (node) +
grub_bfs_to_cpu_treehead
(node.total_key_len), BTREE_ALIGN),
keylen_idx,
grub_bfs_to_cpu_treehead (node.count_keys) *
sizeof (grub_uint16_t), 0, 0);
if (err)
return 0;
err = read_bfs_file (disk, sb, ino, node_off
+ ALIGN_UP (sizeof (node) +
grub_bfs_to_cpu_treehead
(node.total_key_len),
BTREE_ALIGN) +
grub_bfs_to_cpu_treehead (node.count_keys) *
sizeof (grub_uint16_t), key_values,
grub_bfs_to_cpu_treehead (node.count_keys) *
sizeof (grub_uint64_t), 0, 0);
if (err) if (err)
return 0; return 0;
for (i = 0; i < grub_bfs_to_cpu_treehead (node.count_keys); i++) for (i = 0; i < grub_bfs_to_cpu_treehead (node->count_keys); i++)
{ {
char c; char c;
start = end; start = end;
end = grub_bfs_to_cpu16 (keylen_idx[i]); end = grub_bfs_to_cpu16 (keylen_idx[i]);
if (grub_bfs_to_cpu_treehead (node.total_key_len) <= end) if (grub_bfs_to_cpu_treehead (node->total_key_len) <= end)
end = grub_bfs_to_cpu_treehead (node.total_key_len); end = grub_bfs_to_cpu_treehead (node->total_key_len);
c = key_data[end]; c = key_data[end];
key_data[end] = 0; key_data[end] = 0;
if (hook (key_data + start, grub_bfs_to_cpu64 (key_values[i]), if (hook (key_data + start, grub_bfs_to_cpu64 (key_values[i].val),
ctx)) ctx))
{
grub_free (node);
return 1; return 1;
}
key_data[end] = c; key_data[end] = c;
} }
node_off = grub_bfs_to_cpu64 (node.right); node_off = grub_bfs_to_cpu64 (node->right);
grub_free (node);
if (node_off == POINTER_INVALID) if (node_off == POINTER_INVALID)
return 0; return 0;
} }
}
} }
static int static int
bfs_strcmp (const char *a, const char *b, grub_size_t alen) bfs_strcmp (const char *a, const char *b, grub_size_t alen, grub_size_t blen)
{ {
while (*b && alen) char ac, bc;
while (blen && alen)
{ {
if (*a != *b) if (*a != *b)
break; break;
@ -533,18 +572,16 @@ bfs_strcmp (const char *a, const char *b, grub_size_t alen)
a++; a++;
b++; b++;
alen--; alen--;
blen--;
} }
ac = alen ? *a : 0;
bc = blen ? *b : 0;
#ifdef MODE_AFS #ifdef MODE_AFS
if (!alen) return (int) (grub_int8_t) ac - (int) (grub_int8_t) bc;
return - (int) (grub_int8_t) *b;
return (int) (grub_int8_t) *a - (int) (grub_int8_t) *b;
#else #else
if (!alen) return (int) (grub_uint8_t) ac - (int) (grub_uint8_t) bc;
return - (int) (grub_uint8_t) *b;
return (int) (grub_uint8_t) *a - (int) (grub_uint8_t) *b;
#endif #endif
} }
@ -552,6 +589,7 @@ static grub_err_t
find_in_b_tree (grub_disk_t disk, find_in_b_tree (grub_disk_t disk,
const struct grub_bfs_superblock *sb, const struct grub_bfs_superblock *sb,
const struct grub_bfs_inode *ino, const char *name, const struct grub_bfs_inode *ino, const char *name,
grub_size_t name_len,
grub_uint64_t * res) grub_uint64_t * res)
{ {
struct grub_bfs_btree_header head; struct grub_bfs_btree_header head;
@ -567,50 +605,25 @@ find_in_b_tree (grub_disk_t disk,
level = grub_bfs_to_cpu32 (head.level) - 1; level = grub_bfs_to_cpu32 (head.level) - 1;
while (1) while (1)
{ {
struct grub_bfs_btree_node node; struct grub_bfs_btree_node *node;
err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), char *key_data;
0, 0); grub_uint16_t *keylen_idx;
grub_unaligned_uint64_t *key_values;
int lg, j;
unsigned i;
err = read_b_node (disk, sb, ino, node_off, &node, &key_data, &keylen_idx, &key_values);
if (err) if (err)
return err; return err;
if (node.count_keys == 0)
if (node->count_keys == 0)
{
grub_free (node);
return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"),
name); name);
{ }
char key_data[grub_bfs_to_cpu_treehead (node.total_key_len) + 1];
grub_uint16_t keylen_idx[grub_bfs_to_cpu_treehead (node.count_keys)];
grub_uint64_t key_values[grub_bfs_to_cpu_treehead (node.count_keys)];
unsigned i;
err =
read_bfs_file (disk, sb, ino, node_off + sizeof (node), key_data,
grub_bfs_to_cpu_treehead (node.total_key_len), 0, 0);
if (err)
return err;
key_data[grub_bfs_to_cpu_treehead (node.total_key_len)] = 0;
err = read_bfs_file (disk, sb, ino, node_off
+
ALIGN_UP (sizeof (node) +
grub_bfs_to_cpu_treehead (node.
total_key_len),
BTREE_ALIGN), keylen_idx,
grub_bfs_to_cpu_treehead (node.count_keys) *
sizeof (grub_uint16_t), 0, 0);
if (err)
return err;
err = read_bfs_file (disk, sb, ino, node_off
+ ALIGN_UP (sizeof (node) +
grub_bfs_to_cpu_treehead
(node.total_key_len),
BTREE_ALIGN) +
grub_bfs_to_cpu_treehead (node.count_keys) *
sizeof (grub_uint16_t), key_values,
grub_bfs_to_cpu_treehead (node.count_keys) *
sizeof (grub_uint64_t), 0, 0);
if (err)
return err;
int lg, j; for (lg = 0; grub_bfs_to_cpu_treehead (node->count_keys) >> lg; lg++);
for (lg = 0; grub_bfs_to_cpu_treehead (node.count_keys) >> lg; lg++);
i = 0; i = 0;
@ -618,16 +631,17 @@ find_in_b_tree (grub_disk_t disk,
{ {
int cmp; int cmp;
grub_uint16_t start = 0, end = 0; grub_uint16_t start = 0, end = 0;
if ((i | (1 << j)) >= grub_bfs_to_cpu_treehead (node.count_keys)) if ((i | (1 << j)) >= grub_bfs_to_cpu_treehead (node->count_keys))
continue; continue;
start = grub_bfs_to_cpu16 (keylen_idx[(i | (1 << j)) - 1]); start = grub_bfs_to_cpu16 (keylen_idx[(i | (1 << j)) - 1]);
end = grub_bfs_to_cpu16 (keylen_idx[(i | (1 << j))]); end = grub_bfs_to_cpu16 (keylen_idx[(i | (1 << j))]);
if (grub_bfs_to_cpu_treehead (node.total_key_len) <= end) if (grub_bfs_to_cpu_treehead (node->total_key_len) <= end)
end = grub_bfs_to_cpu_treehead (node.total_key_len); end = grub_bfs_to_cpu_treehead (node->total_key_len);
cmp = bfs_strcmp (key_data + start, name, end - start); cmp = bfs_strcmp (key_data + start, name, end - start, name_len);
if (cmp == 0 && level == 0) if (cmp == 0 && level == 0)
{ {
*res = grub_bfs_to_cpu64 (key_values[i | (1 << j)]); *res = grub_bfs_to_cpu64 (key_values[i | (1 << j)].val);
grub_free (node);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
#ifdef MODE_AFS #ifdef MODE_AFS
@ -642,12 +656,13 @@ find_in_b_tree (grub_disk_t disk,
grub_uint16_t end = 0; grub_uint16_t end = 0;
int cmp; int cmp;
end = grub_bfs_to_cpu16 (keylen_idx[0]); end = grub_bfs_to_cpu16 (keylen_idx[0]);
if (grub_bfs_to_cpu_treehead (node.total_key_len) <= end) if (grub_bfs_to_cpu_treehead (node->total_key_len) <= end)
end = grub_bfs_to_cpu_treehead (node.total_key_len); end = grub_bfs_to_cpu_treehead (node->total_key_len);
cmp = bfs_strcmp (key_data, name, end); cmp = bfs_strcmp (key_data, name, end, name_len);
if (cmp == 0 && level == 0) if (cmp == 0 && level == 0)
{ {
*res = grub_bfs_to_cpu64 (key_values[0]); *res = grub_bfs_to_cpu64 (key_values[0].val);
grub_free (node);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
#ifdef MODE_AFS #ifdef MODE_AFS
@ -656,42 +671,47 @@ find_in_b_tree (grub_disk_t disk,
if (cmp >= 0 && level != 0) if (cmp >= 0 && level != 0)
#endif #endif
{ {
node_off = grub_bfs_to_cpu64 (key_values[0]); node_off = grub_bfs_to_cpu64 (key_values[0].val);
level--; level--;
grub_free (node);
continue; continue;
} }
else if (level != 0 else if (level != 0
&& grub_bfs_to_cpu_treehead (node.count_keys) >= 2) && grub_bfs_to_cpu_treehead (node->count_keys) >= 2)
{ {
node_off = grub_bfs_to_cpu64 (key_values[1]); node_off = grub_bfs_to_cpu64 (key_values[1].val);
level--; level--;
grub_free (node);
continue; continue;
} }
} }
else if (level != 0 else if (level != 0
&& i + 1 < grub_bfs_to_cpu_treehead (node.count_keys)) && i + 1 < grub_bfs_to_cpu_treehead (node->count_keys))
{ {
node_off = grub_bfs_to_cpu64 (key_values[i + 1]); node_off = grub_bfs_to_cpu64 (key_values[i + 1].val);
level--; level--;
grub_free (node);
continue; continue;
} }
if (node.overflow != POINTER_INVALID) if (node->overflow != POINTER_INVALID)
{ {
node_off = grub_bfs_to_cpu64 (node.overflow); node_off = grub_bfs_to_cpu64 (node->overflow);
/* This level-- isn't specified but is needed. */ /* This level-- isn't specified but is needed. */
level--; level--;
grub_free (node);
continue; continue;
} }
grub_free (node);
return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"),
name); name);
} }
}
} }
static grub_err_t static grub_err_t
hop_level (grub_disk_t disk, hop_level (grub_disk_t disk,
const struct grub_bfs_superblock *sb, const struct grub_bfs_superblock *sb,
struct grub_bfs_inode *ino, const char *name) struct grub_bfs_inode *ino, const char *name,
const char *name_end)
{ {
grub_err_t err; grub_err_t err;
grub_uint64_t res = 0; grub_uint64_t res = 0;
@ -699,38 +719,35 @@ hop_level (grub_disk_t disk,
if (((grub_bfs_to_cpu32 (ino->mode) & ATTR_TYPE) != ATTR_DIR)) if (((grub_bfs_to_cpu32 (ino->mode) & ATTR_TYPE) != ATTR_DIR))
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
err = find_in_b_tree (disk, sb, ino, name, &res); err = find_in_b_tree (disk, sb, ino, name, name_end - name, &res);
if (err) if (err)
return err; return err;
return grub_disk_read (disk, res return grub_disk_read (disk, res
<< (grub_bfs_to_cpu32 (sb->log2_bsize) << (grub_bfs_to_cpu32 (sb->log2_bsize)
- GRUB_DISK_SECTOR_BITS), 0, - GRUB_DISK_SECTOR_BITS), 0,
grub_bfs_to_cpu32 (sb->bsize), (char *) ino); sizeof (*ino), (char *) ino);
} }
static grub_err_t static grub_err_t
find_file (const char *path, grub_disk_t disk, find_file (const char *path, grub_disk_t disk,
const struct grub_bfs_superblock *sb, struct grub_bfs_inode *ino) const struct grub_bfs_superblock *sb, struct grub_bfs_inode *ino)
{ {
char *ptr, *ptr2; const char *ptr, *next = path;
char *alloc = NULL; char *alloc = NULL;
char *wptr;
grub_err_t err; grub_err_t err;
union struct grub_bfs_inode old_ino;
{
struct grub_bfs_inode ino;
grub_uint8_t raw[grub_bfs_to_cpu32 (sb->bsize)];
} old_ino;
unsigned symlinks_max = 32; unsigned symlinks_max = 32;
err = read_extent (disk, sb, &sb->root_dir, 0, 0, ino, err = read_extent (disk, sb, &sb->root_dir, 0, 0, ino,
grub_bfs_to_cpu32 (sb->bsize)); sizeof (*ino));
if (err) if (err)
return err; return err;
ptr = (char *) path;
while (1) while (1)
{ {
ptr = next;
while (*ptr == '/') while (*ptr == '/')
ptr++; ptr++;
if (*ptr == 0) if (*ptr == 0)
@ -738,17 +755,9 @@ find_file (const char *path, grub_disk_t disk,
grub_free (alloc); grub_free (alloc);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
ptr2 = grub_strchr (ptr, '/'); for (next = ptr; *next && *next != '/'; next++);
grub_memcpy (&old_ino, ino, grub_bfs_to_cpu32 (sb->bsize)); grub_memcpy (&old_ino, ino, sizeof (old_ino));
if (ptr2) err = hop_level (disk, sb, ino, ptr, next);
{
char component[ptr2 - ptr + 1];
grub_memcpy (component, ptr, ptr2 - ptr);
component[ptr2 - ptr] = 0;
err = hop_level (disk, sb, ino, component);
}
else
err = hop_level (disk, sb, ino, ptr);
if (err) if (err)
return err; return err;
@ -767,7 +776,7 @@ find_file (const char *path, grub_disk_t disk,
#endif #endif
{ {
grub_size_t symsize = grub_bfs_to_cpu64 (ino->size); grub_size_t symsize = grub_bfs_to_cpu64 (ino->size);
alloc = grub_malloc ((ptr2 ? grub_strlen (ptr2) : 0) alloc = grub_malloc (grub_strlen (next)
+ symsize + 1); + symsize + 1);
if (!alloc) if (!alloc)
{ {
@ -786,7 +795,7 @@ find_file (const char *path, grub_disk_t disk,
#ifndef MODE_AFS #ifndef MODE_AFS
else else
{ {
alloc = grub_malloc ((ptr2 ? grub_strlen (ptr2) : 0) alloc = grub_malloc (grub_strlen (next)
+ sizeof (ino->inplace_link) + 1); + sizeof (ino->inplace_link) + 1);
if (!alloc) if (!alloc)
{ {
@ -802,7 +811,7 @@ find_file (const char *path, grub_disk_t disk,
if (alloc[0] == '/') if (alloc[0] == '/')
{ {
err = read_extent (disk, sb, &sb->root_dir, 0, 0, ino, err = read_extent (disk, sb, &sb->root_dir, 0, 0, ino,
grub_bfs_to_cpu32 (sb->bsize)); sizeof (*ino));
if (err) if (err)
{ {
grub_free (alloc); grub_free (alloc);
@ -810,21 +819,14 @@ find_file (const char *path, grub_disk_t disk,
} }
} }
else else
grub_memcpy (ino, &old_ino, grub_bfs_to_cpu32 (sb->bsize)); grub_memcpy (ino, &old_ino, sizeof (old_ino));
ptr = alloc + grub_strlen (alloc); wptr = alloc + grub_strlen (alloc);
if (ptr2) if (next)
ptr = grub_stpcpy (ptr, ptr2); wptr = grub_stpcpy (wptr, next);
*ptr = 0; *wptr = 0;
ptr = ptr2 = alloc; next = alloc;
continue; continue;
} }
if (!ptr2)
{
grub_free (alloc);
return GRUB_ERR_NONE;
}
ptr = ptr2 + 1;
} }
} }
@ -866,17 +868,13 @@ grub_bfs_dir_iter (const char *name, grub_uint64_t value,
struct grub_bfs_dir_ctx *ctx) struct grub_bfs_dir_ctx *ctx)
{ {
grub_err_t err2; grub_err_t err2;
union
{
struct grub_bfs_inode ino; struct grub_bfs_inode ino;
grub_uint8_t raw[grub_bfs_to_cpu32 (ctx->sb.bsize)];
} ino;
struct grub_dirhook_info info; struct grub_dirhook_info info;
err2 = grub_disk_read (ctx->device->disk, value err2 = grub_disk_read (ctx->device->disk, value
<< (grub_bfs_to_cpu32 (ctx->sb.log2_bsize) << (grub_bfs_to_cpu32 (ctx->sb.log2_bsize)
- GRUB_DISK_SECTOR_BITS), 0, - GRUB_DISK_SECTOR_BITS), 0,
grub_bfs_to_cpu32 (ctx->sb.bsize), (char *) ino.raw); sizeof (ino), (char *) &ino);
if (err2) if (err2)
{ {
grub_print_error (); grub_print_error ();
@ -886,11 +884,11 @@ grub_bfs_dir_iter (const char *name, grub_uint64_t value,
info.mtimeset = 1; info.mtimeset = 1;
#ifdef MODE_AFS #ifdef MODE_AFS
info.mtime = info.mtime =
grub_divmod64 (grub_bfs_to_cpu64 (ino.ino.mtime), 1000000, 0); grub_divmod64 (grub_bfs_to_cpu64 (ino.mtime), 1000000, 0);
#else #else
info.mtime = grub_bfs_to_cpu64 (ino.ino.mtime) >> 16; info.mtime = grub_bfs_to_cpu64 (ino.mtime) >> 16;
#endif #endif
info.dir = ((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) == ATTR_DIR); info.dir = ((grub_bfs_to_cpu32 (ino.mode) & ATTR_TYPE) == ATTR_DIR);
return ctx->hook (name, &info, ctx->hook_data); return ctx->hook (name, &info, ctx->hook_data);
} }
@ -909,18 +907,14 @@ grub_bfs_dir (grub_device_t device, const char *path,
if (err) if (err)
return err; return err;
{
union
{ {
struct grub_bfs_inode ino; struct grub_bfs_inode ino;
grub_uint8_t raw[grub_bfs_to_cpu32 (ctx.sb.bsize)]; err = find_file (path, device->disk, &ctx.sb, &ino);
} ino;
err = find_file (path, device->disk, &ctx.sb, &ino.ino);
if (err) if (err)
return err; return err;
if (((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) != ATTR_DIR)) if (((grub_bfs_to_cpu32 (ino.mode) & ATTR_TYPE) != ATTR_DIR))
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
iterate_in_b_tree (device->disk, &ctx.sb, &ino.ino, grub_bfs_dir_iter, iterate_in_b_tree (device->disk, &ctx.sb, &ino, grub_bfs_dir_iter,
&ctx); &ctx);
} }
@ -937,27 +931,22 @@ grub_bfs_open (struct grub_file *file, const char *name)
if (err) if (err)
return err; return err;
{
union
{ {
struct grub_bfs_inode ino; struct grub_bfs_inode ino;
grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)];
} ino;
struct grub_bfs_data *data; struct grub_bfs_data *data;
err = find_file (name, file->device->disk, &sb, &ino.ino); err = find_file (name, file->device->disk, &sb, &ino);
if (err) if (err)
return err; return err;
if (((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) != ATTR_REG)) if (((grub_bfs_to_cpu32 (ino.mode) & ATTR_TYPE) != ATTR_REG))
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file"));
data = grub_zalloc (sizeof (struct grub_bfs_data) data = grub_zalloc (sizeof (struct grub_bfs_data));
+ grub_bfs_to_cpu32 (sb.bsize));
if (!data) if (!data)
return grub_errno; return grub_errno;
data->sb = sb; data->sb = sb;
grub_memcpy (&data->ino, &ino, grub_bfs_to_cpu32 (sb.bsize)); grub_memcpy (&data->ino, &ino, sizeof (data->ino));
file->data = data; file->data = data;
file->size = grub_bfs_to_cpu64 (ino.ino.size); file->size = grub_bfs_to_cpu64 (ino.size);
} }
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
@ -978,7 +967,7 @@ grub_bfs_read (grub_file_t file, char *buf, grub_size_t len)
struct grub_bfs_data *data = file->data; struct grub_bfs_data *data = file->data;
err = read_bfs_file (file->device->disk, &data->sb, err = read_bfs_file (file->device->disk, &data->sb,
data->ino, file->offset, buf, len, &data->ino, file->offset, buf, len,
file->read_hook, file->read_hook_data); file->read_hook, file->read_hook_data);
if (err) if (err)
return -1; return -1;
@ -1005,7 +994,7 @@ grub_bfs_label (grub_device_t device, char **label)
static grub_ssize_t static grub_ssize_t
read_bfs_attr (grub_disk_t disk, read_bfs_attr (grub_disk_t disk,
const struct grub_bfs_superblock *sb, const struct grub_bfs_superblock *sb,
const struct grub_bfs_inode *ino, struct grub_bfs_inode *ino,
const char *name, void *buf, grub_size_t len) const char *name, void *buf, grub_size_t len)
{ {
grub_uint8_t *ptr = (grub_uint8_t *) ino->small_data; grub_uint8_t *ptr = (grub_uint8_t *) ino->small_data;
@ -1036,32 +1025,27 @@ read_bfs_attr (grub_disk_t disk,
if (ino->attr.len != 0) if (ino->attr.len != 0)
{ {
union
{
struct grub_bfs_inode ino;
grub_uint8_t raw[grub_bfs_to_cpu32 (sb->bsize)];
} ino2;
grub_size_t read; grub_size_t read;
grub_err_t err; grub_err_t err;
grub_uint64_t res; grub_uint64_t res;
err = read_extent (disk, sb, &ino->attr, 0, 0, ino2.raw, err = read_extent (disk, sb, &ino->attr, 0, 0, ino,
grub_bfs_to_cpu32 (sb->bsize)); grub_bfs_to_cpu32 (sb->bsize));
if (err) if (err)
return -1; return -1;
err = find_in_b_tree (disk, sb, &ino2.ino, name, &res); err = find_in_b_tree (disk, sb, ino, name, grub_strlen (name), &res);
if (err) if (err)
return -1; return -1;
grub_disk_read (disk, res grub_disk_read (disk, res
<< (grub_bfs_to_cpu32 (sb->log2_bsize) << (grub_bfs_to_cpu32 (sb->log2_bsize)
- GRUB_DISK_SECTOR_BITS), 0, - GRUB_DISK_SECTOR_BITS), 0,
grub_bfs_to_cpu32 (sb->bsize), (char *) &ino2); grub_bfs_to_cpu32 (sb->bsize), (char *) ino);
read = grub_bfs_to_cpu64 (ino2.ino.size); read = grub_bfs_to_cpu64 (ino->size);
if (read > len) if (read > len)
read = len; read = len;
err = read_bfs_file (disk, sb, &ino2.ino, 0, buf, read, 0, 0); err = read_bfs_file (disk, sb, ino, 0, buf, read, 0, 0);
if (err) if (err)
return -1; return -1;
return read; return read;
@ -1074,6 +1058,8 @@ grub_bfs_uuid (grub_device_t device, char **uuid)
{ {
struct grub_bfs_superblock sb; struct grub_bfs_superblock sb;
grub_err_t err; grub_err_t err;
struct grub_bfs_inode *ino;
grub_uint64_t vid;
*uuid = 0; *uuid = 0;
@ -1081,23 +1067,24 @@ grub_bfs_uuid (grub_device_t device, char **uuid)
if (err) if (err)
return err; return err;
{ ino = grub_malloc (grub_bfs_to_cpu32 (sb.bsize));
union if (!ino)
{ return grub_errno;
struct grub_bfs_inode ino;
grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)];
} ino;
grub_uint64_t vid;
err = read_extent (device->disk, &sb, &sb.root_dir, 0, 0, err = read_extent (device->disk, &sb, &sb.root_dir, 0, 0,
&ino, grub_bfs_to_cpu32 (sb.bsize)); ino, grub_bfs_to_cpu32 (sb.bsize));
if (err) if (err)
{
grub_free (ino);
return err; return err;
if (read_bfs_attr (device->disk, &sb, &ino.ino, "be:volume_id", }
if (read_bfs_attr (device->disk, &sb, ino, "be:volume_id",
&vid, sizeof (vid)) == sizeof (vid)) &vid, sizeof (vid)) == sizeof (vid))
*uuid = *uuid =
grub_xasprintf ("%016" PRIxGRUB_UINT64_T, grub_bfs_to_cpu64 (vid)); grub_xasprintf ("%016" PRIxGRUB_UINT64_T, grub_bfs_to_cpu64 (vid));
}
grub_free (ino);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
#endif #endif

View file

@ -291,15 +291,18 @@ static inline void grub_set_unaligned32 (void *ptr, grub_uint32_t val)
dd->d = val; dd->d = val;
} }
struct grub_unaligned_uint64
{
grub_uint64_t val;
} __attribute__ ((packed));
typedef struct grub_unaligned_uint64 grub_unaligned_uint64_t;
static inline grub_uint64_t grub_get_unaligned64 (const void *ptr) static inline grub_uint64_t grub_get_unaligned64 (const void *ptr)
{ {
struct grub_unaligned_uint64_t const struct grub_unaligned_uint64 *dd
{ = (const struct grub_unaligned_uint64 *) ptr;
grub_uint64_t d; return dd->val;
} __attribute__ ((packed));
const struct grub_unaligned_uint64_t *dd
= (const struct grub_unaligned_uint64_t *)ptr;
return dd->d;
} }
static inline void grub_set_unaligned64 (void *ptr, grub_uint64_t val) static inline void grub_set_unaligned64 (void *ptr, grub_uint64_t val)