vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / kernel / partitioning_systems / apple / apple.cpp
blob848ac1a36b21eabea54f4110152f3b4e40a4d1cc
1 /*
2 ** Copyright 2003-2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3 ** Distributed under the terms of the Haiku License.
4 */
7 #include "apple.h"
9 #include <ddm_modules.h>
10 #include <disk_device_types.h>
11 #include <KernelExport.h>
12 #ifdef _BOOT_MODE
13 # include <boot/partitions.h>
14 #else
15 # include <DiskDeviceTypes.h>
16 #endif
17 #include <util/kernel_cpp.h>
19 #include <unistd.h>
20 #include <string.h>
23 #define TRACE_APPLE 0
24 #if TRACE_APPLE
25 # define TRACE(x) dprintf x
26 #else
27 # define TRACE(x) ;
28 #endif
30 #define APPLE_PARTITION_MODULE_NAME "partitioning_systems/apple/v1"
32 static const char *kApplePartitionTypes[] = {
33 "partition_map", // the partition map itself
34 "Driver", // contains a device driver
35 "Driver43", // the SCSI 4.3 manager
36 "MFS", // Macintosh File System
37 "HFS", // Hierarchical File System (HFS/HFS+)
38 "Unix_SVR2", // UFS
39 "PRODOS",
40 "Free", // unused partition
41 "Scratch", // empty partition
42 "Driver_ATA", // the device driver for an ATA device
43 "Driver_ATAPI", // the device driver for an ATAPI device
44 "Driver43_CD", // an SCSI CD-ROM driver suitable for booting
45 "FWDriver", // a FireWire driver for the device
46 "Void", // dummy partition map entry (used to align entries for CD-ROM)
47 "Patches",
48 NULL
50 #if 0
51 static const char *kOtherPartitionTypes[] = {
52 "Be_BFS", // Be's BFS (not specified endian)
54 #endif
56 static status_t
57 get_next_partition(int fd, apple_driver_descriptor &descriptor, uint32 &cookie,
58 apple_partition_map &partition)
60 uint32 block = cookie;
62 // find first partition map if this is the first call,
63 // or else, just load the next block
64 do {
65 ssize_t bytesRead = read_pos(fd, (off_t)block * descriptor.BlockSize(),
66 (void *)&partition, sizeof(apple_partition_map));
67 if (bytesRead < (ssize_t)sizeof(apple_partition_map))
68 return B_ERROR;
70 block++;
71 } while (cookie == 0 && block < 64 && !partition.HasValidSignature());
73 if (!partition.HasValidSignature()) {
74 if (cookie)
75 return B_ENTRY_NOT_FOUND;
77 // we searched for the first partition map entry and failed
78 return B_ERROR;
81 // the first partition map entry must be of type Apple_partition_map
82 if (!cookie && (strncmp(partition.type, "Apple_", 6)
83 || strcmp(partition.type + 6, kApplePartitionTypes[0])))
84 return B_ERROR;
86 // ToDo: warn about unknown types?
88 cookie = block;
89 return B_OK;
93 // #pragma mark -
94 // Apple public module interface
97 static status_t
98 apple_std_ops(int32 op, ...)
100 switch (op) {
101 case B_MODULE_INIT:
102 case B_MODULE_UNINIT:
103 return B_OK;
106 return B_ERROR;
110 static float
111 apple_identify_partition(int fd, partition_data *partition, void **_cookie)
113 struct apple_driver_descriptor *descriptor;
114 uint8 buffer[512];
116 if (read_pos(fd, 0, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer))
117 return B_ERROR;
119 descriptor = (apple_driver_descriptor *)buffer;
121 TRACE(("apple: read first chunk (signature = %x)\n", descriptor->signature));
123 if (!descriptor->HasValidSignature())
124 return B_ERROR;
126 TRACE(("apple: valid partition descriptor!\n"));
128 // ToDo: Should probably call get_next_partition() once to know if there
129 // are any partitions on this disk
131 // copy the relevant part of the first block
132 descriptor = new apple_driver_descriptor();
133 memcpy(descriptor, buffer, sizeof(apple_driver_descriptor));
135 *_cookie = (void *)descriptor;
137 // ToDo: reevaluate the priority with ISO-9660 and others in mind
138 // (for CD-ROM only, as far as I can tell)
139 return 0.5f;
143 static status_t
144 apple_scan_partition(int fd, partition_data *partition, void *_cookie)
146 TRACE(("apple_scan_partition(cookie = %p)\n", _cookie));
148 apple_driver_descriptor &descriptor = *(apple_driver_descriptor *)_cookie;
150 partition->status = B_PARTITION_VALID;
151 partition->flags |= B_PARTITION_PARTITIONING_SYSTEM
152 | B_PARTITION_READ_ONLY;
153 partition->content_size = descriptor.BlockSize() * descriptor.BlockCount();
155 // scan all children
157 apple_partition_map partitionMap;
158 uint32 index = 0, cookie = 0;
159 status_t status;
161 while ((status = get_next_partition(fd, descriptor, cookie, partitionMap)) == B_OK) {
162 TRACE(("apple: found partition: name = \"%s\", type = \"%s\"\n",
163 partitionMap.name, partitionMap.type));
165 if (partitionMap.Start(descriptor) + partitionMap.Size(descriptor) > (uint64)partition->size) {
166 TRACE(("apple: child partition exceeds existing space (%Ld bytes)\n",
167 partitionMap.Size(descriptor)));
168 continue;
171 partition_data *child = create_child_partition(partition->id, index++,
172 partition->offset + partitionMap.Start(descriptor),
173 partitionMap.Size(descriptor), -1);
174 if (child == NULL) {
175 TRACE(("apple: Creating child at index %ld failed\n", index - 1));
176 return B_ERROR;
179 child->block_size = partition->block_size;
182 if (status == B_ENTRY_NOT_FOUND)
183 return B_OK;
185 return status;
189 static void
190 apple_free_identify_partition_cookie(partition_data *partition, void *_cookie)
192 delete (apple_driver_descriptor *)_cookie;
196 #ifndef _BOOT_MODE
197 static partition_module_info sApplePartitionModule = {
198 #else
199 partition_module_info gApplePartitionModule = {
200 #endif
202 APPLE_PARTITION_MODULE_NAME,
204 apple_std_ops
206 "apple", // short_name
207 APPLE_PARTITION_NAME, // pretty_name
208 0, // flags
210 // scanning
211 apple_identify_partition, // identify_partition
212 apple_scan_partition, // scan_partition
213 apple_free_identify_partition_cookie, // free_identify_partition_cookie
214 NULL,
217 #ifndef _BOOT_MODE
218 partition_module_info *modules[] = {
219 &sApplePartitionModule,
220 NULL
222 #endif