]> git.saurik.com Git - apple/hfs.git/blobdiff - core/hfs_iokit.cpp
hfs-366.1.1.tar.gz
[apple/hfs.git] / core / hfs_iokit.cpp
diff --git a/core/hfs_iokit.cpp b/core/hfs_iokit.cpp
new file mode 100644 (file)
index 0000000..ac9a43d
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2015 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#include <mach/mach_types.h>
+#include <sys/mount.h>
+#include <libkern/libkern.h>
+#include <IOKit/IOService.h>
+#include <IOKit/IOBSD.h>
+#include <IOKit/IOKitKeys.h>
+#include <IOKit/IOPlatformExpert.h>
+
+#include "hfs_iokit.h"
+#include "hfs.h"
+#include "hfs_dbg.h"
+
+#ifndef panic_on_assert
+bool panic_on_assert;
+#endif
+
+#if DEBUG
+bool hfs_corruption_panics = true;
+#endif
+
+class com_apple_filesystems_hfs : public IOService {
+    OSDeclareDefaultStructors(com_apple_filesystems_hfs)
+
+public:
+
+       bool start(IOService *provider) override;
+       void stop(IOService *provider) override;
+
+protected:
+       vfstable_t vfs_handle;
+};
+
+#define super IOService
+OSDefineMetaClassAndStructors(com_apple_filesystems_hfs, IOService)
+
+extern struct vnodeopv_desc hfs_vnodeop_opv_desc;
+#if CONFIG_HFS_STD
+extern struct vnodeopv_desc hfs_std_vnodeop_opv_desc;
+#endif
+extern struct vnodeopv_desc hfs_specop_opv_desc;
+extern struct vnodeopv_desc hfs_fifoop_opv_desc;
+extern struct vfsops hfs_vfsops;
+
+bool com_apple_filesystems_hfs::start(IOService *provider)
+{
+       if (!super::start(provider))
+               return false;
+
+#ifndef panic_on_assert
+       panic_on_assert = PE_i_can_has_kernel_configuration() & kPEICanHasAssertions;
+#endif
+
+#if DEBUG
+       PE_parse_boot_argn("hfs_corruption_panics", &hfs_corruption_panics, sizeof(hfs_corruption_panics));
+#endif
+
+       struct vnodeopv_desc *op_descs[] = {
+               &hfs_vnodeop_opv_desc,
+#if CONFIG_HFS_STD
+               &hfs_std_vnodeop_opv_desc,
+#endif
+               &hfs_specop_opv_desc,
+#if FIFO
+               &hfs_fifoop_opv_desc,
+#endif
+       };
+
+#define lengthof(x) (sizeof(x)/sizeof(*x))
+
+#ifndef VFS_TBLVNOP_SECLUDE_RENAME
+#define VFS_TBLVNOP_SECLUDE_RENAME 0
+#endif
+
+       struct vfs_fsentry vfe = {
+               .vfe_vfsops = &hfs_vfsops,
+               .vfe_vopcnt = lengthof(op_descs),
+               .vfe_opvdescs = op_descs,
+               .vfe_fsname = "hfs",
+               .vfe_flags = (VFS_TBLNOTYPENUM | VFS_TBLLOCALVOL | VFS_TBLREADDIR_EXTENDED
+                                         | VFS_TBL64BITREADY | VFS_TBLVNOP_PAGEOUTV2 | VFS_TBLVNOP_PAGEINV2
+                                         | VFS_TBLTHREADSAFE | VFS_TBLCANMOUNTROOT | VFS_TBLVNOP_SECLUDE_RENAME
+                                         | VFS_TBLNATIVEXATTR)
+       };
+
+       int ret = vfs_fsadd(&vfe, &vfs_handle);
+
+       if (ret) {
+               printf("hfs: vfs_fsadd failed: %d!\n", ret);
+               vfs_handle = NULL;
+               return false;
+       }
+
+       hfs_sysctl_register();
+
+       return true;
+}
+
+void com_apple_filesystems_hfs::stop(IOService *provider)
+{
+       if (vfs_handle) {
+               vfs_fsremove(vfs_handle);
+               hfs_sysctl_unregister();
+               vfs_handle = NULL;
+       }
+
+       super::stop(provider);
+}
+
+int hfs_is_ejectable(const char *cdev_name)
+{
+       int ret = 0;
+       OSDictionary *dictionary;
+       OSString *dev_name;
+
+       if (strncmp(cdev_name, "/dev/", 5) == 0) {
+               cdev_name += 5;
+       }
+
+       dictionary = IOService::serviceMatching("IOMedia");
+       if( dictionary ) {
+               dev_name = OSString::withCString( cdev_name );
+               if( dev_name ) {
+                       IOService *service;
+                       mach_timespec_t tv = { 5, 0 };    // wait up to "timeout" seconds for the device
+
+                       dictionary->setObject(kIOBSDNameKey, dev_name);
+                       dictionary->retain();
+                       service = IOService::waitForService(dictionary, &tv);
+                       if( service ) {
+                               OSBoolean *ejectable = (OSBoolean *)service->getProperty("Ejectable");
+
+                               if( ejectable ) {
+                                       ret = (int)ejectable->getValue();
+                               }
+
+                       }
+                       dev_name->release();
+               }
+               dictionary->release();
+       }
+
+       return ret;
+}
+
+void hfs_iterate_media_with_content(const char *content_uuid_cstring,
+                                                                       int (*func)(const char *device,
+                                                                                               const char *uuid_str,
+                                                                                               void *arg),
+                                                                       void *arg)
+{
+       OSDictionary *dictionary;
+       OSString *content_uuid_string;
+
+       dictionary = IOService::serviceMatching("IOMedia");
+       if (dictionary) {
+               content_uuid_string = OSString::withCString(content_uuid_cstring);
+               if (content_uuid_string) {
+                       IOService *service;
+                       OSIterator *iter;
+
+                       dictionary->setObject("Content", content_uuid_string);
+                       dictionary->retain();
+
+                       iter = IOService::getMatchingServices(dictionary);
+                       while (iter && (service = (IOService *)iter->getNextObject())) {
+                               if (service) {
+                                       OSString *iostr = (OSString *) service->getProperty(kIOBSDNameKey);
+                                       OSString *uuidstr = (OSString *)service->getProperty("UUID");
+                                       const char *uuid;
+
+                                       if (iostr) {
+                                               if (uuidstr) {
+                                                       uuid = uuidstr->getCStringNoCopy();
+                                               } else {
+                                                       uuid = "00000000-0000-0000-0000-000000000000";
+                                               }
+
+                                               if (!func(iostr->getCStringNoCopy(), uuid, arg))
+                                                       break;
+                                       }
+                               }
+                       }
+                       if (iter)
+                               iter->release();
+
+                       content_uuid_string->release();
+               }
+               dictionary->release();
+       }
+}
+
+kern_return_t hfs_get_platform_serial_number(char *serial_number_str,
+                                                                                        uint32_t len)
+{
+       OSDictionary * platform_dict;
+       IOService *platform;
+       OSString *  string;
+
+       if (len < 1) {
+               return 0;
+       }
+       serial_number_str[0] = '\0';
+
+       platform_dict = IOService::serviceMatching( "IOPlatformExpertDevice" );
+       if (platform_dict == NULL) {
+               return KERN_NOT_SUPPORTED;
+       }
+
+       platform = IOService::waitForService( platform_dict );
+       if (platform) {
+               string = (OSString *)platform->getProperty(kIOPlatformSerialNumberKey);
+               if (string == 0) {
+                       return KERN_NOT_SUPPORTED;
+               } else {
+                       strlcpy( serial_number_str, string->getCStringNoCopy(), len);
+               }
+       }
+
+       return KERN_SUCCESS;
+}
+
+// Interface with AKS
+
+static aks_file_system_key_services_t *
+key_services(void)
+{
+       static aks_file_system_key_services_t *g_key_services;
+
+       if (!g_key_services) {
+               IOService *platform = IOService::getPlatform();
+               if (platform) {
+                       IOReturn ret = platform->callPlatformFunction
+                               (kAKSFileSystemKeyServices, true, &g_key_services, NULL, NULL, NULL);
+                       if (ret)
+                               printf("hfs: unable to get " kAKSFileSystemKeyServices " (0x%x)\n", ret);
+               }
+       }
+
+       return g_key_services;
+}
+
+int hfs_unwrap_key(aks_cred_t access, const aks_wrapped_key_t wrapped_key_in,
+                                  aks_raw_key_t key_out)
+{
+       aks_file_system_key_services_t *ks = key_services();
+       if (!ks || !ks->unwrap_key)
+               return ENXIO;
+       return ks->unwrap_key(access, wrapped_key_in, key_out);
+}
+
+int hfs_rewrap_key(aks_cred_t access, cp_key_class_t dp_class,
+                                  const aks_wrapped_key_t wrapped_key_in,
+                                  aks_wrapped_key_t wrapped_key_out)
+{
+       aks_file_system_key_services_t *ks = key_services();
+       if (!ks || !ks->rewrap_key)
+               return ENXIO;
+       return ks->rewrap_key(access, dp_class, wrapped_key_in, wrapped_key_out);
+}
+
+int hfs_new_key(aks_cred_t access, cp_key_class_t dp_class,
+                               aks_raw_key_t key_out, aks_wrapped_key_t wrapped_key_out)
+{
+       aks_file_system_key_services_t *ks = key_services();
+       if (!ks || !ks->new_key)
+               return ENXIO;
+       return ks->new_key(access, dp_class, key_out, wrapped_key_out);
+}
+
+int hfs_backup_key(aks_cred_t access, const aks_wrapped_key_t wrapped_key_in,
+                                  aks_wrapped_key_t wrapped_key_out)
+{
+       aks_file_system_key_services_t *ks = key_services();
+       if (!ks || !ks->backup_key)
+               return ENXIO;
+       return ks->backup_key(access, wrapped_key_in, wrapped_key_out);
+}