Support version 33 including symlinks
This commit is contained in:
parent
11e50e923a
commit
34c5965451
3 changed files with 141 additions and 13 deletions
|
@ -1839,19 +1839,18 @@ dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn,
|
|||
break;
|
||||
|
||||
*path = ch;
|
||||
if (((grub_zfs_to_cpu64(((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_mode, dnode_path->dn.endian) >> 12) & 0xf) == 0xa)
|
||||
if (dnode_path->dn.dn.dn_bonustype == DMU_OT_ZNODE
|
||||
&& ((grub_zfs_to_cpu64(((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_mode, dnode_path->dn.endian) >> 12) & 0xf) == 0xa)
|
||||
{
|
||||
char *sym_value;
|
||||
grub_size_t avail_in_dnode;
|
||||
grub_size_t sym_sz;
|
||||
int free_symval = 0;
|
||||
char *oldpath = path, *oldpathbuf = path_buf;
|
||||
sym_value = ((char *) DN_BONUS (&dnode_path->dn.dn) + sizeof (struct znode_phys));
|
||||
avail_in_dnode = (char *) (&dnode_path->dn + 1) - sym_value;
|
||||
|
||||
sym_sz = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_size, dnode_path->dn.endian);
|
||||
|
||||
if (sym_sz > avail_in_dnode - 8)
|
||||
if (dnode_path->dn.dn.dn_flags & 1)
|
||||
{
|
||||
grub_size_t block;
|
||||
grub_size_t blksz;
|
||||
|
@ -1905,6 +1904,62 @@ dnode_get_path (dnode_end_t * mdn, const char *path_in, dnode_end_t * dn,
|
|||
grub_free (dn_new);
|
||||
}
|
||||
}
|
||||
if (dnode_path->dn.dn.dn_bonustype == DMU_OT_SA)
|
||||
{
|
||||
void *sahdrp;
|
||||
int hdrsize;
|
||||
|
||||
if (dnode_path->dn.dn.dn_bonuslen != 0)
|
||||
{
|
||||
sahdrp = DN_BONUS (&dnode_path->dn.dn);
|
||||
}
|
||||
else if (dnode_path->dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR)
|
||||
{
|
||||
blkptr_t *bp = &dnode_path->dn.dn.dn_spill;
|
||||
|
||||
err = zio_read (bp, dnode_path->dn.endian, &sahdrp, NULL, data);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
else
|
||||
{
|
||||
return grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt");
|
||||
}
|
||||
|
||||
hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
|
||||
|
||||
if (((grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_TYPE_OFFSET), dnode_path->dn.endian) >> 12) & 0xf) == 0xa)
|
||||
{
|
||||
char *sym_value = (char *) sahdrp + hdrsize + SA_SYMLINK_OFFSET;
|
||||
grub_size_t sym_sz =
|
||||
grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET), dnode_path->dn.endian);
|
||||
char *oldpath = path, *oldpathbuf = path_buf;
|
||||
path = path_buf = grub_malloc (sym_sz + grub_strlen (oldpath) + 1);
|
||||
if (!path_buf)
|
||||
{
|
||||
grub_free (oldpathbuf);
|
||||
return grub_errno;
|
||||
}
|
||||
grub_memcpy (path, sym_value, sym_sz);
|
||||
path [sym_sz] = 0;
|
||||
grub_memcpy (path + grub_strlen (path), oldpath,
|
||||
grub_strlen (oldpath) + 1);
|
||||
|
||||
grub_free (oldpathbuf);
|
||||
if (path[0] != '/')
|
||||
{
|
||||
dn_new = dnode_path;
|
||||
dnode_path = dn_new->next;
|
||||
grub_free (dn_new);
|
||||
}
|
||||
else while (dnode_path != root)
|
||||
{
|
||||
dn_new = dnode_path;
|
||||
dnode_path = dn_new->next;
|
||||
grub_free (dn_new);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!err)
|
||||
|
@ -2666,12 +2721,14 @@ grub_zfs_open (struct grub_file *file, const char *fsfilename)
|
|||
}
|
||||
|
||||
hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
|
||||
file->size = *(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET);
|
||||
file->size = grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET), data->dnode.endian);
|
||||
}
|
||||
else
|
||||
else if (data->dnode.dn.dn_bonustype == DMU_OT_ZNODE)
|
||||
{
|
||||
file->size = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&data->dnode.dn))->zp_size, data->dnode.endian);
|
||||
}
|
||||
else
|
||||
return grub_error (GRUB_ERR_BAD_FS, "bad bonus type");
|
||||
|
||||
file->data = data;
|
||||
file->offset = 0;
|
||||
|
@ -2830,8 +2887,39 @@ fill_fs_info (struct grub_dirhook_info *info,
|
|||
return;
|
||||
}
|
||||
|
||||
info->mtimeset = 1;
|
||||
info->mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], dn.endian);
|
||||
if (dn.dn.dn_bonustype == DMU_OT_SA)
|
||||
{
|
||||
void *sahdrp;
|
||||
int hdrsize;
|
||||
|
||||
if (dn.dn.dn_bonuslen != 0)
|
||||
{
|
||||
sahdrp = (sa_hdr_phys_t *) DN_BONUS (&dn.dn);
|
||||
}
|
||||
else if (dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR)
|
||||
{
|
||||
blkptr_t *bp = &dn.dn.dn_spill;
|
||||
|
||||
err = zio_read (bp, dn.endian, &sahdrp, NULL, data);
|
||||
if (err)
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt");
|
||||
return;
|
||||
}
|
||||
|
||||
hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
|
||||
info->mtimeset = 1;
|
||||
info->mtime = grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian);
|
||||
}
|
||||
|
||||
if (dn.dn.dn_bonustype == DMU_OT_ZNODE)
|
||||
{
|
||||
info->mtimeset = 1;
|
||||
info->mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], dn.endian);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2855,10 +2943,47 @@ grub_zfs_dir (grub_device_t device, const char *path,
|
|||
grub_memset (&info, 0, sizeof (info));
|
||||
|
||||
dnode_get (&(data->mdn), val, 0, &dn, data);
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], dn.endian);
|
||||
info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS);
|
||||
grub_dprintf ("zfs", "type=%d, name=%s\n",
|
||||
|
||||
if (dn.dn.dn_bonustype == DMU_OT_SA)
|
||||
{
|
||||
void *sahdrp;
|
||||
int hdrsize;
|
||||
|
||||
if (dn.dn.dn_bonuslen != 0)
|
||||
{
|
||||
sahdrp = (sa_hdr_phys_t *) DN_BONUS (&data->dnode.dn);
|
||||
}
|
||||
else if (dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR)
|
||||
{
|
||||
blkptr_t *bp = &dn.dn.dn_spill;
|
||||
|
||||
err = zio_read (bp, dn.endian, &sahdrp, NULL, data);
|
||||
if (err)
|
||||
{
|
||||
grub_print_error ();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt");
|
||||
grub_print_error ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp));
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian);
|
||||
}
|
||||
|
||||
if (dn.dn.dn_bonustype == DMU_OT_ZNODE)
|
||||
{
|
||||
info.mtimeset = 1;
|
||||
info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0],
|
||||
dn.endian);
|
||||
}
|
||||
info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS);
|
||||
grub_dprintf ("zfs", "type=%d, name=%s\n",
|
||||
(int)dn.dn.dn_type, (char *)name);
|
||||
return hook (name, &info);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,9 @@ typedef struct sa_hdr_phys {
|
|||
} sa_hdr_phys_t;
|
||||
|
||||
#define SA_HDR_SIZE(hdr) BF32_GET_SB(hdr->sa_layout_info, 10, 16, 3, 0)
|
||||
#define SA_TYPE_OFFSET 0x0
|
||||
#define SA_SIZE_OFFSET 0x8
|
||||
#define SA_MTIME_OFFSET 0x38
|
||||
#define SA_SYMLINK_OFFSET 0xa0
|
||||
|
||||
#endif /* _SYS_SA_IMPL_H */
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
/*
|
||||
* On-disk version number.
|
||||
*/
|
||||
#define SPA_VERSION 31ULL
|
||||
#define SPA_VERSION 33ULL
|
||||
|
||||
/*
|
||||
* The following are configuration names used in the nvlist describing a pool's
|
||||
|
|
Loading…
Reference in a new issue