diff options
Diffstat (limited to 'fs/hfsplus/part_tbl.c')
-rw-r--r-- | fs/hfsplus/part_tbl.c | 129 |
1 files changed, 74 insertions, 55 deletions
diff --git a/fs/hfsplus/part_tbl.c b/fs/hfsplus/part_tbl.c index 208b16c645cc..d66ad113b1cc 100644 --- a/fs/hfsplus/part_tbl.c +++ b/fs/hfsplus/part_tbl.c | |||
@@ -2,7 +2,8 @@ | |||
2 | * linux/fs/hfsplus/part_tbl.c | 2 | * linux/fs/hfsplus/part_tbl.c |
3 | * | 3 | * |
4 | * Copyright (C) 1996-1997 Paul H. Hargrove | 4 | * Copyright (C) 1996-1997 Paul H. Hargrove |
5 | * This file may be distributed under the terms of the GNU General Public License. | 5 | * This file may be distributed under the terms of |
6 | * the GNU General Public License. | ||
6 | * | 7 | * |
7 | * Original code to handle the new style Mac partition table based on | 8 | * Original code to handle the new style Mac partition table based on |
8 | * a patch contributed by Holger Schemel (aeglos@valinor.owl.de). | 9 | * a patch contributed by Holger Schemel (aeglos@valinor.owl.de). |
@@ -13,6 +14,7 @@ | |||
13 | * | 14 | * |
14 | */ | 15 | */ |
15 | 16 | ||
17 | #include <linux/slab.h> | ||
16 | #include "hfsplus_fs.h" | 18 | #include "hfsplus_fs.h" |
17 | 19 | ||
18 | /* offsets to various blocks */ | 20 | /* offsets to various blocks */ |
@@ -58,77 +60,94 @@ struct new_pmap { | |||
58 | */ | 60 | */ |
59 | struct old_pmap { | 61 | struct old_pmap { |
60 | __be16 pdSig; /* Signature bytes */ | 62 | __be16 pdSig; /* Signature bytes */ |
61 | struct old_pmap_entry { | 63 | struct old_pmap_entry { |
62 | __be32 pdStart; | 64 | __be32 pdStart; |
63 | __be32 pdSize; | 65 | __be32 pdSize; |
64 | __be32 pdFSID; | 66 | __be32 pdFSID; |
65 | } pdEntry[42]; | 67 | } pdEntry[42]; |
66 | } __packed; | 68 | } __packed; |
67 | 69 | ||
70 | static int hfs_parse_old_pmap(struct super_block *sb, struct old_pmap *pm, | ||
71 | sector_t *part_start, sector_t *part_size) | ||
72 | { | ||
73 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | ||
74 | int i; | ||
75 | |||
76 | for (i = 0; i < 42; i++) { | ||
77 | struct old_pmap_entry *p = &pm->pdEntry[i]; | ||
78 | |||
79 | if (p->pdStart && p->pdSize && | ||
80 | p->pdFSID == cpu_to_be32(0x54465331)/*"TFS1"*/ && | ||
81 | (sbi->part < 0 || sbi->part == i)) { | ||
82 | *part_start += be32_to_cpu(p->pdStart); | ||
83 | *part_size = be32_to_cpu(p->pdSize); | ||
84 | return 0; | ||
85 | } | ||
86 | } | ||
87 | |||
88 | return -ENOENT; | ||
89 | } | ||
90 | |||
91 | static int hfs_parse_new_pmap(struct super_block *sb, struct new_pmap *pm, | ||
92 | sector_t *part_start, sector_t *part_size) | ||
93 | { | ||
94 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | ||
95 | int size = be32_to_cpu(pm->pmMapBlkCnt); | ||
96 | int res; | ||
97 | int i = 0; | ||
98 | |||
99 | do { | ||
100 | if (!memcmp(pm->pmPartType, "Apple_HFS", 9) && | ||
101 | (sbi->part < 0 || sbi->part == i)) { | ||
102 | *part_start += be32_to_cpu(pm->pmPyPartStart); | ||
103 | *part_size = be32_to_cpu(pm->pmPartBlkCnt); | ||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | if (++i >= size) | ||
108 | return -ENOENT; | ||
109 | |||
110 | res = hfsplus_submit_bio(sb->s_bdev, | ||
111 | *part_start + HFS_PMAP_BLK + i, | ||
112 | pm, READ); | ||
113 | if (res) | ||
114 | return res; | ||
115 | } while (pm->pmSig == cpu_to_be16(HFS_NEW_PMAP_MAGIC)); | ||
116 | |||
117 | return -ENOENT; | ||
118 | } | ||
119 | |||
68 | /* | 120 | /* |
69 | * hfs_part_find() | 121 | * Parse the partition map looking for the start and length of a |
70 | * | 122 | * HFS/HFS+ partition. |
71 | * Parse the partition map looking for the | ||
72 | * start and length of the 'part'th HFS partition. | ||
73 | */ | 123 | */ |
74 | int hfs_part_find(struct super_block *sb, | 124 | int hfs_part_find(struct super_block *sb, |
75 | sector_t *part_start, sector_t *part_size) | 125 | sector_t *part_start, sector_t *part_size) |
76 | { | 126 | { |
77 | struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb); | 127 | void *data; |
78 | struct buffer_head *bh; | 128 | int res; |
79 | __be16 *data; | 129 | |
80 | int i, size, res; | 130 | data = kmalloc(HFSPLUS_SECTOR_SIZE, GFP_KERNEL); |
131 | if (!data) | ||
132 | return -ENOMEM; | ||
81 | 133 | ||
82 | res = -ENOENT; | 134 | res = hfsplus_submit_bio(sb->s_bdev, *part_start + HFS_PMAP_BLK, |
83 | bh = sb_bread512(sb, *part_start + HFS_PMAP_BLK, data); | 135 | data, READ); |
84 | if (!bh) | 136 | if (res) |
85 | return -EIO; | 137 | return res; |
86 | 138 | ||
87 | switch (be16_to_cpu(*data)) { | 139 | switch (be16_to_cpu(*((__be16 *)data))) { |
88 | case HFS_OLD_PMAP_MAGIC: | 140 | case HFS_OLD_PMAP_MAGIC: |
89 | { | 141 | res = hfs_parse_old_pmap(sb, data, part_start, part_size); |
90 | struct old_pmap *pm; | ||
91 | struct old_pmap_entry *p; | ||
92 | |||
93 | pm = (struct old_pmap *)bh->b_data; | ||
94 | p = pm->pdEntry; | ||
95 | size = 42; | ||
96 | for (i = 0; i < size; p++, i++) { | ||
97 | if (p->pdStart && p->pdSize && | ||
98 | p->pdFSID == cpu_to_be32(0x54465331)/*"TFS1"*/ && | ||
99 | (sbi->part < 0 || sbi->part == i)) { | ||
100 | *part_start += be32_to_cpu(p->pdStart); | ||
101 | *part_size = be32_to_cpu(p->pdSize); | ||
102 | res = 0; | ||
103 | } | ||
104 | } | ||
105 | break; | 142 | break; |
106 | } | ||
107 | case HFS_NEW_PMAP_MAGIC: | 143 | case HFS_NEW_PMAP_MAGIC: |
108 | { | 144 | res = hfs_parse_new_pmap(sb, data, part_start, part_size); |
109 | struct new_pmap *pm; | 145 | break; |
110 | 146 | default: | |
111 | pm = (struct new_pmap *)bh->b_data; | 147 | res = -ENOENT; |
112 | size = be32_to_cpu(pm->pmMapBlkCnt); | ||
113 | for (i = 0; i < size;) { | ||
114 | if (!memcmp(pm->pmPartType,"Apple_HFS", 9) && | ||
115 | (sbi->part < 0 || sbi->part == i)) { | ||
116 | *part_start += be32_to_cpu(pm->pmPyPartStart); | ||
117 | *part_size = be32_to_cpu(pm->pmPartBlkCnt); | ||
118 | res = 0; | ||
119 | break; | ||
120 | } | ||
121 | brelse(bh); | ||
122 | bh = sb_bread512(sb, *part_start + HFS_PMAP_BLK + ++i, pm); | ||
123 | if (!bh) | ||
124 | return -EIO; | ||
125 | if (pm->pmSig != cpu_to_be16(HFS_NEW_PMAP_MAGIC)) | ||
126 | break; | ||
127 | } | ||
128 | break; | 148 | break; |
129 | } | ||
130 | } | 149 | } |
131 | brelse(bh); | ||
132 | 150 | ||
151 | kfree(data); | ||
133 | return res; | 152 | return res; |
134 | } | 153 | } |