chiark / gitweb /
[PATCH] udev_volume_id: new version of volume_id
[elogind.git] / extras / volume_id / volume_id / mac / mac.c
1 /*
2  * volume_id - reads filesystem label and uuid
3  *
4  * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5  *
6  *      This library is free software; you can redistribute it and/or
7  *      modify it under the terms of the GNU Lesser General Public
8  *      License as published by the Free Software Foundation; either
9  *      version 2.1 of the License, or (at your option) any later version.
10  *
11  *      This library is distributed in the hope that it will be useful,
12  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  *      Lesser General Public License for more details.
15  *
16  *      You should have received a copy of the GNU Lesser General Public
17  *      License along with this library; if not, write to the Free Software
18  *      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20
21 #ifndef _GNU_SOURCE
22 #define _GNU_SOURCE 1
23 #endif
24
25 #ifdef HAVE_CONFIG_H
26 #  include <config.h>
27 #endif
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <ctype.h>
35 #include <asm/types.h>
36
37 #include "../volume_id.h"
38 #include "../logging.h"
39 #include "../util.h"
40 #include "mac.h"
41
42 int volume_id_probe_mac_partition_map(struct volume_id *id, __u64 off)
43 {
44         struct mac_driver_desc {
45                 __u8    signature[2];
46                 __u16   block_size;
47                 __u32   block_count;
48         } __attribute__((__packed__)) *driver;
49
50         struct mac_partition {
51                 __u8    signature[2];
52                 __u16   res1;
53                 __u32   map_count;
54                 __u32   start_block;
55                 __u32   block_count;
56                 __u8    name[32];
57                 __u8    type[32];
58         } __attribute__((__packed__)) *part;
59
60         const __u8 *buf;
61
62         buf = volume_id_get_buffer(id, off, 0x200);
63         if (buf == NULL)
64                 return -1;
65
66         part = (struct mac_partition *) buf;
67         if ((strncmp(part->signature, "PM", 2) == 0) &&
68             (strncmp(part->type, "Apple_partition_map", 19) == 0)) {
69                 /* linux creates an own subdevice for the map
70                  * just return the type if the drive header is missing */
71                 volume_id_set_usage(id, VOLUME_ID_PARTITIONTABLE);
72                 id->type = "mac_partition_map";
73                 return 0;
74         }
75
76         driver = (struct mac_driver_desc *) buf;
77         if (strncmp(driver->signature, "ER", 2) == 0) {
78                 /* we are on a main device, like a CD
79                  * just try to probe the first partition from the map */
80                 unsigned int bsize = be16_to_cpu(driver->block_size);
81                 int part_count;
82                 int i;
83
84                 /* get first entry of partition table */
85                 buf = volume_id_get_buffer(id, off +  bsize, 0x200);
86                 if (buf == NULL)
87                         return -1;
88
89                 part = (struct mac_partition *) buf;
90                 if (strncmp(part->signature, "PM", 2) != 0)
91                         return -1;
92
93                 part_count = be32_to_cpu(part->map_count);
94                 dbg("expecting %d partition entries", part_count);
95
96                 if (id->partitions != NULL)
97                         free(id->partitions);
98                 id->partitions =
99                         malloc(part_count * sizeof(struct volume_id_partition));
100                 if (id->partitions == NULL)
101                         return -1;
102                 memset(id->partitions, 0x00, sizeof(struct volume_id_partition));
103
104                 id->partition_count = part_count;
105
106                 for (i = 0; i < part_count; i++) {
107                         __u64 poff;
108                         __u64 plen;
109
110                         buf = volume_id_get_buffer(id, off + ((i+1) * bsize), 0x200);
111                         if (buf == NULL)
112                                 return -1;
113
114                         part = (struct mac_partition *) buf;
115                         if (strncmp(part->signature, "PM", 2) != 0)
116                                 return -1;
117
118                         poff = be32_to_cpu(part->start_block) * bsize;
119                         plen = be32_to_cpu(part->block_count) * bsize;
120                         dbg("found '%s' partition entry at 0x%llx, len 0x%llx",
121                             part->type, poff, plen);
122
123                         id->partitions[i].off = poff;
124                         id->partitions[i].len = plen;
125
126                         if (strncmp(part->type, "Apple_Free", 10) == 0) {
127                                 volume_id_set_usage_part(&id->partitions[i], VOLUME_ID_UNUSED);
128                         } else if (strncmp(part->type, "Apple_partition_map", 19) == 0) {
129                                 volume_id_set_usage_part(&id->partitions[i], VOLUME_ID_PARTITIONTABLE);
130                         } else {
131                                 volume_id_set_usage_part(&id->partitions[i], VOLUME_ID_UNPROBED);
132                         }
133                 }
134                 volume_id_set_usage(id, VOLUME_ID_PARTITIONTABLE);
135                 id->type = "mac_partition_map";
136                 return 0;
137         }
138
139         return -1;
140 }