volume_id hfs/hfs+ support
Kay Sievers
kay.sievers at vrfy.org
Wed Jul 7 13:53:00 PDT 2004
On Tue, Jul 06, 2004 at 05:42:14PM +0200, David Zeuthen wrote:
> On Tue, 2004-07-06 at 02:51 +0200, Kay Sievers wrote:
> > Here are a few more lines. On a working volume I get:
> >
> > [I] linux/osspec.c:679 handle_udev_node_created_found_device() : dev_file=/udev/cf is for udi=/org/freedesktop/Hal/devices/temp/84
> > get_buffer: read sbbuf len:0x200
> > get_buffer: read sbbuf len:0x11000
> > probe_hfsplus: catalog start 0x20000, len 0x1e000
> > get_buffer: read seekbuf off:0x20000 len:0x1000
> > get_buffer: got 0x1000 (4096) bytes
> > probe_hfsplus: catalog leaf node 0x1, size 0x1000
> > get_buffer: read seekbuf off:0x21000 len:0x1000
> > get_buffer: got 0x1000 (4096) bytes
> > probe_hfsplus: descriptor type 0xff
> > probe_hfsplus: parent id 0x1
> > probe_hfsplus: label unicode16 len 18
> >
> > So, let's fix it. It works pretty nice with "remote debugging" :)
> >
>
> Yay, here is the debug
>
> get_buffer: read sbbuf len:0x200
> get_buffer: read sbbuf len:0x11000
> probe_hfsplus: catalog start 0xdcd000, len 0x1c00000
> get_buffer: read seekbuf off:0xdcd000 len:0x1000
> get_buffer: got 0x1000 (4096) bytes
> probe_hfsplus: catalog leaf node 0x4454, size 0x2000
> get_buffer: read seekbuf off:0x9675000 len:0x1000
> get_buffer: got 0x1000 (4096) bytes
> probe_hfsplus: descriptor type 0xff
> probe_hfsplus: parent id 0xdadd1
Hmm, looks really strange. I will see what I can do.
I got acces to a running OS X machine yesterday :) And formatted my
USB stick with hfs, hfs+ and udf using the Apple disk tool. So here I
have a update to discover hfs wrapped hfs+ partitions, mac_partition_maps
and udf:
http://vrfy.org/projects/hal/hal-mac-partition-ufs.png
http://vrfy.org/projects/hal/hal-hfsplus-unicode.png
Thanks,
Kay
-------------- next part --------------
Index: hald/linux/volume_id/volume_id.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux/volume_id/volume_id.c,v
retrieving revision 1.10
diff -u -r1.10 volume_id.c
--- hald/linux/volume_id/volume_id.c 5 Jul 2004 23:42:20 -0000 1.10
+++ hald/linux/volume_id/volume_id.c 7 Jul 2004 20:36:48 -0000
@@ -726,9 +726,213 @@
return 0;
}
+#define UFS_MAGIC 0x00011954
+#define UFS2_MAGIC 0x19540119
+#define UFS_MAGIC_FEA 0x00195612
+#define UFS_MAGIC_LFN 0x00095014
+
+
+static int probe_ufs(struct volume_id *id)
+{
+ struct ufs_super_block {
+ __u32 fs_link;
+ __u32 fs_rlink;
+ __u32 fs_sblkno;
+ __u32 fs_cblkno;
+ __u32 fs_iblkno;
+ __u32 fs_dblkno;
+ __u32 fs_cgoffset;
+ __u32 fs_cgmask;
+ __u32 fs_time;
+ __u32 fs_size;
+ __u32 fs_dsize;
+ __u32 fs_ncg;
+ __u32 fs_bsize;
+ __u32 fs_fsize;
+ __u32 fs_frag;
+ __u32 fs_minfree;
+ __u32 fs_rotdelay;
+ __u32 fs_rps;
+ __u32 fs_bmask;
+ __u32 fs_fmask;
+ __u32 fs_bshift;
+ __u32 fs_fshift;
+ __u32 fs_maxcontig;
+ __u32 fs_maxbpg;
+ __u32 fs_fragshift;
+ __u32 fs_fsbtodb;
+ __u32 fs_sbsize;
+ __u32 fs_csmask;
+ __u32 fs_csshift;
+ __u32 fs_nindir;
+ __u32 fs_inopb;
+ __u32 fs_nspf;
+ __u32 fs_optim;
+ __u32 fs_npsect_state;
+ __u32 fs_interleave;
+ __u32 fs_trackskew;
+ __u32 fs_id[2];
+ __u32 fs_csaddr;
+ __u32 fs_cssize;
+ __u32 fs_cgsize;
+ __u32 fs_ntrak;
+ __u32 fs_nsect;
+ __u32 fs_spc;
+ __u32 fs_ncyl;
+ __u32 fs_cpg;
+ __u32 fs_ipg;
+ __u32 fs_fpg;
+ struct ufs_csum {
+ __u32 cs_ndir;
+ __u32 cs_nbfree;
+ __u32 cs_nifree;
+ __u32 cs_nffree;
+ } __attribute__((__packed__)) fs_cstotal;
+ __s8 fs_fmod;
+ __s8 fs_clean;
+ __s8 fs_ronly;
+ __s8 fs_flags;
+ union {
+ struct {
+ __s8 fs_fsmnt[512];
+ __u32 fs_cgrotor;
+ __u32 fs_csp[31];
+ __u32 fs_maxcluster;
+ __u32 fs_cpc;
+ __u16 fs_opostbl[16][8];
+ } __attribute__((__packed__)) fs_u1;
+ struct {
+ __s8 fs_fsmnt[468];
+ __u8 fs_volname[32];
+ __u64 fs_swuid;
+ __s32 fs_pad;
+ __u32 fs_cgrotor;
+ __u32 fs_ocsp[28];
+ __u32 fs_contigdirs;
+ __u32 fs_csp;
+ __u32 fs_maxcluster;
+ __u32 fs_active;
+ __s32 fs_old_cpc;
+ __s32 fs_maxbsize;
+ __s64 fs_sparecon64[17];
+ __s64 fs_sblockloc;
+ struct ufs2_csum_total {
+ __u64 cs_ndir;
+ __u64 cs_nbfree;
+ __u64 cs_nifree;
+ __u64 cs_nffree;
+ __u64 cs_numclusters;
+ __u64 cs_spare[3];
+ } __attribute__((__packed__)) fs_cstotal;
+ struct ufs_timeval {
+ __s32 tv_sec;
+ __s32 tv_usec;
+ } __attribute__((__packed__)) fs_time;
+ __s64 fs_size;
+ __s64 fs_dsize;
+ __u64 fs_csaddr;
+ __s64 fs_pendingblocks;
+ __s32 fs_pendinginodes;
+ } __attribute__((__packed__)) fs_u2;
+ } fs_u11;
+ union {
+ struct {
+ __s32 fs_sparecon[53];
+ __s32 fs_reclaim;
+ __s32 fs_sparecon2[1];
+ __s32 fs_state;
+ __u32 fs_qbmask[2];
+ __u32 fs_qfmask[2];
+ } __attribute__((__packed__)) fs_sun;
+ struct {
+ __s32 fs_sparecon[53];
+ __s32 fs_reclaim;
+ __s32 fs_sparecon2[1];
+ __u32 fs_npsect;
+ __u32 fs_qbmask[2];
+ __u32 fs_qfmask[2];
+ } __attribute__((__packed__)) fs_sunx86;
+ struct {
+ __s32 fs_sparecon[50];
+ __s32 fs_contigsumsize;
+ __s32 fs_maxsymlinklen;
+ __s32 fs_inodefmt;
+ __u32 fs_maxfilesize[2];
+ __u32 fs_qbmask[2];
+ __u32 fs_qfmask[2];
+ __s32 fs_state;
+ } __attribute__((__packed__)) fs_44;
+ } fs_u2;
+ __s32 fs_postblformat;
+ __s32 fs_nrpos;
+ __s32 fs_postbloff;
+ __s32 fs_rotbloff;
+ __u32 fs_magic;
+ __u8 fs_space[1];
+ } __attribute__((__packed__)) *ufs;
+
+ __u32 magic;
+ int i;
+ int offsets[] = {0, 8, 64, 256, -1};
+
+ for (i = 0; offsets[i] >= 0; i++) {
+ ufs = (struct ufs_super_block *)
+ get_buffer(id, offsets[i] * 0x400, 0x800);
+ if (ufs == NULL)
+ return -1;
+
+ dbg("offset 0x%x", offsets[i] * 0x400);
+ magic = be32_to_cpu(ufs->fs_magic);
+ if ((magic == UFS_MAGIC) ||
+ (magic == UFS2_MAGIC) ||
+ (magic == UFS_MAGIC_FEA) ||
+ (magic == UFS_MAGIC_LFN)) {
+ dbg("magic 0x%08x(be)", magic);
+ goto found;
+ }
+ magic = le32_to_cpu(ufs->fs_magic);
+ if ((magic == UFS_MAGIC) ||
+ (magic == UFS2_MAGIC) ||
+ (magic == UFS_MAGIC_FEA) ||
+ (magic == UFS_MAGIC_LFN)) {
+ dbg("magic 0x%08x(le)", magic);
+ goto found;
+ }
+ }
+ return -1;
+
+found:
+ id->fs_type = UFS;
+ id->fs_name = "ufs";
+
+ return 0;
+}
+
+
#define HFS_SUPERBLOCK_OFFSET 0x400
-static int probe_hfs(struct volume_id *id)
+#define HFS_NODE_LEAF 0xff
+#define HFSPLUS_POR_CNID 1
+static int probe_hfs_hfsplus(struct volume_id *id)
{
+ struct mac_partition {
+ __u8 signature[2];
+ __u16 res1;
+ __u32 map_count;
+ __u32 start_block;
+ __u32 block_count;
+ __u8 name[32];
+ } __attribute__((__packed__)) *part;
+
+ struct finder_info {
+ __u32 boot_folder;
+ __u32 start_app;
+ __u32 open_folder;
+ __u32 os9_folder;
+ __u32 reserved;
+ __u32 osx_folder;
+ __u8 id[8];
+ } __attribute__((__packed__));
+
struct hfs_mdb {
__u8 signature[2];
__u32 cr_date;
@@ -753,42 +957,12 @@
__u16 num_root_dirs;
__u32 file_count;
__u32 dir_count;
- struct finder_info {
- __u32 boot_folder;
- __u32 start_app;
- __u32 open_folder;
- __u32 os9_folder;
- __u32 reserved;
- __u32 osx_folder;
- __u8 id[8];
- } __attribute__((__packed__)) finfo;
-
+ struct finder_info finfo;
+ __u8 embed_sig[2];
+ __u16 embed_startblock;
+ __u16 embed_blockcount;
} __attribute__((__packed__)) *hfs;
- hfs = (struct hfs_mdb *) get_buffer(id, HFS_SUPERBLOCK_OFFSET, 0x200);
- if (hfs == NULL)
- return -1;
-
- if (strncmp(hfs->signature, "BD", 2) != 0)
- return -1;
-
- if (hfs->label_len > 0 && hfs->label_len < 28) {
- set_label_raw(id, hfs->label, hfs->label_len);
- set_label_string(id, hfs->label, hfs->label_len) ;
- }
-
- set_uuid(id, hfs->finfo.id, 8);
-
- id->fs_type = HFS;
- id->fs_name = "hfs";
-
- return 0;
-}
-
-#define HFS_NODE_LEAF 0xff
-#define HFSPLUS_POR_CNID 1
-static int probe_hfsplus(struct volume_id *id)
-{
struct hfsplus_bnode_descriptor {
__u32 next;
__u32 prev;
@@ -847,15 +1021,7 @@
__u32 next_cnid;
__u32 write_count;
__u64 encodings_bmp;
- struct finder_info {
- __u32 boot_folder;
- __u32 start_app;
- __u32 open_folder;
- __u32 os9_folder;
- __u32 reserved;
- __u32 osx_folder;
- __u8 id[8];
- } __attribute__((__packed__)) finfo;
+ struct finder_info finfo;
struct hfsplus_fork alloc_file;
struct hfsplus_fork ext_file;
struct hfsplus_fork cat_file;
@@ -870,28 +1036,80 @@
unsigned int cat_len;
unsigned int leaf_node_head;
unsigned int leaf_node_size;
+ unsigned int alloc_block_size;
+ unsigned int alloc_first_block;
+ unsigned int embed_first_block;
+ unsigned int embed_off = 0;
struct hfsplus_bnode_descriptor *descr;
struct hfsplus_bheader_record *bnode;
struct hfsplus_catalog_key *key;
unsigned int label_len;
const __u8 *buf;
- hfsplus = (struct hfsplus_vol_header *)
- get_buffer(id, HFS_SUPERBLOCK_OFFSET, 0x200);
- if (hfsplus == NULL)
+ buf = get_buffer(id, 0, 0x200);
+ if (buf == NULL)
return -1;
+
+ part = (struct mac_partition *) buf;
+ if ((strncmp(part->signature, "PM", 2) == 0) &&
+ (strncmp(part->name, "Apple", 5) == 0)) {
+ id->fs_type = MACPARTMAP;
+ id->fs_name = "mac_partition_map";
+ return 0;
+ }
+
+ buf = get_buffer(id, HFS_SUPERBLOCK_OFFSET, 0x200);
+ if (buf == NULL)
+ return -1;
+
+ hfs = (struct hfs_mdb *) buf;
+ if (strncmp(hfs->signature, "BD", 2) != 0)
+ goto checkplus;
+
+ /* it may be just a hfs wrapper for hfs+ */
+ if (strncmp(hfs->embed_sig, "H+", 2) == 0) {
+ alloc_block_size = be32_to_cpu(hfs->al_blk_size);
+ dbg("alloc_block_size 0x%x", alloc_block_size);
+
+ alloc_first_block = be16_to_cpu(hfs->al_bl_st);
+ dbg("alloc_first_block 0x%x", alloc_first_block);
+
+ embed_first_block = be16_to_cpu(hfs->embed_startblock);
+ dbg("embed_first_block 0x%x", embed_first_block);
+
+ embed_off = (alloc_first_block * 512) +
+ (embed_first_block * alloc_block_size);
+ dbg("hfs wrapped hfs+ found at offset 0x%x", embed_off);
+
+ buf = get_buffer(id, embed_off + HFS_SUPERBLOCK_OFFSET, 0x200);
+ if (buf == NULL)
+ return -1;
+ goto checkplus;
+ }
+
+ if (hfs->label_len > 0 && hfs->label_len < 28) {
+ set_label_raw(id, hfs->label, hfs->label_len);
+ set_label_string(id, hfs->label, hfs->label_len) ;
+ }
+ id->fs_type = HFS;
+ id->fs_name = "hfs";
+
+ return 0;
+
+checkplus:
+ hfsplus = (struct hfsplus_vol_header *) buf;
if (strncmp(hfsplus->signature, "H+", 2) == 0)
- goto label;
+ goto hfsplus;
if (strncmp(hfsplus->signature, "HX", 2) == 0)
- goto label;
+ goto hfsplus;
return -1;
-label:
+hfsplus:
blocksize = be32_to_cpu(hfsplus->blocksize);
cat_block = be32_to_cpu(hfsplus->cat_file.extents[0].start_block);
cat_block_count = be32_to_cpu(hfsplus->cat_file.extents[0].block_count);
- cat_off = cat_block * blocksize;
+ cat_off = (cat_block * blocksize) + embed_off;
cat_len = cat_block_count * blocksize;
dbg("catalog start 0x%x, len 0x%x", cat_off, cat_len);
@@ -914,12 +1132,14 @@
goto found;
descr = (struct hfsplus_bnode_descriptor *) buf;
+ dbg("descriptor type 0x%x", descr->type);
if (descr->type != HFS_NODE_LEAF)
goto found;
key = (struct hfsplus_catalog_key *)
&buf[sizeof(struct hfsplus_bnode_descriptor)];
+ dbg("parent id 0x%x", be32_to_cpu(key->parent_id));
if (be32_to_cpu(key->parent_id) != HFSPLUS_POR_CNID)
goto found;
@@ -1149,10 +1369,12 @@
rc = probe_iso9660(id);
break;
case HFS:
- rc = probe_hfs(id);
- break;
case HFSPLUS:
- rc = probe_hfsplus(id);
+ case MACPARTMAP:
+ rc = probe_hfs_hfsplus(id);
+ break;
+ case UFS:
+ rc = probe_ufs(id);
break;
case NTFS:
rc = probe_ntfs(id);
@@ -1197,10 +1419,10 @@
rc = probe_ntfs(id);
if (rc == 0)
break;
- rc = probe_hfsplus(id);
+ rc = probe_hfs_hfsplus(id);
if (rc == 0)
break;
- rc = probe_hfs(id);
+ rc = probe_ufs(id);
if (rc == 0)
break;
rc = -1;
Index: hald/linux/volume_id/volume_id.h
===================================================================
RCS file: /cvs/hal/hal/hald/linux/volume_id/volume_id.h,v
retrieving revision 1.4
diff -u -r1.4 volume_id.h
--- hald/linux/volume_id/volume_id.h 5 Jul 2004 19:27:25 -0000 1.4
+++ hald/linux/volume_id/volume_id.h 7 Jul 2004 20:36:48 -0000
@@ -31,6 +31,7 @@
enum filesystem_type {
ALL,
+ SWAP,
EXT2,
EXT3,
REISER,
@@ -43,7 +44,8 @@
NTFS,
HFS,
HFSPLUS,
- SWAP
+ MACPARTMAP,
+ UFS
};
struct volume_id {
-------------- next part --------------
_______________________________________________
hal mailing list
hal at freedesktop.org
http://freedesktop.org/mailman/listinfo/hal
More information about the Hal
mailing list