Blame view

fs/hfs/part_tbl.c 2.88 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
  /*
   *  linux/fs/hfs/part_tbl.c
   *
   * Copyright (C) 1996-1997  Paul H. Hargrove
   * (C) 2003 Ardis Technologies <roman@ardistech.com>
   * This file may be distributed under the terms of the GNU General Public License.
   *
   * Original code to handle the new style Mac partition table based on
   * a patch contributed by Holger Schemel (aeglos@valinor.owl.de).
   */
  
  #include "hfs_fs.h"
  
  /*
   * The new style Mac partition map
   *
   * For each partition on the media there is a physical block (512-byte
   * block) containing one of these structures.  These blocks are
   * contiguous starting at block 1.
   */
  struct new_pmap {
  	__be16	pmSig;		/* signature */
  	__be16	reSigPad;	/* padding */
  	__be32	pmMapBlkCnt;	/* partition blocks count */
  	__be32	pmPyPartStart;	/* physical block start of partition */
  	__be32	pmPartBlkCnt;	/* physical block count of partition */
  	u8	pmPartName[32];	/* (null terminated?) string
  				   giving the name of this
  				   partition */
  	u8	pmPartType[32];	/* (null terminated?) string
  				   giving the type of this
  				   partition */
  	/* a bunch more stuff we don't need */
  } __packed;
  
  /*
   * The old style Mac partition map
   *
   * The partition map consists for a 2-byte signature followed by an
   * array of these structures.  The map is terminated with an all-zero
   * one of these.
   */
  struct old_pmap {
  	__be16		pdSig;	/* Signature bytes */
  	struct 	old_pmap_entry {
  		__be32	pdStart;
  		__be32	pdSize;
  		__be32	pdFSID;
  	}	pdEntry[42];
  } __packed;
  
  /*
   * hfs_part_find()
   *
   * Parse the partition map looking for the
   * start and length of the 'part'th HFS partition.
   */
  int hfs_part_find(struct super_block *sb,
  		  sector_t *part_start, sector_t *part_size)
  {
  	struct buffer_head *bh;
  	__be16 *data;
  	int i, size, res;
  
  	res = -ENOENT;
  	bh = sb_bread512(sb, *part_start + HFS_PMAP_BLK, data);
  	if (!bh)
  		return -EIO;
  
  	switch (be16_to_cpu(*data)) {
  	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"*/ &&
  			    (HFS_SB(sb)->part < 0 || HFS_SB(sb)->part == i)) {
  				*part_start += be32_to_cpu(p->pdStart);
  				*part_size = be32_to_cpu(p->pdSize);
  				res = 0;
  			}
  		}
  		break;
  	  }
  	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) &&
  			    (HFS_SB(sb)->part < 0 || HFS_SB(sb)->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;
  		}
  		break;
  	  }
  	}
  	brelse(bh);
  
  	return res;
  }