]> git.saurik.com Git - apple/hfs.git/blob - core/hfs_iokit.cpp
hfs-522.100.5.tar.gz
[apple/hfs.git] / core / hfs_iokit.cpp
1 /*
2 * Copyright (c) 2015 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #include <mach/mach_types.h>
30 #include <sys/mount.h>
31 #include <libkern/libkern.h>
32 #include <IOKit/IOService.h>
33 #include <IOKit/IOBSD.h>
34 #include <IOKit/IOKitKeys.h>
35 #include <IOKit/IOPlatformExpert.h>
36
37 #include "hfs_iokit.h"
38 #include "hfs.h"
39 #include "hfs_dbg.h"
40
41 #ifndef panic_on_assert
42 bool panic_on_assert;
43 #endif
44
45 #if DEBUG
46 bool hfs_corruption_panics = true;
47 #endif
48
49 class com_apple_filesystems_hfs : public IOService {
50 OSDeclareDefaultStructors(com_apple_filesystems_hfs)
51
52 public:
53
54 bool start(IOService *provider) override;
55 void stop(IOService *provider) override;
56
57 protected:
58 vfstable_t vfs_handle;
59 };
60
61 #define super IOService
62 OSDefineMetaClassAndStructors(com_apple_filesystems_hfs, IOService)
63
64 extern struct vnodeopv_desc hfs_vnodeop_opv_desc;
65 #if CONFIG_HFS_STD
66 extern struct vnodeopv_desc hfs_std_vnodeop_opv_desc;
67 #endif
68 extern struct vnodeopv_desc hfs_specop_opv_desc;
69 extern struct vnodeopv_desc hfs_fifoop_opv_desc;
70 extern struct vfsops hfs_vfsops;
71
72 bool com_apple_filesystems_hfs::start(IOService *provider)
73 {
74 if (!super::start(provider))
75 return false;
76
77 #ifndef panic_on_assert
78 panic_on_assert = PE_i_can_has_kernel_configuration() & kPEICanHasAssertions;
79 #endif
80
81 #if DEBUG
82 PE_parse_boot_argn("hfs_corruption_panics", &hfs_corruption_panics, sizeof(hfs_corruption_panics));
83 #endif
84
85 struct vnodeopv_desc *op_descs[] = {
86 &hfs_vnodeop_opv_desc,
87 #if CONFIG_HFS_STD
88 &hfs_std_vnodeop_opv_desc,
89 #endif
90 &hfs_specop_opv_desc,
91 #if FIFO
92 &hfs_fifoop_opv_desc,
93 #endif
94 };
95
96 #define lengthof(x) (sizeof(x)/sizeof(*x))
97
98 #ifndef VFS_TBLVNOP_SECLUDE_RENAME
99 #define VFS_TBLVNOP_SECLUDE_RENAME 0
100 #endif
101
102 struct vfs_fsentry vfe = {
103 .vfe_vfsops = &hfs_vfsops,
104 .vfe_vopcnt = lengthof(op_descs),
105 .vfe_opvdescs = op_descs,
106 .vfe_fsname = "hfs",
107 .vfe_flags = (VFS_TBLNOTYPENUM | VFS_TBLLOCALVOL | VFS_TBLREADDIR_EXTENDED
108 | VFS_TBL64BITREADY | VFS_TBLVNOP_PAGEOUTV2 | VFS_TBLVNOP_PAGEINV2
109 | VFS_TBLTHREADSAFE | VFS_TBLCANMOUNTROOT | VFS_TBLVNOP_SECLUDE_RENAME
110 | VFS_TBLNATIVEXATTR)
111 };
112
113 int ret = vfs_fsadd(&vfe, &vfs_handle);
114
115 if (ret) {
116 printf("hfs: vfs_fsadd failed: %d!\n", ret);
117 vfs_handle = NULL;
118 return false;
119 }
120
121 hfs_init_zones();
122
123 hfs_sysctl_register();
124
125 return true;
126 }
127
128 void com_apple_filesystems_hfs::stop(IOService *provider)
129 {
130 if (vfs_handle) {
131 vfs_fsremove(vfs_handle);
132 hfs_sysctl_unregister();
133 vfs_handle = NULL;
134 }
135
136 super::stop(provider);
137 }
138
139 int hfs_is_ejectable(const char *cdev_name)
140 {
141 int ret = 0;
142 OSDictionary *dictionary;
143 OSString *dev_name;
144
145 if (strncmp(cdev_name, "/dev/", 5) == 0) {
146 cdev_name += 5;
147 }
148
149 dictionary = IOService::serviceMatching("IOMedia");
150 if( dictionary ) {
151 dev_name = OSString::withCString( cdev_name );
152 if( dev_name ) {
153 IOService *service;
154 mach_timespec_t tv = { 5, 0 }; // wait up to "timeout" seconds for the device
155
156 dictionary->setObject(kIOBSDNameKey, dev_name);
157 dictionary->retain();
158 service = IOService::waitForService(dictionary, &tv);
159 if( service ) {
160 OSBoolean *ejectable = (OSBoolean *)service->getProperty("Ejectable");
161
162 if( ejectable ) {
163 ret = (int)ejectable->getValue();
164 }
165
166 }
167 dev_name->release();
168 }
169 dictionary->release();
170 }
171
172 return ret;
173 }
174
175 void hfs_iterate_media_with_content(const char *content_uuid_cstring,
176 int (*func)(const char *device,
177 const char *uuid_str,
178 void *arg),
179 void *arg)
180 {
181 OSDictionary *dictionary;
182 OSString *content_uuid_string;
183
184 dictionary = IOService::serviceMatching("IOMedia");
185 if (dictionary) {
186 content_uuid_string = OSString::withCString(content_uuid_cstring);
187 if (content_uuid_string) {
188 IOService *service;
189 OSIterator *iter;
190
191 dictionary->setObject("Content", content_uuid_string);
192 dictionary->retain();
193
194 iter = IOService::getMatchingServices(dictionary);
195 while (iter && (service = (IOService *)iter->getNextObject())) {
196 if (service) {
197 OSString *iostr = (OSString *) service->getProperty(kIOBSDNameKey);
198 OSString *uuidstr = (OSString *)service->getProperty("UUID");
199 const char *uuid;
200
201 if (iostr) {
202 if (uuidstr) {
203 uuid = uuidstr->getCStringNoCopy();
204 } else {
205 uuid = "00000000-0000-0000-0000-000000000000";
206 }
207
208 if (!func(iostr->getCStringNoCopy(), uuid, arg))
209 break;
210 }
211 }
212 }
213 if (iter)
214 iter->release();
215
216 content_uuid_string->release();
217 }
218 dictionary->release();
219 }
220 }
221
222 kern_return_t hfs_get_platform_serial_number(char *serial_number_str,
223 uint32_t len)
224 {
225 OSDictionary * platform_dict;
226 IOService *platform;
227 OSString * string;
228
229 if (len < 1) {
230 return 0;
231 }
232 serial_number_str[0] = '\0';
233
234 platform_dict = IOService::serviceMatching( "IOPlatformExpertDevice" );
235 if (platform_dict == NULL) {
236 return KERN_NOT_SUPPORTED;
237 }
238
239 platform = IOService::waitForService( platform_dict );
240 if (platform) {
241 string = (OSString *)platform->getProperty(kIOPlatformSerialNumberKey);
242 if (string == 0) {
243 return KERN_NOT_SUPPORTED;
244 } else {
245 strlcpy( serial_number_str, string->getCStringNoCopy(), len);
246 }
247 }
248
249 return KERN_SUCCESS;
250 }
251
252 // Interface with AKS
253
254 static aks_file_system_key_services_t *
255 key_services(void)
256 {
257 static aks_file_system_key_services_t *g_key_services;
258
259 if (!g_key_services) {
260 IOService *platform = IOService::getPlatform();
261 if (platform) {
262 IOReturn ret = platform->callPlatformFunction
263 (kAKSFileSystemKeyServices, true, &g_key_services, NULL, NULL, NULL);
264 if (ret)
265 printf("hfs: unable to get " kAKSFileSystemKeyServices " (0x%x)\n", ret);
266 }
267 }
268
269 return g_key_services;
270 }
271
272 int hfs_unwrap_key(aks_cred_t access, const aks_wrapped_key_t wrapped_key_in,
273 aks_raw_key_t key_out)
274 {
275 aks_file_system_key_services_t *ks = key_services();
276 if (!ks || !ks->unwrap_key)
277 return ENXIO;
278 return ks->unwrap_key(access, wrapped_key_in, key_out);
279 }
280
281 int hfs_rewrap_key(aks_cred_t access, cp_key_class_t dp_class,
282 const aks_wrapped_key_t wrapped_key_in,
283 aks_wrapped_key_t wrapped_key_out)
284 {
285 aks_file_system_key_services_t *ks = key_services();
286 if (!ks || !ks->rewrap_key)
287 return ENXIO;
288 return ks->rewrap_key(access, dp_class, wrapped_key_in, wrapped_key_out);
289 }
290
291 int hfs_new_key(aks_cred_t access, cp_key_class_t dp_class,
292 aks_raw_key_t key_out, aks_wrapped_key_t wrapped_key_out)
293 {
294 aks_file_system_key_services_t *ks = key_services();
295 if (!ks || !ks->new_key)
296 return ENXIO;
297 return ks->new_key(access, dp_class, key_out, wrapped_key_out);
298 }
299
300 int hfs_backup_key(aks_cred_t access, const aks_wrapped_key_t wrapped_key_in,
301 aks_wrapped_key_t wrapped_key_out)
302 {
303 aks_file_system_key_services_t *ks = key_services();
304 if (!ks || !ks->backup_key)
305 return ENXIO;
306 return ks->backup_key(access, wrapped_key_in, wrapped_key_out);
307 }