* grub-core/fs/ufs.c: Remove variable length arrays.
This commit is contained in:
parent
1ba6b9b96f
commit
2a40badf82
2 changed files with 150 additions and 127 deletions
|
@ -1,3 +1,7 @@
|
||||||
|
2013-10-20 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
|
* grub-core/fs/ufs.c: Remove variable length arrays.
|
||||||
|
|
||||||
2013-10-20 Vladimir Serbinenko <phcoder@gmail.com>
|
2013-10-20 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
* grub-core/fs/ntfs.c: Add comment about fixed allocation size.
|
* grub-core/fs/ntfs.c: Add comment about fixed allocation size.
|
||||||
|
|
|
@ -61,6 +61,22 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
#define grub_cpu_to_ufs32_compile_time grub_cpu_to_le32_compile_time
|
#define grub_cpu_to_ufs32_compile_time grub_cpu_to_le32_compile_time
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MODE_UFS2
|
||||||
|
typedef grub_uint64_t grub_ufs_blk_t;
|
||||||
|
static inline grub_disk_addr_t
|
||||||
|
grub_ufs_to_cpu_blk (grub_ufs_blk_t blk)
|
||||||
|
{
|
||||||
|
return grub_ufs_to_cpu64 (blk);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
typedef grub_uint32_t grub_ufs_blk_t;
|
||||||
|
static inline grub_disk_addr_t
|
||||||
|
grub_ufs_to_cpu_blk (grub_ufs_blk_t blk)
|
||||||
|
{
|
||||||
|
return grub_ufs_to_cpu32 (blk);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Calculate in which group the inode can be found. */
|
/* Calculate in which group the inode can be found. */
|
||||||
#define UFS_BLKSZ(sblock) (grub_ufs_to_cpu32 (sblock->bsize))
|
#define UFS_BLKSZ(sblock) (grub_ufs_to_cpu32 (sblock->bsize))
|
||||||
#define UFS_LOG_BLKSZ(sblock) (data->log2_blksz)
|
#define UFS_LOG_BLKSZ(sblock) (data->log2_blksz)
|
||||||
|
@ -241,7 +257,6 @@ static grub_err_t grub_ufs_find_file (struct grub_ufs_data *data,
|
||||||
static grub_disk_addr_t
|
static grub_disk_addr_t
|
||||||
grub_ufs_get_file_block (struct grub_ufs_data *data, grub_disk_addr_t blk)
|
grub_ufs_get_file_block (struct grub_ufs_data *data, grub_disk_addr_t blk)
|
||||||
{
|
{
|
||||||
struct grub_ufs_sblock *sblock = &data->sblock;
|
|
||||||
unsigned long indirsz;
|
unsigned long indirsz;
|
||||||
int log2_blksz, log_indirsz;
|
int log2_blksz, log_indirsz;
|
||||||
|
|
||||||
|
@ -255,41 +270,35 @@ grub_ufs_get_file_block (struct grub_ufs_data *data, grub_disk_addr_t blk)
|
||||||
|
|
||||||
log_indirsz = data->log2_blksz - LOG_INODE_BLKSZ;
|
log_indirsz = data->log2_blksz - LOG_INODE_BLKSZ;
|
||||||
indirsz = 1 << log_indirsz;
|
indirsz = 1 << log_indirsz;
|
||||||
|
|
||||||
/* Single indirect block. */
|
/* Single indirect block. */
|
||||||
if (blk < indirsz)
|
if (blk < indirsz)
|
||||||
{
|
{
|
||||||
#ifdef MODE_UFS2
|
grub_ufs_blk_t indir;
|
||||||
grub_uint64_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint64_t)];
|
|
||||||
#else
|
|
||||||
grub_uint32_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint32_t)];
|
|
||||||
#endif
|
|
||||||
grub_disk_read (data->disk,
|
grub_disk_read (data->disk,
|
||||||
((grub_disk_addr_t) INODE_INDIRBLOCKS (data, 0))
|
((grub_disk_addr_t) INODE_INDIRBLOCKS (data, 0))
|
||||||
<< log2_blksz,
|
<< log2_blksz,
|
||||||
0, sizeof (indir), indir);
|
blk * sizeof (indir), sizeof (indir), &indir);
|
||||||
return indir[blk];
|
return indir;
|
||||||
}
|
}
|
||||||
blk -= indirsz;
|
blk -= indirsz;
|
||||||
|
|
||||||
/* Double indirect block. */
|
/* Double indirect block. */
|
||||||
if (blk < (grub_disk_addr_t) indirsz * (grub_disk_addr_t) indirsz)
|
if (blk < (grub_disk_addr_t) indirsz * (grub_disk_addr_t) indirsz)
|
||||||
{
|
{
|
||||||
#ifdef MODE_UFS2
|
grub_ufs_blk_t indir;
|
||||||
grub_uint64_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint64_t)];
|
|
||||||
#else
|
|
||||||
grub_uint32_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint32_t)];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
grub_disk_read (data->disk,
|
grub_disk_read (data->disk,
|
||||||
((grub_disk_addr_t) INODE_INDIRBLOCKS (data, 1))
|
((grub_disk_addr_t) INODE_INDIRBLOCKS (data, 1))
|
||||||
<< log2_blksz,
|
<< log2_blksz,
|
||||||
0, sizeof (indir), indir);
|
(blk >> log_indirsz) * sizeof (indir),
|
||||||
|
sizeof (indir), &indir);
|
||||||
grub_disk_read (data->disk,
|
grub_disk_read (data->disk,
|
||||||
((grub_disk_addr_t) indir [blk >> log_indirsz])
|
grub_ufs_to_cpu_blk (indir) << log2_blksz,
|
||||||
<< log2_blksz,
|
(blk & ((1 << log_indirsz) - 1)) * sizeof (indir),
|
||||||
0, sizeof (indir), indir);
|
sizeof (indir), &indir);
|
||||||
|
|
||||||
return indir[blk & ((1 << log_indirsz) - 1)];
|
return indir;
|
||||||
}
|
}
|
||||||
|
|
||||||
blk -= (grub_disk_addr_t) indirsz * (grub_disk_addr_t) indirsz;
|
blk -= (grub_disk_addr_t) indirsz * (grub_disk_addr_t) indirsz;
|
||||||
|
@ -297,28 +306,25 @@ grub_ufs_get_file_block (struct grub_ufs_data *data, grub_disk_addr_t blk)
|
||||||
/* Triple indirect block. */
|
/* Triple indirect block. */
|
||||||
if (!(blk >> (3 * log_indirsz)))
|
if (!(blk >> (3 * log_indirsz)))
|
||||||
{
|
{
|
||||||
#ifdef MODE_UFS2
|
grub_ufs_blk_t indir;
|
||||||
grub_uint64_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint64_t)];
|
|
||||||
#else
|
|
||||||
grub_uint32_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint32_t)];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
grub_disk_read (data->disk,
|
grub_disk_read (data->disk,
|
||||||
((grub_disk_addr_t) INODE_INDIRBLOCKS (data, 2))
|
((grub_disk_addr_t) INODE_INDIRBLOCKS (data, 2))
|
||||||
<< log2_blksz,
|
<< log2_blksz,
|
||||||
0, sizeof (indir), indir);
|
(blk >> (2 * log_indirsz)) * sizeof (indir),
|
||||||
|
sizeof (indir), &indir);
|
||||||
grub_disk_read (data->disk,
|
grub_disk_read (data->disk,
|
||||||
((grub_disk_addr_t) indir [blk >> (2 * log_indirsz)])
|
grub_ufs_to_cpu_blk (indir) << log2_blksz,
|
||||||
<< log2_blksz,
|
((blk >> log_indirsz)
|
||||||
0, sizeof (indir), indir);
|
& ((1 << log_indirsz) - 1)) * sizeof (indir),
|
||||||
|
sizeof (indir), &indir);
|
||||||
|
|
||||||
grub_disk_read (data->disk,
|
grub_disk_read (data->disk,
|
||||||
((grub_disk_addr_t) indir [(blk >> log_indirsz)
|
grub_ufs_to_cpu_blk (indir) << log2_blksz,
|
||||||
& ((1 << log_indirsz) - 1)])
|
(blk & ((1 << log_indirsz) - 1)) * sizeof (indir),
|
||||||
<< log2_blksz,
|
sizeof (indir), &indir);
|
||||||
0, sizeof (indir), indir);
|
|
||||||
|
|
||||||
return indir[blk & ((1 << log_indirsz) - 1)];
|
return indir;
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_error (GRUB_ERR_BAD_FS,
|
grub_error (GRUB_ERR_BAD_FS,
|
||||||
|
@ -441,11 +447,15 @@ grub_ufs_read_inode (struct grub_ufs_data *data, int ino, char *inode)
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino)
|
grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino)
|
||||||
{
|
{
|
||||||
char symlink[INODE_SIZE (data) + 1];
|
char *symlink;
|
||||||
|
grub_size_t sz = INODE_SIZE (data);
|
||||||
|
|
||||||
if (++data->linknest > GRUB_UFS_MAX_SYMLNK_CNT)
|
if (++data->linknest > GRUB_UFS_MAX_SYMLNK_CNT)
|
||||||
return grub_error (GRUB_ERR_SYMLINK_LOOP, N_("too deep nesting of symlinks"));
|
return grub_error (GRUB_ERR_SYMLINK_LOOP, N_("too deep nesting of symlinks"));
|
||||||
|
|
||||||
|
symlink = grub_malloc (sz + 1);
|
||||||
|
if (!symlink)
|
||||||
|
return grub_errno;
|
||||||
/* Normally we should just check that data->inode.nblocks == 0.
|
/* Normally we should just check that data->inode.nblocks == 0.
|
||||||
However old Linux doesn't maintain nblocks correctly and so it's always
|
However old Linux doesn't maintain nblocks correctly and so it's always
|
||||||
0. If size is bigger than inline space then the symlink is surely not
|
0. If size is bigger than inline space then the symlink is surely not
|
||||||
|
@ -455,8 +465,8 @@ grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino)
|
||||||
&& INODE_SIZE (data) <= sizeof (data->inode.symlink))
|
&& INODE_SIZE (data) <= sizeof (data->inode.symlink))
|
||||||
grub_strcpy (symlink, (char *) data->inode.symlink);
|
grub_strcpy (symlink, (char *) data->inode.symlink);
|
||||||
else
|
else
|
||||||
grub_ufs_read_file (data, 0, 0, 0, INODE_SIZE (data), symlink);
|
grub_ufs_read_file (data, 0, 0, 0, sz, symlink);
|
||||||
symlink[INODE_SIZE (data)] = '\0';
|
symlink[sz] = '\0';
|
||||||
|
|
||||||
/* The symlink is an absolute path, go back to the root inode. */
|
/* The symlink is an absolute path, go back to the root inode. */
|
||||||
if (symlink[0] == '/')
|
if (symlink[0] == '/')
|
||||||
|
@ -464,10 +474,15 @@ grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino)
|
||||||
|
|
||||||
/* Now load in the old inode. */
|
/* Now load in the old inode. */
|
||||||
if (grub_ufs_read_inode (data, ino, 0))
|
if (grub_ufs_read_inode (data, ino, 0))
|
||||||
|
{
|
||||||
|
grub_free (symlink);
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
}
|
||||||
|
|
||||||
grub_ufs_find_file (data, symlink);
|
grub_ufs_find_file (data, symlink);
|
||||||
|
|
||||||
|
grub_free (symlink);
|
||||||
|
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,57 +492,73 @@ grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino)
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_ufs_find_file (struct grub_ufs_data *data, const char *path)
|
grub_ufs_find_file (struct grub_ufs_data *data, const char *path)
|
||||||
{
|
{
|
||||||
char fpath[grub_strlen (path) + 1];
|
const char *name;
|
||||||
char *name = fpath;
|
const char *next = path;
|
||||||
char *next;
|
|
||||||
unsigned int pos = 0;
|
unsigned int pos = 0;
|
||||||
int dirino;
|
int dirino;
|
||||||
|
char *filename;
|
||||||
|
|
||||||
grub_strcpy (fpath, path);
|
/* We reject filenames longer than the one we're looking
|
||||||
|
for without reading, so this allocation is enough. */
|
||||||
|
filename = grub_malloc (grub_strlen (path) + 2);
|
||||||
|
if (!filename)
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
struct grub_ufs_dirent dirent;
|
||||||
|
|
||||||
|
name = next;
|
||||||
/* Skip the first slash. */
|
/* Skip the first slash. */
|
||||||
while (*name == '/')
|
while (*name == '/')
|
||||||
name++;
|
name++;
|
||||||
if (!*name)
|
if (*name == 0)
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Extract the actual part from the pathname. */
|
|
||||||
next = grub_strchr (name, '/');
|
|
||||||
if (next)
|
|
||||||
{
|
{
|
||||||
next[0] = '\0';
|
grub_free (filename);
|
||||||
next++;
|
return GRUB_ERR_NONE;
|
||||||
while (*next == '/')
|
|
||||||
next++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
do
|
if ((INODE_MODE(data) & GRUB_UFS_ATTR_TYPE)
|
||||||
|
!= GRUB_UFS_ATTR_DIR)
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||||
|
N_("not a directory"));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Extract the actual part from the pathname. */
|
||||||
|
for (next = name; *next && *next != '/'; next++);
|
||||||
|
for (pos = 0; ; pos += grub_ufs_to_cpu16 (dirent.direntlen))
|
||||||
{
|
{
|
||||||
struct grub_ufs_dirent dirent;
|
|
||||||
int namelen;
|
int namelen;
|
||||||
|
|
||||||
if (grub_strlen (name) == 0)
|
if (pos >= INODE_SIZE (data))
|
||||||
return GRUB_ERR_NONE;
|
{
|
||||||
|
grub_error (GRUB_ERR_FILE_NOT_FOUND,
|
||||||
|
N_("file `%s' not found"),
|
||||||
|
path);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
if (grub_ufs_read_file (data, 0, 0, pos, sizeof (dirent),
|
if (grub_ufs_read_file (data, 0, 0, pos, sizeof (dirent),
|
||||||
(char *) &dirent) < 0)
|
(char *) &dirent) < 0)
|
||||||
return grub_errno;
|
goto fail;
|
||||||
|
|
||||||
#ifdef MODE_UFS2
|
#ifdef MODE_UFS2
|
||||||
namelen = dirent.namelen_bsd;
|
namelen = dirent.namelen_bsd;
|
||||||
#else
|
#else
|
||||||
namelen = grub_ufs_to_cpu16 (dirent.namelen);
|
namelen = grub_ufs_to_cpu16 (dirent.namelen);
|
||||||
#endif
|
#endif
|
||||||
{
|
if (namelen < next - name)
|
||||||
char filename[namelen + 1];
|
continue;
|
||||||
|
|
||||||
if (grub_ufs_read_file (data, 0, 0, pos + sizeof (dirent),
|
if (grub_ufs_read_file (data, 0, 0, pos + sizeof (dirent),
|
||||||
namelen, filename) < 0)
|
next - name + (namelen != next - name),
|
||||||
return grub_errno;
|
filename) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
filename[namelen] = '\0';
|
if (grub_strncmp (name, filename, next - name) == 0
|
||||||
|
&& (namelen == next - name || filename[next - name] == '\0'))
|
||||||
if (!grub_strcmp (name, filename))
|
|
||||||
{
|
{
|
||||||
dirino = data->ino;
|
dirino = data->ino;
|
||||||
grub_ufs_read_inode (data, grub_ufs_to_cpu32 (dirent.ino), 0);
|
grub_ufs_read_inode (data, grub_ufs_to_cpu32 (dirent.ino), 0);
|
||||||
|
@ -537,35 +568,15 @@ grub_ufs_find_file (struct grub_ufs_data *data, const char *path)
|
||||||
{
|
{
|
||||||
grub_ufs_lookup_symlink (data, dirino);
|
grub_ufs_lookup_symlink (data, dirino);
|
||||||
if (grub_errno)
|
if (grub_errno)
|
||||||
return grub_errno;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!next)
|
break;
|
||||||
return 0;
|
|
||||||
|
|
||||||
pos = 0;
|
|
||||||
|
|
||||||
name = next;
|
|
||||||
next = grub_strchr (name, '/');
|
|
||||||
if (next)
|
|
||||||
{
|
|
||||||
next[0] = '\0';
|
|
||||||
next++;
|
|
||||||
while (*next == '/')
|
|
||||||
next++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((INODE_MODE(data) & GRUB_UFS_ATTR_TYPE) != GRUB_UFS_ATTR_DIR)
|
|
||||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
pos += grub_ufs_to_cpu16 (dirent.direntlen);
|
fail:
|
||||||
} while (pos < INODE_SIZE (data));
|
grub_free (filename);
|
||||||
|
|
||||||
grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path);
|
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -672,8 +683,9 @@ grub_ufs_dir (grub_device_t device, const char *path,
|
||||||
namelen = grub_ufs_to_cpu16 (dirent.namelen);
|
namelen = grub_ufs_to_cpu16 (dirent.namelen);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{
|
char *filename = grub_malloc (namelen + 1);
|
||||||
char filename[namelen + 1];
|
if (!filename)
|
||||||
|
goto fail;
|
||||||
struct grub_dirhook_info info;
|
struct grub_dirhook_info info;
|
||||||
struct grub_ufs_inode inode;
|
struct grub_ufs_inode inode;
|
||||||
|
|
||||||
|
@ -681,7 +693,10 @@ grub_ufs_dir (grub_device_t device, const char *path,
|
||||||
|
|
||||||
if (grub_ufs_read_file (data, 0, 0, pos + sizeof (dirent),
|
if (grub_ufs_read_file (data, 0, 0, pos + sizeof (dirent),
|
||||||
namelen, filename) < 0)
|
namelen, filename) < 0)
|
||||||
|
{
|
||||||
|
grub_free (filename);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
filename[namelen] = '\0';
|
filename[namelen] = '\0';
|
||||||
grub_ufs_read_inode (data, grub_ufs_to_cpu32 (dirent.ino),
|
grub_ufs_read_inode (data, grub_ufs_to_cpu32 (dirent.ino),
|
||||||
|
@ -697,9 +712,13 @@ grub_ufs_dir (grub_device_t device, const char *path,
|
||||||
info.mtimeset = 1;
|
info.mtimeset = 1;
|
||||||
|
|
||||||
if (hook (filename, &info, hook_data))
|
if (hook (filename, &info, hook_data))
|
||||||
|
{
|
||||||
|
grub_free (filename);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grub_free (filename);
|
||||||
|
|
||||||
pos += grub_ufs_to_cpu16 (dirent.direntlen);
|
pos += grub_ufs_to_cpu16 (dirent.direntlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue