Merge Mainline.
This commit is contained in:
commit
85fd555441
191 changed files with 9311 additions and 1208 deletions
|
@ -52,12 +52,20 @@ struct grub_affs_rblock
|
|||
grub_uint32_t hashtable[1];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct grub_affs_time
|
||||
{
|
||||
grub_int32_t day;
|
||||
grub_uint32_t min;
|
||||
grub_uint32_t hz;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* The second part of a file header block. */
|
||||
struct grub_affs_file
|
||||
{
|
||||
grub_uint8_t unused1[12];
|
||||
grub_uint32_t size;
|
||||
grub_uint8_t unused2[104];
|
||||
grub_uint8_t unused2[92];
|
||||
struct grub_affs_time mtime;
|
||||
grub_uint8_t namelen;
|
||||
grub_uint8_t name[30];
|
||||
grub_uint8_t unused3[33];
|
||||
|
@ -87,9 +95,9 @@ struct grub_affs_file
|
|||
struct grub_fshelp_node
|
||||
{
|
||||
struct grub_affs_data *data;
|
||||
int block;
|
||||
int size;
|
||||
int parent;
|
||||
grub_disk_addr_t block;
|
||||
struct grub_fshelp_node *parent;
|
||||
struct grub_affs_file di;
|
||||
};
|
||||
|
||||
/* Information about a "mounted" affs filesystem. */
|
||||
|
@ -117,7 +125,7 @@ grub_affs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
|||
int block = node->block;
|
||||
struct grub_affs_file file;
|
||||
struct grub_affs_data *data = node->data;
|
||||
grub_uint32_t mod;
|
||||
grub_uint64_t mod;
|
||||
|
||||
/* Find the block that points to the fileblock we are looking up by
|
||||
following the chain until the right table is reached. */
|
||||
|
@ -156,7 +164,7 @@ grub_affs_read_file (grub_fshelp_node_t node,
|
|||
{
|
||||
return grub_fshelp_read_file (node->data->disk, node, read_hook,
|
||||
pos, len, buf, grub_affs_read_block,
|
||||
node->size, 0);
|
||||
grub_be_to_cpu32 (node->di.size), 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -168,7 +176,6 @@ grub_affs_mount (grub_disk_t disk)
|
|||
struct grub_affs_rblock *rblock;
|
||||
|
||||
int checksum = 0;
|
||||
int checksumr = 0;
|
||||
int blocksize = 0;
|
||||
|
||||
data = grub_malloc (sizeof (struct grub_affs_data));
|
||||
|
@ -218,8 +225,6 @@ grub_affs_mount (grub_disk_t disk)
|
|||
/* The filesystem blocksize is not stored anywhere in the filesystem
|
||||
itself. One way to determine it is reading blocks for the
|
||||
rootblock until the checksum is correct. */
|
||||
checksumr = grub_be_to_cpu32 (rblock->checksum);
|
||||
rblock->checksum = 0;
|
||||
for (blocksize = 0; blocksize < 8; blocksize++)
|
||||
{
|
||||
grub_uint32_t *currblock = rootblock + GRUB_DISK_SECTOR_SIZE * blocksize;
|
||||
|
@ -228,10 +233,10 @@ grub_affs_mount (grub_disk_t disk)
|
|||
for (i = 0; i < GRUB_DISK_SECTOR_SIZE / sizeof (*currblock); i++)
|
||||
checksum += grub_be_to_cpu32 (currblock[i]);
|
||||
|
||||
if (checksumr == -checksum)
|
||||
if (checksum == 0)
|
||||
break;
|
||||
}
|
||||
if (-checksum != checksumr)
|
||||
if (checksum != 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FS, "AFFS blocksize couldn't be determined");
|
||||
goto fail;
|
||||
|
@ -243,6 +248,8 @@ grub_affs_mount (grub_disk_t disk)
|
|||
data->htsize = grub_be_to_cpu32 (rblock->htsize);
|
||||
data->diropen.data = data;
|
||||
data->diropen.block = grub_be_to_cpu32 (data->bblock.rootblock);
|
||||
data->diropen.parent = NULL;
|
||||
grub_memcpy (&data->diropen.di, rootblock, sizeof (data->diropen.di));
|
||||
|
||||
grub_free (rootblock);
|
||||
|
||||
|
@ -293,12 +300,15 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
|
|||
struct grub_affs_data *data = dir->data;
|
||||
grub_uint32_t *hashtable;
|
||||
|
||||
auto int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, int block,
|
||||
int size, int type);
|
||||
auto int NESTED_FUNC_ATTR grub_affs_create_node (const char *name,
|
||||
grub_disk_addr_t block,
|
||||
const struct grub_affs_file *fil);
|
||||
|
||||
int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, int block,
|
||||
int size, int type)
|
||||
int NESTED_FUNC_ATTR grub_affs_create_node (const char *name,
|
||||
grub_disk_addr_t block,
|
||||
const struct grub_affs_file *fil)
|
||||
{
|
||||
int type;
|
||||
node = grub_malloc (sizeof (*node));
|
||||
if (!node)
|
||||
{
|
||||
|
@ -306,10 +316,19 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
|
|||
return 1;
|
||||
}
|
||||
|
||||
if ((int) grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_DIR)
|
||||
type = GRUB_FSHELP_REG;
|
||||
else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_REG)
|
||||
type = GRUB_FSHELP_DIR;
|
||||
else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_SYMLINK)
|
||||
type = GRUB_FSHELP_SYMLINK;
|
||||
else
|
||||
type = GRUB_FSHELP_UNKNOWN;
|
||||
|
||||
node->data = data;
|
||||
node->size = size;
|
||||
node->block = block;
|
||||
node->parent = grub_be_to_cpu32 (file.parent);
|
||||
node->di = *fil;
|
||||
node->parent = dir;
|
||||
|
||||
if (hook (name, type, node))
|
||||
{
|
||||
|
@ -319,6 +338,24 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Create the directory entries for `.' and `..'. */
|
||||
node = grub_malloc (sizeof (*node));
|
||||
if (!node)
|
||||
return 1;
|
||||
|
||||
*node = *dir;
|
||||
if (hook (".", GRUB_FSHELP_DIR, node))
|
||||
return 1;
|
||||
if (dir->parent)
|
||||
{
|
||||
node = grub_malloc (sizeof (*node));
|
||||
if (!node)
|
||||
return 1;
|
||||
*node = *dir->parent;
|
||||
if (hook ("..", GRUB_FSHELP_DIR, node))
|
||||
return 1;
|
||||
}
|
||||
|
||||
hashtable = grub_malloc (data->htsize * sizeof (*hashtable));
|
||||
if (!hashtable)
|
||||
return 1;
|
||||
|
@ -328,16 +365,8 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
|
|||
if (grub_errno)
|
||||
goto fail;
|
||||
|
||||
/* Create the directory entries for `.' and `..'. */
|
||||
if (grub_affs_create_node (".", dir->block, dir->size, GRUB_FSHELP_DIR))
|
||||
return 1;
|
||||
if (grub_affs_create_node ("..", dir->parent ? dir->parent : dir->block,
|
||||
dir->size, GRUB_FSHELP_DIR))
|
||||
return 1;
|
||||
|
||||
for (i = 0; i < data->htsize; i++)
|
||||
{
|
||||
enum grub_fshelp_filetype type;
|
||||
grub_uint64_t next;
|
||||
|
||||
if (!hashtable[i])
|
||||
|
@ -358,17 +387,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
||||
file.name[file.namelen] = '\0';
|
||||
|
||||
if ((int) grub_be_to_cpu32 (file.type) == GRUB_AFFS_FILETYPE_DIR)
|
||||
type = GRUB_FSHELP_REG;
|
||||
else if (grub_be_to_cpu32 (file.type) == GRUB_AFFS_FILETYPE_REG)
|
||||
type = GRUB_FSHELP_DIR;
|
||||
else if (grub_be_to_cpu32 (file.type) == GRUB_AFFS_FILETYPE_SYMLINK)
|
||||
type = GRUB_FSHELP_SYMLINK;
|
||||
else
|
||||
type = GRUB_FSHELP_UNKNOWN;
|
||||
|
||||
if (grub_affs_create_node ((char *) (file.name), next,
|
||||
grub_be_to_cpu32 (file.size), type))
|
||||
if (grub_affs_create_node ((char *) (file.name), next, &file))
|
||||
return 1;
|
||||
|
||||
next = grub_be_to_cpu32 (file.next);
|
||||
|
@ -403,7 +422,7 @@ grub_affs_open (struct grub_file *file, const char *name)
|
|||
if (grub_errno)
|
||||
goto fail;
|
||||
|
||||
file->size = fdiro->size;
|
||||
file->size = grub_be_to_cpu32 (fdiro->di.size);
|
||||
data->diropen = *fdiro;
|
||||
grub_free (fdiro);
|
||||
|
||||
|
@ -467,6 +486,11 @@ grub_affs_dir (grub_device_t device, const char *path,
|
|||
struct grub_dirhook_info info;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_be_to_cpu32 (node->di.mtime.day) * 86400
|
||||
+ grub_be_to_cpu32 (node->di.mtime.min) * 60
|
||||
+ grub_be_to_cpu32 (node->di.mtime.hz) / 50
|
||||
+ 8 * 365 * 86400 + 86400 * 2;
|
||||
grub_free (node);
|
||||
return hook (filename, &info);
|
||||
}
|
||||
|
|
|
@ -589,10 +589,14 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data,
|
|||
struct grub_btrfs_key *key;
|
||||
struct grub_btrfs_chunk_item *chunk;
|
||||
grub_uint64_t csize;
|
||||
grub_err_t err;
|
||||
grub_err_t err = 0;
|
||||
struct grub_btrfs_key key_out;
|
||||
int challoc = 0;
|
||||
grub_device_t dev;
|
||||
struct grub_btrfs_key key_in;
|
||||
grub_size_t chsize;
|
||||
grub_disk_addr_t chaddr;
|
||||
|
||||
grub_dprintf ("btrfs", "searching for laddr %" PRIxGRUB_UINT64_T "\n",
|
||||
addr);
|
||||
for (ptr = data->sblock.bootstrap_mapping;
|
||||
|
@ -616,9 +620,7 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data,
|
|||
+ sizeof (struct grub_btrfs_chunk_stripe)
|
||||
* grub_le_to_cpu16 (chunk->nstripes);
|
||||
}
|
||||
struct grub_btrfs_key key_in;
|
||||
grub_size_t chsize;
|
||||
grub_disk_addr_t chaddr;
|
||||
|
||||
key_in.object_id = GRUB_BTRFS_OBJECT_ID_CHUNK;
|
||||
key_in.type = GRUB_BTRFS_ITEM_TYPE_CHUNK;
|
||||
key_in.offset = addr;
|
||||
|
@ -647,7 +649,7 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data,
|
|||
|
||||
chunk_found:
|
||||
{
|
||||
grub_uint32_t stripen;
|
||||
grub_uint64_t stripen;
|
||||
grub_uint64_t stripe_offset;
|
||||
grub_uint64_t off = addr - grub_le_to_cpu64 (key->offset);
|
||||
unsigned redundancy = 1;
|
||||
|
@ -677,10 +679,10 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data,
|
|||
{
|
||||
grub_uint64_t stripe_length;
|
||||
grub_dprintf ("btrfs", "single\n");
|
||||
stripe_length = grub_divmod64_full (grub_le_to_cpu64 (chunk->size),
|
||||
grub_le_to_cpu16 (chunk->nstripes),
|
||||
NULL);
|
||||
stripen = grub_divmod64_full (off, stripe_length, &stripe_offset);
|
||||
stripe_length = grub_divmod64 (grub_le_to_cpu64 (chunk->size),
|
||||
grub_le_to_cpu16 (chunk->nstripes),
|
||||
NULL);
|
||||
stripen = grub_divmod64 (off, stripe_length, &stripe_offset);
|
||||
csize = (stripen + 1) * stripe_length - off;
|
||||
break;
|
||||
}
|
||||
|
@ -697,7 +699,7 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data,
|
|||
case GRUB_BTRFS_CHUNK_TYPE_RAID0:
|
||||
{
|
||||
grub_uint64_t middle, high;
|
||||
grub_uint32_t low;
|
||||
grub_uint64_t low;
|
||||
grub_dprintf ("btrfs", "RAID0\n");
|
||||
middle = grub_divmod64 (off,
|
||||
grub_le_to_cpu64 (chunk->stripe_length),
|
||||
|
@ -713,7 +715,7 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data,
|
|||
case GRUB_BTRFS_CHUNK_TYPE_RAID10:
|
||||
{
|
||||
grub_uint64_t middle, high;
|
||||
grub_uint32_t low;
|
||||
grub_uint64_t low;
|
||||
middle = grub_divmod64 (off,
|
||||
grub_le_to_cpu64 (chunk->stripe_length),
|
||||
&low);
|
||||
|
@ -758,7 +760,7 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data,
|
|||
|
||||
grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T
|
||||
"+0x%" PRIxGRUB_UINT64_T " (%d stripes (%d substripes) of %"
|
||||
PRIxGRUB_UINT64_T ") stripe %" PRIxGRUB_UINT32_T
|
||||
PRIxGRUB_UINT64_T ") stripe %" PRIxGRUB_UINT64_T
|
||||
" maps to 0x%" PRIxGRUB_UINT64_T "\n",
|
||||
grub_le_to_cpu64 (key->offset),
|
||||
grub_le_to_cpu64 (chunk->size),
|
||||
|
|
|
@ -80,7 +80,7 @@ static grub_dl_t my_mod;
|
|||
|
||||
static grub_err_t
|
||||
grub_cpio_find_file (struct grub_cpio_data *data, char **name,
|
||||
grub_uint32_t * ofs)
|
||||
grub_int32_t *mtime, grub_uint32_t * ofs)
|
||||
{
|
||||
#ifndef MODE_USTAR
|
||||
struct head hd;
|
||||
|
@ -93,6 +93,8 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name,
|
|||
return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive");
|
||||
|
||||
data->size = (((grub_uint32_t) hd.filesize_1) << 16) + hd.filesize_2;
|
||||
if (mtime)
|
||||
*mtime = (((grub_uint32_t) hd.mtime_1) << 16) + hd.mtime_2;
|
||||
|
||||
if (hd.namesize & 1)
|
||||
hd.namesize++;
|
||||
|
@ -141,6 +143,8 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name,
|
|||
data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE;
|
||||
*ofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) &
|
||||
~(GRUB_DISK_SECTOR_SIZE - 1));
|
||||
if (mtime)
|
||||
*mtime = grub_strtoul (hd.mtime, NULL, 8);
|
||||
#endif
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
@ -206,7 +210,9 @@ grub_cpio_dir (grub_device_t device, const char *path,
|
|||
data->hofs = 0;
|
||||
while (1)
|
||||
{
|
||||
if (grub_cpio_find_file (data, &name, &ofs))
|
||||
grub_int32_t mtime;
|
||||
|
||||
if (grub_cpio_find_file (data, &name, &mtime, &ofs))
|
||||
goto fail;
|
||||
|
||||
if (!ofs)
|
||||
|
@ -229,6 +235,8 @@ grub_cpio_dir (grub_device_t device, const char *path,
|
|||
struct grub_dirhook_info info;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
info.dir = (p != NULL);
|
||||
info.mtime = mtime;
|
||||
info.mtimeset = 1;
|
||||
|
||||
hook (name + len, &info);
|
||||
if (prev)
|
||||
|
@ -271,7 +279,7 @@ grub_cpio_open (grub_file_t file, const char *name)
|
|||
data->hofs = 0;
|
||||
while (1)
|
||||
{
|
||||
if (grub_cpio_find_file (data, &fn, &ofs))
|
||||
if (grub_cpio_find_file (data, &fn, NULL, &ofs))
|
||||
goto fail;
|
||||
|
||||
if (!ofs)
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/charset.h>
|
||||
#include <grub/fat.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
|
@ -51,52 +52,6 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
|||
| GRUB_FAT_ATTR_ARCHIVE \
|
||||
| GRUB_FAT_ATTR_VOLUME_ID)
|
||||
|
||||
struct grub_fat_bpb
|
||||
{
|
||||
grub_uint8_t jmp_boot[3];
|
||||
grub_uint8_t oem_name[8];
|
||||
grub_uint16_t bytes_per_sector;
|
||||
grub_uint8_t sectors_per_cluster;
|
||||
grub_uint16_t num_reserved_sectors;
|
||||
grub_uint8_t num_fats;
|
||||
grub_uint16_t num_root_entries;
|
||||
grub_uint16_t num_total_sectors_16;
|
||||
grub_uint8_t media;
|
||||
grub_uint16_t sectors_per_fat_16;
|
||||
grub_uint16_t sectors_per_track;
|
||||
grub_uint16_t num_heads;
|
||||
grub_uint32_t num_hidden_sectors;
|
||||
grub_uint32_t num_total_sectors_32;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
grub_uint8_t num_ph_drive;
|
||||
grub_uint8_t reserved;
|
||||
grub_uint8_t boot_sig;
|
||||
grub_uint32_t num_serial;
|
||||
grub_uint8_t label[11];
|
||||
grub_uint8_t fstype[8];
|
||||
} __attribute__ ((packed)) fat12_or_fat16;
|
||||
struct
|
||||
{
|
||||
grub_uint32_t sectors_per_fat_32;
|
||||
grub_uint16_t extended_flags;
|
||||
grub_uint16_t fs_version;
|
||||
grub_uint32_t root_cluster;
|
||||
grub_uint16_t fs_info;
|
||||
grub_uint16_t backup_boot_sector;
|
||||
grub_uint8_t reserved[12];
|
||||
grub_uint8_t num_ph_drive;
|
||||
grub_uint8_t reserved1;
|
||||
grub_uint8_t boot_sig;
|
||||
grub_uint32_t num_serial;
|
||||
grub_uint8_t label[11];
|
||||
grub_uint8_t fstype[8];
|
||||
} __attribute__ ((packed)) fat32;
|
||||
} __attribute__ ((packed)) version_specific;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct grub_fat_dir_entry
|
||||
{
|
||||
grub_uint8_t name[11];
|
||||
|
|
|
@ -133,6 +133,8 @@ struct grub_hfs_dirrec
|
|||
grub_uint8_t type;
|
||||
grub_uint8_t unused[5];
|
||||
grub_uint32_t dirid;
|
||||
grub_uint32_t ctime;
|
||||
grub_uint32_t mtime;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Information about a file. */
|
||||
|
@ -144,7 +146,9 @@ struct grub_hfs_filerec
|
|||
grub_uint32_t fileid;
|
||||
grub_uint8_t unused2[2];
|
||||
grub_uint32_t size;
|
||||
grub_uint8_t unused3[44];
|
||||
grub_uint8_t unused3[18];
|
||||
grub_uint32_t mtime;
|
||||
grub_uint8_t unused4[22];
|
||||
|
||||
/* The first 3 extents of the file. The other extents can be found
|
||||
in the extent overflow file. */
|
||||
|
@ -953,19 +957,29 @@ grub_hfs_dir (grub_device_t device, const char *path,
|
|||
int dir_hook (struct grub_hfs_record *rec)
|
||||
{
|
||||
char fname[32] = { 0 };
|
||||
char *filetype = rec->data;
|
||||
struct grub_hfs_dirrec *drec = rec->data;
|
||||
struct grub_hfs_filerec *frec = rec->data;
|
||||
struct grub_hfs_catalog_key *ckey = rec->key;
|
||||
struct grub_dirhook_info info;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
|
||||
grub_strncpy (fname, (char *) (ckey->str), ckey->strlen);
|
||||
|
||||
if (*filetype == GRUB_HFS_FILETYPE_DIR
|
||||
|| *filetype == GRUB_HFS_FILETYPE_FILE)
|
||||
if (drec->type == GRUB_HFS_FILETYPE_DIR)
|
||||
{
|
||||
info.dir = (*filetype == GRUB_HFS_FILETYPE_DIR);
|
||||
info.dir = 1;
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_be_to_cpu32 (drec->mtime) - 2082844800;
|
||||
return hook (fname, &info);
|
||||
}
|
||||
if (frec->type == GRUB_HFS_FILETYPE_FILE)
|
||||
{
|
||||
info.dir = 0;
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_be_to_cpu32 (frec->mtime) - 2082844800;
|
||||
return hook (fname, &info);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1074,6 +1088,22 @@ grub_hfs_label (grub_device_t device, char **label)
|
|||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_hfs_mtime (grub_device_t device, grub_int32_t *tm)
|
||||
{
|
||||
struct grub_hfs_data *data;
|
||||
|
||||
data = grub_hfs_mount (device->disk);
|
||||
|
||||
if (data)
|
||||
*tm = grub_be_to_cpu32 (data->sblock.mtime) - 2082844800;
|
||||
else
|
||||
*tm = 0;
|
||||
|
||||
grub_free (data);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_hfs_uuid (grub_device_t device, char **uuid)
|
||||
{
|
||||
|
@ -1109,6 +1139,7 @@ static struct grub_fs grub_hfs_fs =
|
|||
.close = grub_hfs_close,
|
||||
.label = grub_hfs_label,
|
||||
.uuid = grub_hfs_uuid,
|
||||
.mtime = grub_hfs_mtime,
|
||||
.next = 0
|
||||
};
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <grub/types.h>
|
||||
#include <grub/fshelp.h>
|
||||
#include <grub/charset.h>
|
||||
#include <grub/datetime.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
|
@ -55,6 +56,17 @@ struct grub_iso9660_voldesc
|
|||
grub_uint8_t version;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct grub_iso9660_date2
|
||||
{
|
||||
grub_uint8_t year;
|
||||
grub_uint8_t month;
|
||||
grub_uint8_t day;
|
||||
grub_uint8_t hour;
|
||||
grub_uint8_t minute;
|
||||
grub_uint8_t second;
|
||||
grub_uint8_t offset;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* A directory entry. */
|
||||
struct grub_iso9660_dir
|
||||
{
|
||||
|
@ -64,7 +76,7 @@ struct grub_iso9660_dir
|
|||
grub_uint32_t first_sector_be;
|
||||
grub_uint32_t size;
|
||||
grub_uint32_t size_be;
|
||||
grub_uint8_t unused1[7];
|
||||
struct grub_iso9660_date2 mtime;
|
||||
grub_uint8_t flags;
|
||||
grub_uint8_t unused2[6];
|
||||
grub_uint8_t namelen;
|
||||
|
@ -146,6 +158,7 @@ struct grub_iso9660_data
|
|||
struct grub_fshelp_node
|
||||
{
|
||||
struct grub_iso9660_data *data;
|
||||
struct grub_iso9660_dir dirent;
|
||||
unsigned int size;
|
||||
unsigned int blk;
|
||||
unsigned int dir_blk;
|
||||
|
@ -155,6 +168,52 @@ struct grub_fshelp_node
|
|||
static grub_dl_t my_mod;
|
||||
|
||||
|
||||
static grub_err_t
|
||||
iso9660_to_unixtime (const struct grub_iso9660_date *i, grub_int32_t *nix)
|
||||
{
|
||||
struct grub_datetime datetime;
|
||||
|
||||
if (! i->year[0] && ! i->year[1]
|
||||
&& ! i->year[2] && ! i->year[3]
|
||||
&& ! i->month[0] && ! i->month[1]
|
||||
&& ! i->day[0] && ! i->day[1]
|
||||
&& ! i->hour[0] && ! i->hour[1]
|
||||
&& ! i->minute[0] && ! i->minute[1]
|
||||
&& ! i->second[0] && ! i->second[1]
|
||||
&& ! i->hundredth[0] && ! i->hundredth[1])
|
||||
return grub_error (GRUB_ERR_BAD_NUMBER, "empty date");
|
||||
datetime.year = (i->year[0] - '0') * 1000 + (i->year[1] - '0') * 100
|
||||
+ (i->year[2] - '0') * 10 + (i->year[3] - '0');
|
||||
datetime.month = (i->month[0] - '0') * 10 + (i->month[1] - '0');
|
||||
datetime.day = (i->day[0] - '0') * 10 + (i->day[1] - '0');
|
||||
datetime.hour = (i->hour[0] - '0') * 10 + (i->hour[1] - '0');
|
||||
datetime.minute = (i->minute[0] - '0') * 10 + (i->minute[1] - '0');
|
||||
datetime.second = (i->second[0] - '0') * 10 + (i->second[1] - '0');
|
||||
|
||||
if (!grub_datetime2unixtime (&datetime, nix))
|
||||
return grub_error (GRUB_ERR_BAD_NUMBER, "incorrect date");
|
||||
*nix -= i->offset * 60 * 15;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static int
|
||||
iso9660_to_unixtime2 (const struct grub_iso9660_date2 *i, grub_int32_t *nix)
|
||||
{
|
||||
struct grub_datetime datetime;
|
||||
|
||||
datetime.year = i->year + 1900;
|
||||
datetime.month = i->month;
|
||||
datetime.day = i->day;
|
||||
datetime.hour = i->hour;
|
||||
datetime.minute = i->minute;
|
||||
datetime.second = i->second;
|
||||
|
||||
if (!grub_datetime2unixtime (&datetime, nix))
|
||||
return 0;
|
||||
*nix -= i->offset * 60 * 15;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Iterate over the susp entries, starting with block SUA_BLOCK on the
|
||||
offset SUA_POS with a size of SUA_SIZE bytes. Hook is called for
|
||||
every entry. */
|
||||
|
@ -366,7 +425,6 @@ grub_iso9660_mount (grub_disk_t disk)
|
|||
static char *
|
||||
grub_iso9660_read_symlink (grub_fshelp_node_t node)
|
||||
{
|
||||
struct grub_iso9660_dir dirent;
|
||||
int sua_off;
|
||||
int sua_size;
|
||||
char *symlink = 0;
|
||||
|
@ -444,13 +502,10 @@ grub_iso9660_read_symlink (grub_fshelp_node_t node)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (grub_disk_read (node->data->disk, node->dir_blk, node->dir_off,
|
||||
sizeof (dirent), (char *) &dirent))
|
||||
return 0;
|
||||
|
||||
sua_off = (sizeof (dirent) + dirent.namelen + 1 - (dirent.namelen % 2)
|
||||
sua_off = (sizeof (node->dirent) + node->dirent.namelen + 1
|
||||
- (node->dirent.namelen % 2)
|
||||
+ node->data->susp_skip);
|
||||
sua_size = dirent.len - sua_off;
|
||||
sua_size = node->dirent.len - sua_off;
|
||||
|
||||
symlink = grub_malloc (1);
|
||||
if (!symlink)
|
||||
|
@ -647,6 +702,7 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
|
|||
filename_alloc = 1;
|
||||
}
|
||||
|
||||
node->dirent = dirent;
|
||||
if (hook (filename, type, node))
|
||||
{
|
||||
if (filename_alloc)
|
||||
|
@ -685,6 +741,8 @@ grub_iso9660_dir (grub_device_t device, const char *path,
|
|||
struct grub_dirhook_info info;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
info.mtimeset = !!iso9660_to_unixtime2 (&node->dirent.mtime, &info.mtime);
|
||||
|
||||
grub_free (node);
|
||||
return hook (filename, &info);
|
||||
}
|
||||
|
@ -882,6 +940,32 @@ grub_iso9660_uuid (grub_device_t device, char **uuid)
|
|||
return grub_errno;
|
||||
}
|
||||
|
||||
/* Get writing time of filesystem. */
|
||||
static grub_err_t
|
||||
grub_iso9660_mtime (grub_device_t device, grub_int32_t *timebuf)
|
||||
{
|
||||
struct grub_iso9660_data *data;
|
||||
grub_disk_t disk = device->disk;
|
||||
grub_err_t err;
|
||||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
data = grub_iso9660_mount (disk);
|
||||
if (!data)
|
||||
{
|
||||
grub_dl_unref (my_mod);
|
||||
return grub_errno;
|
||||
}
|
||||
err = iso9660_to_unixtime (&data->voldesc.modified, timebuf);
|
||||
|
||||
grub_dl_unref (my_mod);
|
||||
|
||||
grub_free (data);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static struct grub_fs grub_iso9660_fs =
|
||||
|
@ -893,6 +977,7 @@ static struct grub_fs grub_iso9660_fs =
|
|||
.close = grub_iso9660_close,
|
||||
.label = grub_iso9660_label,
|
||||
.uuid = grub_iso9660_uuid,
|
||||
.mtime = grub_iso9660_mtime,
|
||||
.next = 0
|
||||
};
|
||||
|
||||
|
|
|
@ -155,6 +155,12 @@ struct grub_jfs_leaf_next_dirent
|
|||
grub_uint16_t namepart[15];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct grub_jfs_time
|
||||
{
|
||||
grub_int32_t sec;
|
||||
grub_int32_t nanosec;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct grub_jfs_inode
|
||||
{
|
||||
grub_uint32_t stamp;
|
||||
|
@ -164,7 +170,10 @@ struct grub_jfs_inode
|
|||
grub_uint64_t size;
|
||||
grub_uint8_t unused2[20];
|
||||
grub_uint32_t mode;
|
||||
grub_uint8_t unused3[72];
|
||||
struct grub_jfs_time atime;
|
||||
struct grub_jfs_time ctime;
|
||||
struct grub_jfs_time mtime;
|
||||
grub_uint8_t unused3[48];
|
||||
grub_uint8_t unused4[96];
|
||||
|
||||
union
|
||||
|
@ -760,6 +769,8 @@ grub_jfs_dir (grub_device_t device, const char *path,
|
|||
|
||||
info.dir = (grub_le_to_cpu32 (inode.mode)
|
||||
& GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_DIR;
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_le_to_cpu32 (inode.mtime.sec);
|
||||
if (hook (diro->name, &info))
|
||||
goto fail;
|
||||
}
|
||||
|
|
|
@ -27,14 +27,17 @@
|
|||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
#ifdef MODE_MINIX2
|
||||
#ifdef MODE_MINIX3
|
||||
#define GRUB_MINIX_MAGIC 0x4D5A
|
||||
#elif defined(MODE_MINIX2)
|
||||
#define GRUB_MINIX_MAGIC 0x2468
|
||||
#define GRUB_MINIX_MAGIC_30 0x2478
|
||||
#else
|
||||
#define GRUB_MINIX_MAGIC 0x137F
|
||||
#define GRUB_MINIX_MAGIC_30 0x138F
|
||||
#endif
|
||||
#define GRUB_MINIX_BSIZE 1024U
|
||||
|
||||
#define GRUB_MINIX_INODE_DIR_BLOCKS 7
|
||||
#define GRUB_MINIX_LOG2_BSIZE 1
|
||||
#define GRUB_MINIX_ROOT_INODE 1
|
||||
#define GRUB_MINIX_MAX_SYMLNK_CNT 8
|
||||
|
@ -43,7 +46,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
|||
#define GRUB_MINIX_IFDIR 0040000U
|
||||
#define GRUB_MINIX_IFLNK 0120000U
|
||||
|
||||
#ifdef MODE_MINIX2
|
||||
#if defined(MODE_MINIX2) || defined(MODE_MINIX3)
|
||||
typedef grub_uint32_t grub_minix_uintn_t;
|
||||
#define grub_minix_le_to_cpu_n grub_le_to_cpu32
|
||||
#else
|
||||
|
@ -52,6 +55,13 @@ typedef grub_uint16_t grub_minix_uintn_t;
|
|||
#endif
|
||||
|
||||
#define GRUB_MINIX_INODE_BLKSZ(data) sizeof (grub_minix_uintn_t)
|
||||
#ifdef MODE_MINIX3
|
||||
typedef grub_uint32_t grub_minix_ino_t;
|
||||
#define grub_minix_le_to_cpu_ino grub_le_to_cpu32
|
||||
#else
|
||||
typedef grub_uint16_t grub_minix_ino_t;
|
||||
#define grub_minix_le_to_cpu_ino grub_le_to_cpu16
|
||||
#endif
|
||||
|
||||
#define GRUB_MINIX_INODE_SIZE(data) (grub_minix_le_to_cpu_n (data->inode.size))
|
||||
#define GRUB_MINIX_INODE_MODE(data) (grub_le_to_cpu16 (data->inode.mode))
|
||||
|
@ -62,11 +72,39 @@ typedef grub_uint16_t grub_minix_uintn_t;
|
|||
#define GRUB_MINIX_INODE_DINDIR_ZONE(data) (grub_minix_le_to_cpu_n \
|
||||
(data->inode.double_indir_zone))
|
||||
|
||||
#ifndef MODE_MINIX3
|
||||
#define GRUB_MINIX_LOG2_ZONESZ (GRUB_MINIX_LOG2_BSIZE \
|
||||
+ grub_le_to_cpu16 (sblock->log2_zone_size))
|
||||
#define GRUB_MINIX_ZONESZ (GRUB_MINIX_BSIZE \
|
||||
<< grub_le_to_cpu16 (sblock->log2_zone_size))
|
||||
+ grub_le_to_cpu16 (data->sblock.log2_zone_size))
|
||||
#endif
|
||||
#define GRUB_MINIX_ZONESZ (data->block_size \
|
||||
<< grub_le_to_cpu16 (data->sblock.log2_zone_size))
|
||||
|
||||
#ifdef MODE_MINIX3
|
||||
#define GRUB_MINIX_ZONE2SECT(zone) ((zone) * (data->block_size / GRUB_DISK_SECTOR_SIZE))
|
||||
#else
|
||||
#define GRUB_MINIX_ZONE2SECT(zone) ((zone) << GRUB_MINIX_LOG2_ZONESZ)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MODE_MINIX3
|
||||
struct grub_minix_sblock
|
||||
{
|
||||
grub_uint32_t inode_cnt;
|
||||
grub_uint16_t zone_cnt;
|
||||
grub_uint16_t inode_bmap_size;
|
||||
grub_uint16_t zone_bmap_size;
|
||||
grub_uint16_t first_data_zone;
|
||||
grub_uint16_t log2_zone_size;
|
||||
grub_uint16_t pad;
|
||||
grub_uint32_t max_file_size;
|
||||
grub_uint32_t zones;
|
||||
grub_uint16_t magic;
|
||||
|
||||
grub_uint16_t pad2;
|
||||
grub_uint16_t block_size;
|
||||
grub_uint8_t disk_version;
|
||||
};
|
||||
#else
|
||||
struct grub_minix_sblock
|
||||
{
|
||||
grub_uint16_t inode_cnt;
|
||||
|
@ -78,23 +116,9 @@ struct grub_minix_sblock
|
|||
grub_uint32_t max_file_size;
|
||||
grub_uint16_t magic;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef MODE_MINIX2
|
||||
struct grub_minix_inode
|
||||
{
|
||||
grub_uint16_t mode;
|
||||
grub_uint16_t uid;
|
||||
grub_uint16_t size;
|
||||
grub_uint32_t ctime;
|
||||
grub_uint8_t gid;
|
||||
grub_uint8_t nlinks;
|
||||
grub_uint16_t dir_zones[7];
|
||||
grub_uint16_t indir_zone;
|
||||
grub_uint16_t double_indir_zone;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#if defined(MODE_MINIX3) || defined(MODE_MINIX2)
|
||||
struct grub_minix_inode
|
||||
{
|
||||
grub_uint16_t mode;
|
||||
|
@ -111,6 +135,19 @@ struct grub_minix_inode
|
|||
grub_uint32_t unused;
|
||||
|
||||
};
|
||||
#else
|
||||
struct grub_minix_inode
|
||||
{
|
||||
grub_uint16_t mode;
|
||||
grub_uint16_t uid;
|
||||
grub_uint16_t size;
|
||||
grub_uint32_t ctime;
|
||||
grub_uint8_t gid;
|
||||
grub_uint8_t nlinks;
|
||||
grub_uint16_t dir_zones[7];
|
||||
grub_uint16_t indir_zone;
|
||||
grub_uint16_t double_indir_zone;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -123,6 +160,7 @@ struct grub_minix_data
|
|||
int linknest;
|
||||
grub_disk_t disk;
|
||||
int filename_size;
|
||||
grub_size_t block_size;
|
||||
};
|
||||
|
||||
static grub_dl_t my_mod;
|
||||
|
@ -133,7 +171,6 @@ static grub_err_t grub_minix_find_file (struct grub_minix_data *data,
|
|||
static int
|
||||
grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk)
|
||||
{
|
||||
struct grub_minix_sblock *sblock = &data->sblock;
|
||||
int indir;
|
||||
|
||||
auto int grub_get_indir (int, int);
|
||||
|
@ -143,18 +180,18 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk)
|
|||
{
|
||||
grub_minix_uintn_t indirn;
|
||||
grub_disk_read (data->disk,
|
||||
zone << GRUB_MINIX_LOG2_ZONESZ,
|
||||
GRUB_MINIX_ZONE2SECT(zone),
|
||||
sizeof (grub_minix_uintn_t) * num,
|
||||
sizeof (grub_minix_uintn_t), (char *) &indirn);
|
||||
return grub_minix_le_to_cpu_n (indirn);
|
||||
}
|
||||
|
||||
/* Direct block. */
|
||||
if (blk < 7)
|
||||
if (blk < GRUB_MINIX_INODE_DIR_BLOCKS)
|
||||
return GRUB_MINIX_INODE_DIR_ZONES (data, blk);
|
||||
|
||||
/* Indirect block. */
|
||||
blk -= 7;
|
||||
blk -= GRUB_MINIX_INODE_DIR_BLOCKS;
|
||||
if (blk < GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data))
|
||||
{
|
||||
indir = grub_get_indir (GRUB_MINIX_INODE_INDIR_ZONE (data), blk);
|
||||
|
@ -187,25 +224,26 @@ static grub_ssize_t
|
|||
grub_minix_read_file (struct grub_minix_data *data,
|
||||
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
|
||||
unsigned offset, unsigned length),
|
||||
int pos, grub_disk_addr_t len, char *buf)
|
||||
grub_off_t pos, grub_disk_addr_t len, char *buf)
|
||||
{
|
||||
struct grub_minix_sblock *sblock = &data->sblock;
|
||||
int i;
|
||||
int blockcnt;
|
||||
grub_disk_addr_t i;
|
||||
grub_disk_addr_t blockcnt;
|
||||
grub_uint64_t posblock;
|
||||
grub_uint64_t blockoff;
|
||||
|
||||
/* Adjust len so it we can't read past the end of the file. */
|
||||
if (len + pos > GRUB_MINIX_INODE_SIZE (data))
|
||||
len = GRUB_MINIX_INODE_SIZE (data) - pos;
|
||||
|
||||
blockcnt = (len + pos + GRUB_MINIX_BSIZE - 1) / GRUB_MINIX_BSIZE;
|
||||
blockcnt = grub_divmod64 ((len + pos + data->block_size - 1),
|
||||
data->block_size, 0);
|
||||
posblock = grub_divmod64 (pos, data->block_size, &blockoff);
|
||||
|
||||
for (i = pos / GRUB_MINIX_BSIZE; i < blockcnt; i++)
|
||||
for (i = posblock; i < blockcnt; i++)
|
||||
{
|
||||
int blknr;
|
||||
int blockoff = pos % GRUB_MINIX_BSIZE;
|
||||
int blockend = GRUB_MINIX_BSIZE;
|
||||
|
||||
int skipfirst = 0;
|
||||
grub_disk_addr_t blknr;
|
||||
grub_uint64_t blockend = data->block_size;
|
||||
grub_off_t skipfirst = 0;
|
||||
|
||||
blknr = grub_minix_get_file_block (data, i);
|
||||
if (grub_errno)
|
||||
|
@ -214,28 +252,28 @@ grub_minix_read_file (struct grub_minix_data *data,
|
|||
/* Last block. */
|
||||
if (i == blockcnt - 1)
|
||||
{
|
||||
blockend = (len + pos) % GRUB_MINIX_BSIZE;
|
||||
grub_divmod64 (len + pos, data->block_size, &blockend);
|
||||
|
||||
if (!blockend)
|
||||
blockend = GRUB_MINIX_BSIZE;
|
||||
blockend = data->block_size;
|
||||
}
|
||||
|
||||
/* First block. */
|
||||
if (i == (pos / (int) GRUB_MINIX_BSIZE))
|
||||
if (i == posblock)
|
||||
{
|
||||
skipfirst = blockoff;
|
||||
blockend -= skipfirst;
|
||||
}
|
||||
|
||||
data->disk->read_hook = read_hook;
|
||||
grub_disk_read (data->disk, blknr << GRUB_MINIX_LOG2_ZONESZ,
|
||||
grub_disk_read (data->disk,
|
||||
GRUB_MINIX_ZONE2SECT(blknr),
|
||||
skipfirst, blockend, buf);
|
||||
|
||||
data->disk->read_hook = 0;
|
||||
if (grub_errno)
|
||||
return -1;
|
||||
|
||||
buf += GRUB_MINIX_BSIZE - skipfirst;
|
||||
buf += data->block_size - skipfirst;
|
||||
}
|
||||
|
||||
return len;
|
||||
|
@ -250,16 +288,13 @@ grub_minix_read_inode (struct grub_minix_data *data, int ino)
|
|||
struct grub_minix_sblock *sblock = &data->sblock;
|
||||
|
||||
/* Block in which the inode is stored. */
|
||||
int block;
|
||||
grub_disk_addr_t block;
|
||||
data->ino = ino;
|
||||
|
||||
/* The first inode in minix is inode 1. */
|
||||
ino--;
|
||||
|
||||
block = ((2 + grub_le_to_cpu16 (sblock->inode_bmap_size)
|
||||
+ grub_le_to_cpu16 (sblock->zone_bmap_size))
|
||||
<< GRUB_MINIX_LOG2_BSIZE);
|
||||
|
||||
block = GRUB_MINIX_ZONE2SECT (2 + grub_le_to_cpu16 (sblock->inode_bmap_size)
|
||||
+ grub_le_to_cpu16 (sblock->zone_bmap_size));
|
||||
block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode));
|
||||
int offs = (ino % (GRUB_DISK_SECTOR_SIZE
|
||||
/ sizeof (struct grub_minix_inode))
|
||||
|
@ -335,7 +370,7 @@ grub_minix_find_file (struct grub_minix_data *data, const char *path)
|
|||
|
||||
do
|
||||
{
|
||||
grub_uint16_t ino;
|
||||
grub_minix_ino_t ino;
|
||||
char filename[data->filename_size + 1];
|
||||
|
||||
if (grub_strlen (name) == 0)
|
||||
|
@ -355,7 +390,7 @@ grub_minix_find_file (struct grub_minix_data *data, const char *path)
|
|||
if (!grub_strcmp (name, filename))
|
||||
{
|
||||
dirino = data->ino;
|
||||
grub_minix_read_inode (data, grub_le_to_cpu16 (ino));
|
||||
grub_minix_read_inode (data, grub_minix_le_to_cpu_ino (ino));
|
||||
|
||||
/* Follow the symlink. */
|
||||
if ((GRUB_MINIX_INODE_MODE (data)
|
||||
|
@ -411,20 +446,35 @@ grub_minix_mount (grub_disk_t disk)
|
|||
goto fail;
|
||||
|
||||
if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC)
|
||||
{
|
||||
#if !defined(MODE_MINIX3)
|
||||
data->filename_size = 14;
|
||||
#else
|
||||
data->filename_size = 60;
|
||||
#endif
|
||||
}
|
||||
#if !defined(MODE_MINIX3)
|
||||
else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC_30)
|
||||
data->filename_size = 30;
|
||||
#endif
|
||||
else
|
||||
goto fail;
|
||||
|
||||
data->disk = disk;
|
||||
data->linknest = 0;
|
||||
#ifdef MODE_MINIX3
|
||||
data->block_size = grub_le_to_cpu16 (data->sblock.block_size);
|
||||
#else
|
||||
data->block_size = 1024U;
|
||||
#endif
|
||||
|
||||
return data;
|
||||
|
||||
fail:
|
||||
grub_free (data);
|
||||
#ifdef MODE_MINIX2
|
||||
#if defined(MODE_MINIX3)
|
||||
grub_error (GRUB_ERR_BAD_FS, "not a minix3 filesystem");
|
||||
#elif defined(MODE_MINIX2)
|
||||
grub_error (GRUB_ERR_BAD_FS, "not a minix2 filesystem");
|
||||
#else
|
||||
grub_error (GRUB_ERR_BAD_FS, "not a minix filesystem");
|
||||
|
@ -460,7 +510,7 @@ grub_minix_dir (grub_device_t device, const char *path,
|
|||
|
||||
while (pos < GRUB_MINIX_INODE_SIZE (data))
|
||||
{
|
||||
grub_uint16_t ino;
|
||||
grub_minix_ino_t ino;
|
||||
char filename[data->filename_size + 1];
|
||||
int dirino = data->ino;
|
||||
struct grub_dirhook_info info;
|
||||
|
@ -476,12 +526,22 @@ grub_minix_dir (grub_device_t device, const char *path,
|
|||
(char *) filename) < 0)
|
||||
return grub_errno;
|
||||
filename[data->filename_size] = '\0';
|
||||
if (!ino)
|
||||
{
|
||||
pos += sizeof (ino) + data->filename_size;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* The filetype is not stored in the dirent. Read the inode to
|
||||
find out the filetype. This *REALLY* sucks. */
|
||||
grub_minix_read_inode (data, grub_le_to_cpu16 (ino));
|
||||
grub_minix_read_inode (data, grub_minix_le_to_cpu_ino (ino));
|
||||
info.dir = ((GRUB_MINIX_INODE_MODE (data)
|
||||
& GRUB_MINIX_IFDIR) == GRUB_MINIX_IFDIR);
|
||||
info.mtimeset = 1;
|
||||
#ifndef MODE_MINIX2
|
||||
info.mtime = grub_le_to_cpu32 (data->inode.ctime);
|
||||
#else
|
||||
info.mtime = grub_le_to_cpu32 (data->inode.mtime);
|
||||
#endif
|
||||
|
||||
if (hook (filename, &info) ? 1 : 0)
|
||||
break;
|
||||
|
||||
|
@ -558,7 +618,9 @@ grub_minix_close (grub_file_t file)
|
|||
|
||||
static struct grub_fs grub_minix_fs =
|
||||
{
|
||||
#ifdef MODE_MINIX2
|
||||
#if defined(MODE_MINIX3)
|
||||
.name = "minix3",
|
||||
#elif defined(MODE_MINIX2)
|
||||
.name = "minix2",
|
||||
#else
|
||||
.name = "minix",
|
||||
|
@ -570,7 +632,9 @@ static struct grub_fs grub_minix_fs =
|
|||
.next = 0
|
||||
};
|
||||
|
||||
#ifdef MODE_MINIX2
|
||||
#if defined(MODE_MINIX3)
|
||||
GRUB_MOD_INIT(minix3)
|
||||
#elif defined(MODE_MINIX2)
|
||||
GRUB_MOD_INIT(minix2)
|
||||
#else
|
||||
GRUB_MOD_INIT(minix)
|
||||
|
@ -580,7 +644,9 @@ GRUB_MOD_INIT(minix)
|
|||
my_mod = mod;
|
||||
}
|
||||
|
||||
#ifdef MODE_MINIX2
|
||||
#if defined(MODE_MINIX3)
|
||||
GRUB_MOD_FINI(minix3)
|
||||
#elif defined(MODE_MINIX2)
|
||||
GRUB_MOD_FINI(minix2)
|
||||
#else
|
||||
GRUB_MOD_FINI(minix)
|
||||
|
|
2
grub-core/fs/minix3.c
Normal file
2
grub-core/fs/minix3.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define MODE_MINIX3 1
|
||||
#include "minix.c"
|
|
@ -303,7 +303,7 @@ grub_nilfs2_palloc_entries_per_group (struct grub_nilfs2_data *data)
|
|||
|
||||
static inline grub_uint64_t
|
||||
grub_nilfs2_palloc_group (struct grub_nilfs2_data *data,
|
||||
grub_uint64_t nr, grub_uint32_t * offset)
|
||||
grub_uint64_t nr, grub_uint64_t * offset)
|
||||
{
|
||||
return grub_divmod64 (nr, grub_nilfs2_palloc_entries_per_group (data),
|
||||
offset);
|
||||
|
@ -368,13 +368,15 @@ grub_nilfs2_palloc_entry_offset (struct grub_nilfs2_data *data,
|
|||
grub_uint64_t nr, unsigned long entry_size)
|
||||
{
|
||||
unsigned long group;
|
||||
grub_uint32_t group_offset;
|
||||
grub_uint64_t group_offset;
|
||||
|
||||
group = grub_nilfs2_palloc_group (data, nr, &group_offset);
|
||||
|
||||
return grub_nilfs2_palloc_bitmap_block_offset (data, group,
|
||||
entry_size) + 1 +
|
||||
group_offset / grub_nilfs2_entries_per_block (data, entry_size);
|
||||
grub_divmod64 (group_offset, grub_nilfs2_entries_per_block (data,
|
||||
entry_size),
|
||||
NULL);
|
||||
|
||||
}
|
||||
|
||||
|
@ -577,7 +579,7 @@ grub_nilfs2_dat_translate (struct grub_nilfs2_data *data, grub_uint64_t key)
|
|||
struct grub_nilfs2_dat_entry entry;
|
||||
grub_disk_t disk = data->disk;
|
||||
grub_uint64_t pptr;
|
||||
grub_uint32_t blockno, offset;
|
||||
grub_uint64_t blockno, offset;
|
||||
unsigned int nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data));
|
||||
|
||||
blockno = grub_nilfs2_palloc_entry_offset (data, key,
|
||||
|
@ -641,7 +643,7 @@ grub_nilfs2_read_checkpoint (struct grub_nilfs2_data *data,
|
|||
struct grub_nilfs2_checkpoint *cpp)
|
||||
{
|
||||
grub_uint64_t blockno;
|
||||
grub_uint32_t offset;
|
||||
grub_uint64_t offset;
|
||||
grub_uint64_t pptr;
|
||||
grub_disk_t disk = data->disk;
|
||||
unsigned int nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data));
|
||||
|
@ -679,7 +681,7 @@ grub_nilfs2_read_inode (struct grub_nilfs2_data *data,
|
|||
grub_uint64_t ino, struct grub_nilfs2_inode *inodep)
|
||||
{
|
||||
grub_uint64_t blockno;
|
||||
unsigned int offset;
|
||||
grub_uint64_t offset;
|
||||
grub_uint64_t pptr;
|
||||
grub_disk_t disk = data->disk;
|
||||
unsigned int nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data));
|
||||
|
|
|
@ -431,7 +431,7 @@ read_data (struct grub_ntfs_attr *at, char *pa, char *dest,
|
|||
if (at->flags & AF_GPOS)
|
||||
{
|
||||
grub_disk_addr_t st0, st1;
|
||||
grub_uint32_t m;
|
||||
grub_uint64_t m;
|
||||
|
||||
grub_divmod64 (ofs >> BLK_SHR, ctx->comp.spc, &m);
|
||||
|
||||
|
@ -612,6 +612,10 @@ list_file (struct grub_ntfs_file *diro, char *pos,
|
|||
|
||||
fdiro->data = diro->data;
|
||||
fdiro->ino = u32at (pos, 0);
|
||||
if (u64at (pos, 0x20) > u64at (pos, 0x28))
|
||||
fdiro->mtime = u64at (pos, 0x20);
|
||||
else
|
||||
fdiro->mtime = u64at (pos, 0x28);
|
||||
|
||||
ustr = grub_malloc (ns * 4 + 1);
|
||||
if (ustr == NULL)
|
||||
|
@ -882,6 +886,10 @@ grub_ntfs_dir (grub_device_t device, const char *path,
|
|||
struct grub_dirhook_info info;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_divmod64 (node->mtime, 10000000, 0)
|
||||
- 86400ULL * 365 * (1970 - 1601)
|
||||
- 86400ULL * ((1970 - 1601) / 4) + 86400ULL * ((1970 - 1601) / 100);
|
||||
grub_free (node);
|
||||
return hook (filename, &info);
|
||||
}
|
||||
|
|
|
@ -224,6 +224,7 @@ struct grub_fshelp_node
|
|||
grub_uint32_t block_number; /* 0 if node is not found. */
|
||||
grub_uint16_t block_position;
|
||||
grub_uint64_t next_offset;
|
||||
grub_int32_t mtime;
|
||||
enum grub_reiserfs_item_type type; /* To know how to read the header. */
|
||||
struct grub_reiserfs_item_header header;
|
||||
};
|
||||
|
@ -870,6 +871,7 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item,
|
|||
entry_v1_stat.rdev,
|
||||
entry_v1_stat.first_direct_byte);
|
||||
#endif
|
||||
entry_item->mtime = grub_le_to_cpu32 (entry_v1_stat.mtime);
|
||||
if ((grub_le_to_cpu16 (entry_v1_stat.mode) & S_IFLNK)
|
||||
== S_IFLNK)
|
||||
entry_type = GRUB_FSHELP_SYMLINK;
|
||||
|
@ -916,6 +918,7 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item,
|
|||
entry_v2_stat.blocks,
|
||||
entry_v2_stat.first_direct_byte);
|
||||
#endif
|
||||
entry_item->mtime = grub_le_to_cpu32 (entry_v2_stat.mtime);
|
||||
if ((grub_le_to_cpu16 (entry_v2_stat.mode) & S_IFLNK)
|
||||
== S_IFLNK)
|
||||
entry_type = GRUB_FSHELP_SYMLINK;
|
||||
|
@ -1278,6 +1281,8 @@ grub_reiserfs_dir (grub_device_t device, const char *path,
|
|||
struct grub_dirhook_info info;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
info.mtimeset = 1;
|
||||
info.mtime = node->mtime;
|
||||
grub_free (node);
|
||||
return hook (filename, &info);
|
||||
}
|
||||
|
|
458
grub-core/fs/romfs.c
Normal file
458
grub-core/fs/romfs.c
Normal file
|
@ -0,0 +1,458 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/file.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/fs.h>
|
||||
#include <grub/fshelp.h>
|
||||
|
||||
struct grub_romfs_superblock
|
||||
{
|
||||
char magic[8];
|
||||
#define GRUB_ROMFS_MAGIC "-rom1fs-"
|
||||
grub_uint32_t total_size;
|
||||
grub_uint32_t chksum;
|
||||
char label[0];
|
||||
};
|
||||
|
||||
struct grub_romfs_file_header
|
||||
{
|
||||
grub_uint32_t next_file;
|
||||
grub_uint32_t spec;
|
||||
grub_uint32_t size;
|
||||
grub_uint32_t chksum;
|
||||
char name[0];
|
||||
};
|
||||
|
||||
struct grub_romfs_data
|
||||
{
|
||||
grub_disk_addr_t first_file;
|
||||
grub_disk_t disk;
|
||||
};
|
||||
|
||||
struct grub_fshelp_node
|
||||
{
|
||||
grub_disk_addr_t addr;
|
||||
struct grub_romfs_data *data;
|
||||
grub_disk_addr_t data_addr;
|
||||
/* Not filled for root. */
|
||||
struct grub_romfs_file_header file;
|
||||
};
|
||||
|
||||
#define GRUB_ROMFS_ALIGN 16
|
||||
#define GRUB_ROMFS_TYPE_MASK 7
|
||||
#define GRUB_ROMFS_TYPE_HARDLINK 0
|
||||
#define GRUB_ROMFS_TYPE_DIRECTORY 1
|
||||
#define GRUB_ROMFS_TYPE_REGULAR 2
|
||||
#define GRUB_ROMFS_TYPE_SYMLINK 3
|
||||
|
||||
static grub_err_t
|
||||
do_checksum (void *in, grub_size_t insize)
|
||||
{
|
||||
grub_uint32_t *a = in;
|
||||
grub_size_t sz = insize / 4;
|
||||
grub_uint32_t *b = a + sz;
|
||||
grub_uint32_t csum = 0;
|
||||
|
||||
while (a < b)
|
||||
csum += grub_be_to_cpu32 (*a++);
|
||||
if (csum)
|
||||
return grub_error (GRUB_ERR_BAD_FS, "invalid checksum");
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static struct grub_romfs_data *
|
||||
grub_romfs_mount (grub_device_t dev)
|
||||
{
|
||||
union {
|
||||
struct grub_romfs_superblock sb;
|
||||
char d[512];
|
||||
} sb;
|
||||
grub_err_t err;
|
||||
char *ptr;
|
||||
grub_disk_addr_t sec = 0;
|
||||
struct grub_romfs_data *data;
|
||||
if (!dev->disk)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FS, "not a disk");
|
||||
return NULL;
|
||||
}
|
||||
err = grub_disk_read (dev->disk, 0, 0, sizeof (sb), &sb);
|
||||
if (err == GRUB_ERR_OUT_OF_RANGE)
|
||||
err = grub_errno = GRUB_ERR_BAD_FS;
|
||||
if (err)
|
||||
return NULL;
|
||||
if (grub_be_to_cpu32 (sb.sb.total_size) < sizeof (sb))
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FS, "too short filesystem");
|
||||
return NULL;
|
||||
}
|
||||
err = do_checksum (&sb, sizeof (sb) < grub_be_to_cpu32 (sb.sb.total_size) ?
|
||||
sizeof (sb) : grub_be_to_cpu32 (sb.sb.total_size));
|
||||
if (err)
|
||||
return NULL;
|
||||
for (ptr = sb.sb.label; (void *) ptr < (void *) (&sb + 1)
|
||||
&& ptr < sb.d + grub_be_to_cpu32 (sb.sb.total_size); ptr++)
|
||||
if (!*ptr)
|
||||
break;
|
||||
if ((void *) ptr == &sb + 1)
|
||||
for (sec++; ; sec++)
|
||||
{
|
||||
err = grub_disk_read (dev->disk, sec, 0, sizeof (sb), &sb);
|
||||
if (err == GRUB_ERR_OUT_OF_RANGE)
|
||||
err = grub_errno = GRUB_ERR_BAD_FS;
|
||||
if (err)
|
||||
return NULL;
|
||||
for (ptr = sb.d; (void *) ptr < (void *) (&sb + 1)
|
||||
&& ptr < sb.d + grub_be_to_cpu32 (sb.sb.total_size); ptr++)
|
||||
if (!*ptr)
|
||||
break;
|
||||
}
|
||||
data = grub_malloc (sizeof (*data));
|
||||
if (!data)
|
||||
return NULL;
|
||||
data->first_file = ALIGN_UP (ptr - sb.d, GRUB_ROMFS_ALIGN) + sec * 512;
|
||||
data->disk = dev->disk;
|
||||
return data;
|
||||
}
|
||||
|
||||
static char *
|
||||
grub_romfs_read_symlink (grub_fshelp_node_t node)
|
||||
{
|
||||
char *ret;
|
||||
grub_err_t err;
|
||||
ret = grub_malloc (grub_be_to_cpu32 (node->file.size) + 1);
|
||||
if (!ret)
|
||||
return NULL;
|
||||
err = grub_disk_read (node->data->disk,
|
||||
(node->data_addr) >> GRUB_DISK_SECTOR_BITS,
|
||||
(node->data_addr) & (GRUB_DISK_SECTOR_SIZE - 1),
|
||||
grub_be_to_cpu32 (node->file.size), ret);
|
||||
if (err)
|
||||
{
|
||||
grub_free (ret);
|
||||
return NULL;
|
||||
}
|
||||
ret[grub_be_to_cpu32 (node->file.size)] = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_romfs_iterate_dir (grub_fshelp_node_t dir,
|
||||
int NESTED_FUNC_ATTR
|
||||
(*hook) (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node))
|
||||
{
|
||||
grub_disk_addr_t caddr;
|
||||
struct grub_romfs_file_header hdr;
|
||||
grub_size_t a = 0;
|
||||
char *name = NULL;
|
||||
unsigned nptr;
|
||||
unsigned i, j;
|
||||
for (caddr = dir->data_addr; caddr;
|
||||
caddr = grub_be_to_cpu32 (hdr.next_file) & ~(GRUB_ROMFS_ALIGN - 1))
|
||||
{
|
||||
grub_disk_addr_t naddr = caddr + sizeof (hdr);
|
||||
grub_uint32_t csum = 0;
|
||||
enum grub_fshelp_filetype filetype = GRUB_FSHELP_UNKNOWN;
|
||||
struct grub_fshelp_node *node;
|
||||
grub_err_t err;
|
||||
|
||||
err = grub_disk_read (dir->data->disk, caddr >> GRUB_DISK_SECTOR_BITS,
|
||||
caddr & (GRUB_DISK_SECTOR_SIZE - 1),
|
||||
sizeof (hdr), &hdr);
|
||||
if (err)
|
||||
{
|
||||
grub_free (name);
|
||||
return 1;
|
||||
}
|
||||
for (nptr = 0; ; nptr++, naddr += 16)
|
||||
{
|
||||
if (a >= nptr)
|
||||
{
|
||||
char *on;
|
||||
a = 2 * (nptr + 1);
|
||||
on = name;
|
||||
name = grub_realloc (name, a * 16);
|
||||
if (!name)
|
||||
{
|
||||
grub_free (on);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
err = grub_disk_read (dir->data->disk, naddr >> GRUB_DISK_SECTOR_BITS,
|
||||
naddr & (GRUB_DISK_SECTOR_SIZE - 1),
|
||||
16, name + 16 * nptr);
|
||||
if (err)
|
||||
return 1;
|
||||
for (j = 0; j < 16; j++)
|
||||
if (!name[16 * nptr + j])
|
||||
break;
|
||||
if (j != 16)
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < sizeof (hdr) / sizeof (grub_uint32_t); i++)
|
||||
csum += grub_be_to_cpu32 (((grub_uint32_t *) &hdr)[i]);
|
||||
for (i = 0; i < (nptr + 1) * 4; i++)
|
||||
csum += grub_be_to_cpu32 (((grub_uint32_t *) name)[i]);
|
||||
if (csum != 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FS, "invalid checksum");
|
||||
grub_free (name);
|
||||
return 1;
|
||||
}
|
||||
node = grub_malloc (sizeof (*node));
|
||||
if (!node)
|
||||
return 1;
|
||||
node->addr = caddr;
|
||||
node->data_addr = caddr + (nptr + 1) * 16 + sizeof (hdr);
|
||||
node->data = dir->data;
|
||||
node->file = hdr;
|
||||
switch (grub_be_to_cpu32 (hdr.next_file) & GRUB_ROMFS_TYPE_MASK)
|
||||
{
|
||||
case GRUB_ROMFS_TYPE_REGULAR:
|
||||
filetype = GRUB_FSHELP_REG;
|
||||
break;
|
||||
case GRUB_ROMFS_TYPE_SYMLINK:
|
||||
filetype = GRUB_FSHELP_SYMLINK;
|
||||
break;
|
||||
case GRUB_ROMFS_TYPE_DIRECTORY:
|
||||
node->data_addr = grub_be_to_cpu32 (hdr.spec);
|
||||
filetype = GRUB_FSHELP_DIR;
|
||||
break;
|
||||
case GRUB_ROMFS_TYPE_HARDLINK:
|
||||
{
|
||||
grub_disk_addr_t laddr;
|
||||
node->addr = laddr = grub_be_to_cpu32 (hdr.spec);
|
||||
err = grub_disk_read (dir->data->disk,
|
||||
laddr >> GRUB_DISK_SECTOR_BITS,
|
||||
laddr & (GRUB_DISK_SECTOR_SIZE - 1),
|
||||
sizeof (node->file), &node->file);
|
||||
if (err)
|
||||
return 1;
|
||||
if ((grub_be_to_cpu32 (node->file.next_file) & GRUB_ROMFS_TYPE_MASK)
|
||||
== GRUB_ROMFS_TYPE_REGULAR
|
||||
|| (grub_be_to_cpu32 (node->file.next_file)
|
||||
& GRUB_ROMFS_TYPE_MASK) == GRUB_ROMFS_TYPE_SYMLINK)
|
||||
{
|
||||
laddr += sizeof (hdr);
|
||||
while (1)
|
||||
{
|
||||
char buf[16];
|
||||
err = grub_disk_read (dir->data->disk,
|
||||
laddr >> GRUB_DISK_SECTOR_BITS,
|
||||
laddr & (GRUB_DISK_SECTOR_SIZE - 1),
|
||||
16, buf);
|
||||
if (err)
|
||||
return 1;
|
||||
for (i = 0; i < 16; i++)
|
||||
if (!buf[i])
|
||||
break;
|
||||
if (i != 16)
|
||||
break;
|
||||
laddr += 16;
|
||||
}
|
||||
node->data_addr = laddr + 16;
|
||||
}
|
||||
if ((grub_be_to_cpu32 (node->file.next_file)
|
||||
& GRUB_ROMFS_TYPE_MASK) == GRUB_ROMFS_TYPE_REGULAR)
|
||||
filetype = GRUB_FSHELP_REG;
|
||||
if ((grub_be_to_cpu32 (node->file.next_file)
|
||||
& GRUB_ROMFS_TYPE_MASK) == GRUB_ROMFS_TYPE_SYMLINK)
|
||||
filetype = GRUB_FSHELP_SYMLINK;
|
||||
if ((grub_be_to_cpu32 (node->file.next_file) & GRUB_ROMFS_TYPE_MASK)
|
||||
== GRUB_ROMFS_TYPE_DIRECTORY)
|
||||
{
|
||||
node->data_addr = grub_be_to_cpu32 (node->file.spec);
|
||||
filetype = GRUB_FSHELP_DIR;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hook (name, filetype, node))
|
||||
{
|
||||
grub_free (name);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
grub_free (name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_romfs_dir (grub_device_t device, const char *path,
|
||||
int (*hook) (const char *filename,
|
||||
const struct grub_dirhook_info *info))
|
||||
{
|
||||
struct grub_romfs_data *data = 0;
|
||||
struct grub_fshelp_node *fdiro = 0, start;
|
||||
|
||||
auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node);
|
||||
|
||||
int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node)
|
||||
{
|
||||
struct grub_dirhook_info info;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
grub_free (node);
|
||||
return hook (filename, &info);
|
||||
}
|
||||
|
||||
data = grub_romfs_mount (device);
|
||||
if (! data)
|
||||
goto fail;
|
||||
|
||||
start.addr = data->first_file;
|
||||
start.data_addr = data->first_file;
|
||||
start.data = data;
|
||||
grub_fshelp_find_file (path, &start, &fdiro, grub_romfs_iterate_dir,
|
||||
grub_romfs_read_symlink, GRUB_FSHELP_DIR);
|
||||
if (grub_errno)
|
||||
goto fail;
|
||||
|
||||
grub_romfs_iterate_dir (fdiro, iterate);
|
||||
|
||||
fail:
|
||||
grub_free (data);
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_romfs_open (struct grub_file *file, const char *name)
|
||||
{
|
||||
struct grub_romfs_data *data = 0;
|
||||
struct grub_fshelp_node *fdiro = 0, start;
|
||||
|
||||
data = grub_romfs_mount (file->device);
|
||||
if (! data)
|
||||
goto fail;
|
||||
|
||||
start.addr = data->first_file;
|
||||
start.data_addr = data->first_file;
|
||||
start.data = data;
|
||||
|
||||
grub_fshelp_find_file (name, &start, &fdiro, grub_romfs_iterate_dir,
|
||||
grub_romfs_read_symlink, GRUB_FSHELP_REG);
|
||||
if (grub_errno)
|
||||
goto fail;
|
||||
|
||||
file->size = grub_be_to_cpu32 (fdiro->file.size);
|
||||
file->data = fdiro;
|
||||
|
||||
fail:
|
||||
grub_free (data);
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_ssize_t
|
||||
grub_romfs_read (grub_file_t file, char *buf, grub_size_t len)
|
||||
{
|
||||
struct grub_fshelp_node *data = file->data;
|
||||
|
||||
/* XXX: The file is stored in as a single extent. */
|
||||
data->data->disk->read_hook = file->read_hook;
|
||||
grub_disk_read (data->data->disk,
|
||||
(data->data_addr + file->offset) >> GRUB_DISK_SECTOR_BITS,
|
||||
(data->data_addr + file->offset) & (GRUB_DISK_SECTOR_SIZE - 1),
|
||||
len, buf);
|
||||
data->data->disk->read_hook = NULL;
|
||||
|
||||
if (grub_errno)
|
||||
return -1;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_romfs_close (grub_file_t file)
|
||||
{
|
||||
grub_free (file->data);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_romfs_label (grub_device_t device, char **label)
|
||||
{
|
||||
struct grub_romfs_data *data;
|
||||
grub_err_t err;
|
||||
|
||||
*label = NULL;
|
||||
|
||||
data = grub_romfs_mount (device);
|
||||
if (!data)
|
||||
return grub_errno;
|
||||
*label = grub_malloc (data->first_file + 1
|
||||
- sizeof (struct grub_romfs_superblock));
|
||||
if (!*label)
|
||||
{
|
||||
grub_free (data);
|
||||
return grub_errno;
|
||||
}
|
||||
err = grub_disk_read (device->disk, 0, sizeof (struct grub_romfs_superblock),
|
||||
data->first_file
|
||||
- sizeof (struct grub_romfs_superblock),
|
||||
*label);
|
||||
if (err)
|
||||
{
|
||||
grub_free (data);
|
||||
grub_free (*label);
|
||||
*label = NULL;
|
||||
return err;
|
||||
}
|
||||
(*label)[data->first_file - sizeof (struct grub_romfs_superblock)] = 0;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
||||
static struct grub_fs grub_romfs_fs =
|
||||
{
|
||||
.name = "romfs",
|
||||
.dir = grub_romfs_dir,
|
||||
.open = grub_romfs_open,
|
||||
.read = grub_romfs_read,
|
||||
.close = grub_romfs_close,
|
||||
.label = grub_romfs_label,
|
||||
#ifdef GRUB_UTIL
|
||||
.reserved_first_sector = 0,
|
||||
#endif
|
||||
.next = 0
|
||||
};
|
||||
|
||||
GRUB_MOD_INIT(romfs)
|
||||
{
|
||||
grub_fs_register (&grub_romfs_fs);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(romfs)
|
||||
{
|
||||
grub_fs_unregister (&grub_romfs_fs);
|
||||
}
|
|
@ -68,7 +68,7 @@ struct grub_sfs_obj
|
|||
grub_uint32_t dir_objc;
|
||||
} dir __attribute__ ((packed));
|
||||
} file_dir;
|
||||
grub_uint8_t unused3[4];
|
||||
grub_uint32_t mtime;
|
||||
grub_uint8_t type;
|
||||
grub_uint8_t filename[1];
|
||||
grub_uint8_t comment[1];
|
||||
|
@ -121,6 +121,7 @@ struct grub_fshelp_node
|
|||
struct grub_sfs_data *data;
|
||||
int block;
|
||||
int size;
|
||||
grub_uint32_t mtime;
|
||||
};
|
||||
|
||||
/* Information about a "mounted" sfs filesystem. */
|
||||
|
@ -357,10 +358,12 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
int pos;
|
||||
|
||||
auto int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name, int block,
|
||||
int size, int type);
|
||||
int size, int type,
|
||||
grub_uint32_t mtime);
|
||||
|
||||
int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name, int block,
|
||||
int size, int type)
|
||||
int size, int type,
|
||||
grub_uint32_t mtime)
|
||||
{
|
||||
node = grub_malloc (sizeof (*node));
|
||||
if (!node)
|
||||
|
@ -369,6 +372,7 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
node->data = data;
|
||||
node->size = size;
|
||||
node->block = block;
|
||||
node->mtime = mtime;
|
||||
|
||||
return hook (name, type, node);
|
||||
}
|
||||
|
@ -428,7 +432,7 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
||||
if (grub_sfs_create_node (filename, block,
|
||||
grub_be_to_cpu32 (obj->file_dir.file.size),
|
||||
type))
|
||||
type, grub_be_to_cpu32 (obj->mtime)))
|
||||
{
|
||||
grub_free (objc_data);
|
||||
return 1;
|
||||
|
@ -527,6 +531,8 @@ grub_sfs_dir (grub_device_t device, const char *path,
|
|||
struct grub_dirhook_info info;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
info.mtime = node->mtime + 8 * 365 * 86400 + 86400 * 2;
|
||||
info.mtimeset = 1;
|
||||
grub_free (node);
|
||||
return hook (filename, &info);
|
||||
}
|
||||
|
|
548
grub-core/fs/squash4.c
Normal file
548
grub-core/fs/squash4.c
Normal file
|
@ -0,0 +1,548 @@
|
|||
/* squash4.c - SquashFS */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/err.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/fshelp.h>
|
||||
#include <grub/deflate.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
/*
|
||||
object format Pointed by
|
||||
superblock RAW Fixed offset (0)
|
||||
data RAW ? Fixed offset (60)
|
||||
inode table Chunk superblock
|
||||
dir table Chunk superblock
|
||||
fragment table Chunk unk1
|
||||
unk1 RAW, Chunk superblock
|
||||
unk2 RAW superblock
|
||||
UID/GID Chunk exttblptr
|
||||
exttblptr RAW superblock
|
||||
|
||||
UID/GID table is the array ot uint32_t
|
||||
unk1 contains pointer to unk3 followed by some chunk.
|
||||
unk2 containts one uint64_t
|
||||
*/
|
||||
|
||||
struct grub_squash_super
|
||||
{
|
||||
grub_uint32_t magic;
|
||||
#define SQUASH_MAGIC 0x73717368
|
||||
grub_uint32_t dummy1;
|
||||
grub_uint32_t creation_time;
|
||||
grub_uint32_t dummy2;
|
||||
grub_uint64_t dummy3;
|
||||
grub_uint8_t flags;
|
||||
#define SQUASH_FLAG_UNCOMPRESSED_INODES 1
|
||||
#define SQUASH_FLAG_UNCOMPRESSED_DATA 2
|
||||
#define SQUASH_FLAG_UNCOMPRESSED_FRAGMENTS 8
|
||||
grub_uint8_t dummy4[7];
|
||||
grub_uint16_t root_ino_offset;
|
||||
grub_uint32_t root_ino_chunk;
|
||||
grub_uint16_t dummy5;
|
||||
grub_uint64_t total_size;
|
||||
grub_uint64_t exttbloffset;
|
||||
grub_uint64_t dummy6;
|
||||
grub_uint64_t inodeoffset;
|
||||
grub_uint64_t diroffset;
|
||||
grub_uint64_t unk1offset;
|
||||
grub_uint64_t unk2offset;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/* Chunk-based */
|
||||
struct grub_squash_inode
|
||||
{
|
||||
/* Same values as direlem types. */
|
||||
grub_uint16_t type;
|
||||
grub_uint16_t dummy[3];
|
||||
grub_uint32_t mtime;
|
||||
union
|
||||
{
|
||||
struct {
|
||||
grub_uint32_t dummy;
|
||||
grub_uint32_t chunk;
|
||||
grub_uint32_t fragment;
|
||||
grub_uint32_t offset;
|
||||
grub_uint32_t size;
|
||||
} __attribute__ ((packed)) file;
|
||||
struct {
|
||||
grub_uint32_t dummy1;
|
||||
grub_uint32_t chunk;
|
||||
grub_uint32_t dummy2;
|
||||
grub_uint16_t size;
|
||||
grub_uint32_t offset;
|
||||
grub_uint16_t dummy3;
|
||||
} __attribute__ ((packed)) dir;
|
||||
struct {
|
||||
grub_uint64_t dummy;
|
||||
grub_uint32_t namelen;
|
||||
char name[0];
|
||||
} __attribute__ ((packed)) symlink;
|
||||
} __attribute__ ((packed));
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Chunk-based. */
|
||||
struct grub_squash_dirent_header
|
||||
{
|
||||
/* Actually the value is the number of elements - 1. */
|
||||
grub_uint32_t nelems;
|
||||
grub_uint64_t ino_chunk;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct grub_squash_dirent
|
||||
{
|
||||
grub_uint16_t ino_offset;
|
||||
grub_uint16_t dummy;
|
||||
grub_uint16_t type;
|
||||
#define SQUASH_TYPE_DIR 1
|
||||
#define SQUASH_TYPE_REGULAR 2
|
||||
#define SQUASH_TYPE_SYMLINK 3
|
||||
/* Actually the value is the length of name - 1. */
|
||||
grub_uint16_t namelen;
|
||||
char name[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct grub_squash_frag_desc
|
||||
{
|
||||
grub_uint64_t offset;
|
||||
grub_uint64_t dummy;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define SQUASH_CHUNK_SIZE 0x2000
|
||||
#define SQUASH_CHUNK_FLAGS 0x8000
|
||||
#define SQUASH_CHUNK_UNCOMPRESSED 0x8000
|
||||
|
||||
struct grub_squash_data
|
||||
{
|
||||
grub_disk_t disk;
|
||||
struct grub_squash_super sb;
|
||||
struct grub_squash_inode ino;
|
||||
grub_uint64_t fragments;
|
||||
};
|
||||
|
||||
struct grub_fshelp_node
|
||||
{
|
||||
struct grub_squash_data *data;
|
||||
struct grub_squash_inode ino;
|
||||
grub_uint32_t ino_chunk;
|
||||
grub_uint16_t ino_offset;
|
||||
};
|
||||
|
||||
static grub_err_t
|
||||
read_chunk (grub_disk_t disk, void *buf, grub_size_t len,
|
||||
grub_uint64_t chunk, grub_off_t offset)
|
||||
{
|
||||
grub_uint64_t chunk_start;
|
||||
chunk_start = grub_le_to_cpu64 (chunk);
|
||||
while (len > 0)
|
||||
{
|
||||
grub_uint64_t csize;
|
||||
grub_uint16_t d;
|
||||
grub_err_t err;
|
||||
while (1)
|
||||
{
|
||||
err = grub_disk_read (disk, chunk_start >> GRUB_DISK_SECTOR_BITS,
|
||||
chunk_start & (GRUB_DISK_SECTOR_SIZE - 1),
|
||||
sizeof (d), &d);
|
||||
if (err)
|
||||
return err;
|
||||
if (offset < SQUASH_CHUNK_SIZE)
|
||||
break;
|
||||
offset -= SQUASH_CHUNK_SIZE;
|
||||
chunk_start += 2 + (grub_le_to_cpu16 (d) & ~SQUASH_CHUNK_FLAGS);
|
||||
}
|
||||
|
||||
csize = SQUASH_CHUNK_SIZE - offset;
|
||||
if (csize > len)
|
||||
csize = len;
|
||||
|
||||
if (grub_le_to_cpu16 (d) & SQUASH_CHUNK_UNCOMPRESSED)
|
||||
{
|
||||
grub_disk_addr_t a = chunk_start + 2 + offset;
|
||||
err = grub_disk_read (disk, (a >> GRUB_DISK_SECTOR_BITS),
|
||||
a & (GRUB_DISK_SECTOR_SIZE - 1),
|
||||
csize, buf);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *tmp;
|
||||
grub_size_t bsize = grub_le_to_cpu16 (d) & ~SQUASH_CHUNK_FLAGS;
|
||||
grub_disk_addr_t a = chunk_start + 2;
|
||||
tmp = grub_malloc (bsize);
|
||||
if (!tmp)
|
||||
return grub_errno;
|
||||
/* FIXME: buffer uncompressed data. */
|
||||
err = grub_disk_read (disk, (a >> GRUB_DISK_SECTOR_BITS),
|
||||
a & (GRUB_DISK_SECTOR_SIZE - 1),
|
||||
bsize, tmp);
|
||||
if (err)
|
||||
{
|
||||
grub_free (tmp);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (grub_zlib_decompress (tmp, bsize, offset,
|
||||
buf, csize) < 0)
|
||||
{
|
||||
grub_free (tmp);
|
||||
return grub_errno;
|
||||
}
|
||||
grub_free (tmp);
|
||||
}
|
||||
len -= csize;
|
||||
offset += csize;
|
||||
buf = (char *) buf + csize;
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static struct grub_squash_data *
|
||||
squash_mount (grub_disk_t disk)
|
||||
{
|
||||
struct grub_squash_super sb;
|
||||
grub_err_t err;
|
||||
struct grub_squash_data *data;
|
||||
grub_uint64_t frag;
|
||||
|
||||
err = grub_disk_read (disk, 0, 0, sizeof (sb), &sb);
|
||||
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
|
||||
grub_error (GRUB_ERR_BAD_FS, "not a squash4");
|
||||
if (err)
|
||||
return NULL;
|
||||
if (grub_le_to_cpu32 (sb.magic) != SQUASH_MAGIC)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FS, "not squash4");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = grub_disk_read (disk, grub_le_to_cpu32 (sb.unk1offset)
|
||||
>> GRUB_DISK_SECTOR_BITS,
|
||||
grub_le_to_cpu32 (sb.unk1offset)
|
||||
& (GRUB_DISK_SECTOR_SIZE - 1), sizeof (frag), &frag);
|
||||
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
|
||||
grub_error (GRUB_ERR_BAD_FS, "not a squash4");
|
||||
if (err)
|
||||
return NULL;
|
||||
|
||||
data = grub_malloc (sizeof (*data));
|
||||
if (!data)
|
||||
return NULL;
|
||||
data->sb = sb;
|
||||
data->disk = disk;
|
||||
data->fragments = frag;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static char *
|
||||
grub_squash_read_symlink (grub_fshelp_node_t node)
|
||||
{
|
||||
char *ret;
|
||||
grub_err_t err;
|
||||
ret = grub_malloc (grub_le_to_cpu32 (node->ino.symlink.namelen) + 1);
|
||||
|
||||
err = read_chunk (node->data->disk, ret,
|
||||
grub_le_to_cpu32 (node->ino.symlink.namelen),
|
||||
grub_le_to_cpu64 (node->data->sb.inodeoffset)
|
||||
+ node->ino_chunk,
|
||||
node->ino_offset + (node->ino.symlink.name
|
||||
- (char *) &node->ino));
|
||||
if (err)
|
||||
{
|
||||
grub_free (ret);
|
||||
return NULL;
|
||||
}
|
||||
ret[grub_le_to_cpu32 (node->ino.symlink.namelen)] = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_squash_iterate_dir (grub_fshelp_node_t dir,
|
||||
int NESTED_FUNC_ATTR
|
||||
(*hook) (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node))
|
||||
{
|
||||
grub_uint32_t off = grub_le_to_cpu16 (dir->ino.dir.offset);
|
||||
grub_uint32_t endoff;
|
||||
unsigned i;
|
||||
|
||||
/* FIXME: why - 3 ? */
|
||||
endoff = grub_le_to_cpu32 (dir->ino.dir.size) + off - 3;
|
||||
|
||||
while (off < endoff)
|
||||
{
|
||||
struct grub_squash_dirent_header dh;
|
||||
grub_err_t err;
|
||||
|
||||
err = read_chunk (dir->data->disk, &dh, sizeof (dh),
|
||||
grub_le_to_cpu64 (dir->data->sb.diroffset)
|
||||
+ grub_le_to_cpu32 (dir->ino.dir.chunk), off);
|
||||
if (err)
|
||||
return 0;
|
||||
off += sizeof (dh);
|
||||
for (i = 0; i < (unsigned) grub_le_to_cpu16 (dh.nelems) + 1; i++)
|
||||
{
|
||||
char *buf;
|
||||
int r;
|
||||
struct grub_fshelp_node *node;
|
||||
enum grub_fshelp_filetype filetype = GRUB_FSHELP_REG;
|
||||
struct grub_squash_dirent di;
|
||||
struct grub_squash_inode ino;
|
||||
|
||||
err = read_chunk (dir->data->disk, &di, sizeof (di),
|
||||
grub_le_to_cpu64 (dir->data->sb.diroffset)
|
||||
+ grub_le_to_cpu32 (dir->ino.dir.chunk), off);
|
||||
if (err)
|
||||
return 0;
|
||||
off += sizeof (di);
|
||||
|
||||
err = read_chunk (dir->data->disk, &ino, sizeof (ino),
|
||||
grub_le_to_cpu64 (dir->data->sb.inodeoffset)
|
||||
+ grub_le_to_cpu32 (dh.ino_chunk),
|
||||
grub_cpu_to_le16 (di.ino_offset));
|
||||
if (err)
|
||||
return 0;
|
||||
|
||||
buf = grub_malloc (grub_le_to_cpu16 (di.namelen) + 2);
|
||||
if (!buf)
|
||||
return 0;
|
||||
err = read_chunk (dir->data->disk, buf,
|
||||
grub_le_to_cpu16 (di.namelen) + 1,
|
||||
grub_le_to_cpu64 (dir->data->sb.diroffset)
|
||||
+ grub_le_to_cpu32 (dir->ino.dir.chunk), off);
|
||||
if (err)
|
||||
return 0;
|
||||
|
||||
off += grub_le_to_cpu16 (di.namelen) + 1;
|
||||
buf[grub_le_to_cpu16 (di.namelen) + 1] = 0;
|
||||
if (grub_le_to_cpu16 (di.type) == SQUASH_TYPE_DIR)
|
||||
filetype = GRUB_FSHELP_DIR;
|
||||
if (grub_le_to_cpu16 (di.type) == SQUASH_TYPE_SYMLINK)
|
||||
filetype = GRUB_FSHELP_SYMLINK;
|
||||
|
||||
node = grub_malloc (sizeof (*node));
|
||||
if (! node)
|
||||
return 0;
|
||||
*node = *dir;
|
||||
node->ino = ino;
|
||||
node->ino_chunk = grub_le_to_cpu32 (dh.ino_chunk);
|
||||
node->ino_offset = grub_le_to_cpu16 (di.ino_offset);
|
||||
|
||||
r = hook (buf, filetype, node);
|
||||
|
||||
grub_free (buf);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
make_root_node (struct grub_squash_data *data, struct grub_fshelp_node *root)
|
||||
{
|
||||
grub_memset (root, 0, sizeof (*root));
|
||||
root->data = data;
|
||||
|
||||
return read_chunk (data->disk, &root->ino, sizeof (root->ino),
|
||||
grub_le_to_cpu64 (data->sb.inodeoffset)
|
||||
+ grub_le_to_cpu16 (data->sb.root_ino_chunk),
|
||||
grub_cpu_to_le16 (data->sb.root_ino_offset));
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_squash_dir (grub_device_t device, const char *path,
|
||||
int (*hook) (const char *filename,
|
||||
const struct grub_dirhook_info *info))
|
||||
{
|
||||
auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node);
|
||||
|
||||
int NESTED_FUNC_ATTR iterate (const char *filename,
|
||||
enum grub_fshelp_filetype filetype,
|
||||
grub_fshelp_node_t node)
|
||||
{
|
||||
struct grub_dirhook_info info;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_le_to_cpu32 (node->ino.mtime);
|
||||
return hook (filename, &info);
|
||||
}
|
||||
|
||||
struct grub_squash_data *data = 0;
|
||||
struct grub_fshelp_node *fdiro = 0;
|
||||
struct grub_fshelp_node root;
|
||||
grub_err_t err;
|
||||
|
||||
data = squash_mount (device->disk);
|
||||
if (! data)
|
||||
return grub_errno;
|
||||
|
||||
err = make_root_node (data, &root);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
grub_fshelp_find_file (path, &root, &fdiro, grub_squash_iterate_dir,
|
||||
grub_squash_read_symlink, GRUB_FSHELP_DIR);
|
||||
if (!grub_errno)
|
||||
grub_squash_iterate_dir (fdiro, iterate);
|
||||
|
||||
grub_free (data);
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_squash_open (struct grub_file *file, const char *name)
|
||||
{
|
||||
struct grub_squash_data *data = 0;
|
||||
struct grub_fshelp_node *fdiro = 0;
|
||||
struct grub_fshelp_node root;
|
||||
grub_err_t err;
|
||||
|
||||
data = squash_mount (file->device->disk);
|
||||
if (! data)
|
||||
return grub_errno;
|
||||
|
||||
err = make_root_node (data, &root);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
grub_fshelp_find_file (name, &root, &fdiro, grub_squash_iterate_dir,
|
||||
grub_squash_read_symlink, GRUB_FSHELP_REG);
|
||||
if (grub_errno)
|
||||
{
|
||||
grub_free (data);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
file->data = data;
|
||||
data->ino = fdiro->ino;
|
||||
file->size = grub_le_to_cpu32 (fdiro->ino.file.size);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_ssize_t
|
||||
grub_squash_read_data (struct grub_squash_data *data,
|
||||
grub_disk_t disk, const struct grub_squash_inode *ino,
|
||||
grub_off_t off, char *buf, grub_size_t len)
|
||||
{
|
||||
grub_err_t err;
|
||||
grub_uint64_t a, b;
|
||||
int compressed = 0;
|
||||
|
||||
if (grub_le_to_cpu16 (ino->file.fragment) == 0xffff)
|
||||
{
|
||||
if (grub_le_to_cpu32 (ino->file.chunk))
|
||||
a = grub_le_to_cpu32 (ino->file.chunk);
|
||||
else
|
||||
a = sizeof (struct grub_squash_super);
|
||||
compressed = !(data->sb.flags & SQUASH_FLAG_UNCOMPRESSED_DATA);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct grub_squash_frag_desc frag;
|
||||
err = read_chunk (disk, &frag, sizeof (frag),
|
||||
data->fragments, sizeof (frag)
|
||||
* grub_le_to_cpu16 (ino->file.fragment));
|
||||
if (err)
|
||||
return -1;
|
||||
a = grub_le_to_cpu64 (frag.offset) + grub_le_to_cpu32 (ino->file.chunk);
|
||||
compressed = !(data->sb.flags & SQUASH_FLAG_UNCOMPRESSED_FRAGMENTS);
|
||||
}
|
||||
|
||||
b = grub_le_to_cpu32 (data->ino.file.offset) + off;
|
||||
|
||||
/* FIXME: cache uncompressed chunks. */
|
||||
if (compressed)
|
||||
err = grub_zlib_disk_read (disk, a, b, buf, len);
|
||||
else
|
||||
err = grub_disk_read (disk, (a + b) >> GRUB_DISK_SECTOR_BITS,
|
||||
(a + b) & (GRUB_DISK_SECTOR_SIZE - 1), len, buf);
|
||||
if (err)
|
||||
return -1;
|
||||
return len;
|
||||
}
|
||||
|
||||
static grub_ssize_t
|
||||
grub_squash_read (grub_file_t file, char *buf, grub_size_t len)
|
||||
{
|
||||
struct grub_squash_data *data = file->data;
|
||||
|
||||
return grub_squash_read_data (data, file->device->disk, &data->ino,
|
||||
file->offset, buf, len);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_squash_close (grub_file_t file)
|
||||
{
|
||||
grub_free (file->data);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_squash_mtime (grub_device_t dev, grub_int32_t *tm)
|
||||
{
|
||||
struct grub_squash_data *data = 0;
|
||||
|
||||
data = squash_mount (dev->disk);
|
||||
if (! data)
|
||||
return grub_errno;
|
||||
*tm = grub_le_to_cpu32 (data->sb.creation_time);
|
||||
grub_free (data);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static struct grub_fs grub_squash_fs =
|
||||
{
|
||||
.name = "squash4",
|
||||
.dir = grub_squash_dir,
|
||||
.open = grub_squash_open,
|
||||
.read = grub_squash_read,
|
||||
.close = grub_squash_close,
|
||||
.mtime = grub_squash_mtime,
|
||||
#ifdef GRUB_UTIL
|
||||
.reserved_first_sector = 0,
|
||||
#endif
|
||||
.next = 0
|
||||
};
|
||||
|
||||
GRUB_MOD_INIT(squash4)
|
||||
{
|
||||
grub_fs_register (&grub_squash_fs);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(squash4)
|
||||
{
|
||||
grub_fs_unregister (&grub_squash_fs);
|
||||
}
|
||||
|
|
@ -26,6 +26,7 @@
|
|||
#include <grub/types.h>
|
||||
#include <grub/fshelp.h>
|
||||
#include <grub/charset.h>
|
||||
#include <grub/datetime.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
|
@ -885,6 +886,8 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
|
|||
|
||||
type = ((dirent.characteristics & GRUB_UDF_FID_CHAR_DIRECTORY) ?
|
||||
(GRUB_FSHELP_DIR) : (GRUB_FSHELP_REG));
|
||||
if (child->fe.icbtag.file_type == GRUB_UDF_ICBTAG_TYPE_SYMLINK)
|
||||
type = GRUB_FSHELP_SYMLINK;
|
||||
|
||||
if ((grub_udf_read_file (dir, 0, offset,
|
||||
dirent.file_ident_length,
|
||||
|
@ -912,6 +915,25 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static char *
|
||||
grub_ufs_read_symlink (grub_fshelp_node_t node)
|
||||
{
|
||||
grub_size_t sz = U64 (node->fe.file_size);
|
||||
grub_uint8_t *raw;
|
||||
char *ret;
|
||||
|
||||
if (sz < 4)
|
||||
return NULL;
|
||||
raw = grub_malloc (sz - 4);
|
||||
if (!raw)
|
||||
return NULL;
|
||||
if (grub_udf_read_file (node, NULL, 4, sz - 4, (char *) raw) < 0)
|
||||
return NULL;
|
||||
ret = read_string (raw, sz - 4);
|
||||
grub_free (raw);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_udf_dir (grub_device_t device, const char *path,
|
||||
int (*hook) (const char *filename,
|
||||
|
@ -930,8 +952,36 @@ grub_udf_dir (grub_device_t device, const char *path,
|
|||
grub_fshelp_node_t node)
|
||||
{
|
||||
struct grub_dirhook_info info;
|
||||
const struct grub_udf_timestamp *tstamp = NULL;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
if (U16 (node->fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE)
|
||||
tstamp = &node->fe.modification_time;
|
||||
else if (U16 (node->fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_EFE)
|
||||
tstamp = &node->efe.modification_time;
|
||||
|
||||
if (tstamp && (U16 (tstamp->type_and_timezone) & 0xf000) == 0x1000)
|
||||
{
|
||||
grub_int16_t tz;
|
||||
struct grub_datetime datetime;
|
||||
|
||||
datetime.year = U16 (tstamp->year);
|
||||
datetime.month = tstamp->month;
|
||||
datetime.day = tstamp->day;
|
||||
datetime.hour = tstamp->hour;
|
||||
datetime.minute = tstamp->minute;
|
||||
datetime.second = tstamp->second;
|
||||
|
||||
tz = U16 (tstamp->type_and_timezone) & 0xfff;
|
||||
if (tz & 0x800)
|
||||
tz |= 0xf000;
|
||||
if (tz == -2047)
|
||||
tz = 0;
|
||||
|
||||
info.mtimeset = !!grub_datetime2unixtime (&datetime, &info.mtime);
|
||||
|
||||
info.mtime -= 60 * tz;
|
||||
}
|
||||
grub_free (node);
|
||||
return hook (filename, &info);
|
||||
}
|
||||
|
@ -947,7 +997,8 @@ grub_udf_dir (grub_device_t device, const char *path,
|
|||
|
||||
if (grub_fshelp_find_file (path, &rootnode,
|
||||
&foundnode,
|
||||
grub_udf_iterate_dir, 0, GRUB_FSHELP_DIR))
|
||||
grub_udf_iterate_dir, grub_ufs_read_symlink,
|
||||
GRUB_FSHELP_DIR))
|
||||
goto fail;
|
||||
|
||||
grub_udf_iterate_dir (foundnode, iterate);
|
||||
|
@ -981,7 +1032,8 @@ grub_udf_open (struct grub_file *file, const char *name)
|
|||
|
||||
if (grub_fshelp_find_file (name, &rootnode,
|
||||
&foundnode,
|
||||
grub_udf_iterate_dir, 0, GRUB_FSHELP_REG))
|
||||
grub_udf_iterate_dir, grub_ufs_read_symlink,
|
||||
GRUB_FSHELP_REG))
|
||||
goto fail;
|
||||
|
||||
file->data = foundnode;
|
||||
|
|
|
@ -100,13 +100,22 @@ struct grub_xfs_btree_root
|
|||
grub_uint64_t keys[1];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct grub_xfs_time
|
||||
{
|
||||
grub_uint32_t sec;
|
||||
grub_uint32_t nanosec;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct grub_xfs_inode
|
||||
{
|
||||
grub_uint8_t magic[2];
|
||||
grub_uint16_t mode;
|
||||
grub_uint8_t version;
|
||||
grub_uint8_t format;
|
||||
grub_uint8_t unused2[50];
|
||||
grub_uint8_t unused2[26];
|
||||
struct grub_xfs_time atime;
|
||||
struct grub_xfs_time mtime;
|
||||
struct grub_xfs_time ctime;
|
||||
grub_uint64_t size;
|
||||
grub_uint64_t nblocks;
|
||||
grub_uint32_t extsize;
|
||||
|
@ -654,6 +663,11 @@ grub_xfs_dir (grub_device_t device, const char *path,
|
|||
{
|
||||
struct grub_dirhook_info info;
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
if (node->inode_read)
|
||||
{
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_be_to_cpu32 (node->inode.mtime.sec);
|
||||
}
|
||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
||||
grub_free (node);
|
||||
return hook (filename, &info);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue