|
@@ -13,6 +13,7 @@
|
|
*
|
|
*
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
+#include <linux/slab.h>
|
|
#include "hfsplus_fs.h"
|
|
#include "hfsplus_fs.h"
|
|
|
|
|
|
/* offsets to various blocks */
|
|
/* offsets to various blocks */
|
|
@@ -65,70 +66,87 @@ struct old_pmap {
|
|
} pdEntry[42];
|
|
} pdEntry[42];
|
|
} __packed;
|
|
} __packed;
|
|
|
|
|
|
|
|
+static int hfs_parse_old_pmap(struct super_block *sb, struct old_pmap *pm,
|
|
|
|
+ sector_t *part_start, sector_t *part_size)
|
|
|
|
+{
|
|
|
|
+ struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < 42; i++) {
|
|
|
|
+ struct old_pmap_entry *p = &pm->pdEntry[i];
|
|
|
|
+
|
|
|
|
+ if (p->pdStart && p->pdSize &&
|
|
|
|
+ p->pdFSID == cpu_to_be32(0x54465331)/*"TFS1"*/ &&
|
|
|
|
+ (sbi->part < 0 || sbi->part == i)) {
|
|
|
|
+ *part_start += be32_to_cpu(p->pdStart);
|
|
|
|
+ *part_size = be32_to_cpu(p->pdSize);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return -ENOENT;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm,
|
|
|
|
+ sector_t *part_start, sector_t *part_size)
|
|
|
|
+{
|
|
|
|
+ struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
|
|
|
|
+ int size = be32_to_cpu(pm->pmMapBlkCnt);
|
|
|
|
+ int res;
|
|
|
|
+ int i = 0;
|
|
|
|
+
|
|
|
|
+ do {
|
|
|
|
+ if (!memcmp(pm->pmPartType,"Apple_HFS", 9) &&
|
|
|
|
+ (sbi->part < 0 || sbi->part == i)) {
|
|
|
|
+ *part_start += be32_to_cpu(pm->pmPyPartStart);
|
|
|
|
+ *part_size = be32_to_cpu(pm->pmPartBlkCnt);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (++i >= size)
|
|
|
|
+ return -ENOENT;
|
|
|
|
+
|
|
|
|
+ res = hfsplus_submit_bio(sb->s_bdev,
|
|
|
|
+ *part_start + HFS_PMAP_BLK + i,
|
|
|
|
+ pm, READ);
|
|
|
|
+ if (res)
|
|
|
|
+ return res;
|
|
|
|
+ } while (pm->pmSig == cpu_to_be16(HFS_NEW_PMAP_MAGIC));
|
|
|
|
+
|
|
|
|
+ return -ENOENT;
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
- * hfs_part_find()
|
|
|
|
- *
|
|
|
|
- * Parse the partition map looking for the
|
|
|
|
- * start and length of the 'part'th HFS partition.
|
|
|
|
|
|
+ * Parse the partition map looking for the start and length of a
|
|
|
|
+ * HFS/HFS+ partition.
|
|
*/
|
|
*/
|
|
int hfs_part_find(struct super_block *sb,
|
|
int hfs_part_find(struct super_block *sb,
|
|
- sector_t *part_start, sector_t *part_size)
|
|
|
|
|
|
+ sector_t *part_start, sector_t *part_size)
|
|
{
|
|
{
|
|
- struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
|
|
|
|
- struct buffer_head *bh;
|
|
|
|
- __be16 *data;
|
|
|
|
- int i, size, res;
|
|
|
|
|
|
+ void *data;
|
|
|
|
+ int res;
|
|
|
|
+
|
|
|
|
+ data = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL);
|
|
|
|
+ if (!data)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
|
|
- res = -ENOENT;
|
|
|
|
- bh = sb_bread512(sb, *part_start + HFS_PMAP_BLK, data);
|
|
|
|
- if (!bh)
|
|
|
|
- return -EIO;
|
|
|
|
|
|
+ res = hfsplus_submit_bio(sb->s_bdev, *part_start + HFS_PMAP_BLK,
|
|
|
|
+ data, READ);
|
|
|
|
+ if (res)
|
|
|
|
+ return res;
|
|
|
|
|
|
- switch (be16_to_cpu(*data)) {
|
|
|
|
|
|
+ switch (be16_to_cpu(*((__be16 *)data))) {
|
|
case HFS_OLD_PMAP_MAGIC:
|
|
case HFS_OLD_PMAP_MAGIC:
|
|
- {
|
|
|
|
- struct old_pmap *pm;
|
|
|
|
- struct old_pmap_entry *p;
|
|
|
|
-
|
|
|
|
- pm = (struct old_pmap *)bh->b_data;
|
|
|
|
- p = pm->pdEntry;
|
|
|
|
- size = 42;
|
|
|
|
- for (i = 0; i < size; p++, i++) {
|
|
|
|
- if (p->pdStart && p->pdSize &&
|
|
|
|
- p->pdFSID == cpu_to_be32(0x54465331)/*"TFS1"*/ &&
|
|
|
|
- (sbi->part < 0 || sbi->part == i)) {
|
|
|
|
- *part_start += be32_to_cpu(p->pdStart);
|
|
|
|
- *part_size = be32_to_cpu(p->pdSize);
|
|
|
|
- res = 0;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ res = hfs_parse_old_pmap(sb, data, part_start, part_size);
|
|
break;
|
|
break;
|
|
- }
|
|
|
|
case HFS_NEW_PMAP_MAGIC:
|
|
case HFS_NEW_PMAP_MAGIC:
|
|
- {
|
|
|
|
- struct new_pmap *pm;
|
|
|
|
-
|
|
|
|
- pm = (struct new_pmap *)bh->b_data;
|
|
|
|
- size = be32_to_cpu(pm->pmMapBlkCnt);
|
|
|
|
- for (i = 0; i < size;) {
|
|
|
|
- if (!memcmp(pm->pmPartType,"Apple_HFS", 9) &&
|
|
|
|
- (sbi->part < 0 || sbi->part == i)) {
|
|
|
|
- *part_start += be32_to_cpu(pm->pmPyPartStart);
|
|
|
|
- *part_size = be32_to_cpu(pm->pmPartBlkCnt);
|
|
|
|
- res = 0;
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- brelse(bh);
|
|
|
|
- bh = sb_bread512(sb, *part_start + HFS_PMAP_BLK + ++i, pm);
|
|
|
|
- if (!bh)
|
|
|
|
- return -EIO;
|
|
|
|
- if (pm->pmSig != cpu_to_be16(HFS_NEW_PMAP_MAGIC))
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
|
|
+ res = hfs_parse_new_pmap(sb, data, part_start, part_size);
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ res = -ENOENT;
|
|
break;
|
|
break;
|
|
- }
|
|
|
|
}
|
|
}
|
|
- brelse(bh);
|
|
|
|
|
|
|
|
|
|
+ kfree(data);
|
|
return res;
|
|
return res;
|
|
}
|
|
}
|