]> git.saurik.com Git - apple/hfs.git/blob - core/hfs_iokit.cpp
hfs-556.41.1.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 #include "hfs_cnode.h"
41
42 #ifndef panic_on_assert
43 bool panic_on_assert;
44 #endif
45
46 #if DEBUG
47 bool hfs_corruption_panics = true;
48 #endif
49
50 class com_apple_filesystems_hfs : public IOService {
51 OSDeclareDefaultStructors(com_apple_filesystems_hfs)
52
53 public:
54
55 bool start(IOService *provider) override;
56 void stop(IOService *provider) override;
57
58 protected:
59 vfstable_t vfs_handle;
60 };
61
62 #define super IOService
63 OSDefineMetaClassAndStructors(com_apple_filesystems_hfs, IOService)
64
65 extern struct vnodeopv_desc hfs_vnodeop_opv_desc;
66 #if CONFIG_HFS_STD
67 extern struct vnodeopv_desc hfs_std_vnodeop_opv_desc;
68 #endif
69 extern struct vnodeopv_desc hfs_specop_opv_desc;
70 extern struct vnodeopv_desc hfs_fifoop_opv_desc;
71 extern struct vfsops hfs_vfsops;
72
73 bool com_apple_filesystems_hfs::start(IOService *provider)
74 {
75 if (!super::start(provider))
76 return false;
77
78 #ifndef panic_on_assert
79 panic_on_assert = PE_i_can_has_kernel_configuration() & kPEICanHasAssertions;
80 #endif
81
82 #if DEBUG
83 PE_parse_boot_argn("hfs_corruption_panics", &hfs_corruption_panics, sizeof(hfs_corruption_panics));
84 #endif
85
86 struct vnodeopv_desc *op_descs[] = {
87 &hfs_vnodeop_opv_desc,
88 #if CONFIG_HFS_STD
89 &hfs_std_vnodeop_opv_desc,
90 #endif
91 &hfs_specop_opv_desc,
92 #if FIFO
93 &hfs_fifoop_opv_desc,
94 #endif
95 };
96
97 #define lengthof(x) (sizeof(x)/sizeof(*x))
98
99 #ifndef VFS_TBLVNOP_SECLUDE_RENAME
100 #define VFS_TBLVNOP_SECLUDE_RENAME 0
101 #endif
102
103 struct vfs_fsentry vfe = {
104 .vfe_vfsops = &hfs_vfsops,
105 .vfe_vopcnt = lengthof(op_descs),
106 .vfe_opvdescs = op_descs,
107 .vfe_fsname = "hfs",
108 .vfe_flags = (VFS_TBLNOTYPENUM | VFS_TBLLOCALVOL | VFS_TBLREADDIR_EXTENDED
109 | VFS_TBL64BITREADY | VFS_TBLVNOP_PAGEOUTV2 | VFS_TBLVNOP_PAGEINV2
110 | VFS_TBLTHREADSAFE | VFS_TBLCANMOUNTROOT | VFS_TBLVNOP_SECLUDE_RENAME
111 | VFS_TBLNATIVEXATTR)
112 };
113
114 int ret = vfs_fsadd(&vfe, &vfs_handle);
115
116 if (ret) {
117 printf("hfs: vfs_fsadd failed: %d!\n", ret);
118 vfs_handle = NULL;
119 return false;
120 }
121
122 hfs_init_zones();
123
124 hfs_sysctl_register();
125
126 uint32_t num_cpus;
127 size_t sz = sizeof(num_cpus);
128
129 if (sysctlbyname("hw.physicalcpu", &num_cpus, &sz, NULL, 0) == 0) {
130 if ((2 * num_cpus) > MAX_CACHED_ORIGINS_DEFAULT) {
131 _hfs_max_origins = 2 * num_cpus;
132 _hfs_max_file_origins = 2 * num_cpus;
133 } else if ((2 * num_cpus) > MAX_CACHED_FILE_ORIGINS_DEFAULT) {
134 _hfs_max_file_origins = 2 * num_cpus;
135 }
136 }
137
138 return true;
139 }
140
141 void com_apple_filesystems_hfs::stop(IOService *provider)
142 {
143 if (vfs_handle) {
144 vfs_fsremove(vfs_handle);
145 hfs_sysctl_unregister();
146 vfs_handle = NULL;
147 }
148
149 super::stop(provider);
150 }
151
152 int hfs_is_ejectable(const char *cdev_name)
153 {
154 int ret = 0;
155 OSDictionary *dictionary;
156 OSString *dev_name;
157
158 if (strncmp(cdev_name, "/dev/", 5) == 0) {
159 cdev_name += 5;
160 }
161
162 dictionary = IOService::serviceMatching("IOMedia");
163 if( dictionary ) {
164 dev_name = OSString::withCString( cdev_name );
165 if( dev_name ) {
166 IOService *service;
167 mach_timespec_t tv = { 5, 0 }; // wait up to "timeout" seconds for the device
168
169 dictionary->setObject(kIOBSDNameKey, dev_name);
170 dictionary->retain();
171 service = IOService::waitForService(dictionary, &tv);
172 if( service ) {
173 OSBoolean *ejectable = (OSBoolean *)service->getProperty("Ejectable");
174
175 if( ejectable ) {
176 ret = (int)ejectable->getValue();
177 }
178
179 }
180 dev_name->release();
181 }
182 dictionary->release();
183 }
184
185 return ret;
186 }
187
188 void hfs_iterate_media_with_content(const char *content_uuid_cstring,
189 int (*func)(const char *device,
190 const char *uuid_str,
191 void *arg),
192 void *arg)
193 {
194 OSDictionary *dictionary;
195 OSString *content_uuid_string;
196
197 dictionary = IOService::serviceMatching("IOMedia");
198 if (dictionary) {
199 content_uuid_string = OSString::withCString(content_uuid_cstring);
200 if (content_uuid_string) {
201 IOService *service;
202 OSIterator *iter;
203
204 dictionary->setObject("Content", content_uuid_string);
205 dictionary->retain();
206
207 iter = IOService::getMatchingServices(dictionary);
208 while (iter && (service = (IOService *)iter->getNextObject())) {
209 if (service) {
210 OSString *iostr = (OSString *) service->getProperty(kIOBSDNameKey);
211 OSString *uuidstr = (OSString *)service->getProperty("UUID");
212 const char *uuid;
213
214 if (iostr) {
215 if (uuidstr) {
216 uuid = uuidstr->getCStringNoCopy();
217 } else {
218 uuid = "00000000-0000-0000-0000-000000000000";
219 }
220
221 if (!func(iostr->getCStringNoCopy(), uuid, arg))
222 break;
223 }
224 }
225 }
226 if (iter)
227 iter->release();
228
229 content_uuid_string->release();
230 }
231 dictionary->release();
232 }
233 }
234
235 kern_return_t hfs_get_platform_serial_number(char *serial_number_str,
236 uint32_t len)
237 {
238 OSDictionary * platform_dict;
239 IOService *platform;
240 OSString * string;
241
242 if (len < 1) {
243 return 0;
244 }
245 serial_number_str[0] = '\0';
246
247 platform_dict = IOService::serviceMatching( "IOPlatformExpertDevice" );
248 if (platform_dict == NULL) {
249 return KERN_NOT_SUPPORTED;
250 }
251
252 platform = IOService::waitForService( platform_dict );
253 if (platform) {
254 string = (OSString *)platform->getProperty(kIOPlatformSerialNumberKey);
255 if (string == 0) {
256 return KERN_NOT_SUPPORTED;
257 } else {
258 strlcpy( serial_number_str, string->getCStringNoCopy(), len);
259 }
260 }
261
262 return KERN_SUCCESS;
263 }
264
265 // Interface with AKS
266
267 static aks_file_system_key_services_t *
268 key_services(void)
269 {
270 static aks_file_system_key_services_t *g_key_services;
271
272 if (!g_key_services) {
273 IOService *platform = IOService::getPlatform();
274 if (platform) {
275 IOReturn ret = platform->callPlatformFunction
276 (kAKSFileSystemKeyServices, true, &g_key_services, NULL, NULL, NULL);
277 if (ret)
278 printf("hfs: unable to get " kAKSFileSystemKeyServices " (0x%x)\n", ret);
279 }
280 }
281
282 return g_key_services;
283 }
284
285 int hfs_unwrap_key(aks_cred_t access, const aks_wrapped_key_t wrapped_key_in,
286 aks_raw_key_t key_out)
287 {
288 aks_file_system_key_services_t *ks = key_services();
289 if (!ks || !ks->unwrap_key)
290 return ENXIO;
291 return ks->unwrap_key(access, wrapped_key_in, key_out);
292 }
293
294 int hfs_rewrap_key(aks_cred_t access, cp_key_class_t dp_class,
295 const aks_wrapped_key_t wrapped_key_in,
296 aks_wrapped_key_t wrapped_key_out)
297 {
298 aks_file_system_key_services_t *ks = key_services();
299 if (!ks || !ks->rewrap_key)
300 return ENXIO;
301 return ks->rewrap_key(access, dp_class, wrapped_key_in, wrapped_key_out);
302 }
303
304 int hfs_new_key(aks_cred_t access, cp_key_class_t dp_class,
305 aks_raw_key_t key_out, aks_wrapped_key_t wrapped_key_out)
306 {
307 aks_file_system_key_services_t *ks = key_services();
308 if (!ks || !ks->new_key)
309 return ENXIO;
310 return ks->new_key(access, dp_class, key_out, wrapped_key_out);
311 }
312
313 int hfs_backup_key(aks_cred_t access, const aks_wrapped_key_t wrapped_key_in,
314 aks_wrapped_key_t wrapped_key_out)
315 {
316 aks_file_system_key_services_t *ks = key_services();
317 if (!ks || !ks->backup_key)
318 return ENXIO;
319 return ks->backup_key(access, wrapped_key_in, wrapped_key_out);
320 }