aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hfsplus/part_tbl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/hfsplus/part_tbl.c')
-rw-r--r--fs/hfsplus/part_tbl.c129
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 */
59struct old_pmap { 61struct 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
70static 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
91static 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 */
74int hfs_part_find(struct super_block *sb, 124int 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}