[
  {
    "path": ".gitignore",
    "content": "Archive\nDerivedData\nxcuserdata\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"ThirdParty/Sparkle\"]\n\tpath = ThirdParty/Sparkle\n\turl = ../Sparkle.git\n[submodule \"ZFSWrapper\"]\n\tpath = ZFSWrapper\n\turl = ../ZFSWrapper\n"
  },
  {
    "path": "CommonAuthorization/CommonAuthorization.h",
    "content": "//\n//  CommonAuthorization.h\n//  ZetaWatch\n//\n//  Created by cbreak on 18.01.01.\n//  Copyright © 2018 the-color-black.net. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n@interface CommonAuthorization : NSObject\n\n//! For a given command selector, return the associated authorization right name.\n+ (NSString *)authorizationRightForCommand:(SEL)command;\n\n//! Set up the default authorization rights in the authorization database.\n+ (void)setupAuthorizationRights:(AuthorizationRef)authRef;\n\n@end\n"
  },
  {
    "path": "CommonAuthorization/CommonAuthorization.m",
    "content": "//\n//  CommonAuthorization.m\n//  ZetaWatch\n//\n//  Created by cbreak on 18.01.01.\n//  Copyright © 2018 the-color-black.net. All rights reserved.\n//\n\n#import \"CommonAuthorization.h\"\n\n#import \"ZetaAuthorizationHelperProtocol.h\"\n\n@implementation CommonAuthorization\n\nstatic NSString * kKeyAuthRightName    = @\"authRightName\";\nstatic NSString * kKeyAuthRightDefault = @\"authRightDefault\";\nstatic NSString * kKeyAuthRightDesc    = @\"authRightDescription\";\n\n/*!\n +commandInfo returns a dictionary that represents everything we need to know about the\n authorized commands supported by the app.  Each dictionary key is the string form of\n the command selector.  The corresponding object is a dictionary that contains three items:\n\n o kKeyAuthRightName is the name of the authorization right itself.  This is used by\n both the app (when creating rights and when pre-authorizing rights) and by the tool\n (when doing the final authorization check).\n\n o kKeyAuthRightDefault is the default right specification, used by the app to when\n it needs to create the default right specification.  This is commonly a string contacting\n a rule a name, but it can potentially be more complex.  See the discussion of the\n rightDefinition parameter of AuthorizationRightSet.\n\n o kKeyAuthRightDesc is a user-visible description of the right. This is used by the\n app when it needs to create the default right specification. Actually, string is used\n to look up a localized version of the string in \"CommonAuthorization.strings\".\n This file is generated by the \"genstrings\" cli application.\n */\n+ (NSDictionary *)commandInfo\n{\n\tstatic dispatch_once_t sOnceToken;\n\tstatic NSDictionary * sCommandInfo;\n\n\tdispatch_once(&sOnceToken,^{\n\t\tNSDictionary * dictStop =\n\t\t@{\n\t\t  kKeyAuthRightName: @\"net.the-color-black.ZetaWatch.stop\",\n\t\t  kKeyAuthRightDefault: @kAuthorizationRuleClassAllow,\n\t\t  kKeyAuthRightDesc: NSLocalizedString(\n\t\t\t\t\t\t\t\t\t\t\t   @\"ZetaWatch is trying stop its helper.\",\n\t\t\t\t\t\t\t\t\t\t\t   @\"prompt shown when user is required to authorize helper termination\"\n\t\t\t\t\t\t\t\t\t\t\t   )\n\t\t  };\n\t\tNSDictionary * dictImport =\n\t\t@{\n\t\t  kKeyAuthRightName: @\"net.the-color-black.ZetaWatch.import\",\n\t\t  kKeyAuthRightDefault: @kAuthorizationRuleClassAllow,\n\t\t  kKeyAuthRightDesc: NSLocalizedString(\n\t\t\t\t\t\t\t\t\t\t\t   @\"ZetaWatch is trying to import a pool.\",\n\t\t\t\t\t\t\t\t\t\t\t   @\"prompt shown when user is required to authorize a zpool import\"\n\t\t\t\t\t\t\t\t\t\t\t   )\n\t\t  };\n\t\tNSDictionary * dictExport =\n\t\t@{\n\t\t  kKeyAuthRightName: @\"net.the-color-black.ZetaWatch.export\",\n\t\t  kKeyAuthRightDefault: @kAuthorizationRuleClassAllow,\n\t\t  kKeyAuthRightDesc: NSLocalizedString(\n\t\t\t\t\t\t\t\t\t\t\t   @\"ZetaWatch is trying to export a pool.\",\n\t\t\t\t\t\t\t\t\t\t\t   @\"prompt shown when user is required to authorize a zpool export\"\n\t\t\t\t\t\t\t\t\t\t\t   )\n\t\t  };\n\t\tNSDictionary * dictMount =\n\t\t@{\n\t\t  kKeyAuthRightName: @\"net.the-color-black.ZetaWatch.mount\",\n\t\t  kKeyAuthRightDefault: @kAuthorizationRuleClassAllow,\n\t\t  kKeyAuthRightDesc: NSLocalizedString(\n\t\t\t\t\t\t\t\t\t\t\t   @\"ZetaWatch is trying to mount a filesystem.\",\n\t\t\t\t\t\t\t\t\t\t\t   @\"prompt shown when user is required to authorize a zfs mount\"\n\t\t\t\t\t\t\t\t\t\t\t   )\n\t\t  };\n\t\tNSDictionary * dictUnmount =\n\t\t@{\n\t\t  kKeyAuthRightName: @\"net.the-color-black.ZetaWatch.unmount\",\n\t\t  kKeyAuthRightDefault: @kAuthorizationRuleClassAllow,\n\t\t  kKeyAuthRightDesc: NSLocalizedString(\n\t\t\t\t\t\t\t\t\t\t\t   @\"ZetaWatch is trying to unmount a filesystem.\",\n\t\t\t\t\t\t\t\t\t\t\t   @\"prompt shown when user is required to authorize a zfs unmount\"\n\t\t\t\t\t\t\t\t\t\t\t   )\n\t\t  };\n\t\tNSDictionary * dictSnapshot =\n\t\t@{\n\t\t  kKeyAuthRightName: @\"net.the-color-black.ZetaWatch.snapshot\",\n\t\t  kKeyAuthRightDefault: @kAuthorizationRuleClassAllow,\n\t\t  kKeyAuthRightDesc: NSLocalizedString(\n\t\t\t\t\t\t\t\t\t\t\t   @\"ZetaWatch is trying to snapshot a filesystem.\",\n\t\t\t\t\t\t\t\t\t\t\t   @\"prompt shown when user is required to authorize a zfs snapshot\"\n\t\t\t\t\t\t\t\t\t\t\t   )\n\t\t  };\n\t\tNSDictionary * dictRollback =\n\t\t@{\n\t\t  kKeyAuthRightName: @\"net.the-color-black.ZetaWatch.rollback\",\n\t\t  kKeyAuthRightDefault: @kAuthorizationRuleAuthenticateAsAdmin,\n\t\t  kKeyAuthRightDesc: NSLocalizedString(\n\t\t\t\t\t\t\t\t\t\t\t   @\"ZetaWatch is trying to roll back a filesystem.\",\n\t\t\t\t\t\t\t\t\t\t\t   @\"prompt shown when user is required to authorize a zfs rollback\"\n\t\t\t\t\t\t\t\t\t\t\t   )\n\t\t  };\n\t\tNSDictionary * dictClone =\n\t\t@{\n\t\t  kKeyAuthRightName: @\"net.the-color-black.ZetaWatch.clone\",\n\t\t  kKeyAuthRightDefault: @kAuthorizationRuleAuthenticateAsAdmin,\n\t\t  kKeyAuthRightDesc: NSLocalizedString(\n\t\t\t\t\t\t\t\t\t\t\t   @\"ZetaWatch is trying to clone a snapshot.\",\n\t\t\t\t\t\t\t\t\t\t\t   @\"prompt shown when user is required to authorize a zfs clone\"\n\t\t\t\t\t\t\t\t\t\t\t   )\n\t\t  };\n\t\tNSDictionary * dictCreate =\n\t\t@{\n\t\t  kKeyAuthRightName: @\"net.the-color-black.ZetaWatch.create\",\n\t\t  kKeyAuthRightDefault: @kAuthorizationRuleAuthenticateAsAdmin,\n\t\t  kKeyAuthRightDesc: NSLocalizedString(\n\t\t\t\t\t\t\t\t\t\t\t   @\"ZetaWatch is trying to create a filesystem.\",\n\t\t\t\t\t\t\t\t\t\t\t   @\"prompt shown when user is required to authorize a zfs create\"\n\t\t\t\t\t\t\t\t\t\t\t   )\n\t\t  };\n\t\tNSDictionary * dictDestroy =\n\t\t@{\n\t\t  kKeyAuthRightName: @\"net.the-color-black.ZetaWatch.destroy\",\n\t\t  kKeyAuthRightDefault: @kAuthorizationRuleAuthenticateAsAdmin,\n\t\t  kKeyAuthRightDesc: NSLocalizedString(\n\t\t\t\t\t\t\t\t\t\t\t   @\"ZetaWatch is trying to destroy a filesystem.\",\n\t\t\t\t\t\t\t\t\t\t\t   @\"prompt shown when user is required to authorize a zfs destroy\"\n\t\t\t\t\t\t\t\t\t\t\t   )\n\t\t  };\n\t\tNSDictionary * dictKey =\n\t\t@{\n\t\t  kKeyAuthRightName: @\"net.the-color-black.ZetaWatch.key\",\n\t\t  kKeyAuthRightDefault: @kAuthorizationRuleClassAllow,\n\t\t  kKeyAuthRightDesc: NSLocalizedString(\n\t\t\t\t\t\t\t\t\t\t\t   @\"ZetaWatch is trying to operate on an encryption key.\",\n\t\t\t\t\t\t\t\t\t\t\t   @\"prompt shown when user is required to authorize a crypto key operation\"\n\t\t\t\t\t\t\t\t\t\t\t   )\n\t\t  };\n\t\tNSDictionary * dictScrub =\n\t\t@{\n\t\t  kKeyAuthRightName: @\"net.the-color-black.ZetaWatch.scrub\",\n\t\t  kKeyAuthRightDefault: @kAuthorizationRuleClassAllow,\n\t\t  kKeyAuthRightDesc: NSLocalizedString(\n\t\t\t\t\t\t\t\t\t\t\t   @\"ZetaWatch is trying to scrub a pool.\",\n\t\t\t\t\t\t\t\t\t\t\t   @\"prompt shown when user is required to authorize a zpool scrub\"\n\t\t\t\t\t\t\t\t\t\t\t   )\n\t\t  };\n\n\t\tsCommandInfo =\n\t\t@{\n\t\t  NSStringFromSelector(@selector(stopHelperWithAuthorization:withReply:)): dictStop,\n\t\t  NSStringFromSelector(@selector(importPools:authorization:withReply:)): dictImport,\n\t\t  NSStringFromSelector(@selector(importablePools:authorization:withReply:)): dictImport,\n\t\t  NSStringFromSelector(@selector(exportPools:authorization:withReply:)): dictExport,\n\t\t  NSStringFromSelector(@selector(mountFilesystems:authorization:withReply:)): dictMount,\n\t\t  NSStringFromSelector(@selector(unmountFilesystems:authorization:withReply:)): dictUnmount,\n\t\t  NSStringFromSelector(@selector(snapshotFilesystem:authorization:withReply:)):\n\t\t\t  dictSnapshot,\n\t\t  NSStringFromSelector(@selector(rollbackFilesystem:authorization:withReply:)):\n\t\t\t  dictRollback,\n\t\t  NSStringFromSelector(@selector(cloneSnapshot:authorization:withReply:)):\n\t\t\t  dictClone,\n\t\t  NSStringFromSelector(@selector(createFilesystem:authorization:withReply:)):\n\t\t\t  dictCreate,\n\t\t  NSStringFromSelector(@selector(createVolume:authorization:withReply:)):\n\t\t\t  dictCreate,\n\t\t  NSStringFromSelector(@selector(destroy:authorization:withReply:)):\n\t\t\t  dictDestroy,\n\t\t  NSStringFromSelector(@selector(loadKeyForFilesystem:authorization:withReply:)): dictKey,\n\t\t  NSStringFromSelector(@selector(unloadKeyForFilesystem:authorization:withReply:)): dictKey,\n\t\t  NSStringFromSelector(@selector(scrubPool:authorization:withReply:)): dictScrub,\n\t\t  };\n\t});\n\n\treturn sCommandInfo;\n}\n\n+ (NSString *)authorizationRightForCommand:(SEL)command\n{\n\treturn [self commandInfo][NSStringFromSelector(command)][kKeyAuthRightName];\n}\n\n+ (void)enumerateRightsUsingBlock:(void (^)(NSString * authRightName, id authRightDefault, NSString * authRightDesc))block\n{\n\t[self.commandInfo enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL * stop)\n\t{\n\t\tNSDictionary * commandDict = (NSDictionary *) obj;\n\t\tassert([commandDict isKindOfClass:[NSDictionary class]]);\n\n\t\tNSString * authRightName = [commandDict objectForKey:kKeyAuthRightName];\n\t\tassert([authRightName isKindOfClass:[NSString class]]);\n\n\t\tid authRightDefault = [commandDict objectForKey:kKeyAuthRightDefault];\n\t\tassert(authRightDefault != nil);\n\n\t\tNSString * authRightDesc = [commandDict objectForKey:kKeyAuthRightDesc];\n\t\tassert([authRightDesc isKindOfClass:[NSString class]]);\n\n\t\tblock(authRightName, authRightDefault, authRightDesc);\n\t}];\n}\n\n+ (void)setupAuthorizationRights:(AuthorizationRef)authRef\n// See comment in header.\n{\n\tassert(authRef != NULL);\n\t[CommonAuthorization enumerateRightsUsingBlock:^(NSString * authRightName, id authRightDefault, NSString * authRightDesc)\n\t{\n\t\t// First get the right.  If we get back errAuthorizationDenied that means there's\n\t\t// no current definition, so we add our default one.\n\n\t\tOSStatus blockErr = AuthorizationRightGet([authRightName UTF8String], NULL);\n\t\tif (blockErr == errAuthorizationDenied)\n\t\t{\n\t\t\tblockErr = AuthorizationRightSet(authRef, [authRightName UTF8String],\n\t\t\t\t\t\t\t\t\t\t\t (__bridge CFTypeRef)authRightDefault,\n\t\t\t\t\t\t\t\t\t\t\t (__bridge CFStringRef)authRightDesc,\n\t\t\t\t\t\t\t\t\t\t\t NULL, CFSTR(\"CommonAuthorization\")\n\t\t\t\t\t\t\t\t\t\t\t );\n\t\t\tassert(blockErr == errAuthorizationSuccess);\n\t\t}\n\t}];\n}\n\n@end\n"
  },
  {
    "path": "LICENSE.md",
    "content": "Copyright (c) 2014, Gerhard Röthlin\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\n* Neither the name of the Project nor the names of its\n  contributors may be used to endorse or promote products derived from\n  this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "README.md",
    "content": "ZetaWatch\n=========\n\n![ZetaWatch displaying pool status and filesystems][ZFSImage]\n\nZetaWatch is a small OS X program that displays the zfs status in the menu bar, similar to\nwhat iStat Menus does for other information. It is fairly well tested, but due to the\ncurrent state of libzfs and libzfs_core, changes will be required until the API\nstabilizes. ZetaWatch is usually compiled for the latest available [ZFS release for Mac\nOS](https://openzfsonosx.org/), and might not be compatible with other releases.\n\nCurrently supported features are:\n\n * Show pool, vdev, filesystem stats\n * Show pool / filesystem properties\n * Start, stop, pause scrubs, and monitor their progress.\n * Import and Export pools manually, or auto-import when they become available\n * Mount / unmount datasets manually or at pool import automatically\n * Load/Unload encryption keys for encrypted datasets manually or automatically\n * Optionally store pass phrases in the Mac OS X Keychain\n * Create, Display, Delete, Clone Snapshots or roll back to them\n * Report errors in notification center when they are discovered\n\n\nInstallation\n------------\n\nZetaWatch Releases can be downloaded from the [GitHub Releases Page](https://github.com/cbreak-black/ZetaWatch/releases).\nPlease verify that the Version of ZetaWatch matches your ZFS Version. Usually,\nonly the newest official Release is supported, since code changes are sometimes\nrequired to be fully compatible with the new library version.\n\nZetaWatch does not require manual installation. Simply copy it into /Application or where\never else it fits. The bundled helper tool gets installed automatically the first time the\nprogram is started. This requires user-authentication.\n\nZetaWatch supports auto updates, if enabled.\n\n\nFor Developers\n==============\n\nZFS Interaction\n---------------\n\nZetaWatch communicates with zfs using `libzfs.dylib`, `libzfs_core.dylib` ,\n`libzpool.dylib` and `libnvpair.dylib`, just like the command line tools do. This gives\nit all the flexibility of the command line tools, at the cost of having to reimplement\nfunctionality that is found in the tools and not the library. And since the libraries are\nexplicitly not meant to provide a stable ABI, ZetaWatch is also closely coupled to the\nZFS version it is built and written for.\n\nAll the ZFS interaction is wrapped in the ZFSWrapper library. This C++ library isolates\nthe issues mentioned above and provides a more convenient and safe API than the original\nC interface does. The library is used both by the helper tool and the frontend app. This\nis the most reusable part of ZetaWatch, and might be split out as separate project later.\n\n * *ZFSUtils* contains most of the advanced functionality, such as C++ Wrappers around the\nlibrary, pool, vdev or file system handles. Those classes also have functionality to query\nstate and iterate over members.\n * *ZFSNVList* provides a wrapper around the `nvpair_t` / `nvlist_t` data structure that\nis used in ZFS for a lot of userland / kernel communication. It manages resources in both\nowning and non-owning fashion, and allows for easier iteration over sequences.\n * *ZFSStrings* translate ZFS status enums into the user facing emoji or string\ndescription, optionally with localization. (Localization is not well tested or supported\nat the moment.)\n\n\nHelper Tool\n-----------\n\nThe implementation of the helper tool follows apple's [EvenBetterAuthorizationSample].\n\nThe helper tool communicates with the user application via `AuthorizationService` and\n`NSXPCConnection`. The application side of code for this is in `ZetaAuthorization.m`. The\nRPC protocol can be found in `ZetaAuthorizationHelperProtocol.h`, and is implemented in\n`ZetaAuthorizationHelper.mm`. The `CommonAuthorization.m` file contains the supported\ncommands and associated default permissions.\n\nThe helper tool can be uninstalled with the `uninstall-helper.sh` script. This is useful\nfor debugging the installation of the helper, or updating the helper without increasing\nthe bundle version.\n\n\nAuthorization\n-------------\n\nThe ZetaWatch helper tool uses the Security framework to authorize users before performing\nprivileged operations. It currently supports the following permissions.\n\n * `net.the-color-black.ZetaWatch.import`, allowed by default, required for importing a pool.\n * `net.the-color-black.ZetaWatch.export`, allowed by default, required for exporting a pool.\n * `net.the-color-black.ZetaWatch.mount`, allowed by default, required for mounting a dataset.\n * `net.the-color-black.ZetaWatch.unmount`, allowed by default, required for unmounting a\n dataset.\n * `net.the-color-black.ZetaWatch.snapshot`, allowed by default, required for creating a\n snapshot.\n * `net.the-color-black.ZetaWatch.rollback`, requires admin authentication by default,\nrequired for rolling back a filesystem.\n * `net.the-color-black.ZetaWatch.clone`, requires admin authentication by default,\nrequired for cloning a filesystem.\n * `net.the-color-black.ZetaWatch.create`, requires admin authentication by default,\nrequired for creating a new filesystem.\n * `net.the-color-black.ZetaWatch.destroy`, requires admin authentication by default,\nrequired for destroying a filesystem or snapshot.\n * `net.the-color-black.ZetaWatch.key`, allowed by default, required for loading or\nunloading a key for a dataset. This also includes the ability to auto mount / unmount them.\n * `net.the-color-black.ZetaWatch.scrub`, allowed by default, required for starting,\nstopping or pausing scrubs.\n\nThese permissions can be manipulated via the `security` command line program. To inspect\nthe current dataset creation permissions, and switching it to allow this to all users:\n\n```\nsecurity authorizationdb read net.the-color-black.ZetaWatch.create\nsecurity authorizationdb write net.the-color-black.ZetaWatch.create allow\n```\n\nPermissions include `allow`, `deny` or `authenticate-admin`.\n\nMore detailed information about this topic can be found in the article apples documentation\nabout [AuthorizationServices] and [Managing the Authorization Database in OS X Mavericks].\n\n\nSecurity & Code Signing\n-----------------------\n\nOfficial release builds are signed and notarized, and should run without issues even on\nnewer Mac OS X. But there are still issues with authentication reported with the program\nnot being recognized as signed. To verify security manually, the following commands can\nbe used:\n\n```bash\ncodesign -v -v -d ZetaWatch.app\nxcrun stapler validate -v ZetaWatch.app\n```\n\nBuilding ZetaWatch requires an apple developer account with DeveloperID signing\ncapabilities, since it uses [`SMJobBless`] to run a helper service as root. This service\nexecutes actions on behalf of the user, such as mounting, unmounting or loading a key.\n[Notarization] is required to create binaries that can be run without without warning on\nthe newest Mac OS X.\n\n\nSelf Updating\n-------------\n\nThe self-updating uses [SparkleFramework]. Since the newest released sparkle does not yet\nsupport hardened runtime, it needs to be compiled manually. Building the \"Distribution\"\ntarget in the Sparkle submodule in release mode is sufficient.\nThe sparkle submodule contains a version that is slimmed down by removing most languages,\nwhich saves space. Since ZetaWatch is not localized, this is not a problem.\nTo create a working fork, adjust the public key and update url in the Info.plist file.\n\n\nZFS Binary Compatibility\n------------------------\n\nSince ZetaWatch directly links to the zfs libraries, it only works if those are\ncompatible. And while Sparkle has built-in support for OS compatibility checking, it\ndoesn't have the same for other dependencies. There is support for custom appcast\nfiltering, to select a suitable version, but since the ZFS version and the ZetaWatch\nversion are kind of orthogonal, this didn't seem fitting.\n\nThe chosen solution was to have a ZFS version specific appcast URL, and make ZetaWatch\nquery the appropriate appcast. This allows updating ZetaWatch when the used ZFS version\nchanges, but also have several supported parallel builds. Currently, the only supported\nZFS version is 1.9.\n\n\nLicense\n=======\n\nThis program is copyrighted by me, because I wrote it.\nThis program is licensed under the \"3-clause BSD\" License. See the LICENSE.md file for\ndetails.\n\n[EvenBetterAuthorizationSample]: https://developer.apple.com/library/content/samplecode/EvenBetterAuthorizationSample/Introduction/Intro.html\n[`SMJobBless`]: https://developer.apple.com/documentation/servicemanagement/1431078-smjobbless?language=objc\n[Notarization]: https://developer.apple.com/documentation/security/notarizing_your_app_before_distribution?language=objc\n[ZFSImage]: https://raw.githubusercontent.com/cbreak-black/ZetaWatch/master/doc/ZetaWatch.jpg\n[SparkleFramework]: https://sparkle-project.org/\n[SparkleGithub]: https://github.com/sparkle-project/Sparkle\n[AuthorizationServices]: https://developer.apple.com/documentation/security/authorization_services?language=objc\n[Managing the Authorization Database in OS X Mavericks]: https://derflounder.wordpress.com/2014/02/16/managing-the-authorization-database-in-os-x-mavericks/\n"
  },
  {
    "path": "ZetaAuthorizationHelper/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>net.the-color-black.ZetaAuthorizationHelper</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>ZetaAuthorizationHelper</string>\n\t<key>CFBundleVersion</key>\n\t<string>$(ZETA_VERSION)</string>\n\t<key>SMAuthorizedClients</key>\n\t<array>\n\t\t<string>anchor apple generic and identifier \"net.the-color-black.ZetaWatch\" and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = \"8THUW5GT6P\")</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "ZetaAuthorizationHelper/Launchd.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>Label</key>\n\t<string>net.the-color-black.ZetaAuthorizationHelper</string>\n\t<key>MachServices</key>\n\t<dict>\n\t\t<key>net.the-color-black.ZetaAuthorizationHelper</key>\n\t\t<true/>\n\t</dict>\n</dict>\n</plist>\n"
  },
  {
    "path": "ZetaAuthorizationHelper/ZetaAuthorizationHelper.h",
    "content": "//\n//  ZetaAuthorizationHelper.h\n//  ZetaAuthorizationHelper\n//\n//  Created by cbreak on 18.01.01.\n//  Copyright © 2018 the-color-black.net. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n@interface ZetaAuthorizationHelper : NSObject\n\n- (id)init;\n- (void)run;\n\n@end\n"
  },
  {
    "path": "ZetaAuthorizationHelper/ZetaAuthorizationHelper.mm",
    "content": "//\n//  ZetaAuthorizationHelper.m\n//  ZetaAuthorizationHelper\n//\n//  Created by cbreak on 18.01.01.\n//  Copyright © 2018 the-color-black.net. All rights reserved.\n//\n\n#import \"ZetaAuthorizationHelper.h\"\n#import \"ZetaAuthorizationHelperProtocol.h\"\n\n#import \"CommonAuthorization.h\"\n\n#include \"ZFSWrapper/ZFSUtils.hpp\"\n#include \"ZetaCPPUtils.hpp\"\n\n@interface ZetaAuthorizationHelper () <NSXPCListenerDelegate, ZetaAuthorizationHelperProtocol>\n{\n\tbool shouldRun;\n}\n\n@property (atomic, strong, readwrite) NSXPCListener * listener;\n\n@end\n\nNSMutableArray<NSString*> * toArray(std::vector<std::string> const & strings)\n{\n\tNSMutableArray<NSString*> * array = [[NSMutableArray<NSString*> alloc] initWithCapacity:strings.size()];\n\tfor (auto const & s : strings)\n\t{\n\t\t[array addObject:[NSString stringWithUTF8String:s.c_str()]];\n\t}\n\treturn array;\n}\n\nstd::vector<std::string> fromArray(NSArray<NSString*> * array)\n{\n\tstd::vector<std::string> vec;\n\tfor (NSString * string in array)\n\t{\n\t\tvec.push_back([string UTF8String]);\n\t}\n\treturn vec;\n}\n\n@implementation ZetaAuthorizationHelper\n\n- (id)init\n{\n\tself = [super init];\n\tif (self != nil)\n\t{\n\t\tshouldRun = true;\n\t\t// Set up our XPC listener to handle requests on our Mach service.\n\t\tself->_listener = [[NSXPCListener alloc] initWithMachServiceName:kHelperToolMachServiceName];\n\t\tself->_listener.delegate = self;\n\t}\n\treturn self;\n}\n\n- (void)run\n{\n\t// Tell the XPC listener to start processing requests.\n\t[self.listener resume];\n\t// Run the run loop until it's time to terminate.\n\tbool runLoopSuccess = true;\n\twhile (shouldRun && runLoopSuccess)\n\t{\n\t\trunLoopSuccess = [[NSRunLoop mainRunLoop]\n\t\t\trunMode:NSDefaultRunLoopMode\n\t\t\tbeforeDate:[NSDate distantFuture]];\n\t}\n}\n\n- (void)stop\n{\n\tshouldRun = false;\n\t[self.listener invalidate];\n\t// Stop the run loop\n\tCFRunLoopStop(CFRunLoopGetMain());\n}\n\n- (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection\n{\n\tassert(listener == self.listener);\n\tassert(newConnection != nil);\n\n\tnewConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(ZetaAuthorizationHelperProtocol)];\n\tnewConnection.exportedObject = self;\n\t[newConnection resume];\n\n\treturn YES;\n}\n\nNSError * checkAuthorization(NSData * authData, SEL command)\n{\n\tNSError * error = nil;\n\tAuthorizationRef authRef = NULL;\n\n\tassert(command != nil);\n\n\t// First check that authData looks reasonable.\n\terror = nil;\n\tif ((authData == nil) || ([authData length] != sizeof(AuthorizationExternalForm)))\n\t{\n\t\terror = [NSError errorWithDomain:NSOSStatusErrorDomain code:paramErr userInfo:nil];\n\t\treturn error;\n\t}\n\n\t// Create an authorization ref from that the external form data contained within.\n\tauto extForm = static_cast<const AuthorizationExternalForm *>([authData bytes]);\n\tOSStatus err = AuthorizationCreateFromExternalForm(extForm, &authRef);\n\n\t// Authorize the right associated with the command.\n\tif (err == errAuthorizationSuccess)\n\t{\n\t\tAuthorizationItem oneRight = { NULL, 0, NULL, 0 };\n\t\tAuthorizationRights rights   = { 1, &oneRight };\n\n\t\tauto right = [CommonAuthorization authorizationRightForCommand:command];\n\t\tif (!right)\n\t\t{\n\t\t\terror = [NSError errorWithDomain:NSOSStatusErrorDomain code:paramErr userInfo:nil];\n\t\t\treturn error;\n\t\t}\n\n\t\toneRight.name = [right UTF8String];\n\n\t\terr = AuthorizationCopyRights(authRef, &rights, NULL,\n\t\t\tkAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed,\n\t\t\tNULL);\n\t}\n\tif (err != errAuthorizationSuccess)\n\t{\n\t\terror = [NSError errorWithDomain:NSOSStatusErrorDomain code:err userInfo:nil];\n\t}\n\n\tif (authRef != NULL)\n\t{\n\t\tOSStatus junk = AuthorizationFree(authRef, 0);\n\t\tassert(junk == errAuthorizationSuccess);\n\t}\n\n\treturn error;\n}\n\n- (void)getVersionWithReply:(void (^)(NSError * error, NSString *))reply\n{\n\treply(nil, [[NSBundle mainBundle] objectForInfoDictionaryKey:@\"CFBundleVersion\"]);\n}\n\n// Checks authorization, and handles c++ exceptions by forwarding them to the\n// caller.\ntemplate<typename C, typename R>\nvoid processWithExceptionForwarding(NSData * authData, SEL command,\n\t\t\t\t\t\t\t\t\tR reply, C callable)\n{\n\tNSError * error = checkAuthorization(authData, command);\n\tif (error)\n\t{\n\t\treply(error);\n\t\treturn;\n\t}\n\ttry\n\t{\n\t\tcallable();\n\t}\n\tcatch (std::exception const & e)\n\t{\n\t\treply([NSError errorWithDomain:@\"ZFSException\" code:-1 userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithUTF8String:e.what()]}]);\n\t}\n}\n\n- (void)stopHelperWithAuthorization:(NSData *)authData\n\t\t\t\t\t\t  withReply:(void (^)(NSError *))reply\n{\n\tprocessWithExceptionForwarding(authData, _cmd, reply, [=]()\n\t{\n\t\t// Acknowledge receipt of stop request, performed asyncronously\n\t\treply(nullptr);\n\t\t[self stop];\n\t});\n}\n\n- (void)importPools:(NSDictionary *)importData authorization:(NSData *)authData\n\t\t  withReply:(void (^)(NSError *))reply\n{\n\tprocessWithExceptionForwarding(authData, _cmd, reply, [=]()\n\t{\n\t\tstd::vector<std::string> failures;\n\t\tNSNumber * pool = [importData objectForKey:@\"poolGUID\"];\n\t\tzfs::LibZFSHandle::ImportProps props;\n\t\tif (id ar = [importData objectForKey:@\"altroot\"])\n\t\t\tprops.altroot.assign([ar UTF8String]);\n\t\tif (id aidm = [importData objectForKey:@\"allowHostIDMismatch\"])\n\t\t\tprops.allowHostIDMismatch = [aidm boolValue];\n\t\tif (id auh = [importData objectForKey:@\"allowUnhealthy\"])\n\t\t\tprops.allowUnhealthy = [auh boolValue];\n\t\tif (id ro = [importData objectForKey:@\"readOnly\"])\n\t\t\tprops.readOnly = [ro boolValue];\n\t\tif (id spo = [importData objectForKey:@\"searchPathOverride\"])\n\t\t\tprops.searchPathOverride = fromArray(spo);\n\t\tstd::vector<zfs::ZPool> importedPools;\n\t\tzfs::LibZFSHandle zfs;\n\t\tif (pool != nil)\n\t\t{\n\t\t\timportedPools.emplace_back(zfs.import([pool unsignedLongLongValue], props));\n\t\t}\n\t\telse\n\t\t{\n\t\t\timportedPools = zfs.importAllPools(props);\n\t\t}\n\t\tif (failures.empty())\n\t\t{\n\t\t\treply(nullptr);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tNSDictionary * userInfo = @{\n\t\t\t\tNSLocalizedDescriptionKey: [NSString stringWithUTF8String:\n\t\t\t\t\tformatForHumans(failures).c_str()]\n\t\t\t};\n\t\t\treply([NSError errorWithDomain:@\"ZFSError\" code:-1 userInfo:userInfo]);\n\t\t}\n\t});\n}\n\n- (void)importablePools:(NSDictionary *)importData\n\t\t  authorization:(NSData *)authData\n\t\t\t  withReply:(void (^)(NSError *, NSArray *))reply\n{\n\tNSError * error = checkAuthorization(authData, _cmd);\n\tif (error)\n\t{\n\t\treply(error, nullptr);\n\t\treturn;\n\t}\n\ttry\n\t{\n\t\tzfs::LibZFSHandle zfs;\n\t\tstd::vector<std::string> searchPathOverride;\n\t\tif (id spo = [importData objectForKey:@\"searchPathOverride\"])\n\t\t\tsearchPathOverride = fromArray(spo);\n\t\tauto pools = zfs.importablePools(searchPathOverride);\n\t\tNSMutableArray * poolsArray = [[NSMutableArray alloc] initWithCapacity:pools.size()];\n\t\tfor (auto const & pool : pools)\n\t\t{\n\t\t\tNSString * name = [NSString stringWithUTF8String:pool.name.c_str()];\n\t\t\tNSNumber * guid = [NSNumber numberWithUnsignedLongLong:pool.guid];\n\t\t\tNSNumber * status = [NSNumber numberWithUnsignedLongLong:pool.status];\n\t\t\tNSMutableArray<NSString*> * deviceArray = toArray(pool.devices);\n\t\t\tNSDictionary * poolDict =\n\t\t\t@{@\"name\": name, @\"guid\": guid, @\"status\": status, @\"devices\": deviceArray};\n\t\t\t[poolsArray addObject:poolDict];\n\t\t}\n\t\treply(nullptr, poolsArray);\n\t}\n\tcatch (std::exception const & e)\n\t{\n\t\treply([NSError errorWithDomain:@\"ZFSException\" code:-1 userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithUTF8String:e.what()]}], nullptr);\n\t}\n}\n\n- (void)exportPools:(NSDictionary *)exportData authorization:(NSData *)authData withReply:(void(^)(NSError * error))reply\n{\n\tprocessWithExceptionForwarding(authData, _cmd, reply, [=]()\n\t{\n\t\tNSString * poolName = [exportData objectForKey:@\"pool\"];\n\t\tbool force = false;\n\t\tif (id o = [exportData objectForKey:@\"force\"])\n\t\t\tforce = [o boolValue];\n\t\tif (!poolName)\n\t\t{\n\t\t\treply([NSError errorWithDomain:@\"ZFSArgError\" code:-1 userInfo:@{NSLocalizedDescriptionKey: @\"Missing Arguments\"}]);\n\t\t\treturn;\n\t\t}\n\t\tzfs::LibZFSHandle zfs;\n\t\tauto pool = zfs.pool(std::string(poolName.UTF8String));\n\t\t// Export Pool\n\t\tpool.exportPool(force);\n\t\treply(nullptr);\n\t});\n}\n\n- (void)mountFilesystems:(NSDictionary *)mountData authorization:(NSData *)authData\n\t\t\t   withReply:(void (^)(NSError *))reply\n{\n\tprocessWithExceptionForwarding(authData, _cmd, reply, [=]()\n\t{\n\t\tNSString * fsName = [mountData objectForKey:@\"filesystem\"];\n\t\tbool recursive = false;\n\t\tif (id o = [mountData objectForKey:@\"recursive\"])\n\t\t\trecursive = [o boolValue];\n\t\tif (!fsName)\n\t\t{\n\t\t\treply([NSError errorWithDomain:@\"ZFSArgError\" code:-1 userInfo:@{NSLocalizedDescriptionKey: @\"Missing Arguments\"}]);\n\t\t\treturn;\n\t\t}\n\t\tzfs::LibZFSHandle zfs;\n\t\tauto fs = zfs.filesystem([fsName UTF8String]);\n\t\tint ret = 0;\n\t\tif (recursive)\n\t\t\tret = fs.mountRecursive();\n\t\telse\n\t\t\tret = fs.mount();\n\t\tif (ret == 0)\n\t\t{\n\t\t\treply(nullptr);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tNSDictionary * userInfo = @{\n\t\t\t\tNSLocalizedDescriptionKey: [NSString stringWithUTF8String:\n\t\t\t\t\tzfs.lastError().c_str()]\n\t\t\t};\n\t\t\treply([NSError errorWithDomain:@\"ZFSError\" code:-1 userInfo:userInfo]);\n\t\t}\n\t});\n}\n\n- (void)unmountFilesystems:(NSDictionary *)mountData authorization:(NSData *)authData\n\t\t\t\t withReply:(void (^)(NSError *))reply\n{\n\tprocessWithExceptionForwarding(authData, _cmd, reply, [=]()\n\t{\n\t\tNSString * fsName = [mountData objectForKey:@\"filesystem\"];\n\t\tbool force = false;\n\t\tif (id o = [mountData objectForKey:@\"force\"])\n\t\t\tforce = [o boolValue];\n\t\tbool recursive = false;\n\t\tif (id o = [mountData objectForKey:@\"recursive\"])\n\t\t\trecursive = [o boolValue];\n\t\tif (!fsName)\n\t\t{\n\t\t\treply([NSError errorWithDomain:@\"ZFSArgError\" code:-1 userInfo:@{NSLocalizedDescriptionKey: @\"Missing Arguments\"}]);\n\t\t\treturn;\n\t\t}\n\t\tzfs::LibZFSHandle zfs;\n\t\tauto fs = zfs.filesystem([fsName UTF8String]);\n\t\tint ret = 0;\n\t\tif (recursive)\n\t\t\tret = fs.unmountRecursive(force);\n\t\telse\n\t\t\tret = fs.unmount();\n\t\tif (ret == 0)\n\t\t{\n\t\t\treply(nullptr);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tNSDictionary * userInfo = @{\n\t\t\t\tNSLocalizedDescriptionKey: [NSString stringWithUTF8String:\n\t\t\t\t\tzfs.lastError().c_str()]\n\t\t\t};\n\t\t\treply([NSError errorWithDomain:@\"ZFSError\" code:-1 userInfo:userInfo]);\n\t\t}\n\t});\n}\n\n- (void)snapshotFilesystem:(NSDictionary *)fsData authorization:(NSData *)authData withReply:(void(^)(NSError * error))reply\n{\n\tprocessWithExceptionForwarding(authData, _cmd, reply, [=]()\n\t{\n\t\tNSString * fsName = [fsData objectForKey:@\"filesystem\"];\n\t\tNSString * snapName = [fsData objectForKey:@\"snapshot\"];\n\t\tbool recursive = false;\n\t\tif (id o = [fsData objectForKey:@\"recursive\"])\n\t\t\trecursive = [o boolValue];\n\t\tif (!fsName || !snapName)\n\t\t{\n\t\t\treply([NSError errorWithDomain:@\"ZFSArgError\" code:-1 userInfo:@{NSLocalizedDescriptionKey: @\"Missing Arguments\"}]);\n\t\t\treturn;\n\t\t}\n\t\tzfs::LibZFSHandle zfs;\n\t\tauto fs = zfs.filesystem([fsName UTF8String]);\n\t\tauto ret = fs.snapshot([snapName UTF8String], recursive);\n\t\tif (ret == 0)\n\t\t{\n\t\t\treply(nullptr);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tNSDictionary * userInfo = @{\n\t\t\t\tNSLocalizedDescriptionKey: [NSString stringWithUTF8String:zfs.lastError().c_str()]\n\t\t\t};\n\t\t\treply([NSError errorWithDomain:@\"ZFSError\" code:-1 userInfo:userInfo]);\n\t\t}\n\t});\n}\n\n- (void)rollbackFilesystem:(NSDictionary *)fsData authorization:(NSData *)authData withReply:(void(^)(NSError * error))reply\n{\n\tprocessWithExceptionForwarding(authData, _cmd, reply, [=]()\n\t{\n\t\tNSString * snapName = [fsData objectForKey:@\"snapshot\"];\n\t\tbool force = false;\n\t\tif (id o = [fsData objectForKey:@\"force\"])\n\t\t\tforce = [o boolValue];\n\t\tif (!snapName)\n\t\t{\n\t\t\treply([NSError errorWithDomain:@\"ZFSArgError\" code:-1 userInfo:@{NSLocalizedDescriptionKey: @\"Missing Arguments\"}]);\n\t\t\treturn;\n\t\t}\n\t\tzfs::LibZFSHandle zfs;\n\t\tauto snap = zfs.filesystem([snapName UTF8String]);\n\t\tauto res = snap.rollback(force);\n\t\tif (res == 0)\n\t\t{\n\t\t\treply(nullptr);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tNSDictionary * userInfo = @{\n\t\t\t\tNSLocalizedDescriptionKey: [NSString stringWithUTF8String:zfs.lastError().c_str()]\n\t\t\t};\n\t\t\treply([NSError errorWithDomain:@\"ZFSError\" code:-1 userInfo:userInfo]);\n\t\t}\n\t});\n}\n\n- (void)cloneSnapshot:(NSDictionary *)fsData authorization:(NSData *)authData withReply:(void(^)(NSError * error))reply\n{\n\tprocessWithExceptionForwarding(authData, _cmd, reply, [=]()\n\t{\n\t\tNSString * snapName = [fsData objectForKey:@\"snapshot\"];\n\t\tNSString * newFSName = [fsData objectForKey:@\"newFilesystem\"];\n\t\tif (!snapName || !newFSName)\n\t\t{\n\t\t\treply([NSError errorWithDomain:@\"ZFSArgError\" code:-1 userInfo:@{NSLocalizedDescriptionKey: @\"Missing Arguments\"}]);\n\t\t\treturn;\n\t\t}\n\t\tzfs::LibZFSHandle zfs;\n\t\tstd::string newFSNameStr = [newFSName UTF8String];\n\t\tauto snap = zfs.filesystem([snapName UTF8String]);\n\t\tif (snap.clone(newFSNameStr) == 0)\n\t\t{\n\t\t\tauto newFS = zfs.filesystem(newFSNameStr);\n\t\t\tif (newFS.mount() == 0)\n\t\t\t{\n\t\t\t\treply(nullptr);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tNSDictionary * userInfo = @{\n\t\t\tNSLocalizedDescriptionKey: [NSString stringWithUTF8String:zfs.lastError().c_str()]\n\t\t};\n\t\treply([NSError errorWithDomain:@\"ZFSError\" code:-1 userInfo:userInfo]);\n\t});\n}\n\n- (void)createFilesystem:(NSDictionary *)fsData authorization:(NSData *)authData withReply:(void(^)(NSError * error))reply\n{\n\tprocessWithExceptionForwarding(authData, _cmd, reply, [=]()\n\t{\n\t\tNSString * newFSName = [fsData objectForKey:@\"filesystem\"];\n\t\tNSString * mountpoint = [fsData objectForKey:@\"mountpoint\"];\n\t\tif (!newFSName)\n\t\t{\n\t\t\treply([NSError errorWithDomain:@\"ZFSArgError\" code:-1 userInfo:@{NSLocalizedDescriptionKey: @\"Missing Arguments\"}]);\n\t\t\treturn;\n\t\t}\n\t\tzfs::LibZFSHandle zfs;\n\t\tstd::string newFSNameStr = [newFSName UTF8String];\n\t\tstd::string mountpointStr = mountpoint ? [mountpoint UTF8String] : \"\";\n\t\tif (zfs.createFilesystem(newFSNameStr, mountpointStr) == 0)\n\t\t{\n\t\t\tauto newFS = zfs.filesystem(newFSNameStr);\n\t\t\tif (newFS.mount() == 0)\n\t\t\t{\n\t\t\t\treply(nullptr);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tNSDictionary * userInfo = @{\n\t\t\tNSLocalizedDescriptionKey: [NSString stringWithUTF8String:zfs.lastError().c_str()]\n\t\t};\n\t\treply([NSError errorWithDomain:@\"ZFSError\" code:-1 userInfo:userInfo]);\n\t});\n}\n\n- (void)createVolume:(NSDictionary *)fsData authorization:(NSData *)authData withReply:(void(^)(NSError * error))reply\n{\n\tprocessWithExceptionForwarding(authData, _cmd, reply, [=]()\n\t{\n\t\tNSString * newFSName = [fsData objectForKey:@\"filesystem\"];\n\t\tNSNumber * size = [fsData objectForKey:@\"size\"];\n\t\tNSNumber * blocksize = [fsData objectForKey:@\"blocksize\"];\n\t\tif (!newFSName || size == nullptr)\n\t\t{\n\t\t\treply([NSError errorWithDomain:@\"ZFSArgError\" code:-1 userInfo:@{NSLocalizedDescriptionKey: @\"Missing Arguments\"}]);\n\t\t\treturn;\n\t\t}\n\t\tzfs::LibZFSHandle zfs;\n\t\tstd::string newFSNameStr = [newFSName UTF8String];\n\t\tauto s = [size unsignedLongLongValue];\n\t\tauto bs = blocksize != nullptr ? [blocksize unsignedLongLongValue] : 0;\n\t\tif (zfs.createVolume(newFSNameStr, s, bs) == 0)\n\t\t{\n\t\t\treply(nullptr);\n\t\t\treturn;\n\t\t}\n\t\tNSDictionary * userInfo = @{\n\t\t\tNSLocalizedDescriptionKey: [NSString stringWithUTF8String:zfs.lastError().c_str()]\n\t\t};\n\t\treply([NSError errorWithDomain:@\"ZFSError\" code:-1 userInfo:userInfo]);\n\t});\n}\n\n- (void)destroy:(NSDictionary *)fsData authorization:(NSData *)authData withReply:(void(^)(NSError * error))reply\n{\n\tprocessWithExceptionForwarding(authData, _cmd, reply, [=]()\n\t{\n\t\tNSString * fsName = [fsData objectForKey:@\"filesystem\"];\n\t\tbool recursive = false;\n\t\tif (id o = [fsData objectForKey:@\"recursive\"])\n\t\t\trecursive = [o boolValue];\n\t\tbool force = false;\n\t\tif (id o = [fsData objectForKey:@\"force\"])\n\t\t\tforce = [o boolValue];\n\t\tif (!fsName)\n\t\t{\n\t\t\treply([NSError errorWithDomain:@\"ZFSArgError\" code:-1 userInfo:@{NSLocalizedDescriptionKey: @\"Missing Arguments\"}]);\n\t\t\treturn;\n\t\t}\n\t\tzfs::LibZFSHandle zfs;\n\t\tauto fs = zfs.filesystem([fsName UTF8String]);\n\t\tint ret = 0;\n\t\tif (recursive)\n\t\t{\n\t\t\tret = fs.destroyRecursive(force);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tauto dependents = fs.dependents();\n\t\t\tif (dependents.empty())\n\t\t\t{\n\t\t\t\tret = fs.destroy(force);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tNSDictionary * userInfo = @{\n\t\t\t\t\tNSLocalizedDescriptionKey: @\"Filesystem has Dependents\"\n\t\t\t\t};\n\t\t\t\treply([NSError errorWithDomain:@\"ZFSError\" code:-1 userInfo:userInfo]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tif (ret == 0)\n\t\t{\n\t\t\treply(nullptr);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tNSDictionary * userInfo = @{\n\t\t\t\tNSLocalizedDescriptionKey: [NSString stringWithUTF8String:zfs.lastError().c_str()]\n\t\t\t};\n\t\t\treply([NSError errorWithDomain:@\"ZFSError\" code:-1 userInfo:userInfo]);\n\t\t}\n\t});\n}\n\n- (void)loadKeyForFilesystem:(NSDictionary *)loadData authorization:(NSData *)authData withReply:(void(^)(NSError * error))reply\n{\n\tprocessWithExceptionForwarding(authData, _cmd, reply, [=]()\n\t{\n\t\tNSString * fsName = [loadData objectForKey:@\"filesystem\"];\n\t\tNSString * key = [loadData objectForKey:@\"key\"];\n\t\tif (!fsName)\n\t\t{\n\t\t\treply([NSError errorWithDomain:@\"ZFSArgError\" code:-1 userInfo:@{NSLocalizedDescriptionKey: @\"Missing Arguments\"}]);\n\t\t\treturn;\n\t\t}\n\t\tzfs::LibZFSHandle zfs;\n\t\tauto fs = zfs.filesystem([fsName UTF8String]);\n\t\tint ret = 0;\n\t\tif (key)\n\t\t{\n\t\t\tret = fs.loadKey([key UTF8String]);\n\t\t}\n\t\telse if (fs.keyLocation() == zfs::ZFileSystem::KeyLocation::uri)\n\t\t{\n\t\t\tret = fs.loadKeyFile();\n\t\t}\n\t\telse\n\t\t{\n\t\t\treply([NSError errorWithDomain:@\"ZFSKeyError\" code:-1 userInfo:@{NSLocalizedDescriptionKey: @\"Missing Key\"}]);\n\t\t\treturn;\n\t\t}\n\t\tif (ret)\n\t\t{\n\t\t\tNSDictionary * userInfo = @{\n\t\t\t\tNSLocalizedDescriptionKey: [NSString stringWithUTF8String:zfs.lastError().c_str()]\n\t\t\t};\n\t\t\treply([NSError errorWithDomain:@\"ZFSKeyError\" code:-1 userInfo:userInfo]);\n\t\t\treturn;\n\t\t}\n\t\t// Encryption Root Filesystem and contained filesystems recursively\n\t\tret = fs.automountRecursive();\n\t\tif (ret)\n\t\t{\n\t\t\tNSDictionary * userInfo = @{\n\t\t\t\tNSLocalizedDescriptionKey: [NSString stringWithUTF8String:zfs.lastError().c_str()]\n\t\t\t};\n\t\t\treply([NSError errorWithDomain:@\"ZFSError\" code:-1 userInfo:userInfo]);\n\t\t}\n\t\treply(nullptr);\n\t});\n}\n\n- (void)unloadKeyForFilesystem:(NSDictionary *)unloadData authorization:(NSData *)authData withReply:(void(^)(NSError * error))reply\n{\n\tprocessWithExceptionForwarding(authData, _cmd, reply, [=]()\n\t{\n\t\tNSString * fsName = [unloadData objectForKey:@\"filesystem\"];\n\t\tif (!fsName)\n\t\t{\n\t\t\treply([NSError errorWithDomain:@\"ZFSArgError\" code:-1 userInfo:@{NSLocalizedDescriptionKey: @\"Missing Arguments\"}]);\n\t\t\treturn;\n\t\t}\n\t\tzfs::LibZFSHandle zfs;\n\t\tauto fs = zfs.filesystem([fsName UTF8String]);\n\t\tauto ret = fs.unloadKey();\n\t\tif (ret == 0)\n\t\t{\n\t\t\treply(nullptr);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tNSDictionary * userInfo = @{\n\t\t\t\tNSLocalizedDescriptionKey: [NSString stringWithUTF8String:\n\t\t\t\t\tzfs.lastError().c_str()]\n\t\t\t};\n\t\t\treply([NSError errorWithDomain:@\"ZFSError\" code:-1 userInfo:userInfo]);\n\t\t}\n\t});\n}\n\n- (void)scrubPool:(NSDictionary *)poolData authorization:(NSData *)authData\n\t\twithReply:(void (^)(NSError *))reply\n{\n\tprocessWithExceptionForwarding(authData, _cmd, reply, [=]()\n\t{\n\t\tNSString * poolName = [poolData objectForKey:@\"pool\"];\n\t\tNSString * command = [poolData objectForKey:@\"command\"];\n\t\tif (!poolName)\n\t\t{\n\t\t\treply([NSError errorWithDomain:@\"ZFSArgError\" code:-1 userInfo:@{NSLocalizedDescriptionKey: @\"Missing Arguments\"}]);\n\t\t\treturn;\n\t\t}\n\t\tzfs::LibZFSHandle zfs;\n\t\tauto pool = zfs.pool(std::string(poolName.UTF8String));\n\t\tif (command)\n\t\t{\n\t\t\tif ([command isEqualToString:@\"stop\"])\n\t\t\t\tpool.scrubStop();\n\t\t\telse if ([command isEqualToString:@\"pause\"])\n\t\t\t\tpool.scrubPause();\n\t\t\t// No other commands are supported\n\t\t\telse\n\t\t\t\treply([NSError errorWithDomain:@\"ZFSArgError\" code:-1 userInfo:@{NSLocalizedDescriptionKey: @\"Invalid Scrub Command\"}]);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpool.scrub();\n\t\t}\n\t\treply(nullptr);\n\t});\n}\n\n@end\n"
  },
  {
    "path": "ZetaAuthorizationHelper/ZetaAuthorizationHelperProtocol.h",
    "content": "//\n//  ZetaAuthorizationHelperProtocol.h\n//  ZetaWatch\n//\n//  Created by cbreak on 18.01.01.\n//  Copyright © 2018 the-color-black.net. All rights reserved.\n//\n\n#define kHelperToolMachServiceName @\"net.the-color-black.ZetaAuthorizationHelper\"\n\n@protocol ZetaAuthorizationHelperProtocol\n\n@required\n\n- (void)getVersionWithReply:(void(^)(NSError * error, NSString * version))reply;\n\n- (void)stopHelperWithAuthorization:(NSData *)authData\n\t\t\t\t\t\t  withReply:(void(^)(NSError * error))reply;\n\n- (void)importPools:(NSDictionary *)importData authorization:(NSData *)authData withReply:(void(^)(NSError * error))reply;\n\n- (void)importablePools:(NSDictionary *)importData authorization:(NSData*)authData withReply:(void(^)(NSError * error, NSArray * importablePools))reply;\n\n- (void)exportPools:(NSDictionary *)exportData authorization:(NSData *)authData withReply:(void(^)(NSError * error))reply;\n\n- (void)mountFilesystems:(NSDictionary *)mountData authorization:(NSData *)authData withReply:(void(^)(NSError * error))reply;\n\n- (void)unmountFilesystems:(NSDictionary *)mountData authorization:(NSData *)authData withReply:(void(^)(NSError * error))reply;\n\n- (void)snapshotFilesystem:(NSDictionary *)fsData authorization:(NSData *)authData withReply:(void(^)(NSError * error))reply;\n\n- (void)rollbackFilesystem:(NSDictionary *)fsData authorization:(NSData *)authData withReply:(void(^)(NSError * error))reply;\n\n- (void)cloneSnapshot:(NSDictionary *)fsData authorization:(NSData *)authData withReply:(void(^)(NSError * error))reply;\n\n- (void)createFilesystem:(NSDictionary *)fsData authorization:(NSData *)authData withReply:(void(^)(NSError * error))reply;\n\n- (void)createVolume:(NSDictionary *)fsData authorization:(NSData *)authData withReply:(void(^)(NSError * error))reply;\n\n- (void)destroy:(NSDictionary *)fsData authorization:(NSData *)authData withReply:(void(^)(NSError * error))reply;\n\n- (void)loadKeyForFilesystem:(NSDictionary *)loadData authorization:(NSData *)authData withReply:(void(^)(NSError * error))reply;\n\n- (void)unloadKeyForFilesystem:(NSDictionary *)unloadData authorization:(NSData *)authData withReply:(void(^)(NSError * error))reply;\n\n- (void)scrubPool:(NSDictionary *)poolData authorization:(NSData *)authData withReply:(void(^)(NSError * error))reply;\n\n@end\n"
  },
  {
    "path": "ZetaAuthorizationHelper/ZetaCPPUtils.hpp",
    "content": "//\n//  ZetaCPPUtils.hpp\n//  ZetaWatch\n//\n//  Created by cbreak on 19.07.28.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#ifndef ZetaCPPUtils_h\n#define ZetaCPPUtils_h\n\n#include \"ZFSWrapper/ZFSUtils.hpp\"\n\n#include <vector>\n#include <sstream>\n\ntemplate<typename T>\ninline std::string formatForHumans(std::vector<T> const & things)\n{\n\tif (things.empty())\n\t\treturn std::string();\n\tstd::stringstream ss;\n\tss << things[0];\n\tfor (size_t i = 1; i < things.size(); ++i)\n\t{\n\t\tss << \", \" << things[i];\n\t}\n\treturn ss.str();\n}\n\n#endif /* ZetaCPPUtils_h */\n"
  },
  {
    "path": "ZetaAuthorizationHelper/main.m",
    "content": "//\n//  main.m\n//  ZetaAuthorizationHelper\n//\n//  Created by cbreak on 18.01.01.\n//  Copyright © 2018 the-color-black.net. All rights reserved.\n//\n\n#include \"ZetaAuthorizationHelper.h\"\n\n#import <Foundation/Foundation.h>\n\nint main(int argc, const char * argv[])\n{\n\t@autoreleasepool\n\t{\n\t\tZetaAuthorizationHelper *  helper = [[ZetaAuthorizationHelper alloc] init];\n\t\t[helper run];\n\t}\n\treturn 0;\n}\n"
  },
  {
    "path": "ZetaLoginItemHelper/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>$(DEVELOPMENT_LANGUAGE)</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n\t<key>LSApplicationCategoryType</key>\n\t<string>public.app-category.utilities</string>\n\t<key>LSBackgroundOnly</key>\n\t<true/>\n\t<key>LSMinimumSystemVersion</key>\n\t<string>$(MACOSX_DEPLOYMENT_TARGET)</string>\n\t<key>NSHumanReadableCopyright</key>\n\t<string>Copyright © 2021 the-color-black.net. All rights reserved.</string>\n\t<key>NSPrincipalClass</key>\n\t<string>NSApplication</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "ZetaLoginItemHelper/main.m",
    "content": "//\n//  main.m\n//  ZetaLoginItemHelper\n//\n//  Created by cbreak on 19.11.02.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import <Cocoa/Cocoa.h>\n\nint main(int argc, const char * argv[])\n{\n\t// Start the main ZetaWatch application\n\t// This trampoline is needed since SMLoginItemSetEnabled only allows adding\n\t// helpers to start at login, not the main bundle.\n\t// see ZetaWatch/ZetaWatchDelegate.mm for the login item adding code\n\t@autoreleasepool\n\t{\n\t\t// Start any ZetaWatch without adding a new instance\n\t\t[[NSWorkspace sharedWorkspace]\n\t\t launchAppWithBundleIdentifier:@\"net.the-color-black.ZetaWatch\"\n\t\t options:NSWorkspaceLaunchDefault\n\t\t additionalEventParamDescriptor:0\n\t\t launchIdentifier:0];\n\t}\n\t// Don't exit since ServiceManagement doesn't like it\n\treturn NSApplicationMain(argc, argv);\n}\n"
  },
  {
    "path": "ZetaWatch/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"size\" : \"16x16\",\n      \"idiom\" : \"mac\",\n      \"filename\" : \"Zetaicoon-16.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"16x16\",\n      \"idiom\" : \"mac\",\n      \"filename\" : \"Zetaicoon-32.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"32x32\",\n      \"idiom\" : \"mac\",\n      \"filename\" : \"Zetaicoon-32.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"32x32\",\n      \"idiom\" : \"mac\",\n      \"filename\" : \"Zetaicoon-64.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"128x128\",\n      \"idiom\" : \"mac\",\n      \"filename\" : \"Zetaicoon-128.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"128x128\",\n      \"idiom\" : \"mac\",\n      \"filename\" : \"Zetaicoon-256.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"256x256\",\n      \"idiom\" : \"mac\",\n      \"filename\" : \"Zetaicoon-256.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"256x256\",\n      \"idiom\" : \"mac\",\n      \"filename\" : \"Zetaicoon-512.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"512x512\",\n      \"idiom\" : \"mac\",\n      \"filename\" : \"Zetaicoon-512.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"512x512\",\n      \"idiom\" : \"mac\",\n      \"filename\" : \"Zetaicoon-1024.png\",\n      \"scale\" : \"2x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "ZetaWatch/Assets.xcassets/Contents.json",
    "content": "{\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "ZetaWatch/Assets.xcassets/Zeta.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"Zetaicoon.pdf\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "ZetaWatch/Base.lproj/MainMenu.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"17701\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"17701\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"NSApplication\">\n            <connections>\n                <outlet property=\"delegate\" destination=\"Voe-Tx-rLC\" id=\"GzC-gU-4Uq\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customObject id=\"Voe-Tx-rLC\" userLabel=\"ZetaWatchDelegate\" customClass=\"ZetaWatchDelegate\">\n            <connections>\n                <outlet property=\"authorization\" destination=\"GUh-uV-dxo\" id=\"989-1T-oct\"/>\n                <outlet property=\"poolWatcher\" destination=\"Gim-eq-VbR\" id=\"l93-hb-HuX\"/>\n                <outlet property=\"settings\" destination=\"h6V-8x-hYX\" id=\"nvs-pP-koq\"/>\n                <outlet property=\"updater\" destination=\"7Va-uZ-m1K\" id=\"VUM-ji-fYM\"/>\n                <outlet property=\"zetaConfirmDialog\" destination=\"YY7-LW-cAD\" id=\"N6U-3T-0X2\"/>\n                <outlet property=\"zetaKeyLoader\" destination=\"R7D-cp-kuE\" id=\"Uml-Lc-GeC\"/>\n                <outlet property=\"zetaMainMenu\" destination=\"8rf-zp-5r9\" id=\"20J-Sj-1ol\"/>\n                <outlet property=\"zetaMenu\" destination=\"Xld-Up-BZ8\" id=\"YRA-tL-FBE\"/>\n                <outlet property=\"zetaQueryDialog\" destination=\"TB2-7Z-kJ2\" id=\"d4N-Ym-SU3\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"8rf-zp-5r9\" userLabel=\"ZetaMainMenu\" customClass=\"ZetaMainMenu\">\n            <connections>\n                <outlet property=\"_authorization\" destination=\"GUh-uV-dxo\" id=\"LTt-go-j7Z\"/>\n                <outlet property=\"notificationCenter\" destination=\"ZZj-pd-85j\" id=\"DDy-Za-7rV\"/>\n                <outlet property=\"poolWatcher\" destination=\"Gim-eq-VbR\" id=\"Sat-ah-3Qq\"/>\n                <outlet property=\"zetaConfirmDialog\" destination=\"YY7-LW-cAD\" id=\"Yck-ti-hMt\"/>\n                <outlet property=\"zetaKeyLoader\" destination=\"R7D-cp-kuE\" id=\"aMW-DQ-FcT\"/>\n                <outlet property=\"zetaQueryDialog\" destination=\"TB2-7Z-kJ2\" id=\"F0s-lJ-1nh\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"geo-tu-CMM\" userLabel=\"ZetaImportMenu\" customClass=\"ZetaImportMenu\">\n            <connections>\n                <outlet property=\"_authorization\" destination=\"GUh-uV-dxo\" id=\"Psx-ls-DeC\"/>\n                <outlet property=\"autoImporter\" destination=\"PVX-FU-gbc\" id=\"Wpo-l0-uGC\"/>\n                <outlet property=\"importMenu\" destination=\"fE9-G4-NH4\" id=\"jfo-ja-1Zj\"/>\n                <outlet property=\"poolWatcher\" destination=\"Gim-eq-VbR\" id=\"aD3-N2-eyI\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"R7D-cp-kuE\" userLabel=\"ZetaKeyLoader\" customClass=\"ZetaKeyLoader\">\n            <connections>\n                <outlet property=\"_authorization\" destination=\"GUh-uV-dxo\" id=\"j1a-fu-F0a\"/>\n                <outlet property=\"loadButton\" destination=\"Xth-17-Uyp\" id=\"ShD-Rm-nkI\"/>\n                <outlet property=\"passwordField\" destination=\"JpZ-yq-Swt\" id=\"wki-ew-pno\"/>\n                <outlet property=\"poolWatcher\" destination=\"Gim-eq-VbR\" id=\"hdd-tK-37f\"/>\n                <outlet property=\"popover\" destination=\"5Lh-hG-dv8\" id=\"bFc-sJ-D7x\"/>\n                <outlet property=\"progressIndicator\" destination=\"IW2-QV-nuy\" id=\"1wo-S0-51q\"/>\n                <outlet property=\"queryField\" destination=\"vtC-BP-wc5\" id=\"cQa-7q-bCw\"/>\n                <outlet property=\"skipButton\" destination=\"sXs-lU-vuw\" id=\"jjX-d7-NRy\"/>\n                <outlet property=\"statusField\" destination=\"egb-Mb-iyZ\" id=\"FbE-63-Kfl\"/>\n                <outlet property=\"useKeychainCheckbox\" destination=\"2s9-7L-bQq\" id=\"6dw-gL-9v1\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"TB2-7Z-kJ2\" userLabel=\"ZetaQueryDialog\" customClass=\"ZetaQueryDialog\">\n            <connections>\n                <outlet property=\"popover\" destination=\"BNT-uI-e5Z\" id=\"Yz7-Dw-vEz\"/>\n                <outlet property=\"queryField\" destination=\"VwX-rR-NXB\" id=\"dK5-xq-IgY\"/>\n                <outlet property=\"replyField\" destination=\"aF4-gD-hTY\" id=\"8bG-cA-Ey2\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"YY7-LW-cAD\" userLabel=\"ZetaConfirmDialog\" customClass=\"ZetaConfirmDialog\">\n            <connections>\n                <outlet property=\"infoField\" destination=\"KzI-U2-jrx\" id=\"er4-6R-hpv\"/>\n                <outlet property=\"popover\" destination=\"n6f-GT-2V0\" id=\"Qhx-3R-efB\"/>\n                <outlet property=\"queryField\" destination=\"Bjp-t2-sCZ\" id=\"Arh-fc-VT8\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"Gim-eq-VbR\" userLabel=\"ZetaPoolWatcher\" customClass=\"ZetaPoolWatcher\"/>\n        <customObject id=\"PVX-FU-gbc\" userLabel=\"ZetaAutoImporter\" customClass=\"ZetaAutoImporter\">\n            <connections>\n                <outlet property=\"_authorization\" destination=\"GUh-uV-dxo\" id=\"hKw-Oj-ONj\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"ZZj-pd-85j\" userLabel=\"ZetaNotificationCenter\" customClass=\"ZetaNotificationCenter\">\n            <connections>\n                <outlet property=\"poolWatcher\" destination=\"Gim-eq-VbR\" id=\"Lp3-zU-Amk\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"GUh-uV-dxo\" userLabel=\"ZetaAuthorization\" customClass=\"ZetaAuthorization\">\n            <connections>\n                <outlet property=\"notificationCenter\" destination=\"ZZj-pd-85j\" id=\"TOz-7T-gp3\"/>\n            </connections>\n        </customObject>\n        <menu title=\"Zeta\" id=\"Xld-Up-BZ8\">\n            <items>\n                <menuItem title=\"ZFS Pools\" tag=\"100\" hidden=\"YES\" enabled=\"NO\" id=\"SFT-8i-4hp\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                </menuItem>\n                <menuItem isSeparatorItem=\"YES\" id=\"V2G-dn-yYW\"/>\n                <menuItem title=\"Actions\" tag=\"101\" hidden=\"YES\" enabled=\"NO\" id=\"Wnr-ig-9x9\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                </menuItem>\n                <menuItem title=\"Import Pool\" id=\"bAG-Ud-NX6\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"Import Pool\" id=\"fE9-G4-NH4\" userLabel=\"Import Pool Menu\">\n                        <connections>\n                            <outlet property=\"delegate\" destination=\"geo-tu-CMM\" id=\"rbu-7n-mSX\"/>\n                        </connections>\n                    </menu>\n                </menuItem>\n                <menuItem isSeparatorItem=\"YES\" id=\"Ttd-8u-p8d\"/>\n                <menuItem title=\"Settings\" id=\"abZ-nP-vC5\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"Settings\" id=\"Zp5-as-Y5e\">\n                        <items>\n                            <menuItem title=\"Use Keychain by default\" id=\"orV-Zm-zgL\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <binding destination=\"oMO-Og-s5N\" name=\"value\" keyPath=\"values.useKeychain\" id=\"BYu-QP-V3e\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"M9f-nT-c4H\"/>\n                            <menuItem title=\"Auto-Import Pools\" id=\"O0q-h1-njv\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <binding destination=\"oMO-Og-s5N\" name=\"value\" keyPath=\"values.autoImport\" id=\"LV6-2F-8fO\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Auto-Unlock Datasets\" id=\"1bo-el-qdg\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <binding destination=\"oMO-Og-s5N\" name=\"value\" keyPath=\"values.autoUnlock\" id=\"sSC-4i-zjn\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"k2v-Lw-Y2t\"/>\n                            <menuItem title=\"Start at Login\" id=\"WkG-Hl-jeI\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <binding destination=\"oMO-Og-s5N\" name=\"value\" keyPath=\"values.startAtLogin\" id=\"Vwc-yO-K6u\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"wz1-YY-4Wk\"/>\n                            <menuItem title=\"Auto Update\" id=\"PuO-P5-LRP\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <binding destination=\"7Va-uZ-m1K\" name=\"value\" keyPath=\"automaticallyChecksForUpdates\" id=\"cJl-aO-zqY\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Check for Updates now...\" id=\"e40-VT-eEj\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"checkForUpdates:\" target=\"7Va-uZ-m1K\" id=\"yj1-Ju-zDX\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"438-n3-d29\"/>\n                            <menuItem title=\"More Settings...\" id=\"2HR-5O-7CX\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"showSettings:\" target=\"Voe-Tx-rLC\" id=\"5H4-tn-qq1\"/>\n                                </connections>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem isSeparatorItem=\"YES\" id=\"ZkL-mf-Ahh\"/>\n                <menuItem title=\"Quit\" id=\"PuA-D0-otp\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <connections>\n                        <action selector=\"terminate:\" target=\"-2\" id=\"L56-LL-ZV3\"/>\n                    </connections>\n                </menuItem>\n            </items>\n            <connections>\n                <outlet property=\"delegate\" destination=\"8rf-zp-5r9\" id=\"L78-mK-psa\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"132\" y=\"183\"/>\n        </menu>\n        <menu title=\"Main Menu\" systemMenu=\"main\" id=\"AYu-sK-qS6\">\n            <items>\n                <menuItem title=\"ZetaWatch\" id=\"1Xt-HY-uBw\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"ZetaWatch\" systemMenu=\"apple\" id=\"uQy-DD-JDr\">\n                        <items>\n                            <menuItem title=\"About ZetaWatch\" id=\"5kV-Vb-QxS\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"orderFrontStandardAboutPanel:\" target=\"-1\" id=\"Exp-CZ-Vem\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"VOq-y0-SEH\"/>\n                            <menuItem title=\"Preferences…\" keyEquivalent=\",\" id=\"BOF-NM-1cW\"/>\n                            <menuItem isSeparatorItem=\"YES\" id=\"wFC-TO-SCJ\"/>\n                            <menuItem title=\"Services\" id=\"NMo-om-nkz\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Services\" systemMenu=\"services\" id=\"hz9-B4-Xy5\"/>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"4je-JR-u6R\"/>\n                            <menuItem title=\"Hide ZetaWatch\" keyEquivalent=\"h\" id=\"Olw-nP-bQN\">\n                                <connections>\n                                    <action selector=\"hide:\" target=\"-1\" id=\"PnN-Uc-m68\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Hide Others\" keyEquivalent=\"h\" id=\"Vdr-fp-XzO\">\n                                <modifierMask key=\"keyEquivalentModifierMask\" option=\"YES\" command=\"YES\"/>\n                                <connections>\n                                    <action selector=\"hideOtherApplications:\" target=\"-1\" id=\"VT4-aY-XCT\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Show All\" id=\"Kd2-mp-pUS\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"unhideAllApplications:\" target=\"-1\" id=\"Dhg-Le-xox\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"kCx-OE-vgT\"/>\n                            <menuItem title=\"Quit ZetaWatch\" keyEquivalent=\"q\" id=\"4sb-4s-VLi\">\n                                <connections>\n                                    <action selector=\"terminate:\" target=\"-1\" id=\"Te7-pn-YzF\"/>\n                                </connections>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"File\" id=\"dMs-cI-mzQ\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"File\" id=\"bib-Uj-vzu\">\n                        <items>\n                            <menuItem title=\"New\" keyEquivalent=\"n\" id=\"Was-JA-tGl\">\n                                <connections>\n                                    <action selector=\"newDocument:\" target=\"-1\" id=\"4Si-XN-c54\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Open…\" keyEquivalent=\"o\" id=\"IAo-SY-fd9\">\n                                <connections>\n                                    <action selector=\"openDocument:\" target=\"-1\" id=\"bVn-NM-KNZ\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Open Recent\" id=\"tXI-mr-wws\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Open Recent\" systemMenu=\"recentDocuments\" id=\"oas-Oc-fiZ\">\n                                    <items>\n                                        <menuItem title=\"Clear Menu\" id=\"vNY-rz-j42\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"clearRecentDocuments:\" target=\"-1\" id=\"Daa-9d-B3U\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"m54-Is-iLE\"/>\n                            <menuItem title=\"Close\" keyEquivalent=\"w\" id=\"DVo-aG-piG\">\n                                <connections>\n                                    <action selector=\"performClose:\" target=\"-1\" id=\"HmO-Ls-i7Q\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Save…\" keyEquivalent=\"s\" id=\"pxx-59-PXV\">\n                                <connections>\n                                    <action selector=\"saveDocument:\" target=\"-1\" id=\"teZ-XB-qJY\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Save As…\" keyEquivalent=\"S\" id=\"Bw7-FT-i3A\">\n                                <connections>\n                                    <action selector=\"saveDocumentAs:\" target=\"-1\" id=\"mDf-zr-I0C\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Revert to Saved\" id=\"KaW-ft-85H\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"revertDocumentToSaved:\" target=\"-1\" id=\"iJ3-Pv-kwq\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"aJh-i4-bef\"/>\n                            <menuItem title=\"Page Setup…\" keyEquivalent=\"P\" id=\"qIS-W8-SiK\">\n                                <modifierMask key=\"keyEquivalentModifierMask\" shift=\"YES\" command=\"YES\"/>\n                                <connections>\n                                    <action selector=\"runPageLayout:\" target=\"-1\" id=\"Din-rz-gC5\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Print…\" keyEquivalent=\"p\" id=\"aTl-1u-JFS\">\n                                <connections>\n                                    <action selector=\"print:\" target=\"-1\" id=\"qaZ-4w-aoO\"/>\n                                </connections>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"Edit\" id=\"5QF-Oa-p0T\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"Edit\" id=\"W48-6f-4Dl\">\n                        <items>\n                            <menuItem title=\"Undo\" keyEquivalent=\"z\" id=\"dRJ-4n-Yzg\">\n                                <connections>\n                                    <action selector=\"undo:\" target=\"-1\" id=\"M6e-cu-g7V\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Redo\" keyEquivalent=\"Z\" id=\"6dh-zS-Vam\">\n                                <connections>\n                                    <action selector=\"redo:\" target=\"-1\" id=\"oIA-Rs-6OD\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"WRV-NI-Exz\"/>\n                            <menuItem title=\"Cut\" keyEquivalent=\"x\" id=\"uRl-iY-unG\">\n                                <connections>\n                                    <action selector=\"cut:\" target=\"-1\" id=\"YJe-68-I9s\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Copy\" keyEquivalent=\"c\" id=\"x3v-GG-iWU\">\n                                <connections>\n                                    <action selector=\"copy:\" target=\"-1\" id=\"G1f-GL-Joy\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Paste\" keyEquivalent=\"v\" id=\"gVA-U4-sdL\">\n                                <connections>\n                                    <action selector=\"paste:\" target=\"-1\" id=\"UvS-8e-Qdg\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Paste and Match Style\" keyEquivalent=\"V\" id=\"WeT-3V-zwk\">\n                                <modifierMask key=\"keyEquivalentModifierMask\" option=\"YES\" command=\"YES\"/>\n                                <connections>\n                                    <action selector=\"pasteAsPlainText:\" target=\"-1\" id=\"cEh-KX-wJQ\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Delete\" id=\"pa3-QI-u2k\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"delete:\" target=\"-1\" id=\"0Mk-Ml-PaM\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Select All\" keyEquivalent=\"a\" id=\"Ruw-6m-B2m\">\n                                <connections>\n                                    <action selector=\"selectAll:\" target=\"-1\" id=\"VNm-Mi-diN\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"uyl-h8-XO2\"/>\n                            <menuItem title=\"Find\" id=\"4EN-yA-p0u\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Find\" id=\"1b7-l0-nxx\">\n                                    <items>\n                                        <menuItem title=\"Find…\" tag=\"1\" keyEquivalent=\"f\" id=\"Xz5-n4-O0W\">\n                                            <connections>\n                                                <action selector=\"performFindPanelAction:\" target=\"-1\" id=\"cD7-Qs-BN4\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Find and Replace…\" tag=\"12\" keyEquivalent=\"f\" id=\"YEy-JH-Tfz\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\" option=\"YES\" command=\"YES\"/>\n                                            <connections>\n                                                <action selector=\"performFindPanelAction:\" target=\"-1\" id=\"WD3-Gg-5AJ\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Find Next\" tag=\"2\" keyEquivalent=\"g\" id=\"q09-fT-Sye\">\n                                            <connections>\n                                                <action selector=\"performFindPanelAction:\" target=\"-1\" id=\"NDo-RZ-v9R\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Find Previous\" tag=\"3\" keyEquivalent=\"G\" id=\"OwM-mh-QMV\">\n                                            <connections>\n                                                <action selector=\"performFindPanelAction:\" target=\"-1\" id=\"HOh-sY-3ay\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Use Selection for Find\" tag=\"7\" keyEquivalent=\"e\" id=\"buJ-ug-pKt\">\n                                            <connections>\n                                                <action selector=\"performFindPanelAction:\" target=\"-1\" id=\"U76-nv-p5D\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Jump to Selection\" keyEquivalent=\"j\" id=\"S0p-oC-mLd\">\n                                            <connections>\n                                                <action selector=\"centerSelectionInVisibleArea:\" target=\"-1\" id=\"IOG-6D-g5B\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem title=\"Spelling and Grammar\" id=\"Dv1-io-Yv7\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Spelling\" id=\"3IN-sU-3Bg\">\n                                    <items>\n                                        <menuItem title=\"Show Spelling and Grammar\" keyEquivalent=\":\" id=\"HFo-cy-zxI\">\n                                            <connections>\n                                                <action selector=\"showGuessPanel:\" target=\"-1\" id=\"vFj-Ks-hy3\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Check Document Now\" keyEquivalent=\";\" id=\"hz2-CU-CR7\">\n                                            <connections>\n                                                <action selector=\"checkSpelling:\" target=\"-1\" id=\"fz7-VC-reM\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"bNw-od-mp5\"/>\n                                        <menuItem title=\"Check Spelling While Typing\" id=\"rbD-Rh-wIN\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleContinuousSpellChecking:\" target=\"-1\" id=\"7w6-Qz-0kB\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Check Grammar With Spelling\" id=\"mK6-2p-4JG\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleGrammarChecking:\" target=\"-1\" id=\"muD-Qn-j4w\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Correct Spelling Automatically\" id=\"78Y-hA-62v\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticSpellingCorrection:\" target=\"-1\" id=\"2lM-Qi-WAP\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem title=\"Substitutions\" id=\"9ic-FL-obx\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Substitutions\" id=\"FeM-D8-WVr\">\n                                    <items>\n                                        <menuItem title=\"Show Substitutions\" id=\"z6F-FW-3nz\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"orderFrontSubstitutionsPanel:\" target=\"-1\" id=\"oku-mr-iSq\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"gPx-C9-uUO\"/>\n                                        <menuItem title=\"Smart Copy/Paste\" id=\"9yt-4B-nSM\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleSmartInsertDelete:\" target=\"-1\" id=\"3IJ-Se-DZD\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Smart Quotes\" id=\"hQb-2v-fYv\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticQuoteSubstitution:\" target=\"-1\" id=\"ptq-xd-QOA\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Smart Dashes\" id=\"rgM-f4-ycn\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticDashSubstitution:\" target=\"-1\" id=\"oCt-pO-9gS\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Smart Links\" id=\"cwL-P1-jid\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticLinkDetection:\" target=\"-1\" id=\"Gip-E3-Fov\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Data Detectors\" id=\"tRr-pd-1PS\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticDataDetection:\" target=\"-1\" id=\"R1I-Nq-Kbl\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Text Replacement\" id=\"HFQ-gK-NFA\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticTextReplacement:\" target=\"-1\" id=\"DvP-Fe-Py6\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem title=\"Transformations\" id=\"2oI-Rn-ZJC\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Transformations\" id=\"c8a-y6-VQd\">\n                                    <items>\n                                        <menuItem title=\"Make Upper Case\" id=\"vmV-6d-7jI\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"uppercaseWord:\" target=\"-1\" id=\"sPh-Tk-edu\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Make Lower Case\" id=\"d9M-CD-aMd\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"lowercaseWord:\" target=\"-1\" id=\"iUZ-b5-hil\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Capitalize\" id=\"UEZ-Bs-lqG\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"capitalizeWord:\" target=\"-1\" id=\"26H-TL-nsh\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem title=\"Speech\" id=\"xrE-MZ-jX0\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Speech\" id=\"3rS-ZA-NoH\">\n                                    <items>\n                                        <menuItem title=\"Start Speaking\" id=\"Ynk-f8-cLZ\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"startSpeaking:\" target=\"-1\" id=\"654-Ng-kyl\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Stop Speaking\" id=\"Oyz-dy-DGm\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"stopSpeaking:\" target=\"-1\" id=\"dX8-6p-jy9\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"Format\" id=\"jxT-CU-nIS\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"Format\" id=\"GEO-Iw-cKr\">\n                        <items>\n                            <menuItem title=\"Font\" id=\"Gi5-1S-RQB\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Font\" systemMenu=\"font\" id=\"aXa-aM-Jaq\">\n                                    <items>\n                                        <menuItem title=\"Show Fonts\" keyEquivalent=\"t\" id=\"Q5e-8K-NDq\"/>\n                                        <menuItem title=\"Bold\" tag=\"2\" keyEquivalent=\"b\" id=\"GB9-OM-e27\"/>\n                                        <menuItem title=\"Italic\" tag=\"1\" keyEquivalent=\"i\" id=\"Vjx-xi-njq\"/>\n                                        <menuItem title=\"Underline\" keyEquivalent=\"u\" id=\"WRG-CD-K1S\">\n                                            <connections>\n                                                <action selector=\"underline:\" target=\"-1\" id=\"FYS-2b-JAY\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"5gT-KC-WSO\"/>\n                                        <menuItem title=\"Bigger\" tag=\"3\" keyEquivalent=\"+\" id=\"Ptp-SP-VEL\"/>\n                                        <menuItem title=\"Smaller\" tag=\"4\" keyEquivalent=\"-\" id=\"i1d-Er-qST\"/>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"kx3-Dk-x3B\"/>\n                                        <menuItem title=\"Kern\" id=\"jBQ-r6-VK2\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <menu key=\"submenu\" title=\"Kern\" id=\"tlD-Oa-oAM\">\n                                                <items>\n                                                    <menuItem title=\"Use Default\" id=\"GUa-eO-cwY\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"useStandardKerning:\" target=\"-1\" id=\"6dk-9l-Ckg\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Use None\" id=\"cDB-IK-hbR\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"turnOffKerning:\" target=\"-1\" id=\"U8a-gz-Maa\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Tighten\" id=\"46P-cB-AYj\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"tightenKerning:\" target=\"-1\" id=\"hr7-Nz-8ro\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Loosen\" id=\"ogc-rX-tC1\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"loosenKerning:\" target=\"-1\" id=\"8i4-f9-FKE\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                </items>\n                                            </menu>\n                                        </menuItem>\n                                        <menuItem title=\"Ligatures\" id=\"o6e-r0-MWq\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <menu key=\"submenu\" title=\"Ligatures\" id=\"w0m-vy-SC9\">\n                                                <items>\n                                                    <menuItem title=\"Use Default\" id=\"agt-UL-0e3\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"useStandardLigatures:\" target=\"-1\" id=\"7uR-wd-Dx6\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Use None\" id=\"J7y-lM-qPV\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"turnOffLigatures:\" target=\"-1\" id=\"iX2-gA-Ilz\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Use All\" id=\"xQD-1f-W4t\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"useAllLigatures:\" target=\"-1\" id=\"KcB-kA-TuK\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                </items>\n                                            </menu>\n                                        </menuItem>\n                                        <menuItem title=\"Baseline\" id=\"OaQ-X3-Vso\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <menu key=\"submenu\" title=\"Baseline\" id=\"ijk-EB-dga\">\n                                                <items>\n                                                    <menuItem title=\"Use Default\" id=\"3Om-Ey-2VK\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"unscript:\" target=\"-1\" id=\"0vZ-95-Ywn\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Superscript\" id=\"Rqc-34-cIF\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"superscript:\" target=\"-1\" id=\"3qV-fo-wpU\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Subscript\" id=\"I0S-gh-46l\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"subscript:\" target=\"-1\" id=\"Q6W-4W-IGz\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Raise\" id=\"2h7-ER-AoG\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"raiseBaseline:\" target=\"-1\" id=\"4sk-31-7Q9\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Lower\" id=\"1tx-W0-xDw\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"lowerBaseline:\" target=\"-1\" id=\"OF1-bc-KW4\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                </items>\n                                            </menu>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"Ndw-q3-faq\"/>\n                                        <menuItem title=\"Show Colors\" keyEquivalent=\"C\" id=\"bgn-CT-cEk\">\n                                            <connections>\n                                                <action selector=\"orderFrontColorPanel:\" target=\"-1\" id=\"mSX-Xz-DV3\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"iMs-zA-UFJ\"/>\n                                        <menuItem title=\"Copy Style\" keyEquivalent=\"c\" id=\"5Vv-lz-BsD\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\" option=\"YES\" command=\"YES\"/>\n                                            <connections>\n                                                <action selector=\"copyFont:\" target=\"-1\" id=\"GJO-xA-L4q\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Paste Style\" keyEquivalent=\"v\" id=\"vKC-jM-MkH\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\" option=\"YES\" command=\"YES\"/>\n                                            <connections>\n                                                <action selector=\"pasteFont:\" target=\"-1\" id=\"JfD-CL-leO\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem title=\"Text\" id=\"Fal-I4-PZk\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Text\" id=\"d9c-me-L2H\">\n                                    <items>\n                                        <menuItem title=\"Align Left\" keyEquivalent=\"{\" id=\"ZM1-6Q-yy1\">\n                                            <connections>\n                                                <action selector=\"alignLeft:\" target=\"-1\" id=\"zUv-R1-uAa\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Center\" keyEquivalent=\"|\" id=\"VIY-Ag-zcb\">\n                                            <connections>\n                                                <action selector=\"alignCenter:\" target=\"-1\" id=\"spX-mk-kcS\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Justify\" id=\"J5U-5w-g23\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"alignJustified:\" target=\"-1\" id=\"ljL-7U-jND\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Align Right\" keyEquivalent=\"}\" id=\"wb2-vD-lq4\">\n                                            <connections>\n                                                <action selector=\"alignRight:\" target=\"-1\" id=\"r48-bG-YeY\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"4s2-GY-VfK\"/>\n                                        <menuItem title=\"Writing Direction\" id=\"H1b-Si-o9J\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <menu key=\"submenu\" title=\"Writing Direction\" id=\"8mr-sm-Yjd\">\n                                                <items>\n                                                    <menuItem title=\"Paragraph\" enabled=\"NO\" id=\"ZvO-Gk-QUH\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                    <menuItem id=\"YGs-j5-SAR\">\n                                                        <string key=\"title\">\tDefault</string>\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"makeBaseWritingDirectionNatural:\" target=\"-1\" id=\"qtV-5e-UBP\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem id=\"Lbh-J2-qVU\">\n                                                        <string key=\"title\">\tLeft to Right</string>\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"makeBaseWritingDirectionLeftToRight:\" target=\"-1\" id=\"S0X-9S-QSf\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem id=\"jFq-tB-4Kx\">\n                                                        <string key=\"title\">\tRight to Left</string>\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"makeBaseWritingDirectionRightToLeft:\" target=\"-1\" id=\"5fk-qB-AqJ\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem isSeparatorItem=\"YES\" id=\"swp-gr-a21\"/>\n                                                    <menuItem title=\"Selection\" enabled=\"NO\" id=\"cqv-fj-IhA\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                    <menuItem id=\"Nop-cj-93Q\">\n                                                        <string key=\"title\">\tDefault</string>\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"makeTextWritingDirectionNatural:\" target=\"-1\" id=\"lPI-Se-ZHp\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem id=\"BgM-ve-c93\">\n                                                        <string key=\"title\">\tLeft to Right</string>\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"makeTextWritingDirectionLeftToRight:\" target=\"-1\" id=\"caW-Bv-w94\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem id=\"RB4-Sm-HuC\">\n                                                        <string key=\"title\">\tRight to Left</string>\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"makeTextWritingDirectionRightToLeft:\" target=\"-1\" id=\"EXD-6r-ZUu\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                </items>\n                                            </menu>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"fKy-g9-1gm\"/>\n                                        <menuItem title=\"Show Ruler\" id=\"vLm-3I-IUL\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleRuler:\" target=\"-1\" id=\"FOx-HJ-KwY\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Copy Ruler\" keyEquivalent=\"c\" id=\"MkV-Pr-PK5\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\" control=\"YES\" command=\"YES\"/>\n                                            <connections>\n                                                <action selector=\"copyRuler:\" target=\"-1\" id=\"71i-fW-3W2\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Paste Ruler\" keyEquivalent=\"v\" id=\"LVM-kO-fVI\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\" control=\"YES\" command=\"YES\"/>\n                                            <connections>\n                                                <action selector=\"pasteRuler:\" target=\"-1\" id=\"cSh-wd-qM2\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"View\" id=\"H8h-7b-M4v\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"View\" id=\"HyV-fh-RgO\">\n                        <items>\n                            <menuItem title=\"Show Toolbar\" keyEquivalent=\"t\" id=\"snW-S8-Cw5\">\n                                <modifierMask key=\"keyEquivalentModifierMask\" option=\"YES\" command=\"YES\"/>\n                                <connections>\n                                    <action selector=\"toggleToolbarShown:\" target=\"-1\" id=\"BXY-wc-z0C\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Customize Toolbar…\" id=\"1UK-8n-QPP\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"runToolbarCustomizationPalette:\" target=\"-1\" id=\"pQI-g3-MTW\"/>\n                                </connections>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"Window\" id=\"aUF-d1-5bR\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"Window\" systemMenu=\"window\" id=\"Td7-aD-5lo\">\n                        <items>\n                            <menuItem title=\"Minimize\" keyEquivalent=\"m\" id=\"OY7-WF-poV\">\n                                <connections>\n                                    <action selector=\"performMiniaturize:\" target=\"-1\" id=\"VwT-WD-YPe\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Zoom\" id=\"R4o-n2-Eq4\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"performZoom:\" target=\"-1\" id=\"DIl-cC-cCs\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"eu3-7i-yIM\"/>\n                            <menuItem title=\"Bring All to Front\" id=\"LE2-aR-0XJ\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"arrangeInFront:\" target=\"-1\" id=\"DRN-fu-gQh\"/>\n                                </connections>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"Help\" id=\"wpr-3q-Mcd\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"Help\" systemMenu=\"help\" id=\"F2S-fz-NVQ\">\n                        <items>\n                            <menuItem title=\"ZetaWatch Help\" keyEquivalent=\"?\" id=\"FKE-Sm-Kum\">\n                                <connections>\n                                    <action selector=\"showHelp:\" target=\"-1\" id=\"y7X-2Q-9no\"/>\n                                </connections>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n            </items>\n            <point key=\"canvasLocation\" x=\"159\" y=\"1264\"/>\n        </menu>\n        <customView id=\"40L-u9-aeI\" userLabel=\"PasswordDialog\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"555\" height=\"134\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <secureTextField verticalHuggingPriority=\"750\" verticalCompressionResistancePriority=\"751\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"JpZ-yq-Swt\">\n                    <rect key=\"frame\" x=\"92\" y=\"68\" width=\"443\" height=\"21\"/>\n                    <secureTextFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" borderStyle=\"bezel\" drawsBackground=\"YES\" usesSingleLineMode=\"YES\" id=\"nB2-dg-ZrZ\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <allowedInputSourceLocales>\n                            <string>NSAllRomanInputSourcesLocaleIdentifier</string>\n                        </allowedInputSourceLocales>\n                        <connections>\n                            <action selector=\"loadKey:\" target=\"R7D-cp-kuE\" id=\"Wfm-Ep-xcX\"/>\n                        </connections>\n                    </secureTextFieldCell>\n                </secureTextField>\n                <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"vtC-BP-wc5\">\n                    <rect key=\"frame\" x=\"90\" y=\"97\" width=\"447\" height=\"17\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"height\" relation=\"greaterThanOrEqual\" constant=\"17\" id=\"J3h-Ms-Ygd\"/>\n                    </constraints>\n                    <textFieldCell key=\"cell\" refusesFirstResponder=\"YES\" title=\"Enter the password for %@\" id=\"zNZ-X6-NWc\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField horizontalHuggingPriority=\"249\" verticalHuggingPriority=\"750\" verticalCompressionResistancePriority=\"752\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"egb-Mb-iyZ\">\n                    <rect key=\"frame\" x=\"114\" y=\"22\" width=\"277\" height=\"16\"/>\n                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Status\" id=\"Mwk-R6-lED\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <progressIndicator wantsLayer=\"YES\" horizontalHuggingPriority=\"750\" verticalHuggingPriority=\"750\" maxValue=\"100\" displayedWhenStopped=\"NO\" bezeled=\"NO\" indeterminate=\"YES\" controlSize=\"small\" style=\"spinning\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"IW2-QV-nuy\">\n                    <rect key=\"frame\" x=\"92\" y=\"22\" width=\"16\" height=\"16\"/>\n                </progressIndicator>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Xth-17-Uyp\">\n                    <rect key=\"frame\" x=\"458\" y=\"32\" width=\"83\" height=\"32\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Unlock\" bezelStyle=\"rounded\" alignment=\"center\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"piW-QM-gQc\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <string key=\"keyEquivalent\" base64-UTF8=\"YES\">\nDQ\n</string>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"loadKey:\" target=\"R7D-cp-kuE\" id=\"062-OO-Y0n\"/>\n                    </connections>\n                </button>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"sXs-lU-vuw\">\n                    <rect key=\"frame\" x=\"391\" y=\"32\" width=\"67\" height=\"32\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Skip\" bezelStyle=\"rounded\" alignment=\"center\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"vVt-vK-kZ4\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <string key=\"keyEquivalent\" base64-UTF8=\"YES\">\nGw\n</string>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"skipFileSystem:\" target=\"R7D-cp-kuE\" id=\"HLD-XO-u4Y\"/>\n                    </connections>\n                </button>\n                <button horizontalHuggingPriority=\"249\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"2s9-7L-bQq\">\n                    <rect key=\"frame\" x=\"90\" y=\"44\" width=\"301\" height=\"18\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"Store in Keychain\" bezelStyle=\"regularSquare\" imagePosition=\"left\" state=\"on\" inset=\"2\" id=\"sK3-hH-Yef\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                    </buttonCell>\n                </button>\n                <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"LRH-QE-iBn\">\n                    <rect key=\"frame\" x=\"20\" y=\"50\" width=\"64\" height=\"64\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"height\" constant=\"64\" id=\"TDZ-YV-zW0\"/>\n                        <constraint firstAttribute=\"width\" constant=\"64\" id=\"x8p-su-1N7\"/>\n                    </constraints>\n                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"NSApplicationIcon\" id=\"qon-SO-Jhf\"/>\n                </imageView>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"2s9-7L-bQq\" firstAttribute=\"leading\" secondItem=\"vtC-BP-wc5\" secondAttribute=\"leading\" id=\"00p-YA-u2F\"/>\n                <constraint firstAttribute=\"bottom\" relation=\"greaterThanOrEqual\" secondItem=\"sXs-lU-vuw\" secondAttribute=\"bottom\" constant=\"20\" symbolic=\"YES\" id=\"0VA-kp-xSZ\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"Xth-17-Uyp\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"1cC-Nw-Mpg\"/>\n                <constraint firstItem=\"vtC-BP-wc5\" firstAttribute=\"leading\" secondItem=\"LRH-QE-iBn\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"1gu-dR-bQA\"/>\n                <constraint firstItem=\"IW2-QV-nuy\" firstAttribute=\"leading\" secondItem=\"vtC-BP-wc5\" secondAttribute=\"leading\" id=\"2Yw-EI-3P1\"/>\n                <constraint firstItem=\"LRH-QE-iBn\" firstAttribute=\"leading\" secondItem=\"40L-u9-aeI\" secondAttribute=\"leading\" constant=\"20\" symbolic=\"YES\" id=\"8Ld-Ru-1X8\"/>\n                <constraint firstItem=\"vtC-BP-wc5\" firstAttribute=\"top\" secondItem=\"40L-u9-aeI\" secondAttribute=\"top\" priority=\"750\" constant=\"20\" symbolic=\"YES\" id=\"AfF-td-1Z6\"/>\n                <constraint firstAttribute=\"bottom\" relation=\"greaterThanOrEqual\" secondItem=\"Xth-17-Uyp\" secondAttribute=\"bottom\" constant=\"20\" symbolic=\"YES\" id=\"KPl-GI-4YV\"/>\n                <constraint firstItem=\"2s9-7L-bQq\" firstAttribute=\"top\" secondItem=\"JpZ-yq-Swt\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"Mef-as-LYH\"/>\n                <constraint firstItem=\"egb-Mb-iyZ\" firstAttribute=\"leading\" secondItem=\"IW2-QV-nuy\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"Nl8-ra-JyC\"/>\n                <constraint firstItem=\"Xth-17-Uyp\" firstAttribute=\"top\" secondItem=\"JpZ-yq-Swt\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"P47-oI-yFJ\"/>\n                <constraint firstItem=\"Xth-17-Uyp\" firstAttribute=\"leading\" secondItem=\"sXs-lU-vuw\" secondAttribute=\"trailing\" constant=\"12\" symbolic=\"YES\" id=\"XSz-Lh-EYu\"/>\n                <constraint firstItem=\"IW2-QV-nuy\" firstAttribute=\"top\" secondItem=\"2s9-7L-bQq\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"ZPU-AH-PdX\"/>\n                <constraint firstItem=\"JpZ-yq-Swt\" firstAttribute=\"top\" secondItem=\"vtC-BP-wc5\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"abq-QG-ftd\"/>\n                <constraint firstAttribute=\"bottom\" relation=\"greaterThanOrEqual\" secondItem=\"egb-Mb-iyZ\" secondAttribute=\"bottom\" constant=\"20\" symbolic=\"YES\" id=\"emi-Ch-eys\"/>\n                <constraint firstItem=\"sXs-lU-vuw\" firstAttribute=\"leading\" secondItem=\"2s9-7L-bQq\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"hSW-tq-jqR\"/>\n                <constraint firstItem=\"egb-Mb-iyZ\" firstAttribute=\"top\" secondItem=\"2s9-7L-bQq\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"l8W-4p-UJX\"/>\n                <constraint firstItem=\"sXs-lU-vuw\" firstAttribute=\"leading\" secondItem=\"egb-Mb-iyZ\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"tdT-So-PUO\"/>\n                <constraint firstItem=\"JpZ-yq-Swt\" firstAttribute=\"leading\" secondItem=\"vtC-BP-wc5\" secondAttribute=\"leading\" id=\"tqi-ow-0BQ\"/>\n                <constraint firstItem=\"LRH-QE-iBn\" firstAttribute=\"top\" secondItem=\"40L-u9-aeI\" secondAttribute=\"top\" constant=\"20\" symbolic=\"YES\" id=\"u0N-kd-ick\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"JpZ-yq-Swt\" secondAttribute=\"trailing\" constant=\"20\" id=\"xXA-Ui-KUB\"/>\n                <constraint firstItem=\"sXs-lU-vuw\" firstAttribute=\"top\" secondItem=\"JpZ-yq-Swt\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"yUJ-Wh-FsI\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"vtC-BP-wc5\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"ziC-dL-Eus\"/>\n            </constraints>\n            <connections>\n                <outlet property=\"nextKeyView\" destination=\"JpZ-yq-Swt\" id=\"djn-Eh-4Qs\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"145\" y=\"510\"/>\n        </customView>\n        <viewController id=\"3wl-p9-tQW\" userLabel=\"Password Popover View Controller\">\n            <connections>\n                <outlet property=\"view\" destination=\"40L-u9-aeI\" id=\"SJp-sP-WqY\"/>\n            </connections>\n        </viewController>\n        <popover behavior=\"semitransient\" id=\"5Lh-hG-dv8\" userLabel=\"Password Popover\">\n            <connections>\n                <outlet property=\"contentViewController\" destination=\"3wl-p9-tQW\" id=\"3c9-rd-q9f\"/>\n                <outlet property=\"delegate\" destination=\"R7D-cp-kuE\" id=\"4kg-JY-FmY\"/>\n            </connections>\n        </popover>\n        <viewController id=\"cvg-uB-4z4\" userLabel=\"Query Popover View Controller\">\n            <connections>\n                <outlet property=\"view\" destination=\"xBy-DS-Zxq\" id=\"boV-oP-ybM\"/>\n            </connections>\n        </viewController>\n        <popover behavior=\"semitransient\" id=\"BNT-uI-e5Z\" userLabel=\"Query Popover\">\n            <connections>\n                <outlet property=\"contentViewController\" destination=\"cvg-uB-4z4\" id=\"ihh-qg-O93\"/>\n            </connections>\n        </popover>\n        <viewController id=\"6oG-mj-9NA\" userLabel=\"Confirm View Controller\">\n            <connections>\n                <outlet property=\"view\" destination=\"sBQ-2t-b2A\" id=\"1oL-R8-65K\"/>\n            </connections>\n        </viewController>\n        <popover id=\"n6f-GT-2V0\" userLabel=\"Confirm Popover\">\n            <connections>\n                <outlet property=\"contentViewController\" destination=\"6oG-mj-9NA\" id=\"YDZ-xj-0gV\"/>\n            </connections>\n        </popover>\n        <userDefaultsController representsSharedInstance=\"YES\" id=\"oMO-Og-s5N\"/>\n        <customObject id=\"7Va-uZ-m1K\" customClass=\"SUUpdater\"/>\n        <customView id=\"xBy-DS-Zxq\" userLabel=\"QueryDialog\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"555\" height=\"115\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"VwX-rR-NXB\" userLabel=\"QueryTextField\">\n                    <rect key=\"frame\" x=\"90\" y=\"78\" width=\"447\" height=\"17\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"height\" relation=\"greaterThanOrEqual\" constant=\"17\" id=\"bI6-0C-vUT\"/>\n                    </constraints>\n                    <textFieldCell key=\"cell\" refusesFirstResponder=\"YES\" title=\"Query\" id=\"qSb-DF-62v\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"975-gg-tbR\">\n                    <rect key=\"frame\" x=\"484\" y=\"13\" width=\"57\" height=\"32\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Ok\" bezelStyle=\"rounded\" alignment=\"center\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"4cM-PF-O9d\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <string key=\"keyEquivalent\" base64-UTF8=\"YES\">\nDQ\n</string>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"ok:\" target=\"TB2-7Z-kJ2\" id=\"rNC-zb-KEI\"/>\n                    </connections>\n                </button>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"7YP-fB-fKc\">\n                    <rect key=\"frame\" x=\"402\" y=\"13\" width=\"82\" height=\"32\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Cancel\" bezelStyle=\"rounded\" alignment=\"center\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"fsa-Sc-vN6\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <string key=\"keyEquivalent\" base64-UTF8=\"YES\">\nGw\n</string>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"cancel:\" target=\"TB2-7Z-kJ2\" id=\"MnW-9i-IFa\"/>\n                    </connections>\n                </button>\n                <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"flA-4i-OSt\">\n                    <rect key=\"frame\" x=\"20\" y=\"31\" width=\"64\" height=\"64\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"64\" id=\"Wbu-ja-J2J\"/>\n                        <constraint firstAttribute=\"height\" constant=\"64\" id=\"hnI-ca-3jH\"/>\n                    </constraints>\n                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"NSApplicationIcon\" id=\"mfz-8D-mnE\"/>\n                </imageView>\n                <textField verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"aF4-gD-hTY\">\n                    <rect key=\"frame\" x=\"92\" y=\"49\" width=\"443\" height=\"21\"/>\n                    <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"ztY-kw-Z07\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"flA-4i-OSt\" firstAttribute=\"leading\" secondItem=\"xBy-DS-Zxq\" secondAttribute=\"leading\" constant=\"20\" symbolic=\"YES\" id=\"5Y2-Cs-uzD\"/>\n                <constraint firstItem=\"975-gg-tbR\" firstAttribute=\"top\" secondItem=\"aF4-gD-hTY\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"6bj-Ds-15S\"/>\n                <constraint firstItem=\"7YP-fB-fKc\" firstAttribute=\"leading\" relation=\"greaterThanOrEqual\" secondItem=\"aF4-gD-hTY\" secondAttribute=\"leading\" id=\"C7M-q4-fHe\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"975-gg-tbR\" secondAttribute=\"bottom\" constant=\"20\" symbolic=\"YES\" id=\"GqB-xX-tBM\"/>\n                <constraint firstItem=\"flA-4i-OSt\" firstAttribute=\"top\" secondItem=\"xBy-DS-Zxq\" secondAttribute=\"top\" constant=\"20\" symbolic=\"YES\" id=\"L38-PC-unr\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"aF4-gD-hTY\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"Q90-Fo-k83\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"975-gg-tbR\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"ViS-af-HY5\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"VwX-rR-NXB\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"a5q-sl-5GT\"/>\n                <constraint firstItem=\"975-gg-tbR\" firstAttribute=\"leading\" secondItem=\"7YP-fB-fKc\" secondAttribute=\"trailing\" constant=\"12\" symbolic=\"YES\" id=\"aYI-j7-vek\"/>\n                <constraint firstItem=\"aF4-gD-hTY\" firstAttribute=\"leading\" secondItem=\"VwX-rR-NXB\" secondAttribute=\"leading\" id=\"acM-8z-O5p\"/>\n                <constraint firstItem=\"VwX-rR-NXB\" firstAttribute=\"leading\" secondItem=\"flA-4i-OSt\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"hiA-RE-dVE\"/>\n                <constraint firstItem=\"aF4-gD-hTY\" firstAttribute=\"top\" secondItem=\"VwX-rR-NXB\" secondAttribute=\"bottom\" constant=\"8\" id=\"lTK-Kf-8of\"/>\n                <constraint firstItem=\"7YP-fB-fKc\" firstAttribute=\"top\" secondItem=\"aF4-gD-hTY\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"s41-PV-p6O\"/>\n                <constraint firstItem=\"VwX-rR-NXB\" firstAttribute=\"top\" secondItem=\"xBy-DS-Zxq\" secondAttribute=\"top\" priority=\"750\" constant=\"20\" symbolic=\"YES\" id=\"zMj-zA-y4l\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"144.5\" y=\"732\"/>\n        </customView>\n        <customView id=\"sBQ-2t-b2A\" userLabel=\"ConfirmationDialog\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"555\" height=\"272\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ksH-SQ-feV\">\n                    <rect key=\"frame\" x=\"20\" y=\"188\" width=\"64\" height=\"64\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"width\" constant=\"64\" id=\"SYz-2n-tdp\"/>\n                        <constraint firstAttribute=\"height\" constant=\"64\" id=\"cbC-aV-dbT\"/>\n                    </constraints>\n                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"NSApplicationIcon\" id=\"jGe-fX-ycL\"/>\n                </imageView>\n                <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Bjp-t2-sCZ\" userLabel=\"QueryTextField\">\n                    <rect key=\"frame\" x=\"90\" y=\"235\" width=\"447\" height=\"17\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"height\" relation=\"greaterThanOrEqual\" constant=\"17\" id=\"YhE-iC-0mY\"/>\n                    </constraints>\n                    <textFieldCell key=\"cell\" refusesFirstResponder=\"YES\" title=\"Query\" id=\"D6G-X2-Ubq\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField horizontalCompressionResistancePriority=\"250\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"KzI-U2-jrx\">\n                    <rect key=\"frame\" x=\"92\" y=\"61\" width=\"443\" height=\"166\"/>\n                    <textFieldCell key=\"cell\" controlSize=\"small\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" sendsActionOnEndEditing=\"YES\" state=\"on\" borderStyle=\"bezel\" drawsBackground=\"YES\" id=\"9lS-cc-3KX\">\n                        <font key=\"font\" metaFont=\"message\" size=\"11\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"j4u-aq-qhY\">\n                    <rect key=\"frame\" x=\"484\" y=\"13\" width=\"57\" height=\"32\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Ok\" bezelStyle=\"rounded\" alignment=\"center\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"CUl-rd-k52\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <string key=\"keyEquivalent\" base64-UTF8=\"YES\">\nDQ\n</string>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"ok:\" target=\"YY7-LW-cAD\" id=\"YEn-e2-lYC\"/>\n                    </connections>\n                </button>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"FAa-ai-LRq\">\n                    <rect key=\"frame\" x=\"402\" y=\"13\" width=\"82\" height=\"32\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Cancel\" bezelStyle=\"rounded\" alignment=\"center\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"ldU-dB-OJf\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <string key=\"keyEquivalent\" base64-UTF8=\"YES\">\nGw\n</string>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"cancel:\" target=\"YY7-LW-cAD\" id=\"yno-up-e0z\"/>\n                    </connections>\n                </button>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"KzI-U2-jrx\" firstAttribute=\"top\" secondItem=\"Bjp-t2-sCZ\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"0CO-b4-7l4\"/>\n                <constraint firstItem=\"Bjp-t2-sCZ\" firstAttribute=\"top\" secondItem=\"sBQ-2t-b2A\" secondAttribute=\"top\" constant=\"20\" symbolic=\"YES\" id=\"20o-E8-Ue7\"/>\n                <constraint firstItem=\"KzI-U2-jrx\" firstAttribute=\"trailing\" secondItem=\"j4u-aq-qhY\" secondAttribute=\"trailing\" id=\"6Pu-s7-W1c\"/>\n                <constraint firstItem=\"ksH-SQ-feV\" firstAttribute=\"top\" secondItem=\"sBQ-2t-b2A\" secondAttribute=\"top\" constant=\"20\" symbolic=\"YES\" id=\"9yf-4D-dCy\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"j4u-aq-qhY\" secondAttribute=\"bottom\" constant=\"20\" symbolic=\"YES\" id=\"FwY-zg-B0k\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"Bjp-t2-sCZ\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"LYY-tf-Xcn\"/>\n                <constraint firstItem=\"Bjp-t2-sCZ\" firstAttribute=\"leading\" secondItem=\"ksH-SQ-feV\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"M3d-bq-AkO\"/>\n                <constraint firstItem=\"j4u-aq-qhY\" firstAttribute=\"leading\" secondItem=\"FAa-ai-LRq\" secondAttribute=\"trailing\" constant=\"12\" symbolic=\"YES\" id=\"XcM-SV-Ej8\"/>\n                <constraint firstItem=\"FAa-ai-LRq\" firstAttribute=\"top\" secondItem=\"KzI-U2-jrx\" secondAttribute=\"bottom\" constant=\"20\" symbolic=\"YES\" id=\"am7-vv-7qp\"/>\n                <constraint firstItem=\"j4u-aq-qhY\" firstAttribute=\"top\" secondItem=\"KzI-U2-jrx\" secondAttribute=\"bottom\" constant=\"20\" symbolic=\"YES\" id=\"b04-dC-BUg\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"j4u-aq-qhY\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"cXN-99-Ft9\"/>\n                <constraint firstItem=\"ksH-SQ-feV\" firstAttribute=\"leading\" secondItem=\"sBQ-2t-b2A\" secondAttribute=\"leading\" constant=\"20\" symbolic=\"YES\" id=\"veU-Ix-P9F\"/>\n                <constraint firstItem=\"FAa-ai-LRq\" firstAttribute=\"leading\" relation=\"greaterThanOrEqual\" secondItem=\"ksH-SQ-feV\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"yiD-9F-pJN\"/>\n                <constraint firstItem=\"KzI-U2-jrx\" firstAttribute=\"leading\" secondItem=\"ksH-SQ-feV\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"zGA-kB-ZnU\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"144.5\" y=\"1063\"/>\n        </customView>\n        <viewController id=\"wow-Hy-QXj\" userLabel=\"Settings View Controller\">\n            <connections>\n                <outlet property=\"view\" destination=\"lzX-XA-XzO\" id=\"QzI-Ao-jyd\"/>\n            </connections>\n        </viewController>\n        <popover behavior=\"t\" id=\"h6V-8x-hYX\" userLabel=\"Settings\">\n            <connections>\n                <outlet property=\"contentViewController\" destination=\"wow-Hy-QXj\" id=\"Iba-Pd-Csq\"/>\n            </connections>\n        </popover>\n        <view id=\"lzX-XA-XzO\" userLabel=\"SettingsView\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"563\" height=\"178\"/>\n            <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n            <subviews>\n                <pathControl verticalHuggingPriority=\"750\" allowsExpansionToolTips=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"3QB-P7-si2\">\n                    <rect key=\"frame\" x=\"116\" y=\"14\" width=\"430\" height=\"25\"/>\n                    <pathCell key=\"cell\" selectable=\"YES\" editable=\"YES\" alignment=\"left\" placeholderString=\"Default Mountpoint\" pathStyle=\"popUp\" id=\"tfh-lb-I0Y\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <url key=\"url\" string=\"file:///Volumes/\"/>\n                        <allowedTypes>\n                            <string>public.folder</string>\n                        </allowedTypes>\n                        <connections>\n                            <binding destination=\"oMO-Og-s5N\" name=\"value\" keyPath=\"values.defaultAltroot\" id=\"O5x-Zo-nGc\">\n                                <dictionary key=\"options\">\n                                    <string key=\"NSValueTransformerName\">PathValueTransformer</string>\n                                </dictionary>\n                            </binding>\n                        </connections>\n                    </pathCell>\n                </pathControl>\n                <button horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"O5K-Z7-VRD\">\n                    <rect key=\"frame\" x=\"18\" y=\"18\" width=\"95\" height=\"18\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"Use Altroot:\" bezelStyle=\"regularSquare\" imagePosition=\"left\" inset=\"2\" id=\"cbb-cy-BJO\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <connections>\n                            <binding destination=\"oMO-Og-s5N\" name=\"value\" keyPath=\"values.useAltroot\" id=\"xMN-cB-aSW\"/>\n                        </connections>\n                    </buttonCell>\n                </button>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"owe-My-lsx\">\n                    <rect key=\"frame\" x=\"18\" y=\"38\" width=\"527\" height=\"18\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"Keep awake during Scrub\" bezelStyle=\"regularSquare\" imagePosition=\"left\" state=\"on\" inset=\"2\" id=\"dX7-Wx-70H\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <connections>\n                            <binding destination=\"oMO-Og-s5N\" name=\"value\" keyPath=\"values.keepAwakeDuringScrub\" id=\"mgD-hN-TIk\"/>\n                        </connections>\n                    </buttonCell>\n                </button>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Pt1-2o-MSz\">\n                    <rect key=\"frame\" x=\"18\" y=\"58\" width=\"527\" height=\"18\"/>\n                    <buttonCell key=\"cell\" type=\"check\" title=\"Allow host id mismatch\" bezelStyle=\"regularSquare\" imagePosition=\"left\" state=\"on\" inset=\"2\" id=\"GxS-Vj-BcC\">\n                        <behavior key=\"behavior\" changeContents=\"YES\" doesNotDimImage=\"YES\" lightByContents=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <connections>\n                            <binding destination=\"oMO-Og-s5N\" name=\"value\" keyPath=\"values.allowHostIDMismatch\" id=\"Dns-nF-r7O\"/>\n                        </connections>\n                    </buttonCell>\n                </button>\n                <scrollView verticalHuggingPriority=\"200\" verticalCompressionResistancePriority=\"1000\" autohidesScrollers=\"YES\" horizontalLineScroll=\"22\" horizontalPageScroll=\"10\" verticalLineScroll=\"22\" verticalPageScroll=\"10\" usesPredominantAxisScrolling=\"NO\" verticalScrollElasticity=\"allowed\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"qzi-84-8Hb\">\n                    <rect key=\"frame\" x=\"20\" y=\"82\" width=\"523\" height=\"76\"/>\n                    <clipView key=\"contentView\" ambiguous=\"YES\" id=\"fKK-4M-wy0\">\n                        <rect key=\"frame\" x=\"1\" y=\"0.0\" width=\"521\" height=\"75\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <tableView verticalHuggingPriority=\"750\" ambiguous=\"YES\" allowsExpansionToolTips=\"YES\" columnAutoresizingStyle=\"lastColumnOnly\" columnReordering=\"NO\" columnResizing=\"NO\" multipleSelection=\"NO\" autosaveColumns=\"NO\" rowHeight=\"20\" rowSizeStyle=\"automatic\" headerView=\"8kc-tN-1kV\" viewBased=\"YES\" floatsGroupRows=\"NO\" id=\"Op4-MF-bkS\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"521\" height=\"50\"/>\n                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                <size key=\"intercellSpacing\" width=\"3\" height=\"2\"/>\n                                <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <color key=\"gridColor\" name=\"gridColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                <tableColumns>\n                                    <tableColumn width=\"518\" minWidth=\"40\" maxWidth=\"1000\" id=\"xU7-mk-oli\">\n                                        <tableHeaderCell key=\"headerCell\" lineBreakMode=\"truncatingTail\" borderStyle=\"border\" title=\"Search Path\">\n                                            <color key=\"textColor\" name=\"headerTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"headerColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </tableHeaderCell>\n                                        <textFieldCell key=\"dataCell\" lineBreakMode=\"truncatingTail\" selectable=\"YES\" editable=\"YES\" title=\"Text Cell\" id=\"fAD-76-93W\">\n                                            <font key=\"font\" metaFont=\"system\"/>\n                                            <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                        </textFieldCell>\n                                        <tableColumnResizingMask key=\"resizingMask\" resizeWithTable=\"YES\" userResizable=\"YES\"/>\n                                        <prototypeCellViews>\n                                            <tableCellView id=\"eD7-n2-0Ve\">\n                                                <rect key=\"frame\" x=\"1\" y=\"1\" width=\"518\" height=\"20\"/>\n                                                <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                                <subviews>\n                                                    <pathControl verticalHuggingPriority=\"750\" allowsExpansionToolTips=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"0aW-al-p9r\">\n                                                        <rect key=\"frame\" x=\"2\" y=\"0.0\" width=\"496\" height=\"20\"/>\n                                                        <pathCell key=\"cell\" controlSize=\"small\" selectable=\"YES\" alignment=\"left\" id=\"5dc-aU-BGm\">\n                                                            <font key=\"font\" metaFont=\"smallSystem\"/>\n                                                            <url key=\"url\" string=\"file://localhost/Applications/\"/>\n                                                        </pathCell>\n                                                        <connections>\n                                                            <binding destination=\"eD7-n2-0Ve\" name=\"value\" keyPath=\"objectValue\" id=\"Nal-1Z-Efh\">\n                                                                <dictionary key=\"options\">\n                                                                    <bool key=\"NSAllowsEditingMultipleValuesSelection\" value=\"NO\"/>\n                                                                    <bool key=\"NSConditionallySetsEnabled\" value=\"NO\"/>\n                                                                    <string key=\"NSValueTransformerName\">PathValueTransformer</string>\n                                                                </dictionary>\n                                                            </binding>\n                                                        </connections>\n                                                    </pathControl>\n                                                </subviews>\n                                                <constraints>\n                                                    <constraint firstAttribute=\"trailing\" secondItem=\"0aW-al-p9r\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"MJu-VA-Vk7\"/>\n                                                    <constraint firstItem=\"0aW-al-p9r\" firstAttribute=\"leading\" secondItem=\"eD7-n2-0Ve\" secondAttribute=\"leading\" constant=\"2\" id=\"MVD-8c-nqY\"/>\n                                                    <constraint firstAttribute=\"bottom\" secondItem=\"0aW-al-p9r\" secondAttribute=\"bottom\" id=\"UiB-2d-Zxj\"/>\n                                                    <constraint firstItem=\"0aW-al-p9r\" firstAttribute=\"top\" secondItem=\"eD7-n2-0Ve\" secondAttribute=\"top\" id=\"vk8-tQ-CiF\"/>\n                                                </constraints>\n                                            </tableCellView>\n                                        </prototypeCellViews>\n                                    </tableColumn>\n                                </tableColumns>\n                                <connections>\n                                    <binding destination=\"JiR-wc-2kO\" name=\"content\" keyPath=\"arrangedObjects\" id=\"xc3-po-ZOI\"/>\n                                    <binding destination=\"JiR-wc-2kO\" name=\"selectionIndexes\" keyPath=\"selectionIndexes\" previousBinding=\"xc3-po-ZOI\" id=\"6B1-9o-UpY\"/>\n                                </connections>\n                            </tableView>\n                        </subviews>\n                    </clipView>\n                    <constraints>\n                        <constraint firstAttribute=\"height\" relation=\"greaterThanOrEqual\" constant=\"64\" id=\"s8e-Sk-EIe\"/>\n                    </constraints>\n                    <scroller key=\"horizontalScroller\" hidden=\"YES\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"YES\" id=\"enK-Gr-bvp\">\n                        <rect key=\"frame\" x=\"1\" y=\"118\" width=\"238\" height=\"16\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                    </scroller>\n                    <scroller key=\"verticalScroller\" hidden=\"YES\" wantsLayer=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"NO\" id=\"vG5-V5-ygO\">\n                        <rect key=\"frame\" x=\"224\" y=\"17\" width=\"15\" height=\"102\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                    </scroller>\n                    <tableHeaderView key=\"headerView\" id=\"8kc-tN-1kV\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"521\" height=\"25\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                    </tableHeaderView>\n                </scrollView>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"Pt1-2o-MSz\" firstAttribute=\"top\" secondItem=\"qzi-84-8Hb\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"3dG-kN-FVm\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"O5K-Z7-VRD\" secondAttribute=\"bottom\" constant=\"20\" symbolic=\"YES\" id=\"CHT-u3-7ne\"/>\n                <constraint firstItem=\"owe-My-lsx\" firstAttribute=\"leading\" secondItem=\"O5K-Z7-VRD\" secondAttribute=\"leading\" id=\"FYT-Pg-8s0\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"Pt1-2o-MSz\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"Hlb-0P-HXl\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"qzi-84-8Hb\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"KPS-Wl-ZNb\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"owe-My-lsx\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"SFA-sa-jNk\"/>\n                <constraint firstItem=\"O5K-Z7-VRD\" firstAttribute=\"top\" secondItem=\"owe-My-lsx\" secondAttribute=\"bottom\" constant=\"6\" symbolic=\"YES\" id=\"T5M-wM-ZpK\"/>\n                <constraint firstItem=\"qzi-84-8Hb\" firstAttribute=\"top\" secondItem=\"lzX-XA-XzO\" secondAttribute=\"top\" constant=\"20\" symbolic=\"YES\" id=\"Tuz-OK-yTc\"/>\n                <constraint firstItem=\"3QB-P7-si2\" firstAttribute=\"leading\" secondItem=\"O5K-Z7-VRD\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"csk-OS-mva\"/>\n                <constraint firstItem=\"owe-My-lsx\" firstAttribute=\"top\" secondItem=\"Pt1-2o-MSz\" secondAttribute=\"bottom\" constant=\"6\" symbolic=\"YES\" id=\"dc1-XQ-HyI\"/>\n                <constraint firstItem=\"3QB-P7-si2\" firstAttribute=\"firstBaseline\" secondItem=\"O5K-Z7-VRD\" secondAttribute=\"firstBaseline\" id=\"j1W-kM-lY5\"/>\n                <constraint firstItem=\"owe-My-lsx\" firstAttribute=\"leading\" secondItem=\"lzX-XA-XzO\" secondAttribute=\"leading\" constant=\"20\" symbolic=\"YES\" id=\"mhR-Hz-n9N\"/>\n                <constraint firstItem=\"qzi-84-8Hb\" firstAttribute=\"leading\" secondItem=\"lzX-XA-XzO\" secondAttribute=\"leading\" constant=\"20\" symbolic=\"YES\" id=\"mmv-DP-j88\"/>\n                <constraint firstItem=\"Pt1-2o-MSz\" firstAttribute=\"leading\" secondItem=\"lzX-XA-XzO\" secondAttribute=\"leading\" constant=\"20\" symbolic=\"YES\" id=\"nyW-Kp-F2F\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"3QB-P7-si2\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"x30-HK-XS1\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"144.5\" y=\"1491\"/>\n        </view>\n        <arrayController objectClassName=\"NSMutableString\" automaticallyPreparesContent=\"YES\" id=\"JiR-wc-2kO\" userLabel=\"SearchPathOverride Controller\">\n            <connections>\n                <binding destination=\"oMO-Og-s5N\" name=\"contentArray\" keyPath=\"values.searchPathOverride\" id=\"0CQ-4D-uxB\">\n                    <dictionary key=\"options\">\n                        <bool key=\"NSConditionallySetsEditable\" value=\"NO\"/>\n                        <bool key=\"NSDeletesObjectsOnRemove\" value=\"YES\"/>\n                        <bool key=\"NSHandlesContentAsCompoundValue\" value=\"YES\"/>\n                    </dictionary>\n                </binding>\n            </connections>\n        </arrayController>\n    </objects>\n    <resources>\n        <image name=\"NSApplicationIcon\" width=\"32\" height=\"32\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "ZetaWatch/Base.lproj/NewFS.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"14460.31\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"14460.31\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"ZetaDictQueryDialog\">\n            <connections>\n                <outlet property=\"popover\" destination=\"0wU-rJ-gHT\" id=\"RJA-Wc-e5P\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customView id=\"Y1R-F4-349\" userLabel=\"NewFSDialog\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"555\" height=\"148\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"1dp-Iq-Zlw\" userLabel=\"QueryTextField\">\n                    <rect key=\"frame\" x=\"90\" y=\"111\" width=\"447\" height=\"17\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"height\" relation=\"greaterThanOrEqual\" constant=\"17\" id=\"Jtk-1e-ewV\"/>\n                    </constraints>\n                    <textFieldCell key=\"cell\" refusesFirstResponder=\"YES\" title=\"Create new filesystem:\" id=\"PO3-tn-mgG\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"tDb-2y-bDq\">\n                    <rect key=\"frame\" x=\"484\" y=\"13\" width=\"57\" height=\"32\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Ok\" bezelStyle=\"rounded\" alignment=\"center\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"fN5-5d-JCF\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <string key=\"keyEquivalent\" base64-UTF8=\"YES\">\nDQ\n</string>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"ok:\" target=\"-2\" id=\"HPd-GH-Mi8\"/>\n                    </connections>\n                </button>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"j9L-jr-sWA\">\n                    <rect key=\"frame\" x=\"402\" y=\"13\" width=\"82\" height=\"32\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Cancel\" bezelStyle=\"rounded\" alignment=\"center\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"RPy-h3-YWQ\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <string key=\"keyEquivalent\" base64-UTF8=\"YES\">\nGw\n</string>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"cancel:\" target=\"-2\" id=\"oGC-62-njg\"/>\n                    </connections>\n                </button>\n                <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"7yl-N2-YqW\">\n                    <rect key=\"frame\" x=\"20\" y=\"64\" width=\"64\" height=\"64\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"height\" constant=\"64\" id=\"994-r0-jca\"/>\n                        <constraint firstAttribute=\"width\" constant=\"64\" id=\"JZ6-vK-bzz\"/>\n                    </constraints>\n                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"NSApplicationIcon\" id=\"ZYf-0t-nIl\"/>\n                </imageView>\n                <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"FNR-fj-4rT\">\n                    <rect key=\"frame\" x=\"90\" y=\"84\" width=\"44\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Name:\" id=\"dZr-UM-kGp\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"i54-l9-xMh\">\n                    <rect key=\"frame\" x=\"174\" y=\"81\" width=\"361\" height=\"22\"/>\n                    <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" title=\"Name\" drawsBackground=\"YES\" id=\"Gxt-2u-LZb\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                    <connections>\n                        <binding destination=\"-2\" name=\"value\" keyPath=\"self.queryDict.filesystem\" id=\"dra-gB-sxT\">\n                            <dictionary key=\"options\">\n                                <bool key=\"NSAllowsEditingMultipleValuesSelection\" value=\"NO\"/>\n                                <bool key=\"NSContinuouslyUpdatesValue\" value=\"YES\"/>\n                                <bool key=\"NSValidatesImmediately\" value=\"YES\"/>\n                            </dictionary>\n                        </binding>\n                    </connections>\n                </textField>\n                <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"TtX-Ig-20c\">\n                    <rect key=\"frame\" x=\"90\" y=\"52\" width=\"78\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Mountpoint:\" id=\"suq-Kc-sjY\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"lsr-yr-QsN\">\n                    <rect key=\"frame\" x=\"174\" y=\"49\" width=\"361\" height=\"22\"/>\n                    <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" title=\"Mountpoint\" drawsBackground=\"YES\" id=\"haT-1t-5JI\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                    <connections>\n                        <binding destination=\"-2\" name=\"value\" keyPath=\"self.queryDict.mountpoint\" id=\"ozk-Rv-kNc\">\n                            <dictionary key=\"options\">\n                                <bool key=\"NSAllowsEditingMultipleValuesSelection\" value=\"NO\"/>\n                                <bool key=\"NSContinuouslyUpdatesValue\" value=\"YES\"/>\n                                <bool key=\"NSValidatesImmediately\" value=\"YES\"/>\n                            </dictionary>\n                        </binding>\n                    </connections>\n                </textField>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"7yl-N2-YqW\" firstAttribute=\"top\" secondItem=\"Y1R-F4-349\" secondAttribute=\"top\" constant=\"20\" symbolic=\"YES\" id=\"1jM-pH-zzz\"/>\n                <constraint firstItem=\"tDb-2y-bDq\" firstAttribute=\"leading\" secondItem=\"j9L-jr-sWA\" secondAttribute=\"trailing\" constant=\"12\" symbolic=\"YES\" id=\"26k-uY-ND8\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"tDb-2y-bDq\" secondAttribute=\"bottom\" constant=\"20\" symbolic=\"YES\" id=\"8IT-Vz-RIq\"/>\n                <constraint firstItem=\"tDb-2y-bDq\" firstAttribute=\"top\" secondItem=\"lsr-yr-QsN\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"BDj-Xj-yEc\"/>\n                <constraint firstItem=\"lsr-yr-QsN\" firstAttribute=\"leading\" secondItem=\"TtX-Ig-20c\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"BOS-Lq-Yc6\"/>\n                <constraint firstItem=\"7yl-N2-YqW\" firstAttribute=\"leading\" secondItem=\"Y1R-F4-349\" secondAttribute=\"leading\" constant=\"20\" symbolic=\"YES\" id=\"Ced-2V-BMV\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"i54-l9-xMh\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"E4M-nK-fQg\"/>\n                <constraint firstItem=\"i54-l9-xMh\" firstAttribute=\"top\" secondItem=\"1dp-Iq-Zlw\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"Jcn-xO-1hQ\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"tDb-2y-bDq\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"KvF-fC-8kz\"/>\n                <constraint firstItem=\"i54-l9-xMh\" firstAttribute=\"leading\" relation=\"greaterThanOrEqual\" secondItem=\"FNR-fj-4rT\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"L0W-yB-dlg\"/>\n                <constraint firstItem=\"i54-l9-xMh\" firstAttribute=\"trailing\" secondItem=\"lsr-yr-QsN\" secondAttribute=\"trailing\" id=\"LGA-pH-jY3\"/>\n                <constraint firstItem=\"i54-l9-xMh\" firstAttribute=\"leading\" secondItem=\"lsr-yr-QsN\" secondAttribute=\"leading\" id=\"Q3W-vn-0mb\"/>\n                <constraint firstItem=\"FNR-fj-4rT\" firstAttribute=\"leading\" secondItem=\"1dp-Iq-Zlw\" secondAttribute=\"leading\" id=\"ad7-mz-DrS\"/>\n                <constraint firstItem=\"i54-l9-xMh\" firstAttribute=\"firstBaseline\" secondItem=\"FNR-fj-4rT\" secondAttribute=\"firstBaseline\" id=\"gYn-yp-NRz\"/>\n                <constraint firstItem=\"1dp-Iq-Zlw\" firstAttribute=\"leading\" secondItem=\"7yl-N2-YqW\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"h8e-AX-oaa\"/>\n                <constraint firstItem=\"FNR-fj-4rT\" firstAttribute=\"leading\" secondItem=\"TtX-Ig-20c\" secondAttribute=\"leading\" id=\"ic1-wn-oiH\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"1dp-Iq-Zlw\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"jXH-th-x2x\"/>\n                <constraint firstItem=\"j9L-jr-sWA\" firstAttribute=\"firstBaseline\" secondItem=\"tDb-2y-bDq\" secondAttribute=\"firstBaseline\" id=\"mGb-j2-POm\"/>\n                <constraint firstItem=\"lsr-yr-QsN\" firstAttribute=\"top\" secondItem=\"i54-l9-xMh\" secondAttribute=\"bottom\" constant=\"10\" symbolic=\"YES\" id=\"nfG-pr-GUW\"/>\n                <constraint firstItem=\"j9L-jr-sWA\" firstAttribute=\"leading\" relation=\"greaterThanOrEqual\" secondItem=\"Y1R-F4-349\" secondAttribute=\"leading\" constant=\"20\" symbolic=\"YES\" id=\"pSw-8x-TM7\"/>\n                <constraint firstItem=\"1dp-Iq-Zlw\" firstAttribute=\"top\" secondItem=\"Y1R-F4-349\" secondAttribute=\"top\" priority=\"750\" constant=\"20\" symbolic=\"YES\" id=\"sD8-QV-07k\"/>\n                <constraint firstItem=\"TtX-Ig-20c\" firstAttribute=\"firstBaseline\" secondItem=\"lsr-yr-QsN\" secondAttribute=\"firstBaseline\" id=\"x23-1c-w5i\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"815\" y=\"748\"/>\n        </customView>\n        <userDefaultsController representsSharedInstance=\"YES\" id=\"7zF-te-Tq6\"/>\n        <viewController id=\"Xpw-zj-uOl\" userLabel=\"NewFS Popover View Controller\">\n            <connections>\n                <outlet property=\"view\" destination=\"Y1R-F4-349\" id=\"DWH-F2-RhI\"/>\n            </connections>\n        </viewController>\n        <popover id=\"0wU-rJ-gHT\" userLabel=\"NewFS Popover\">\n            <connections>\n                <outlet property=\"contentViewController\" destination=\"Xpw-zj-uOl\" id=\"cnk-CD-wG3\"/>\n            </connections>\n        </popover>\n    </objects>\n    <resources>\n        <image name=\"NSApplicationIcon\" width=\"128\" height=\"128\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "ZetaWatch/Base.lproj/NewVol.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"14460.31\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <deployment identifier=\"macosx\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"14460.31\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"ZetaDictQueryDialog\">\n            <connections>\n                <outlet property=\"popover\" destination=\"0wU-rJ-gHT\" id=\"RJA-Wc-e5P\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customView id=\"Y1R-F4-349\" userLabel=\"NewVolDialog\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"555\" height=\"180\"/>\n            <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMinY=\"YES\"/>\n            <subviews>\n                <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"1dp-Iq-Zlw\" userLabel=\"QueryTextField\">\n                    <rect key=\"frame\" x=\"90\" y=\"143\" width=\"447\" height=\"17\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"height\" relation=\"greaterThanOrEqual\" constant=\"17\" id=\"Jtk-1e-ewV\"/>\n                    </constraints>\n                    <textFieldCell key=\"cell\" refusesFirstResponder=\"YES\" title=\"Create new volume:\" id=\"PO3-tn-mgG\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"tDb-2y-bDq\">\n                    <rect key=\"frame\" x=\"484\" y=\"13\" width=\"57\" height=\"32\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Ok\" bezelStyle=\"rounded\" alignment=\"center\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"fN5-5d-JCF\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <string key=\"keyEquivalent\" base64-UTF8=\"YES\">\nDQ\n</string>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"ok:\" target=\"-2\" id=\"HPd-GH-Mi8\"/>\n                    </connections>\n                </button>\n                <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"j9L-jr-sWA\">\n                    <rect key=\"frame\" x=\"402\" y=\"13\" width=\"82\" height=\"32\"/>\n                    <buttonCell key=\"cell\" type=\"push\" title=\"Cancel\" bezelStyle=\"rounded\" alignment=\"center\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"RPy-h3-YWQ\">\n                        <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <string key=\"keyEquivalent\" base64-UTF8=\"YES\">\nGw\n</string>\n                    </buttonCell>\n                    <connections>\n                        <action selector=\"cancel:\" target=\"-2\" id=\"oGC-62-njg\"/>\n                    </connections>\n                </button>\n                <imageView horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"7yl-N2-YqW\">\n                    <rect key=\"frame\" x=\"20\" y=\"96\" width=\"64\" height=\"64\"/>\n                    <constraints>\n                        <constraint firstAttribute=\"height\" constant=\"64\" id=\"994-r0-jca\"/>\n                        <constraint firstAttribute=\"width\" constant=\"64\" id=\"JZ6-vK-bzz\"/>\n                    </constraints>\n                    <imageCell key=\"cell\" refusesFirstResponder=\"YES\" alignment=\"left\" imageScaling=\"proportionallyDown\" image=\"NSApplicationIcon\" id=\"ZYf-0t-nIl\"/>\n                </imageView>\n                <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"FNR-fj-4rT\">\n                    <rect key=\"frame\" x=\"90\" y=\"116\" width=\"65\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Name:\" id=\"dZr-UM-kGp\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"i54-l9-xMh\">\n                    <rect key=\"frame\" x=\"161\" y=\"113\" width=\"374\" height=\"22\"/>\n                    <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" title=\"Name\" drawsBackground=\"YES\" id=\"Gxt-2u-LZb\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                    <connections>\n                        <binding destination=\"-2\" name=\"value\" keyPath=\"self.queryDict.filesystem\" id=\"dra-gB-sxT\">\n                            <dictionary key=\"options\">\n                                <bool key=\"NSAllowsEditingMultipleValuesSelection\" value=\"NO\"/>\n                                <bool key=\"NSContinuouslyUpdatesValue\" value=\"YES\"/>\n                                <bool key=\"NSValidatesImmediately\" value=\"YES\"/>\n                            </dictionary>\n                        </binding>\n                    </connections>\n                </textField>\n                <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"TtX-Ig-20c\">\n                    <rect key=\"frame\" x=\"90\" y=\"84\" width=\"65\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Size:\" id=\"suq-Kc-sjY\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n                <textField verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"lsr-yr-QsN\">\n                    <rect key=\"frame\" x=\"161\" y=\"81\" width=\"374\" height=\"22\"/>\n                    <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" title=\"Size\" drawsBackground=\"YES\" id=\"haT-1t-5JI\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                    <connections>\n                        <binding destination=\"-2\" name=\"value\" keyPath=\"self.queryDict.size\" id=\"FBg-vF-o8l\">\n                            <dictionary key=\"options\">\n                                <bool key=\"NSAllowsEditingMultipleValuesSelection\" value=\"NO\"/>\n                                <bool key=\"NSContinuouslyUpdatesValue\" value=\"YES\"/>\n                                <bool key=\"NSValidatesImmediately\" value=\"YES\"/>\n                                <string key=\"NSValueTransformerName\">SizeTransformer</string>\n                            </dictionary>\n                        </binding>\n                    </connections>\n                </textField>\n                <textField verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Uvx-B3-kFr\">\n                    <rect key=\"frame\" x=\"161\" y=\"49\" width=\"374\" height=\"22\"/>\n                    <textFieldCell key=\"cell\" scrollable=\"YES\" lineBreakMode=\"clipping\" selectable=\"YES\" editable=\"YES\" sendsActionOnEndEditing=\"YES\" borderStyle=\"bezel\" title=\"Blocksize\" drawsBackground=\"YES\" id=\"51K-lm-Qe9\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                    <connections>\n                        <binding destination=\"-2\" name=\"value\" keyPath=\"self.queryDict.blocksize\" id=\"Bg9-ia-qLS\">\n                            <dictionary key=\"options\">\n                                <bool key=\"NSAllowsEditingMultipleValuesSelection\" value=\"NO\"/>\n                                <bool key=\"NSContinuouslyUpdatesValue\" value=\"YES\"/>\n                                <bool key=\"NSValidatesImmediately\" value=\"YES\"/>\n                                <string key=\"NSValueTransformerName\">SizeTransformer</string>\n                            </dictionary>\n                        </binding>\n                    </connections>\n                </textField>\n                <textField horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Ns6-44-PQg\">\n                    <rect key=\"frame\" x=\"90\" y=\"52\" width=\"65\" height=\"17\"/>\n                    <textFieldCell key=\"cell\" lineBreakMode=\"clipping\" title=\"Blocksize:\" id=\"ZNp-jl-N5X\">\n                        <font key=\"font\" metaFont=\"system\"/>\n                        <color key=\"textColor\" name=\"labelColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        <color key=\"backgroundColor\" name=\"textBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                    </textFieldCell>\n                </textField>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"Uvx-B3-kFr\" firstAttribute=\"leading\" secondItem=\"Ns6-44-PQg\" secondAttribute=\"trailing\" constant=\"8\" id=\"018-Wy-Y1j\"/>\n                <constraint firstItem=\"7yl-N2-YqW\" firstAttribute=\"top\" secondItem=\"Y1R-F4-349\" secondAttribute=\"top\" constant=\"20\" symbolic=\"YES\" id=\"1jM-pH-zzz\"/>\n                <constraint firstItem=\"tDb-2y-bDq\" firstAttribute=\"leading\" secondItem=\"j9L-jr-sWA\" secondAttribute=\"trailing\" constant=\"12\" symbolic=\"YES\" id=\"26k-uY-ND8\"/>\n                <constraint firstItem=\"Ns6-44-PQg\" firstAttribute=\"firstBaseline\" secondItem=\"Uvx-B3-kFr\" secondAttribute=\"firstBaseline\" id=\"77h-b7-F2G\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"tDb-2y-bDq\" secondAttribute=\"bottom\" constant=\"20\" symbolic=\"YES\" id=\"8IT-Vz-RIq\"/>\n                <constraint firstItem=\"lsr-yr-QsN\" firstAttribute=\"leading\" secondItem=\"TtX-Ig-20c\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"BOS-Lq-Yc6\"/>\n                <constraint firstItem=\"7yl-N2-YqW\" firstAttribute=\"leading\" secondItem=\"Y1R-F4-349\" secondAttribute=\"leading\" constant=\"20\" symbolic=\"YES\" id=\"Ced-2V-BMV\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"i54-l9-xMh\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"E4M-nK-fQg\"/>\n                <constraint firstItem=\"i54-l9-xMh\" firstAttribute=\"top\" secondItem=\"1dp-Iq-Zlw\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"Jcn-xO-1hQ\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"tDb-2y-bDq\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"KvF-fC-8kz\"/>\n                <constraint firstItem=\"i54-l9-xMh\" firstAttribute=\"leading\" secondItem=\"FNR-fj-4rT\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"L0W-yB-dlg\"/>\n                <constraint firstItem=\"i54-l9-xMh\" firstAttribute=\"trailing\" secondItem=\"lsr-yr-QsN\" secondAttribute=\"trailing\" id=\"LGA-pH-jY3\"/>\n                <constraint firstItem=\"i54-l9-xMh\" firstAttribute=\"leading\" secondItem=\"lsr-yr-QsN\" secondAttribute=\"leading\" id=\"Q3W-vn-0mb\"/>\n                <constraint firstItem=\"Uvx-B3-kFr\" firstAttribute=\"top\" secondItem=\"lsr-yr-QsN\" secondAttribute=\"bottom\" constant=\"10\" id=\"YFf-2D-EH1\"/>\n                <constraint firstItem=\"FNR-fj-4rT\" firstAttribute=\"leading\" secondItem=\"1dp-Iq-Zlw\" secondAttribute=\"leading\" id=\"ad7-mz-DrS\"/>\n                <constraint firstItem=\"i54-l9-xMh\" firstAttribute=\"firstBaseline\" secondItem=\"FNR-fj-4rT\" secondAttribute=\"firstBaseline\" id=\"gYn-yp-NRz\"/>\n                <constraint firstItem=\"1dp-Iq-Zlw\" firstAttribute=\"leading\" secondItem=\"7yl-N2-YqW\" secondAttribute=\"trailing\" constant=\"8\" symbolic=\"YES\" id=\"h8e-AX-oaa\"/>\n                <constraint firstItem=\"FNR-fj-4rT\" firstAttribute=\"leading\" secondItem=\"TtX-Ig-20c\" secondAttribute=\"leading\" id=\"ic1-wn-oiH\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"1dp-Iq-Zlw\" secondAttribute=\"trailing\" constant=\"20\" symbolic=\"YES\" id=\"jXH-th-x2x\"/>\n                <constraint firstItem=\"Uvx-B3-kFr\" firstAttribute=\"leading\" secondItem=\"lsr-yr-QsN\" secondAttribute=\"leading\" id=\"kIp-Z6-T5e\"/>\n                <constraint firstItem=\"j9L-jr-sWA\" firstAttribute=\"firstBaseline\" secondItem=\"tDb-2y-bDq\" secondAttribute=\"firstBaseline\" id=\"mGb-j2-POm\"/>\n                <constraint firstItem=\"Ns6-44-PQg\" firstAttribute=\"leading\" secondItem=\"TtX-Ig-20c\" secondAttribute=\"leading\" id=\"nDd-qO-w6y\"/>\n                <constraint firstItem=\"lsr-yr-QsN\" firstAttribute=\"top\" secondItem=\"i54-l9-xMh\" secondAttribute=\"bottom\" constant=\"10\" symbolic=\"YES\" id=\"nfG-pr-GUW\"/>\n                <constraint firstItem=\"j9L-jr-sWA\" firstAttribute=\"leading\" relation=\"greaterThanOrEqual\" secondItem=\"Y1R-F4-349\" secondAttribute=\"leading\" constant=\"20\" symbolic=\"YES\" id=\"pSw-8x-TM7\"/>\n                <constraint firstItem=\"1dp-Iq-Zlw\" firstAttribute=\"top\" secondItem=\"Y1R-F4-349\" secondAttribute=\"top\" priority=\"750\" constant=\"20\" symbolic=\"YES\" id=\"sD8-QV-07k\"/>\n                <constraint firstItem=\"tDb-2y-bDq\" firstAttribute=\"top\" secondItem=\"Uvx-B3-kFr\" secondAttribute=\"bottom\" constant=\"8\" symbolic=\"YES\" id=\"tOu-Yr-4f2\"/>\n                <constraint firstItem=\"Uvx-B3-kFr\" firstAttribute=\"trailing\" secondItem=\"lsr-yr-QsN\" secondAttribute=\"trailing\" id=\"vqP-u8-1Ud\"/>\n                <constraint firstItem=\"TtX-Ig-20c\" firstAttribute=\"firstBaseline\" secondItem=\"lsr-yr-QsN\" secondAttribute=\"firstBaseline\" id=\"x23-1c-w5i\"/>\n            </constraints>\n            <point key=\"canvasLocation\" x=\"814.5\" y=\"769.5\"/>\n        </customView>\n        <userDefaultsController representsSharedInstance=\"YES\" id=\"7zF-te-Tq6\"/>\n        <viewController id=\"Xpw-zj-uOl\" userLabel=\"NewFS Popover View Controller\">\n            <connections>\n                <outlet property=\"view\" destination=\"Y1R-F4-349\" id=\"DWH-F2-RhI\"/>\n            </connections>\n        </viewController>\n        <popover id=\"0wU-rJ-gHT\" userLabel=\"NewFS Popover\">\n            <connections>\n                <outlet property=\"contentViewController\" destination=\"Xpw-zj-uOl\" id=\"cnk-CD-wG3\"/>\n            </connections>\n        </popover>\n    </objects>\n    <resources>\n        <image name=\"NSApplicationIcon\" width=\"128\" height=\"128\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "ZetaWatch/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIconFile</key>\n\t<string></string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>$(ZETA_VERSION)</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>$(ZETA_VERSION)</string>\n\t<key>LSApplicationCategoryType</key>\n\t<string>public.app-category.utilities</string>\n\t<key>LSBackgroundOnly</key>\n\t<false/>\n\t<key>LSMinimumSystemVersion</key>\n\t<string>$(MACOSX_DEPLOYMENT_TARGET)</string>\n\t<key>LSUIElement</key>\n\t<true/>\n\t<key>NSHumanReadableCopyright</key>\n\t<string>Copyright © 2021 the-color-black.net. All rights reserved.</string>\n\t<key>NSMainNibFile</key>\n\t<string>MainMenu</string>\n\t<key>NSPrincipalClass</key>\n\t<string>NSApplication</string>\n\t<key>NSUSerNotificationAlertStyle</key>\n\t<string>alert</string>\n\t<key>SMPrivilegedExecutables</key>\n\t<dict>\n\t\t<key>net.the-color-black.ZetaAuthorizationHelper</key>\n\t\t<string>anchor apple generic and identifier &quot;net.the-color-black.ZetaAuthorizationHelper&quot; and (certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = &quot;8THUW5GT6P&quot;)</string>\n\t</dict>\n\t<key>SUFeedURL</key>\n\t<string>https://zetawatch.the-color-black.net/download/2.1/appcast.xml</string>\n\t<key>SUPublicEDKey</key>\n\t<string>Ed/JNtoVf4G8CX7qffgoFFHmb4303SFsmJ3yh2vAhyc=</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "ZetaWatch/InvariantDisks/IDDiskArbitrationDispatcher.cpp",
    "content": "//\n//  IDDiskArbitrationDispatcher.cpp\n//  InvariantDisks\n//\n//  Created by Gerhard Röthlin on 2014.04.27.\n//  Copyright (c) 2014 the-color-black.net. All rights reserved.\n//\n//  Redistribution and use in source and binary forms, with or without modification, are permitted\n//  provided that the conditions of the \"3-Clause BSD\" license described in the BSD.LICENSE file are met.\n//  Additional licensing options are described in the README file.\n//\n\n#include \"IDDiskArbitrationDispatcher.hpp\"\n\n#include \"IDDiskArbitrationHandler.hpp\"\n#include \"IDDiskArbitrationUtils.hpp\"\n\n#include <DiskArbitration/DiskArbitration.h>\n\n#include <thread>\n#include <vector>\n#include <algorithm>\n\nnamespace ID\n{\n\tstruct DiskArbitrationDispatcher::Impl\n\t{\n\t\tstd::mutex mutex;\n\t\tstd::vector<Handler> handler;\n\t\tDASessionRef session = nullptr;\n\t\tbool scheduled = false;\n\t};\n\n\tDiskArbitrationDispatcher::DiskArbitrationDispatcher() :\n\t\tm_impl(new Impl)\n\t{\n\t\tm_impl->session = DASessionCreate(kCFAllocatorDefault);\n\t\tDARegisterDiskAppearedCallback(m_impl->session, nullptr, [](DADiskRef disk, void * ctx)\n\t\t\t{ static_cast<DiskArbitrationDispatcher*>(ctx)->diskAppeared(disk); }, this);\n\t\tDARegisterDiskDisappearedCallback(m_impl->session, nullptr, [](DADiskRef disk, void * ctx)\n\t\t\t{ static_cast<DiskArbitrationDispatcher*>(ctx)->diskDisappeared(disk); }, this);\n\t}\n\n\tDiskArbitrationDispatcher::~DiskArbitrationDispatcher()\n\t{\n\t\tstop();\n\t\tCFRelease(m_impl->session);\n\t}\n\n\tvoid DiskArbitrationDispatcher::addHandler(Handler handler)\n\t{\n\t\tstd::lock_guard<std::mutex> lock(m_impl->mutex);\n\t\tm_impl->handler.push_back(std::move(handler));\n\t}\n\n\tvoid DiskArbitrationDispatcher::removeHandler(Handler const & handler)\n\t{\n\t\tstd::lock_guard<std::mutex> lock(m_impl->mutex);\n\t\tm_impl->handler.erase(std::find(m_impl->handler.begin(), m_impl->handler.end(), handler),\n\t\t\t\t\t\t\t  m_impl->handler.end());\n\t}\n\n\tvoid DiskArbitrationDispatcher::clearHandler()\n\t{\n\t\tstd::lock_guard<std::mutex> lock(m_impl->mutex);\n\t\tm_impl->handler.clear();\n\t}\n\n\tvoid DiskArbitrationDispatcher::start()\n\t{\n\t\tstd::lock_guard<std::mutex> lock(m_impl->mutex);\n\t\tif (!m_impl->scheduled)\n\t\t{\n\t\t\tDASessionScheduleWithRunLoop(m_impl->session,\n\t\t\t\tCFRunLoopGetCurrent(), kCFRunLoopDefaultMode);\n\t\t\tm_impl->scheduled = true;\n\t\t}\n\t}\n\n\tvoid DiskArbitrationDispatcher::stop()\n\t{\n\t\tstd::lock_guard<std::mutex> lock(m_impl->mutex);\n\t\tif (m_impl->scheduled)\n\t\t{\n\t\t\tDASessionUnscheduleFromRunLoop(m_impl->session,\n\t\t\t\tCFRunLoopGetCurrent(), kCFRunLoopDefaultMode);\n\t\t\tm_impl->scheduled = false;\n\t\t}\n\t}\n\n\tvoid DiskArbitrationDispatcher::diskAppeared(DADiskRef disk) const\n\t{\n\t\tDiskInformation info = getDiskInformation(disk);\n\t\tstd::lock_guard<std::mutex> lock(m_impl->mutex);\n\t\tfor (auto const & handler: m_impl->handler)\n\t\t\thandler->diskAppeared(disk, info);\n\t}\n\n\tvoid DiskArbitrationDispatcher::diskDisappeared(DADiskRef disk) const\n\t{\n\t\tDiskInformation info = getDiskInformation(disk);\n\t\tstd::lock_guard<std::mutex> lock(m_impl->mutex);\n\t\tfor (auto const & handler: m_impl->handler)\n\t\t\thandler->diskDisappeared(disk, info);\n\t}\n}\n"
  },
  {
    "path": "ZetaWatch/InvariantDisks/IDDiskArbitrationDispatcher.hpp",
    "content": "//\n//  IDDiskArbitrationDispatcher.hpp\n//  InvariantDisks\n//\n//  Created by Gerhard Röthlin on 2014.04.27.\n//  Copyright (c) 2014 the-color-black.net. All rights reserved.\n//\n//  Redistribution and use in source and binary forms, with or without modification, are permitted\n//  provided that the conditions of the \"3-Clause BSD\" license described in the BSD.LICENSE file are met.\n//  Additional licensing options are described in the README file.\n//\n\n#ifndef ID_DISKARBITRATIONDISPATCHER_HPP\n#define ID_DISKARBITRATIONDISPATCHER_HPP\n\n#include <DiskArbitration/DADisk.h>\n\n#include <memory>\n\nnamespace ID\n{\n\tclass DiskArbitrationHandler;\n\n\t/*!\n\t \\brief Dispatches DiskArbitration events, wrapper around the DiskArbitration framework\n\t */\n\tclass DiskArbitrationDispatcher\n\t{\n\tpublic:\n\t\ttypedef std::shared_ptr<DiskArbitrationHandler> Handler;\n\n\tpublic:\n\t\tDiskArbitrationDispatcher();\n\t\t~DiskArbitrationDispatcher();\n\n\tpublic:\n\t\tvoid addHandler(Handler handler);\n\t\tvoid removeHandler(Handler const & handler);\n\t\tvoid clearHandler();\n\n\tpublic:\n\t\tvoid start();\n\t\tvoid stop();\n\n\tprivate:\n\t\tvoid diskAppeared(DADiskRef disk) const;\n\t\tvoid diskDisappeared(DADiskRef disk) const;\n\n\tprivate:\n\t\tstruct Impl;\n\t\tstd::unique_ptr<Impl> m_impl;\n\t};\n}\n\n#endif\n"
  },
  {
    "path": "ZetaWatch/InvariantDisks/IDDiskArbitrationHandler.hpp",
    "content": "//\n//  IDDiskArbitrationHandler.hpp\n//  InvariantDisks\n//\n//  Created by Gerhard Röthlin on 2014.04.27.\n//  Copyright (c) 2014 the-color-black.net. All rights reserved.\n//\n//  Redistribution and use in source and binary forms, with or without modification, are permitted\n//  provided that the conditions of the \"3-Clause BSD\" license described in the BSD.LICENSE file are met.\n//  Additional licensing options are described in the README file.\n//\n\n#ifndef ID_DISKARBITRATIONHANDLER_HPP\n#define ID_DISKARBITRATIONHANDLER_HPP\n\n#include <DiskArbitration/DADisk.h>\n\nnamespace ID\n{\n\tclass DiskInformation;\n\n\tclass DiskArbitrationHandler\n\t{\n\tpublic:\n\t\texplicit DiskArbitrationHandler() {}\n\t\tvirtual ~DiskArbitrationHandler() = default;\n\n\tpublic:\n\t\tvirtual void diskAppeared(DADiskRef disk, DiskInformation const & info) = 0;\n\t\tvirtual void diskDisappeared(DADiskRef disk, DiskInformation const & info) = 0;\n\t};\n}\n\n#endif\n"
  },
  {
    "path": "ZetaWatch/InvariantDisks/IDDiskArbitrationUtils.cpp",
    "content": "//\n//  IDDiskArbitrationUtils.cpp\n//  InvariantDisks\n//\n//  Created by Gerhard Röthlin on 2014.04.27.\n//  Copyright (c) 2014 the-color-black.net. All rights reserved.\n//\n//  Redistribution and use in source and binary forms, with or without modification, are permitted\n//  provided that the conditions of the \"3-Clause BSD\" license described in the BSD.LICENSE file are met.\n//  Additional licensing options are described in the README file.\n//\n\n#include \"IDDiskArbitrationUtils.hpp\"\n\n#include <IOKit/storage/IOStorageProtocolCharacteristics.h>\n\n#include <sstream>\n\nnamespace ID\n{\n\tstd::ostream & operator<<(std::ostream & os, DADiskRef disk)\n\t{\n\t\treturn os << getDiskInformation(disk);\n\t}\n\n\tstd::ostream & operator<<(std::ostream & os, DiskInformation const & disk)\n\t{\n\t\treturn os << \"Disk: (\\n\"\n\t\t\t<< \"\\tVolumeKind=\\\"\" << disk.volumeKind << \"\\\"\\n\"\n\t\t\t<< \"\\tVolumeUUID=\\\"\" << disk.volumeUUID << \"\\\"\\n\"\n\t\t\t<< \"\\tVolumeName=\\\"\" << disk.volumeName << \"\\\"\\n\"\n\t\t\t<< \"\\tVolumePath=\\\"\" << disk.volumePath << \"\\\"\\n\"\n\t\t\t<< \"\\tMediaKind=\\\"\" << disk.mediaKind << \"\\\"\\n\"\n\t\t\t<< \"\\tMediaType=\\\"\" << disk.mediaType  << \"\\\"\\n\"\n\t\t\t<< \"\\tMediaUUID=\\\"\" << disk.mediaUUID << \"\\\"\\n\"\n\t\t\t<< \"\\tMediaBSDName=\\\"\" << disk.mediaBSDName << \"\\\"\\n\"\n\t\t\t<< \"\\tMediaName=\\\"\" << disk.mediaName << \"\\\"\\n\"\n\t\t\t<< \"\\tMediaPath=\\\"\" << disk.mediaPath << \"\\\"\\n\"\n\t\t\t<< \"\\tMediaContent=\\\"\" << disk.mediaContent << \"\\\"\\n\"\n\t\t\t<< \"\\tMedia(Whole,Leaf,Writable)=(\" << disk.mediaWhole << \", \"\n\t\t\t\t<< disk.mediaLeaf << \", \" << disk.mediaWritable << \")\\n\"\n\t\t\t<< \"\\tDeviceGUID=\\\"\" << disk.deviceGUID << \"\\\"\\n\"\n\t\t\t<< \"\\tDevicePath=\\\"\" << disk.devicePath << \"\\\"\\n\"\n\t\t\t<< \"\\tDeviceProtocol=\\\"\" << disk.deviceProtocol << \"\\\"\\n\"\n\t\t\t<< \"\\tDeviceModel=\\\"\" << disk.deviceModel << \"\\\"\\n\"\n\t\t\t<< \"\\tBusName=\\\"\" << disk.busName << \"\\\"\\n\"\n\t\t\t<< \"\\tBusPath=\\\"\" << disk.busPath << \"\\\"\\n\"\n\t\t\t<< \"\\tIOSerial=\\\"\" << disk.ioSerial << \"\\\"\\n\"\n\t\t\t<< \"\\tImagePath=\\\"\" << disk.imagePath << \"\\\"\\n\"\n\t\t\t<< \")\";\n\t}\n\n\tstd::string to_string(CFStringRef str)\n\t{\n\t\tstd::string result;\n\t\tCFRange strRange = CFRangeMake(0, CFStringGetLength(str));\n\t\tCFIndex strBytes = 0;\n\t\tCFStringGetBytes(str, strRange, kCFStringEncodingUTF8, 0, false, nullptr, 0, &strBytes);\n\t\tif (strBytes > 0)\n\t\t{\n\t\t\tresult.resize(static_cast<size_t>(strBytes), '\\0');\n\t\t\tCFStringGetBytes(str, strRange, kCFStringEncodingUTF8, 0, false,\n\t\t\t\t\t\t\t reinterpret_cast<UInt8*>(&result[0]), strBytes, nullptr);\n\t\t}\n\t\treturn result;\n\t}\n\n\tstd::string to_string(CFURLRef url)\n\t{\n\t\tCFStringRef str = CFURLCopyPath(url);\n\t\tstd::string result = to_string(str);\n\t\tCFRelease(str);\n\t\treturn result;\n\t}\n\n\tstd::string to_string(CFDataRef data)\n\t{\n\t\tchar const * bytesBegin = reinterpret_cast<char const *>(CFDataGetBytePtr(data));\n\t\tchar const * bytesEnd = bytesBegin + CFDataGetLength(data);\n\t\tstd::stringstream ss;\n\t\tss << std::hex;\n\t\tfor (char const * byteIt = bytesBegin; byteIt != bytesEnd; ++byteIt)\n\t\t\tss << static_cast<unsigned>(*byteIt);\n\t\treturn ss.str();\n\t}\n\n\tstd::string to_string(CFUUIDRef uuid)\n\t{\n\t\tCFStringRef str = CFUUIDCreateString(kCFAllocatorDefault, uuid);\n\t\tstd::string result = to_string(str);\n\t\tCFRelease(str);\n\t\treturn result;\n\t}\n\n\tstd::string to_string(CFTypeRef variant)\n\t{\n\t\tif (!variant)\n\t\t\treturn std::string();\n\t\tCFTypeID typeID = CFGetTypeID(variant);\n\t\tif (typeID == CFStringGetTypeID())\n\t\t\treturn to_string(CFStringRef(variant));\n\t\telse if (typeID == CFURLGetTypeID())\n\t\t\treturn to_string(CFURLRef(variant));\n\t\telse if (typeID == CFDataGetTypeID())\n\t\t\treturn to_string(CFDataRef(variant));\n\t\telse if (typeID == CFUUIDGetTypeID())\n\t\t\treturn to_string(CFUUIDRef(variant));\n\t\treturn std::string();\n\t}\n\n\tstd::string interpret_as_string(CFDataRef data)\n\t{\n\t\tchar const * bytesBegin = reinterpret_cast<char const *>(CFDataGetBytePtr(data));\n\t\tchar const * bytesEnd = bytesBegin + CFDataGetLength(data);\n\t\treturn std::string(bytesBegin, bytesEnd);\n\t}\n\n\ttemplate<typename T>\n\tstd::string stringFromDictionary(CFDictionaryRef dict, CFStringRef key)\n\t{\n\t\tif (T value = static_cast<T>(CFDictionaryGetValue(dict, key)))\n\t\t\treturn to_string(value);\n\t\treturn std::string();\n\t}\n\n\tint64_t numberFromDictionary(CFDictionaryRef dict, CFStringRef key)\n\t{\n\t\tif (CFNumberRef value = static_cast<CFNumberRef>(CFDictionaryGetValue(dict, key)))\n\t\t{\n\t\t\tint64_t number = 0;\n\t\t\tCFNumberGetValue(value, kCFNumberSInt64Type, &number);\n\t\t\treturn number;\n\t\t}\n\t\treturn 0;\n\t}\n\n\tbool boolFromDictionary(CFDictionaryRef dict, CFStringRef key)\n\t{\n\t\tif (CFBooleanRef value = static_cast<CFBooleanRef>(CFDictionaryGetValue(dict, key)))\n\t\t{\n\t\t\treturn CFBooleanGetValue(value);\n\t\t}\n\t\treturn false;\n\t}\n\n\tstd::string stringFromIOObjectWithParents(io_object_t ioObject, CFStringRef key)\n\t{\n\t\tstd::string result;\n\t\tCFTypeRef resultRef = IORegistryEntrySearchCFProperty(ioObject, kIOServicePlane, key,\n\t\t\tkCFAllocatorDefault, kIORegistryIterateRecursively | kIORegistryIterateParents);\n\t\tif (resultRef)\n\t\t{\n\t\t\tresult = to_string(resultRef);\n\t\t\tCFRelease(resultRef);\n\t\t}\n\t\treturn result;\n\t}\n\n\tstd::string serialNumberFromIOObject(io_object_t ioObject)\n\t{\n\t\tstatic CFStringRef const serialStrings[] = {\n\t\t\tCFSTR(\"Serial Number\"),\n\t\t\tCFSTR(\"INQUIRY Unit Serial Number\"),\n\t\t\tCFSTR(\"USB Serial Number\")\n\t\t};\n\t\tfor (CFStringRef serialString: serialStrings)\n\t\t{\n\t\t\tstd::string serial = stringFromIOObjectWithParents(ioObject, serialString);\n\t\t\tif (!serial.empty())\n\t\t\t\treturn serial;\n\t\t}\n\t\treturn std::string();\n\t}\n\n\tstd::string imagePathFromIOObject(io_object_t ioObject)\n\t{\n\t\tstd::string path;\n\t\tCFStringRef key = CFSTR(\"image-path\");\n\t\tCFTypeRef resultRef = IORegistryEntrySearchCFProperty(ioObject, kIOServicePlane, key,\n\t\t\tkCFAllocatorDefault, kIORegistryIterateRecursively | kIORegistryIterateParents);\n\t\tif (resultRef)\n\t\t{\n\t\t\tif (CFGetTypeID(resultRef) == CFDataGetTypeID())\n\t\t\t{\n\t\t\t\tCFDataRef resultDataRef = CFDataRef(resultRef);\n\t\t\t\tpath = interpret_as_string(resultDataRef);\n\t\t\t}\n\t\t\tCFRelease(resultRef);\n\t\t}\n\t\treturn path;\n\t}\n\n\tstatic std::string coreStorageMark = \"/CoreStoragePhysical/\";\n\n\tDiskInformation getDiskInformation(DADiskRef disk)\n\t{\n\t\tDiskInformation info;\n\t\t// DiskArbitration\n\t\tCFDictionaryRef descDict = DADiskCopyDescription(disk);\n\t\tif (!descDict)\n\t\t\treturn info;\n\t\tinfo.volumeKind = stringFromDictionary<CFStringRef>(descDict, kDADiskDescriptionVolumeKindKey);\n\t\tinfo.volumeUUID = stringFromDictionary<CFUUIDRef>(descDict, kDADiskDescriptionVolumeUUIDKey);\n\t\tinfo.volumeName = stringFromDictionary<CFStringRef>(descDict, kDADiskDescriptionVolumeNameKey);\n\t\tinfo.volumePath = stringFromDictionary<CFURLRef>(descDict, kDADiskDescriptionVolumePathKey);\n\t\tinfo.mediaKind = stringFromDictionary<CFStringRef>(descDict, kDADiskDescriptionMediaKindKey);\n\t\tinfo.mediaType = stringFromDictionary<CFStringRef>(descDict, kDADiskDescriptionMediaTypeKey);\n\t\tinfo.mediaUUID = stringFromDictionary<CFUUIDRef>(descDict, kDADiskDescriptionMediaUUIDKey);\n\t\tinfo.mediaBSDName = stringFromDictionary<CFStringRef>(descDict, kDADiskDescriptionMediaBSDNameKey);\n\t\tinfo.mediaName = stringFromDictionary<CFStringRef>(descDict, kDADiskDescriptionMediaNameKey);\n\t\tinfo.mediaPath = stringFromDictionary<CFStringRef>(descDict, kDADiskDescriptionMediaPathKey);\n\t\tinfo.mediaContent = stringFromDictionary<CFStringRef>(descDict, kDADiskDescriptionMediaContentKey);\n\t\tinfo.mediaWhole = boolFromDictionary(descDict, kDADiskDescriptionMediaWholeKey);\n\t\tinfo.mediaLeaf = boolFromDictionary(descDict, kDADiskDescriptionMediaLeafKey);\n\t\tinfo.mediaWritable = boolFromDictionary(descDict, kDADiskDescriptionMediaWritableKey);\n\t\tinfo.deviceGUID = stringFromDictionary<CFDataRef>(descDict, kDADiskDescriptionDeviceGUIDKey);\n\t\tinfo.devicePath = stringFromDictionary<CFStringRef>(descDict, kDADiskDescriptionDevicePathKey);\n\t\tinfo.deviceProtocol = stringFromDictionary<CFStringRef>(descDict, kDADiskDescriptionDeviceProtocolKey);\n\t\tinfo.deviceModel = stringFromDictionary<CFStringRef>(descDict, kDADiskDescriptionDeviceModelKey);\n\t\tinfo.busName = stringFromDictionary<CFStringRef>(descDict, kDADiskDescriptionBusNameKey);\n\t\tinfo.busPath = stringFromDictionary<CFStringRef>(descDict, kDADiskDescriptionBusPathKey);\n\t\tCFRelease(descDict);\n\t\t// IOKit\n\t\tio_service_t io = DADiskCopyIOMedia(disk);\n\t\tinfo.ioSerial = serialNumberFromIOObject(io);\n\t\tinfo.imagePath = imagePathFromIOObject(io);\n\t\tCFMutableDictionaryRef ioDict = nullptr;\n\t\tif (IORegistryEntryCreateCFProperties(io, &ioDict, kCFAllocatorDefault, 0) == kIOReturnSuccess)\n\t\t{\n\t\t\t// TODO: Pick out useful IOKit properties\n\t\t\tCFRelease(ioDict);\n\t\t}\n\t\tIOObjectRelease(io);\n\t\t// Guess wether this is an actual device\n\t\tbool isCoreStorage = info.mediaPath.find(coreStorageMark) != std::string::npos;\n\t\tbool isVirtual = info.deviceProtocol == kIOPropertyPhysicalInterconnectTypeVirtual;\n\t\tinfo.isDevice = !isCoreStorage && !isVirtual;\n\t\treturn info;\n\t}\n\n\tbool isDevice(DiskInformation const & di)\n\t{\n\t\treturn di.isDevice;\n\t}\n\n\tbool isWhole(DiskInformation const & di)\n\t{\n\t\treturn di.mediaWhole;\n\t}\n\n\tstd::string partitionSuffix(DiskInformation const & di)\n\t{\n\t\tif (!isWhole(di))\n\t\t{\n\t\t\tsize_t suffixStart = di.mediaBSDName.find_last_not_of(\"0123456789\");\n\t\t\tif (suffixStart != std::string::npos &&\n\t\t\t\tsuffixStart+1 < di.mediaBSDName.size() &&\n\t\t\t\tdi.mediaBSDName[suffixStart] == 's')\n\t\t\t{\n\t\t\t\treturn ':' + di.mediaBSDName.substr(suffixStart+1);\n\t\t\t}\n\t\t}\n\t\treturn std::string();\n\t}\n}\n"
  },
  {
    "path": "ZetaWatch/InvariantDisks/IDDiskArbitrationUtils.hpp",
    "content": "//\n//  IDDiskArbitrationUtils.hpp\n//  InvariantDisks\n//\n//  Created by Gerhard Röthlin on 2014.04.27.\n//  Copyright (c) 2014 the-color-black.net. All rights reserved.\n//\n//  Redistribution and use in source and binary forms, with or without modification, are permitted\n//  provided that the conditions of the \"3-Clause BSD\" license described in the BSD.LICENSE file are met.\n//  Additional licensing options are described in the README file.\n//\n\n#ifndef ID_DISKARBITRATIONUTILS_HPP\n#define ID_DISKARBITRATIONUTILS_HPP\n\n#include <DiskArbitration/DiskArbitration.h>\n\n#include <iostream>\n#include <string>\n\nnamespace ID\n{\n\tstruct DiskInformation\n\t{\n\t\tstd::string volumeKind;\n\t\tstd::string volumeUUID;\n\t\tstd::string volumeName;\n\t\tstd::string volumePath;\n\t\tstd::string mediaKind;\n\t\tstd::string mediaType;\n\t\tstd::string mediaUUID;\n\t\tstd::string mediaBSDName;\n\t\tstd::string mediaName;\n\t\tstd::string mediaPath;\n\t\tstd::string mediaContent;\n\t\tbool isDevice;\n\t\tbool mediaWhole;\n\t\tbool mediaLeaf;\n\t\tbool mediaWritable;\n\t\tstd::string deviceGUID;\n\t\tstd::string devicePath;\n\t\tstd::string deviceProtocol;\n\t\tstd::string deviceModel;\n\t\tstd::string busName;\n\t\tstd::string busPath;\n\t\tstd::string ioSerial;\n\t\tstd::string imagePath;\n\t};\n\n\tDiskInformation getDiskInformation(DADiskRef disk);\n\n\tbool isDevice(DiskInformation const & di);\n\tbool isWhole(DiskInformation const & di);\n\tstd::string partitionSuffix(DiskInformation const & di);\n\n\tstd::ostream & operator<<(std::ostream & os, DADiskRef disk);\n\tstd::ostream & operator<<(std::ostream & os, DiskInformation const & disk);\n}\n\n#endif\n"
  },
  {
    "path": "ZetaWatch/PathValueTransformer.m",
    "content": "//\n//  PathValueTransformer.m\n//  ZetaWatch\n//\n//  Created by cbreak on 19.11.08.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n/*!\n \\brief Transforms a path URL into a string and back, used for value binding\n from a xib file.\n */\n@interface PathValueTransformer : NSValueTransformer\n\n@end\n\n@implementation PathValueTransformer\n\n+ (Class)transformedValueClass\n{\n\treturn [NSString class];\n}\n\n+ (BOOL)allowsReverseTransformation\n{\n\treturn YES;\n}\n\n- (id)transformedValue:(id)value\n{\n\tNSString * string = value;\n\treturn [NSURL URLWithString:string];\n}\n\n- (id)reverseTransformedValue:(id)value\n{\n\tNSURL * url = value;\n\treturn [url path];\n}\n\n- (void)initialize\n{\n\tif (self == [PathValueTransformer self])\n\t{\n\t\tPathValueTransformer * transformer = [[PathValueTransformer alloc] init];\n\t\t[NSValueTransformer setValueTransformer:transformer\n\t\t\t\t\t\t\t\t\t\tforName:@\"PathValueTransformer\"];\n\t}\n}\n\n@end\n"
  },
  {
    "path": "ZetaWatch/SizeTransformer.mm",
    "content": "//\n//  SizeTransformer.m\n//  ZetaWatch\n//\n//  Created by cbreak on 19.11.08.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n#include \"ZetaFormatHelpers.hpp\"\n\n/*!\n \\brief Transforms between a string and a byte number, used for value binding\n from a xib file.\n */\n@interface SizeTransformer : NSValueTransformer\n\n@end\n\n@implementation SizeTransformer\n\n+ (Class)transformedValueClass\n{\n\treturn [NSString class];\n}\n\n+ (BOOL)allowsReverseTransformation\n{\n\treturn YES;\n}\n\n- (id)transformedValue:(id)value\n{\n\tNSNumber * number = value;\n\tauto str = formatBytes([number unsignedLongLongValue]);\n\treturn [NSString stringWithUTF8String:str.c_str()];\n}\n\n- (id)reverseTransformedValue:(id)value\n{\n\tNSString * string = value;\n\tstd::size_t bytes;\n\tif (parseBytes<std::size_t>([string UTF8String], bytes))\n\t{\n\t\treturn [NSNumber numberWithUnsignedLongLong:bytes];\n\t}\n\treturn nullptr;\n}\n\n- (void)initialize\n{\n\tif (self == [SizeTransformer self])\n\t{\n\t\tSizeTransformer * transformer = [[SizeTransformer alloc] init];\n\t\t[NSValueTransformer setValueTransformer:transformer\n\t\t\t\t\t\t\t\t\t\tforName:@\"SizeTransformer\"];\n\t}\n}\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaAuthorization.h",
    "content": "//\n//  ZetaAuthoized.h\n//  ZetaWatch\n//\n//  Created by cbreak on 17.12.31.\n//  Copyright © 2017 the-color-black.net. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n@class ZetaNotificationCenter;\n\n/*!\n This class wraps privileged operations that require authorization.\n\n This is heavily based on apple's EvenBetterAuthorizationSample\n https://developer.apple.com/library/content/samplecode/EvenBetterAuthorizationSample/Introduction/Intro.html\n */\n@interface ZetaAuthorization : NSObject\n\n//! Call this after the program finished starting\n-(void)connectToAuthorization;\n\n- (void)stopHelper;\n\n- (void)importPools:(NSDictionary *)importData\n\t\t  withReply:(void(^)(NSError * error))reply;\n\n- (void)importablePools:(NSDictionary *)importData\n\t\t\t  withReply:(void(^)(NSError * error, NSArray * importablePools))reply;\n\n- (void)exportPools:(NSDictionary *)exportData\n\t\t  withReply:(void(^)(NSError * error))reply;\n\n- (void)mountFilesystems:(NSDictionary *)mountData\n\t\t\t   withReply:(void(^)(NSError * error))reply;\n\n- (void)unmountFilesystems:(NSDictionary *)mountData\n\t\t\t\t withReply:(void(^)(NSError * error))reply;\n\n- (void)snapshotFilesystem:(NSDictionary *)snapshotData\n\t\t\t\t withReply:(void(^)(NSError * error))reply;\n\n- (void)rollbackFilesystem:(NSDictionary *)rollbackData\n\t\t\t\t withReply:(void(^)(NSError * error))reply;\n\n- (void)cloneSnapshot:(NSDictionary *)fsData\n\t\t\twithReply:(void(^)(NSError * error))reply;\n\n- (void)createFilesystem:(NSDictionary *)fsData\n\t\t\t   withReply:(void(^)(NSError * error))reply;\n\n- (void)createVolume:(NSDictionary *)fsData\n\t\t\t   withReply:(void(^)(NSError * error))reply;\n\n- (void)destroy:(NSDictionary *)fsData\n\t  withReply:(void(^)(NSError * error))reply;\n\n- (void)loadKeyForFilesystem:(NSDictionary *)loadData\n\t\t\t\t   withReply:(void(^)(NSError * error))reply;\n\n- (void)unloadKeyForFilesystem:(NSDictionary *)unloadData\n\t\t\t\t\t withReply:(void(^)(NSError * error))reply;\n\n- (void)scrubPool:(NSDictionary *)poolData\n\t\twithReply:(void(^)(NSError * error))reply;\n\n- (void)executeWhenConnected:(void(^)(id proxy))task\n\t\t\t\t\t onError:(void(^)(NSError * error))handleError;\n\n@property (weak) IBOutlet ZetaNotificationCenter * notificationCenter;\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaAuthorization.mm",
    "content": "//\n//  ZetaAuthoized.m\n//  ZetaWatch\n//\n//  Created by cbreak on 17.12.31.\n//  Copyright © 2017 the-color-black.net. All rights reserved.\n//\n\n#import \"ZetaAuthorization.h\"\n\n#import \"ZetaAuthorizationHelperProtocol.h\"\n#import \"CommonAuthorization.h\"\n\n#import \"ZetaNotificationCenter.h\"\n\n#include <ServiceManagement/ServiceManagement.h>\n\n#include <dispatch/dispatch.h>\n\n@interface ZetaAuthorization ()\n{\n\tAuthorizationRef _authRef;\n}\n\n@property (atomic, copy, readwrite) NSData * authorization;\n@property (atomic, strong, readwrite) NSXPCConnection * helperToolConnection;\n\n@end\n\n@implementation ZetaAuthorization\n\n- (void)awakeFromNib\n{\n\t[self connectToAuthorization];\n\t[self installIfNeeded];\n}\n\n-(void)connectToAuthorization\n{\n\t// Create our connection to the authorization system.\n\t//\n\t// If we can't create an authorization reference then the app is not going\n\t// to be able to do anything requiring authorization. Generally this only\n\t// happens when you launch the app in some wacky, and typically unsupported,\n\t// way. We continue with self->_authRef as NULL, which will cause all\n\t// authorized operations to fail.\n\n\tAuthorizationExternalForm extForm = {};\n\tOSStatus err = AuthorizationCreate(NULL, NULL, 0, &self->_authRef);\n\tif (err == errAuthorizationSuccess)\n\t{\n\t\terr = AuthorizationMakeExternalForm(self->_authRef, &extForm);\n\t}\n\tif (err == errAuthorizationSuccess)\n\t{\n\t\tself.authorization = [[NSData alloc] initWithBytes:&extForm length:sizeof(extForm)];\n\t}\n\n\t// If we successfully connected to Authorization Services, add definitions\n\t// for our default rights (unless they're already in the database).\n\n\tif (self->_authRef)\n\t{\n\t\t[CommonAuthorization setupAuthorizationRights:self->_authRef];\n\t}\n}\n\n-(void)install\n{\n\t// Install the helper tool into the system location. As of 10.12 this is\n\t// /Library/LaunchDaemons/<TOOL> and /Library/PrivilegedHelperTools/<TOOL>\n\tBoolean success = NO;\n\tCFErrorRef error = nil;\n\n\tsuccess = SMJobBless(kSMDomainSystemLaunchd,\n\t\t\t\t\t\t CFSTR(\"net.the-color-black.ZetaAuthorizationHelper\"),\n\t\t\t\t\t\t self->_authRef, &error);\n\n\tif (success)\n\t{\n\t}\n\telse\n\t{\n\t\tNSLog(@\"Error installing helper tool: %@\\n\", error);\n\t\tCFRelease(error);\n\t}\n}\n\n- (void)connectToHelperTool\n{\n\tassert([NSThread isMainThread]);\n\tif (self.helperToolConnection == nil)\n\t{\n\t\tself.helperToolConnection = [[NSXPCConnection alloc] initWithMachServiceName:kHelperToolMachServiceName options:NSXPCConnectionPrivileged];\n\t\tself.helperToolConnection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(ZetaAuthorizationHelperProtocol)];\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Warc-retain-cycles\"\n\t\t// We can ignore the retain cycle warning because a) the retain taken by the\n\t\t// invalidation handler block is released by us setting it to nil when the block\n\t\t// actually runs, and b) the retain taken by the block passed to -addOperationWithBlock:\n\t\t// will be released when that operation completes and the operation itself is deallocated\n\t\t// (notably self does not have a reference to the NSBlockOperation).\n\t\tself.helperToolConnection.invalidationHandler = ^{\n\t\t\t// If the connection gets invalidated then, on the main thread, nil out our\n\t\t\t// reference to it.  This ensures that we attempt to rebuild it the next time around.\n\t\t\tself.helperToolConnection.invalidationHandler = nil;\n\t\t\t[[NSOperationQueue mainQueue] addOperationWithBlock:^{\n\t\t\t\tself.helperToolConnection = nil;\n\t\t\t}];\n\t\t};\n#pragma clang diagnostic pop\n\t\t[self.helperToolConnection resume];\n\t}\n}\n\n- (void)stopHelper\n{\n\tid proxy = [self.helperToolConnection synchronousRemoteObjectProxyWithErrorHandler:^(NSError * error)\n\t{\n\t\t// Ignore errors, invalidate connection anyway\n\t\t[self.helperToolConnection invalidate];\n\t\tself.helperToolConnection = nil;\n\t}];\n\t[proxy stopHelperWithAuthorization:self->_authorization\n\t\t\t\t\t\t\t withReply:[=](NSError * error)\n\t{\n\t\t// Invalidate connection\n\t\t[self.helperToolConnection invalidate];\n\t\tself.helperToolConnection = nil;\n\t}];\n}\n\n- (void)installIfNeeded\n{\n\t// Ensure that there's a helper tool connection in place.\n\t[self connectToHelperTool];\n\tid proxy = [self.helperToolConnection remoteObjectProxyWithErrorHandler:\n\t\t\t\t^(NSError * proxyError)\n\t{\n\t\t// Install on proxy error\n\t\tdispatch_async(dispatch_get_main_queue(), ^(){\n\t\t\t// Install if there's a proxy error\n\t\t\t[self install];\n\t\t});\n\t}];\n\n\t[proxy getVersionWithReply:^(NSError * error, NSString * helperVersion)\n\t {\n\t\t // Install if there's no valid helper version (because of error)\n\t\t if (error)\n\t\t {\n\t\t\t dispatch_async(dispatch_get_main_queue(), ^(){\n\t\t\t\t [self install];\n\t\t\t });\n\t\t\t return;\n\t\t }\n\t\t NSString * localVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@\"CFBundleVersion\"];\n\t\t // Install if the versions don't match exactly\n\t\t if (![localVersion isEqualToString:helperVersion])\n\t\t {\n\t\t\t dispatch_async(dispatch_get_main_queue(), ^(){\n\t\t\t\t [self install];\n\t\t\t });\n\t\t\t return;\n\t\t }\n\t }];\n}\n\n- (void)executeWhenConnected:(void(^)(id proxy))task\n\t\t\t\t\t onError:(void(^)(NSError * error))handleError;\n{\n\t// Ensure that there's a helper tool connection in place.\n\t[self connectToHelperTool];\n\tid proxy = [self.helperToolConnection remoteObjectProxyWithErrorHandler:handleError];\n\ttask(proxy);\n}\n\n- (void)executeOnProxy:(SEL)selector\n\t\t\t  withData:(NSDictionary *)data\n\t\t\t withReply:(void(^)(NSError * error))reply\n\t  withNotification:(ZetaNotification*)notification\n{\n\t[self executeWhenConnected:^(id proxy)\n\t {\n\t\t auto block = ^(NSError * error)\n\t\t {\n\t\t\t [self dispatchReply:^(){\n\t\t\t\t reply(error);\n\t\t\t\t [self stopNotification:notification withError:error];\n\t\t\t }];\n\t\t };\n\t\t auto sig = [proxy methodSignatureForSelector:selector];\n\t\t auto inv = [NSInvocation invocationWithMethodSignature:sig];\n\t\t [inv setTarget:proxy];\n\t\t [inv setSelector:selector];\n\t\t NSDictionary * dataLoc = data;\n\t\t [inv setArgument:&dataLoc atIndex:2];\n\t\t [inv setArgument:&self->_authorization atIndex:3];\n\t\t [inv setArgument:&block atIndex:4];\n\t\t [inv invoke];\n\t }\n\t\t\t\t\t   onError:^(NSError * error)\n\t {\n\t\t [self dispatchReply:^(){\n\t\t\t reply(error);\n\t\t\t [self stopNotification:notification withError:error];\n\t\t }];\n\t }];\n}\n\n- (void)dispatchReply:(void(^)(void))reply\n{\n\t[self performSelectorOnMainThread:@selector(dispatchReplyMainThread:) withObject:reply waitUntilDone:FALSE];\n}\n\n- (void)dispatchReplyMainThread:(void(^)(void))reply\n{\n\treply();\n}\n\n- (void)getVersionWithReply:(void (^)(NSError * error, NSString *))reply\n{\n\t[self executeWhenConnected:^(id proxy)\n\t {\n\t\t [proxy getVersionWithReply:^(NSError * error, NSString * version)\n\t\t  {\n\t\t\t  [self dispatchReply:^(){ reply(error, version); }];\n\t\t  }];\n\t }\n\t\t\t\t\t   onError:^(NSError * error)\n\t {\n\t\t [self dispatchReply:^(){ reply(error, nil); }];\n\t }];\n}\n\n- (void)importPools:(NSDictionary *)importData\n\t\t  withReply:(void(^)(NSError * error))reply\n{\n\tNSString * targetGUID = importData[@\"poolGUID\"];\n\tNSString * targetName = importData[@\"poolName\"];\n\tNSString * target;\n\tif (targetGUID == nil)\n\t\ttarget = @\"all pools\";\n\telse\n\t\ttarget = [NSString stringWithFormat:@\"%@ (%@)\", targetName, targetGUID];\n\tZetaNotification * notification = [self startNotificationForAction:\n\t\tNSLocalizedString(@\"Importing\", @\"Importing Action\") withTarget:target];\n\t[self executeOnProxy:@selector(importPools:authorization:withReply:)\n\t\t\t\twithData:importData withReply:reply\n\t\twithNotification:notification];\n}\n\n- (void)importablePools:(NSDictionary *)importData\n\t\t\t  withReply:(void(^)(NSError * error, NSArray * importablePools))reply\n{\n\t[self executeWhenConnected:^(id proxy)\n\t {\n\t\t [proxy importablePools:importData\n\t\t\t\t  authorization:self.authorization\n\t\t\t\t\t  withReply:^(NSError * error, NSArray * importablePools)\n\t\t  {\n\t\t\t  [self dispatchReply:^(){ reply(error, importablePools); }];\n\t\t  }];\n\t }\n\t\t\t\t\t   onError:^(NSError * error)\n\t {\n\t\t [self dispatchReply:^(){ reply(error, nil); }];\n\t }];\n}\n\n- (void)exportPools:(NSDictionary *)exportData\n\t\t  withReply:(void(^)(NSError * error))reply\n{\n\tNSString * target = exportData[@\"pool\"];\n\tif (target == nil)\n\t\ttarget = NSLocalizedString(@\"all pools\", @\"All Pools\");\n\tZetaNotification * notification = [self startNotificationForAction:\n\t\tNSLocalizedString(@\"Exporting\", @\"Exporting Action\") withTarget:target];\n\t[self executeOnProxy:@selector(exportPools:authorization:withReply:)\n\t\t\t\twithData:exportData withReply:reply\n\t\twithNotification:notification];\n}\n\n- (void)mountFilesystems:(NSDictionary *)mountData\n\t\t\t   withReply:(void(^)(NSError * error))reply\n{\n\tNSString * target = mountData[@\"filesystem\"];\n\tif (target == nil)\n\t\ttarget = NSLocalizedString(@\"all filesystems\", @\"All Filesystems\");\n\tZetaNotification * notification = [self startNotificationForAction:\n\t\tNSLocalizedString(@\"Mounting\", @\"Mounting Action\") withTarget:target];\n\t[self executeOnProxy:@selector(mountFilesystems:authorization:withReply:)\n\t\t\t\twithData:mountData withReply:reply\n\t\twithNotification:notification];\n}\n\n- (void)unmountFilesystems:(NSDictionary *)mountData\n\t\t\t   withReply:(void(^)(NSError * error))reply\n{\n\tNSString * target = mountData[@\"filesystem\"];\n\tif (target == nil)\n\t\ttarget = NSLocalizedString(@\"all filesystems\", @\"All Filesystems\");\n\tZetaNotification * notification = [self startNotificationForAction:\n\t\tNSLocalizedString(@\"Unmounting\", @\"Unmounting Action\") withTarget:target];\n\t[self executeOnProxy:@selector(unmountFilesystems:authorization:withReply:)\n\t\t\t\twithData:mountData withReply:reply\n\t\twithNotification:notification];\n}\n\n- (void)snapshotFilesystem:(NSDictionary *)snapshotData\n\t\t\t\t withReply:(void(^)(NSError * error))reply\n{\n\tNSString * filesystem = snapshotData[@\"filesystem\"];\n\tif (filesystem == nil)\n\t\tstd::logic_error(\"Missing required parameter \\\"filesystem\\\"\");\n\tNSString * snapshot = snapshotData[@\"snapshot\"];\n\tif (snapshot == nil)\n\t\tstd::logic_error(\"Missing required parameter \\\"snapshot\\\"\");\n\tNSString * target = [NSString stringWithFormat:@\"%@@%@\", filesystem, snapshot];\n\tZetaNotification * notification = [self startNotificationForAction:\n\t\tNSLocalizedString(@\"Snapshotting\", @\"Snapshot Action\") withTarget:target];\n\t[self executeOnProxy:@selector(snapshotFilesystem:authorization:withReply:)\n\t\t\t\twithData:snapshotData withReply:reply\n\t\twithNotification:notification];\n}\n\n- (void)rollbackFilesystem:(NSDictionary *)rollbackData\n\t\t\t\t withReply:(void(^)(NSError * error))reply\n{\n\tNSString * target = rollbackData[@\"snapshot\"];\n\tif (target == nil)\n\t\tstd::logic_error(\"Missing required parameter \\\"snapshot\\\"\");\n\tZetaNotification * notification = [self startNotificationForAction:\n\t\tNSLocalizedString(@\"Rolling back\", @\"Rollback Action\") withTarget:target];\n\t[self executeOnProxy:@selector(rollbackFilesystem:authorization:withReply:)\n\t\t\t\twithData:rollbackData withReply:reply\n\t\twithNotification:notification];\n}\n\n- (void)cloneSnapshot:(NSDictionary *)fsData\n\t\t\twithReply:(void(^)(NSError * error))reply\n{\n\tNSString * target = fsData[@\"snapshot\"];\n\tif (target == nil)\n\t\tstd::logic_error(\"Missing required parameter \\\"snapshot\\\"\");\n\tZetaNotification * notification = [self startNotificationForAction:\n\t\tNSLocalizedString(@\"Cloning\", @\"Cloning Action\") withTarget:target];\n\t[self executeOnProxy:@selector(cloneSnapshot:authorization:withReply:)\n\t\t\t\twithData:fsData withReply:reply\n\t\twithNotification:notification];\n}\n\n- (void)createFilesystem:(NSDictionary *)fsData\n\t\t\t   withReply:(void(^)(NSError * error))reply\n{\n\tNSString * target = fsData[@\"filesystem\"];\n\tif (target == nil)\n\t\tstd::logic_error(\"Missing required parameter \\\"filesystem\\\"\");\n\tZetaNotification * notification = [self startNotificationForAction:\n\t\tNSLocalizedString(@\"Creating\", @\"Create Action\") withTarget:target];\n\t[self executeOnProxy:@selector(createFilesystem:authorization:withReply:)\n\t\t\t\twithData:fsData withReply:reply\n\t\twithNotification:notification];\n}\n\n- (void)createVolume:(NSDictionary *)fsData\n\t\t   withReply:(void(^)(NSError * error))reply\n{\n\tNSString * target = fsData[@\"filesystem\"];\n\tif (target == nil)\n\t\tstd::logic_error(\"Missing required parameter \\\"filesystem\\\"\");\n\tZetaNotification * notification = [self startNotificationForAction:\n\t\tNSLocalizedString(@\"Creating\", @\"Create Action\") withTarget:target];\n\t[self executeOnProxy:@selector(createVolume:authorization:withReply:)\n\t\t\t\twithData:fsData withReply:reply\n\t\twithNotification:notification];\n}\n\n- (void)destroy:(NSDictionary *)fsData\n\t  withReply:(void(^)(NSError * error))reply\n{\n\tNSString * target = fsData[@\"filesystem\"];\n\tif (target == nil)\n\t\tstd::logic_error(\"Missing required parameter \\\"filesystem\\\"\");\n\tZetaNotification * notification = [self startNotificationForAction:\n\t\tNSLocalizedString(@\"Destroying\", @\"Destroy Action\") withTarget:target];\n\t[self executeOnProxy:@selector(destroy:authorization:withReply:)\n\t\t\t\twithData:fsData withReply:reply\n\t\twithNotification:notification];\n}\n\n- (void)loadKeyForFilesystem:(NSDictionary *)data\n\t\t\t\t\twithReply:(void(^)(NSError * error))reply\n{\n\tNSString * target = data[@\"filesystem\"];\n\tif (target == nil)\n\t\tstd::logic_error(\"Missing required parameter \\\"filesystem\\\"\");\n\tZetaNotification * notification = [self startNotificationForAction:\n\t\tNSLocalizedString(@\"Loading Key for\", @\"LoadKey Action\") withTarget:target];\n\t[self executeOnProxy:@selector(loadKeyForFilesystem:authorization:withReply:)\n\t\t\t\twithData:data withReply:reply\n\t\twithNotification:notification];\n}\n\n- (void)unloadKeyForFilesystem:(NSDictionary *)data\n\t\t\t\t\t withReply:(void(^)(NSError * error))reply\n{\n\tNSString * target = data[@\"filesystem\"];\n\tif (target == nil)\n\t\tstd::logic_error(\"Missing required parameter \\\"filesystem\\\"\");\n\tZetaNotification * notification = [self startNotificationForAction:\n\t\tNSLocalizedString(@\"Unloading Key for\", @\"UnloadKey Action\") withTarget:target];\n\t[self executeOnProxy:@selector(unloadKeyForFilesystem:authorization:withReply:)\n\t\t\t\twithData:data withReply:reply\n\t\twithNotification:notification];\n}\n\n- (void)scrubPool:(NSDictionary *)poolData\n\t\twithReply:(void(^)(NSError * error))reply\n{\n\t[self executeOnProxy:@selector(scrubPool:authorization:withReply:)\n\t\t\t\twithData:poolData withReply:reply\n\t\twithNotification:nullptr];\n}\n\n- (ZetaNotification*)startNotificationForAction:(NSString*)action withTarget:(NSString*)target\n{\n\tNSString * titleFormat = NSLocalizedString(@\"%@ %@\", @\"Helper Status notification Title Format\");\n\tNSString * title = [NSString stringWithFormat:titleFormat, action, target];\n\treturn [self.notificationCenter startAction:title];\n}\n\n- (void)stopNotification:(ZetaNotification*)notification withError:(NSError*)error\n{\n\tif (notification)\n\t{\n\t\t[self.notificationCenter stopAction:notification withError:error];\n\t}\n}\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaAutoImporter.h",
    "content": "//\n//  ZetaAutoImporter.h\n//  ZetaWatch\n//\n//  Created by cbreak on 19.08.02.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import <Cocoa/Cocoa.h>\n\n#import \"ZetaCommanderBase.h\"\n#import \"ZetaPoolWatcher.h\"\n\n#include \"ZFSUtils.hpp\"\n\n#include <vector>\n\n@interface ZetaAutoImporter : ZetaCommanderBase\n\n- (id)init;\n\n@property (readonly) std::vector<zfs::ImportablePool> const & importablePools;\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaAutoImporter.mm",
    "content": "//\n//  ZetaIDWatcher.cpp\n//  ZetaWatch\n//\n//  Created by cbreak on 19.08.02.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import \"ZetaAutoImporter.h\"\n\n#include \"IDDiskArbitrationDispatcher.hpp\"\n#include \"IDDiskArbitrationHandler.hpp\"\n#include \"IDDiskArbitrationUtils.hpp\"\n\n#include <vector>\n#include <set>\n#include <string>\n#include <algorithm>\n\n/*!\n If Auto-Import is configured:\n Discovered importable pools get classified into known and new pools. Pools that\n have not been seen recently are importable and are imported automatically. This\n set prevents attempting to import a pool multiple times in case of an error.\n Pools that were imported previously are added to the knownPools set and are\n not imported. They are ignored until one of their underlying devices disappears.\n */\n@interface ZetaAutoImporter ()\n{\n\t// ID\n\tID::DiskArbitrationDispatcher _idDispatcher;\n\tNSTimer * checkTimer;\n\n\t// Management\n\tstd::vector<zfs::ImportablePool> _importable;\n\tstd::vector<zfs::ImportablePool> _importedBefore;\n}\n\n- (void)scheduleChecking;\n- (void)handleDisappearedDevice:(ID::DiskInformation const &)info;\n\n@end\n\nclass ZetaIDHandler : public ID::DiskArbitrationHandler\n{\npublic:\n\tZetaIDHandler(ZetaAutoImporter * watcher) : watcher(watcher)\n\t{\n\t\tscheduleChecking();\n\t}\n\npublic:\n\tvirtual void diskAppeared(DADiskRef disk, ID::DiskInformation const & info)\n\t{\n\t\tscheduleChecking();\n\t}\n\n\tvirtual void diskDisappeared(DADiskRef disk, ID::DiskInformation const & info)\n\t{\n\t\tscheduleChecking();\n\t\t[watcher handleDisappearedDevice:info];\n\t}\n\nprivate:\n\tvoid scheduleChecking()\n\t{\n\t\t[watcher scheduleChecking];\n\t}\n\nprivate:\n\tZetaAutoImporter __weak * watcher;\n};\n\n@implementation ZetaAutoImporter\n\n- (id)init\n{\n\tif (self = [super init])\n\t{\n\t\t// ID\n\t\t_idDispatcher.addHandler(std::make_shared<ZetaIDHandler>(self));\n\t\t_idDispatcher.start();\n\t\t// Auto-Import handling\n\t\t[self seedKnownPools];\n\t}\n\treturn self;\n}\n\n- (void)dealloc\n{\n\t_idDispatcher.stop();\n}\n\n- (void)scheduleChecking\n{\n\tif (checkTimer && [checkTimer isValid])\n\t{\n\t\treturn;\n\t}\n\tcheckTimer = [NSTimer timerWithTimeInterval:4 target:self\n\t\tselector:@selector(checkForImportablePools) userInfo:nil repeats:NO];\n\tcheckTimer.tolerance = 2;\n\t[[NSRunLoop currentRunLoop] addTimer:checkTimer forMode:NSDefaultRunLoopMode];\n}\n\n- (void)handleDisappearedDevice:(ID::DiskInformation const &)info\n{\n\tif (info.mediaBSDName.empty())\n\t\treturn;\n\tstd::string devicePath = \"/dev/\" + info.mediaBSDName;\n\t// Forget pools that were once importable but now are no longer since at\n\t// least one device was removed\n\t_importedBefore.erase(\n\t\tstd::remove_if(_importedBefore.begin(), _importedBefore.end(),\n\t\t\t\t\t   [&](zfs::ImportablePool const & pool)\n\t{\n\t\tauto const & devices = pool.devices;\n\t\treturn std::find(devices.begin(), devices.end(), devicePath) != devices.end();\n\t}), _importedBefore.end());\n}\n\n- (void)checkForImportablePools\n{\n\tauto defaults = [NSUserDefaults standardUserDefaults];\n\tNSMutableDictionary * importData = [[NSMutableDictionary alloc] init];\n\tif (auto spo = [defaults arrayForKey:@\"searchPathOverride\"])\n\t{\n\t\t[importData setObject:spo forKey:@\"searchPathOverride\"];\n\t}\n\t[_authorization importablePools:importData withReply:\n\t ^(NSError * error, NSArray * importablePools)\n\t {\n\t\tif (error)\n\t\t\t[self notifyErrorFromHelper:error];\n\t\telse\n\t\t\t[self handleImportablePools:importablePools];\n\t }];\n}\n\nstd::vector<std::string> arrayToStringVec(NSArray<NSString*> * stringArray)\n{\n\tstd::vector<std::string> strings;\n\tfor (NSString * string in stringArray)\n\t{\n\t\tstrings.push_back([string UTF8String]);\n\t}\n\treturn strings;\n}\n\nstd::vector<zfs::ImportablePool> arrayToPoolVec(NSArray * poolsArray)\n{\n\tstd::vector<zfs::ImportablePool> pools;\n\tfor (NSDictionary * poolDict in poolsArray)\n\t{\n\t\tpools.push_back({\n\t\t\t[poolDict[@\"name\"] UTF8String],\n\t\t\t[poolDict[@\"guid\"] unsignedLongLongValue],\n\t\t\t[poolDict[@\"status\"] unsignedLongLongValue],\n\t\t\tarrayToStringVec(poolDict[@\"devices\"]),\n\t\t});\n\t}\n\tstd::sort(pools.begin(), pools.end());\n\treturn pools;\n}\n\n- (void)seedKnownPools\n{\n\tzfs::LibZFSHandle lib;\n\tstd::vector<zfs::ImportablePool> knownPools;\n\tfor (auto const & pool : lib.pools())\n\t{\n\t\tknownPools.push_back({\n\t\t\tpool.name(),\n\t\t\tpool.guid(),\n\t\t\tpool.status(),\n\t\t\tlib.devicesFromPoolConfig(pool.config()),\n\t\t});\n\t}\n\tstd::sort(knownPools.begin(), knownPools.end());\n\t_importedBefore = std::move(knownPools);\n}\n\n- (void)handleImportablePools:(NSArray*)importablePools\n{\n\tstd::vector<zfs::ImportablePool> importableCurrent = arrayToPoolVec(importablePools);\n\t// Find the pools that had not been imported before, for auto import\n\tstd::vector<zfs::ImportablePool> importableNew;\n\tstd::set_difference(importableCurrent.begin(), importableCurrent.end(),\n\t\t\t\t\t\t_importedBefore.begin(), _importedBefore.end(),\n\t\t\t\t\t\tstd::back_inserter(importableNew));\n\tauto importedPools = [self handleNewImportablePools:importableNew];\n\t// Aggregate all known pools to prevent double-auto import\n\tstd::vector<zfs::ImportablePool> importedBefore;\n\tstd::set_union(_importedBefore.begin(), _importedBefore.end(),\n\t\t\t\t   importedPools.begin(), importedPools.end(),\n\t\t\t\t   std::back_inserter(importedBefore));\n\t// Update currently importable pools collection\n\t_importable = std::move(importableCurrent);\n\t_importedBefore = std::move(importedBefore);\n}\n\n- (std::vector<zfs::ImportablePool>)handleNewImportablePools:(std::vector<zfs::ImportablePool> const &)importableNew\n{\n\tstd::vector<zfs::ImportablePool> importedPools;\n\tauto defaults = [NSUserDefaults standardUserDefaults];\n\tbool allowHostIDMismatch = [defaults boolForKey:@\"allowHostIDMismatch\"];\n\tif ([defaults boolForKey:@\"autoImport\"])\n\t{\n\t\tfor (auto const & pool : importableNew)\n\t\t{\n\t\t\tif (!zfs::healthy(pool.status, allowHostIDMismatch))\n\t\t\t\tcontinue; // skip pools that aren't healthy\n\t\t\tNSNumber * guid = [NSNumber numberWithUnsignedLongLong:pool.guid];\n\t\t\tNSString * name = [NSString stringWithUTF8String:pool.name.c_str()];\n\t\t\tNSString * title = [NSString stringWithFormat:\n\t\t\t\tNSLocalizedString(@\"Auto-importing %@\",\n\t\t\t\t\t\t\t\t  @\"Pool AutoImport short format\"),\n\t\t\t\t\tname];\n\t\t\tNSString * text = [NSString stringWithFormat:\n\t\t\t\tNSLocalizedString(@\"Auto-importing Pool %@ (%@)\",\n\t\t\t\t\t\t\t\t  @\"Pool AutoImport format\"),\n\t\t\t\t\t\t\t\tname, guid];\n\t\t\t[self notifySuccessWithTitle:title text:text];\n\t\t\tNSDictionary * poolDict = @{ @\"poolGUID\": guid, @\"poolName\": name};\n\t\t\tNSMutableDictionary * mutablePool = [poolDict mutableCopy];\n\t\t\t[mutablePool setValue:[NSNumber numberWithBool:allowHostIDMismatch]\n\t\t\t\t\t\t   forKey:@\"allowHostIDMismatch\"];\n\t\t\tif ([defaults boolForKey:@\"useAltroot\"])\n\t\t\t{\n\t\t\t\t[mutablePool setObject:[defaults stringForKey:@\"defaultAltroot\"]\n\t\t\t\t\t\t\t\tforKey:@\"altroot\"];\n\t\t\t}\n\t\t\tif (auto spo = [defaults arrayForKey:@\"searchPathOverride\"])\n\t\t\t{\n\t\t\t\t[mutablePool setObject:spo forKey:@\"searchPathOverride\"];\n\t\t\t}\n\t\t\t[_authorization importPools:mutablePool withReply:^(NSError * error)\n\t\t\t {\n\t\t\t\t [self handlePoolImportReply:error forPool:poolDict];\n\t\t\t }];\n\t\t\timportedPools.push_back(pool);\n\t\t}\n\t}\n\treturn importedPools;\n}\n\n- (void)handlePoolImportReply:(NSError*)error forPool:(NSDictionary*)pool\n{\n\tif (error)\n\t{\n\t\t[self notifyErrorFromHelper:error];\n\t}\n\telse\n\t{\n\t\tNSString * title = [NSString stringWithFormat:\n\t\t\tNSLocalizedString(@\"Pool %@ auto-imported\",\n\t\t\t\t\t\t\t  @\"Pool AutoImport Success short format\"),\n\t\t\t\tpool[@\"poolName\"]];\n\t\tNSString * text = [NSString stringWithFormat:\n\t\t\tNSLocalizedString(@\"Pool %@ (%@) auto-imported\",\n\t\t\t\t\t\t\t  @\"Pool AutoImport Success format\"),\n\t\t\tpool[@\"poolName\"], pool[@\"poolGUID\"]];\n\t\t[self notifySuccessWithTitle:title text:text];\n\t}\n}\n\n- (std::vector<zfs::ImportablePool> const &)importablePools\n{\n\treturn _importable;\n}\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaBookmarkMenu.h",
    "content": "//\n//  ZetaBookmarkMenu.h\n//  ZetaWatch\n//\n//  Created by cbreak on 19.12.14.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import <Cocoa/Cocoa.h>\n\n#import \"ZetaCommanderBase.h\"\n\n#include \"ZFSUtils.hpp\"\n\nNS_ASSUME_NONNULL_BEGIN\n\n@class ZetaMainMenu;\n\n@interface ZetaBookmarkMenu : ZetaCommanderBase <NSMenuDelegate>\n\n- (id)initWithFileSystem:(zfs::ZFileSystem)fs delegate:(ZetaMainMenu*)main;\n\n- (void)menuNeedsUpdate:(NSMenu*)menu;\n\n@end\n\nNS_ASSUME_NONNULL_END\n"
  },
  {
    "path": "ZetaWatch/ZetaBookmarkMenu.mm",
    "content": "//\n//  ZetaBookmarkMenu.m\n//  ZetaWatch\n//\n//  Created by cbreak on 19.12.14.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import \"ZetaBookmarkMenu.h\"\n\n#import \"ZetaMainMenu.h\"\n\n@implementation ZetaBookmarkMenu\n{\n\tzfs::ZFileSystem _fs;\n\tZetaMainMenu __weak * _delegate;\n}\n\n- (id)initWithFileSystem:(zfs::ZFileSystem)fs delegate:(ZetaMainMenu*)delegate\n{\n\tif (self = [super init])\n\t{\n\t\t_fs = std::move(fs);\n\t\t_delegate = delegate;\n\t}\n\treturn self;\n}\n\nNSMenuItem * createBookmarkMenu(zfs::ZFileSystem const & bookmark, ZetaMainMenu * delegate)\n{\n\tNSMenu * bMenu = [[NSMenu alloc] init];\n\t[bMenu setAutoenablesItems:NO];\n\tNSString * bName = [NSString stringWithUTF8String:bookmark.name()];\n\tauto addBookmarkCommand = [&](NSString * title, SEL selector)\n\t{\n\t\tauto item = [bMenu addItemWithTitle:title\n\t\t\t\t\t\t\t\t\t action:selector keyEquivalent:@\"\"];\n\t\titem.representedObject = bName;\n\t\titem.target = delegate;\n\t};\n\taddBookmarkCommand(NSLocalizedString(@\"Destroy\", @\"Destroy\"), @selector(destroy:));\n\tauto item = [[NSMenuItem alloc] initWithTitle:bName action:nullptr keyEquivalent:@\"\"];\n\titem.representedObject = bName;\n\titem.submenu = bMenu;\n\treturn item;\n}\n\n- (void)menuNeedsUpdate:(NSMenu*)menu\n{\n\t[menu removeAllItems];\n\tauto bookmarks = _fs.bookmarks();\n\tif (!bookmarks.empty())\n\t{\n\t\tfor (size_t i = bookmarks.size(); i > 0; --i)\n\t\t{\n\t\t\tNSMenuItem * item = createBookmarkMenu(bookmarks[i-1], _delegate);\n\t\t\t[menu addItem:item];\n\t\t}\n\t}\n\telse\n\t{\n\t\t[menu addItemWithTitle:NSLocalizedString(@\"No bookmarks found\", @\"No Bookmarks\")\n\t\t\t\t\t\taction:NULL keyEquivalent:@\"\"];\n\t}\n}\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaCommanderBase.h",
    "content": "//\n//  ZetaCommanderBase.h\n//  ZetaWatch\n//\n//  Created by cbreak on 19.06.02.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#ifndef ZetaMenuBase_h\n#define ZetaMenuBase_h\n\n#import <Cocoa/Cocoa.h>\n\n#import \"ZetaAuthorization.h\"\n\n#include \"ZetaFormatHelpers.hpp\"\n\n@interface ZetaCommanderBase : NSObject\n{\n\tIBOutlet ZetaAuthorization * _authorization;\n}\n\n- (void)notifySuccessWithTitle:(NSString*)title text:(NSString*)text;\n- (void)notifyErrorFromHelper:(NSError*)error;\n\n- (IBAction)copyRepresentedObject:(id)sender;\n\n@end\n\n// C++ Variadic Templates and Objective-C Vararg functions don't work well together\ninline NSString * formatNSString(NSString * format)\n{\n\treturn format;\n}\n\ntemplate<typename T>\nNSString * formatNSString(NSString * format, T const & t)\n{\n\treturn [NSString stringWithFormat:format, toFormatable(t)];\n}\n\ntemplate<typename T, typename U>\nNSString * formatNSString(NSString * format, T const & t, U const & u)\n{\n\treturn [NSString stringWithFormat:format, toFormatable(t), toFormatable(u)];\n}\n\ntemplate<typename T, typename U, typename V>\nNSString * formatNSString(NSString * format, T const & t, U const & u, V const & v)\n{\n\treturn [NSString stringWithFormat:format, toFormatable(t), toFormatable(u), toFormatable(v)];\n}\n\ntemplate<typename... T>\nNSMenuItem * addMenuItem(NSMenu * menu, ZetaCommanderBase * delegate,\n\t\t\t\t\t\t NSString * format, T const & ... t)\n{\n\tauto title = formatNSString(format, t...);\n\tauto item = [menu addItemWithTitle:title action:@selector(copyRepresentedObject:) keyEquivalent:@\"\"];\n\titem.representedObject = title;\n\titem.target = delegate;\n\treturn item;\n}\n\n#endif /* ZetaMenuBase_h */\n"
  },
  {
    "path": "ZetaWatch/ZetaCommanderBase.mm",
    "content": "//\n//  ZetaCommanderBase.mm\n//  ZetaWatch\n//\n//  Created by cbreak on 19.06.02.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import \"ZetaCommanderBase.h\"\n\n@implementation ZetaCommanderBase\n\n- (void)notifySuccessWithTitle:(NSString*)title text:(NSString*)text\n{\n\tNSUserNotification * notification = [[NSUserNotification alloc] init];\n\tnotification.title = title;\n\tnotification.informativeText = text == nil ? title : text;\n\tnotification.hasActionButton = NO;\n\tauto nc = [NSUserNotificationCenter defaultUserNotificationCenter];\n\t[nc deliverNotification:notification];\n\t[nc performSelector:@selector(removeDeliveredNotification:)\n\t\t\t withObject:notification afterDelay:10];\n}\n\n- (void)notifyErrorFromHelper:(NSError*)error\n{\n\tNSUserNotification * notification = [[NSUserNotification alloc] init];\n\tnotification.title = NSLocalizedString(@\"ZetaWatch Error\", @\"Helper Error notification Title\");\n\tNSString * errorFormat = NSLocalizedString(@\"%@.\", @\"Helper Error notification Format\");\n\tnotification.informativeText = [NSString stringWithFormat:errorFormat, [error localizedDescription]];\n\tnotification.hasActionButton = NO;\n\t[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];\n}\n\n- (IBAction)copyRepresentedObject:(id)sender\n{\n\tNSPasteboard * pb = [NSPasteboard generalPasteboard];\n\t[pb clearContents];\n\t[pb writeObjects:@[[sender representedObject]]];\n}\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaConfirmDialog.h",
    "content": "//\n//  ZetaConfirmDialog.h\n//  ZetaWatch\n//\n//  Created by cbreak on 19.10.13.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import <Cocoa/Cocoa.h>\n\n@interface ZetaConfirmDialog : NSObject <NSPopoverDelegate>\n\n@property (weak) NSStatusItem * statusItem;\n@property (weak) IBOutlet NSPopover * popover;\n@property (weak) IBOutlet NSTextField * queryField;\n@property (weak) IBOutlet NSTextField * infoField;\n\n- (IBAction)ok:(id)sender;\n- (IBAction)cancel:(id)sender;\n\n- (BOOL)popoverShouldDetach:(NSPopover *)popover;\n\n- (void)addQuery:(NSString*)query\n withInformation:(NSString*)info\n\twithCallback:(void(^)(bool))callback;\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaConfirmDialog.mm",
    "content": "//\n//  ZetaConfirmDialog.mm\n//  ZetaWatch\n//\n//  Created by cbreak on 19.10.13.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import \"ZetaConfirmDialog.h\"\n\n#include <deque>\n#include <type_traits>\n\nnamespace\n{\n\ttypedef void (^QueryCallback)(bool);\n\n\tstruct Query\n\t{\n\t\tNSString * query;\n\t\tNSString * info;\n\t\tQueryCallback reply;\n\t};\n}\n\n@interface ZetaConfirmDialog ()\n{\n\tstd::deque<Query> queries;\n}\n\n@end\n\n@implementation ZetaConfirmDialog\n\n- (void)addQuery:(NSString*)query\n withInformation:(NSString*)info\n\twithCallback:(void(^)(bool))callback\n{\n\tqueries.push_back({query, info, callback});\n\tif (queries.size() == 1)\n\t\t[self updateQuery];\n\tif (![_popover isShown])\n\t\t[self show];\n}\n\n- (void)show\n{\n\t[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];\n\tNSView * positioningView = [_statusItem button];\n\t[_popover showRelativeToRect:NSMakeRect(0, 0, 0, 0)\n\t\t\t\t\t\t  ofView:positioningView\n\t\t\t\t   preferredEdge:NSRectEdgeMinY];\n}\n\n- (IBAction)ok:(id)sender\n{\n\tif (!queries.empty())\n\t\tqueries.front().reply(true);\n\t[self advanceQuery];\n}\n\n- (IBAction)cancel:(id)sender\n{\n\tif (!queries.empty())\n\t\tqueries.front().reply(false);\n\t[self advanceQuery];\n}\n\n- (BOOL)popoverShouldDetach:(NSPopover *)popover\n{\n\treturn YES;\n}\n\n- (void)advanceQuery\n{\n\tqueries.pop_front();\n\t[self updateQuery];\n\tif (queries.empty())\n\t{\n\t\t[_popover performClose:self];\n\t}\n}\n\n- (void)updateQuery\n{\n\tif (queries.empty())\n\t{\n\t\t[_queryField setStringValue:@\"\"];\n\t\t[_infoField setStringValue:@\"\"];\n\t}\n\telse\n\t{\n\t\t[_queryField setStringValue:queries.front().query];\n\t\t[_infoField setStringValue:queries.front().info];\n\t}\n}\n\n- (BOOL)popoverShouldClose:(NSPopover *)popover\n{\n\tif (!queries.empty())\n\t{\n\t\tqueries.front().reply(false);\n\t\tqueries.pop_front();\n\t\tif (queries.empty())\n\t\t\treturn YES;\n\t\t[self updateQuery];\n\t\treturn NO;\n\t}\n\telse\n\t{\n\t\treturn YES;\n\t}\n}\n\n- (void)popoverWillShow:(NSNotification *)notification\n{\n}\n\n- (void)popoverDidClose:(NSNotification *)notification\n{\n}\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaDictQueryDialog.h",
    "content": "//\n//  ZetaDictQueryDialog.h\n//  ZetaWatch\n//\n//  Created by cbreak on 19.10.06.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import <Cocoa/Cocoa.h>\n\n@interface ZetaDictQueryDialog : NSObject <NSPopoverDelegate>\n\n@property (weak) NSStatusItem * statusItem;\n@property (weak) IBOutlet NSPopover * popover;\n@property (retain) NSMutableDictionary * queryDict;\n\n- (IBAction)ok:(id)sender;\n- (IBAction)cancel:(id)sender;\n\n- (BOOL)popoverShouldDetach:(NSPopover *)popover;\n\n- (void)addQuery:(NSMutableDictionary*)query\n\twithCallback:(void(^)(NSDictionary*))callback;\n\n- (id)initWithDialog:(NSString*)dialogName;\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaDictQueryDialog.mm",
    "content": "//\n//  ZetaNewFSDialog.mm\n//  ZetaWatch\n//\n//  Created by cbreak on 19.10.06.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import \"ZetaDictQueryDialog.h\"\n\n#include <deque>\n#include <type_traits>\n\nnamespace\n{\n\ttypedef void (^QueryCallback)(NSDictionary *);\n\n\tstruct Query\n\t{\n\t\tNSMutableDictionary * query;\n\t\tQueryCallback reply;\n\t};\n}\n\n@interface ZetaDictQueryDialog ()\n{\n\tstd::deque<Query> queries;\n\tNSArray * topLevelObjects;\n}\n\n@end\n\n@implementation ZetaDictQueryDialog\n\n- (id)initWithDialog:(NSString*)dialogName\n{\n\tif (self = [super init])\n\t{\n\t\tNSArray * tlo;\n\t\t[[NSBundle mainBundle] loadNibNamed:dialogName owner:self topLevelObjects:&tlo];\n\t\ttopLevelObjects = tlo;\n\t}\n\treturn self;\n}\n\n- (void)addQuery:(NSMutableDictionary*)query\n\twithCallback:(void(^)(NSDictionary*))callback\n{\n\tqueries.push_back({query, callback});\n\tif (queries.size() == 1)\n\t\t[self updateQuery];\n\tif (![_popover isShown])\n\t\t[self show];\n}\n\n- (void)show\n{\n\t[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];\n\tNSView * positioningView = [_statusItem button];\n\t[_popover showRelativeToRect:NSMakeRect(0, 0, 0, 0)\n\t\t\t\t\t\t  ofView:positioningView\n\t\t\t\t   preferredEdge:NSRectEdgeMinY];\n}\n\n- (IBAction)ok:(id)sender\n{\n\tif (!queries.empty())\n\t\tqueries.front().reply(queries.front().query);\n\t[self advanceQuery];\n}\n\n- (IBAction)cancel:(id)sender\n{\n\t[self advanceQuery];\n}\n\n- (BOOL)popoverShouldDetach:(NSPopover *)popover\n{\n\treturn YES;\n}\n\n- (void)advanceQuery\n{\n\tqueries.pop_front();\n\t[self updateQuery];\n\tif (queries.empty())\n\t{\n\t\t[_popover performClose:self];\n\t}\n}\n\n- (void)updateQuery\n{\n\tif (!queries.empty())\n\t{\n\t\tself.queryDict = queries.front().query;\n\t}\n\telse\n\t{\n\t\tself.queryDict = nullptr;\n\t}\n}\n\n- (BOOL)popoverShouldClose:(NSPopover *)popover\n{\n\tif (!queries.empty())\n\t{\n\t\tqueries.pop_front();\n\t\tif (queries.empty())\n\t\t\treturn YES;\n\t\t[self updateQuery];\n\t\treturn NO;\n\t}\n\telse\n\t{\n\t\treturn YES;\n\t}\n}\n\n- (void)popoverWillShow:(NSNotification *)notification\n{\n}\n\n- (void)popoverDidClose:(NSNotification *)notification\n{\n\tself.queryDict = nullptr;\n}\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaFileSystemPropertyMenu.h",
    "content": "//\n//  ZetaFileSystemPropertyMenu.h\n//  ZetaWatch\n//\n//  Created by cbreak on 19.06.22.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import <Cocoa/Cocoa.h>\n\n#import \"ZetaCommanderBase.h\"\n\n#include \"ZFSUtils.hpp\"\n\n@interface ZetaFileSystemPropertyMenu : ZetaCommanderBase <NSMenuDelegate>\n\n- (id)initWithFileSystem:(zfs::ZFileSystem)fs;\n\n- (void)menuNeedsUpdate:(NSMenu*)menu;\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaFileSystemPropertyMenu.mm",
    "content": "//\n//  ZetaFileSystemPropertyMenu.mm\n//  ZetaWatch\n//\n//  Created by cbreak on 19.06.22.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import \"ZetaFileSystemPropertyMenu.h\"\n\n@implementation ZetaFileSystemPropertyMenu\n{\n\tzfs::ZFileSystem _fs;\n}\n\n- (id)initWithFileSystem:(zfs::ZFileSystem)fs\n{\n\tif (self = [super init])\n\t{\n\t\t_fs = std::move(fs);\n\t}\n\treturn self;\n}\n\n- (void)menuNeedsUpdate:(NSMenu*)menu\n{\n\t[menu removeAllItems];\n\tauto props = _fs.properties();\n\tfor (auto const & p : props)\n\t{\n\t\tif (p.source.size() > 0)\n\t\t{\n\t\t\taddMenuItem(menu, self, NSLocalizedString(@\"%-64s \\t %-32s \\t (from %s)\", @\"KeyValueSource\"),\n\t\t\t\t\t\tp.name, p.value, p.source);\n\t\t}\n\t\telse\n\t\t{\n\t\t\taddMenuItem(menu, self, NSLocalizedString(@\"%-64s \\t %s\", @\"KeyValue\"),\n\t\t\t\t\t\tp.name, p.value);\n\t\t}\n\t}\n}\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaFormatHelpers.cpp",
    "content": "//\n//  ZetaFormatHelpers.cpp\n//  ZetaWatch\n//\n//  Created by cbreak on 19.06.22.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#include \"ZetaFormatHelpers.hpp\"\n\nPrefix const metricPrefixes[] = {\n\t{ 1000000000000000000, \"E\" },\n\t{    1000000000000000, \"P\" },\n\t{       1000000000000, \"T\" },\n\t{\t       1000000000, \"G\" },\n\t{             1000000, \"M\" },\n\t{                1000, \"k\" },\n};\n\nsize_t const metricPrefixCount = std::extent<decltype(metricPrefixes)>::value;\n\n// https://en.wikipedia.org/wiki/Binary_prefix\nPrefix const binaryPrefixes[] = {\n\t{ 1ull << 60, \"Ei\" },\n\t{ 1ull << 50, \"Pi\" },\n\t{ 1ull << 40, \"Ti\" },\n\t{ 1ull << 30, \"Gi\" },\n\t{ 1ull << 20, \"Mi\" },\n\t{ 1ull << 10, \"ki\" },\n};\n\nsize_t const binaryPrefixCount = std::extent<decltype(binaryPrefixes)>::value;\n"
  },
  {
    "path": "ZetaWatch/ZetaFormatHelpers.hpp",
    "content": "//\n//  ZetaFormatHelpers.hpp\n//  ZetaWatch\n//\n//  Created by cbreak on 19.06.22.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#ifndef ZetaFormatHelpers_hpp\n#define ZetaFormatHelpers_hpp\n\n#include <sstream>\n#include <string>\n#include <iomanip>\n#include <regex>\n\nstruct Prefix\n{\n\tuint64_t factor;\n\tchar const * prefix;\n};\n\nextern Prefix const metricPrefixes[];\nextern size_t const metricPrefixCount;\n\nextern Prefix const binaryPrefixes[];\nextern size_t const binaryPrefixCount;\n\ntemplate<typename T>\nstd::string formatPrefixedValue(T size, Prefix const * prefix, size_t prefixCount)\n{\n\tfor (size_t p = 0; p < prefixCount; ++p)\n\t{\n\t\tif (size >= prefix[p].factor)\n\t\t{\n\t\t\tdouble scaledSize = size / double(prefix[p].factor);\n\t\t\tstd::stringstream ss;\n\t\t\tss << std::setprecision(2) << std::fixed << scaledSize << \" \" << prefix[p].prefix;\n\t\t\treturn ss.str();\n\t\t}\n\t}\n\treturn std::to_string(size) + \" \";\n}\n\ntemplate<typename T>\nstd::string formatInformationValue(T size)\n{\n\treturn formatPrefixedValue(size, binaryPrefixes, binaryPrefixCount);\n}\n\ntemplate<typename T>\nstd::string formatNormalValue(T size)\n{\n\treturn formatPrefixedValue(size, metricPrefixes, metricPrefixCount);\n}\n\ntemplate<typename T>\nstd::string formatBytes(T bytes)\n{\n\treturn formatInformationValue(bytes) + \"B\";\n}\n\ntemplate<typename T>\nbool parseBytes(char const * byteString, T & outBytes)\n{\n\tstd::regex byteRegex(R\"((\\d+\\.?\\d*)\\s*([EPTGMk]?i?)B?)\", std::regex::icase);\n\tstd::cmatch match;\n\tif (std::regex_match(byteString, match, byteRegex))\n\t{\n\t\tdouble bytesFormated = std::stod(std::string(match[1].first, match[1].second));\n\t\tstd::string prefix(match[2].first, match[2].second);\n\t\tstd::transform(prefix.begin(), prefix.end(), prefix.begin(), ::tolower);\n\t\tif (prefix.length() == 1)\n\t\t\tprefix += 'i';\n\t\tPrefix const * foundPrefix = std::find_if(binaryPrefixes, binaryPrefixes + binaryPrefixCount,\n\t\t\t[=](Prefix const & p)\n\t\t{\n\t\t\tstd::string pp(p.prefix);\n\t\t\tstd::transform(pp.begin(), pp.end(), pp.begin(), ::tolower);\n\t\t\treturn prefix == pp;\n\t\t});\n\t\tif (foundPrefix != binaryPrefixes + binaryPrefixCount)\n\t\t{\n\t\t\toutBytes = static_cast<T>(bytesFormated * foundPrefix->factor);\n\t\t}\n\t\telse\n\t\t{\n\t\t\toutBytes = static_cast<T>(bytesFormated);\n\t\t}\n\t\treturn true;\n\t}\n\treturn false;\n}\n\ninline std::string formatRate(uint64_t bytes, std::chrono::seconds const & time)\n{\n\treturn formatBytes(bytes / time.count()) + \"/s\";\n}\n\ntemplate<typename T> T toFormatable(T t)\n{\n\treturn t;\n}\n\ninline char const * toFormatable(std::string const & str)\n{\n\treturn str.c_str();\n}\n\ninline std::string trim(std::string const & s)\n{\n\tsize_t first = s.find_first_not_of(' ');\n\tsize_t last = s.find_last_not_of(' ');\n\tif (first != std::string::npos)\n\t\treturn s.substr(first, last - first + 1);\n\treturn s;\n}\n\n#endif /* ZetaMenuHelpers_h */\n"
  },
  {
    "path": "ZetaWatch/ZetaImportMenu.h",
    "content": "//\n//  ZetaImportMenu.h\n//  ZetaWatch\n//\n//  Created by cbreak on 19.06.02.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#ifndef ZetaImportMenu_h\n#define ZetaImportMenu_h\n\n#import <Cocoa/Cocoa.h>\n\n#import \"ZetaAuthorization.h\"\n#import \"ZetaCommanderBase.h\"\n#import \"ZetaAutoImporter.h\"\n\n@class ZetaPoolWatcher;\n\n@interface ZetaImportMenu : ZetaCommanderBase <NSMenuDelegate>\n\n@property (weak) IBOutlet NSMenu * importMenu;\n@property (weak) IBOutlet ZetaPoolWatcher * poolWatcher;\n@property (weak) IBOutlet ZetaAutoImporter * autoImporter;\n\n@end\n\n#endif /* ZetaImportMenuDelegate_h */\n"
  },
  {
    "path": "ZetaWatch/ZetaImportMenu.mm",
    "content": "//\n//  ZetaImportMenu.m\n//  ZetaWatch\n//\n//  Created by cbreak on 19.06.02.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import \"ZetaImportMenu.h\"\n\n#import \"ZetaAuthorization.h\"\n#import \"ZetaPoolWatcher.h\"\n\n#include \"ZFSStrings.hpp\"\n\n@implementation ZetaImportMenu\n\n- (void)menuNeedsUpdate:(NSMenu*)menu\n{\n\t[menu removeAllItems];\n\tNSMenuItem * importAllItem = [menu addItemWithTitle:@\"Import all Pools\" action:@selector(importAllPools:) keyEquivalent:@\"\"];\n\timportAllItem.target = self;\n\t[menu addItem:[NSMenuItem separatorItem]];\n\tauto importablePools = [self.autoImporter importablePools];\n\tif (importablePools.size() > 0)\n\t{\n\t\tauto addPoolImportMenu = [self](NSMenu * menu, auto const & pool)\n\t\t{\n\t\t\tNSString * title = [NSString stringWithFormat:@\"%s %@ (%llu)\",\n\t\t\t\tpool.name.c_str(),\n\t\t\t\tzfs::emojistring_pool_status_t(pool.status),\n\t\t\t\tpool.guid];\n\t\t\tNSMenuItem * item = [menu addItemWithTitle:title action:@selector(importPool:) keyEquivalent:@\"\"];\n\t\t\t[item setAction:@selector(importPool:)];\n\t\t\t[item setTarget:self];\n\t\t\t// Communicate pool to callback\n\t\t\tNSNumber * guid = [NSNumber numberWithUnsignedLongLong:pool.guid];\n\t\t\tNSString * name = [NSString stringWithUTF8String:pool.name.c_str()];\n\t\t\tNSMutableDictionary * poolDict = [NSMutableDictionary dictionary];\n\t\t\tpoolDict[@\"poolGUID\"] = guid;\n\t\t\tpoolDict[@\"poolName\"] = name;\n\t\t\t[item setRepresentedObject:poolDict];\n\t\t\treturn poolDict;\n\t\t};\n\t\tfor (auto const & pool : importablePools)\n\t\t{\n\t\t\taddPoolImportMenu(menu, pool);\n\t\t}\n\t\t[menu addItem:[NSMenuItem separatorItem]];\n\t\t// Read-Only Menu\n\t\tNSMenuItem * importROItem = [menu addItemWithTitle:\n\t\t\tNSLocalizedString(@\"Import Read Only\", @\"Import Read Only\") action:NULL keyEquivalent:@\"\"];\n\t\tNSMenu * importROMenu = [[NSMenu alloc] init];\n\t\timportROItem.submenu = importROMenu;\n\t\tfor (auto const & pool : importablePools)\n\t\t{\n\t\t\tauto dict = addPoolImportMenu(importROMenu, pool);\n\t\t\tdict[@\"readOnly\"] = @YES;\n\t\t}\n\t\t// Read-Write Menu\n\t\tNSMenuItem * importRWItem = [menu addItemWithTitle:\n\t\t\tNSLocalizedString(@\"Import Read Write\", @\"Import Read Write\") action:NULL keyEquivalent:@\"\"];\n\t\tNSMenu * importRWMenu = [[NSMenu alloc] init];\n\t\timportRWItem.submenu = importRWMenu;\n\t\tfor (auto const & pool : importablePools)\n\t\t{\n\t\t\tauto dict = addPoolImportMenu(importRWMenu, pool);\n\t\t\tdict[@\"readOnly\"] = @NO;\n\t\t}\n\t}\n\telse\n\t{\n\t\t[_importMenu addItemWithTitle:NSLocalizedString(@\"No importable Pools found\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t@\"No Importable Pools\")\n\t\t\t\t\t\t\t   action:NULL keyEquivalent:@\"\"];\n\t}\n}\n\n- (void)importablePoolsDiscovered:(NSDictionary*)importablePools\n{\n}\n\n- (void)importablePoolsError:(NSError*)error\n{\n\tNSMenuItem * item = [_importMenu itemAtIndex:2];\n\t[item setTitle:[error localizedDescription]];\n}\n\n- (IBAction)importPool:(id)sender\n{\n\tNSDictionary * pool = [sender representedObject];\n\tNSMutableDictionary * mutablePool = [pool mutableCopy];\n\tauto defaults = [NSUserDefaults standardUserDefaults];\n\tif ([defaults boolForKey:@\"useAltroot\"])\n\t{\n\t\t[mutablePool setObject:[defaults stringForKey:@\"defaultAltroot\"] forKey:@\"altroot\"];\n\t}\n\tif (auto spo = [defaults arrayForKey:@\"searchPathOverride\"])\n\t{\n\t\t[mutablePool setObject:spo forKey:@\"searchPathOverride\"];\n\t}\n\t// Direct imports always allow unhealthy pools with mismatching host IDs.\n\t[mutablePool setObject:@YES forKey:@\"allowUnhealthy\"];\n\t[mutablePool setObject:@YES forKey:@\"allowHostIDMismatch\"];\n\t[_authorization importPools:mutablePool withReply:^(NSError * error)\n\t {\n\t\t if (!error)\n\t\t {\n\t\t\t NSString * title = [NSString stringWithFormat:\n\t\t\t\tNSLocalizedString(@\"Pool %@ imported\",\n\t\t\t\t\t\t\t\t  @\"Pool Import Success short format\"),\n\t\t\t\tpool[@\"poolName\"]];\n\t\t\t NSString * text = [NSString stringWithFormat:\n\t\t\t\tNSLocalizedString(@\"%@ (%@) imported\",\n\t\t\t\t\t\t\t\t  @\"Pool Import Success format\"),\n\t\t\t\tpool[@\"poolName\"], pool[@\"poolGUID\"]];\n\t\t\t [self notifySuccessWithTitle:title text:text];\n\t\t }\n\t\t [self handlePoolChangeReply:error];\n\t }];\n}\n\n- (IBAction)importAllPools:(id)sender\n{\n\tNSMutableDictionary * mutablePool = [NSMutableDictionary dictionary];\n\tauto defaults = [NSUserDefaults standardUserDefaults];\n\tif ([defaults boolForKey:@\"allowHostIDMismatch\"])\n\t{\n\t\t[mutablePool setObject:@YES forKey:@\"allowHostIDMismatch\"];\n\t}\n\tif ([defaults boolForKey:@\"useAltroot\"])\n\t{\n\t\t[mutablePool setObject:[defaults stringForKey:@\"defaultAltroot\"] forKey:@\"altroot\"];\n\t}\n\tif (auto spo = [defaults arrayForKey:@\"searchPathOverride\"])\n\t{\n\t\t[mutablePool setObject:spo forKey:@\"searchPathOverride\"];\n\t}\n\t[_authorization importPools:mutablePool withReply:^(NSError * error)\n\t {\n\t\t if (!error)\n\t\t {\n\t\t\t NSString * title = [NSString stringWithFormat:\n\t\t\t\tNSLocalizedString(@\"All pools imported\",\n\t\t\t\t\t\t\t\t  @\"Pool Import Success all\")];\n\t\t\t [self notifySuccessWithTitle:title text:nil];\n\t\t }\n\t\t [self handlePoolChangeReply:error];\n\t }];\n}\n\n- (void)handlePoolChangeReply:(NSError*)error\n{\n\tif (error)\n\t{\n\t\t[self notifyErrorFromHelper:error];\n\t}\n\telse\n\t{\n\t\t[[self poolWatcher] checkForChanges];\n\t}\n}\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaKeyLoader.h",
    "content": "//\n//  ZetaKeyLoader.h\n//  ZetaWatch\n//\n//  Created by cbreak on 19.06.16.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import <Cocoa/Cocoa.h>\n\n#import \"ZetaCommanderBase.h\"\n#import \"ZetaPoolWatcher.h\"\n\n@interface ZetaKeyLoader : ZetaCommanderBase <NSPopoverDelegate,ZetaPoolWatcherDelegate>\n\n@property (weak) NSStatusItem * statusItem;\n@property (weak) IBOutlet NSPopover * popover;\n@property (weak) IBOutlet NSSecureTextField * passwordField;\n@property (weak) IBOutlet NSTextField * queryField;\n@property (weak) IBOutlet NSTextField * statusField;\n@property (weak) IBOutlet NSButton * useKeychainCheckbox;\n@property (weak) IBOutlet NSProgressIndicator * progressIndicator;\n@property (weak) IBOutlet NSButton * loadButton;\n@property (weak) IBOutlet NSButton * skipButton;\n\n@property (weak) IBOutlet ZetaPoolWatcher * poolWatcher;\n\n- (void)unlockFileSystem:(NSString*)filesystem;\n\n- (IBAction)loadKey:(id)sender;\n- (IBAction)skipFileSystem:(id)sender;\n\n- (BOOL)popoverShouldDetach:(NSPopover *)popover;\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaKeyLoader.mm",
    "content": "//\n//  ZetaKeyLoader.m\n//  ZetaWatch\n//\n//  Created by cbreak on 19.06.16.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import \"ZetaKeyLoader.h\"\n\n#import <Security/Security.h>\n\n#include \"ZFSWrapper/ZFSUtils.hpp\"\n\n#include <deque>\n#include <type_traits>\n\nenum class LoaderState\n{\n\tidle,\n\texamineFilesystem,\n\tloadKeyfile,\n\tloadStoredKey,\n\tloadInteractiveGet,\n\tloadInteractiveUnlock,\n\tloadCompleted,\n};\n\nenum class LoaderEvent\n{\n\tnewFilesystem,\n\tunlockSucceeded,\n\tunlockFailedPassword,\n\tunlockFailedOther,\n\tbuttonLoad,\n\tbuttonSkip,\n};\n\n@interface ZetaKeyLoader ()\n{\n\tstd::deque<NSString*> filesystems;\n\tLoaderState state;\n\tzfs::LibZFSHandle libZFS;\n}\n\n@end\n\n@implementation ZetaKeyLoader\n\n- (void)awakeFromNib\n{\n\tstate = LoaderState::idle;\n\tif (self.poolWatcher)\n\t{\n\t\t[self.poolWatcher.delegates addObject:self];\n\t}\n}\n\n- (IBAction)loadKey:(id)sender\n{\n\t[self handleLoaderEvent:LoaderEvent::buttonLoad];\n}\n\n- (IBAction)skipFileSystem:(id)sender\n{\n\t[self handleLoaderEvent:LoaderEvent::buttonSkip];\n}\n\n- (void)unlockFileSystem:(NSString*)filesystem\n{\n\tfilesystems.push_back(filesystem);\n\t[self handleLoaderEvent:LoaderEvent::newFilesystem];\n}\n\n- (void)advanceFilesystems\n{\n\tfilesystems.pop_front();\n\tif (filesystems.size() > 0)\n\t\t[self transitionToState:LoaderState::examineFilesystem];\n\telse\n\t\t[self transitionToState:LoaderState::idle];\n}\n\n// State transition function that enters a state, setting up UI, and starting\n// functions that might trigger further state transitions. Can include direct\n// transitions to other states.\n- (void)transitionToState:(LoaderState)nextState\n{\n\tstate = nextState;\n\tswitch (state)\n\t{\n\t\tcase LoaderState::idle:\n\t\t{\n\t\t\t[self updateFileSystem];\n\t\t\t[_popover performClose:self];\n\t\t\tbreak;\n\t\t}\n\t\tcase LoaderState::examineFilesystem:\n\t\t{\n\t\t\t[self updateFileSystem];\n\t\t\t[self show];\n\t\t\t[self examineFilesystem:filesystems.front()];\n\t\t\tbreak;\n\t\t}\n\t\tcase LoaderState::loadKeyfile:\n\t\t{\n\t\t\t[self showActionInProgress:\n\t\t\t NSLocalizedString(@\"Loading Keyfile...\",\n\t\t\t\t\t\t\t   @\"LoadingKeyfileStatus\")];\n\t\t\t[self loadKeyFileForFilesystem:filesystems.front()];\n\t\t\tbreak;\n\t\t}\n\t\tcase LoaderState::loadStoredKey:\n\t\t{\n\t\t\t[self showActionInProgress:\n\t\t\t NSLocalizedString(@\"Loading stored Key...\",\n\t\t\t\t\t\t\t   @\"LoadingNonInteractiveKeyStatus\")];\n\t\t\t[self loadStoredPasswordForFilesystem:filesystems.front()];\n\t\t\tbreak;\n\t\t}\n\t\tcase LoaderState::loadInteractiveGet:\n\t\t{\n\t\t\t[self requestPassword];\n\t\t\tbreak;\n\t\t}\n\t\tcase LoaderState::loadInteractiveUnlock:\n\t\t{\n\t\t\t[self showActionInProgress:\n\t\t\t NSLocalizedString(@\"Loading entered Key...\",\n\t\t\t\t\t\t\t   @\"LoadingInteractiveKeyStatus\")];\n\t\t\t[self loadInteractivePasswordForFilesystem:filesystems.front()];\n\t\t\tbreak;\n\t\t}\n\t\tcase LoaderState::loadCompleted:\n\t\t{\n\t\t\t[self advanceFilesystems];\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n// Event state transition function that decides which state to go to based on\n// events it receives and the current state.\n- (void)handleLoaderEvent:(LoaderEvent)event\n{\n\tswitch (state)\n\t{\n\t\tcase LoaderState::idle:\n\t\t{\n\t\t\tswitch (event)\n\t\t\t{\n\t\t\t\tcase LoaderEvent::newFilesystem:\n\t\t\t\t\t[self transitionToState:LoaderState::examineFilesystem];\n\t\t\t\t\treturn;\n\t\t\t\tdefault:\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase LoaderState::examineFilesystem:\n\t\t{\n\t\t\t// Transitional state\n\t\t\tbreak;\n\t\t}\n\t\tcase LoaderState::loadKeyfile:\n\t\t{\n\t\t\tswitch (event)\n\t\t\t{\n\t\t\t\tcase LoaderEvent::unlockSucceeded:\n\t\t\t\t\t[self transitionToState:LoaderState::loadCompleted];\n\t\t\t\t\treturn;\n\t\t\t\tcase LoaderEvent::unlockFailedPassword:\n\t\t\t\tcase LoaderEvent::unlockFailedOther:\n\t\t\t\t\t[self transitionToState:LoaderState::loadStoredKey];\n\t\t\t\t\treturn;\n\t\t\t\tdefault:\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase LoaderState::loadStoredKey:\n\t\t{\n\t\t\tswitch (event)\n\t\t\t{\n\t\t\t\tcase LoaderEvent::unlockSucceeded:\n\t\t\t\t\t[self transitionToState:LoaderState::loadCompleted];\n\t\t\t\t\treturn;\n\t\t\t\tcase LoaderEvent::unlockFailedPassword:\n\t\t\t\tcase LoaderEvent::unlockFailedOther:\n\t\t\t\t\t[self transitionToState:LoaderState::loadInteractiveGet];\n\t\t\t\t\treturn;\n\t\t\t\tdefault:\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase LoaderState::loadInteractiveGet:\n\t\t{\n\t\t\tswitch (event)\n\t\t\t{\n\t\t\t\tcase LoaderEvent::buttonLoad:\n\t\t\t\t\t[self transitionToState:LoaderState::loadInteractiveUnlock];\n\t\t\t\t\treturn;\n\t\t\t\tcase LoaderEvent::buttonSkip:\n\t\t\t\t\t[self transitionToState:LoaderState::loadCompleted];\n\t\t\t\t\treturn;\n\t\t\t\tdefault:\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase LoaderState::loadInteractiveUnlock:\n\t\t{\n\t\t\tswitch (event)\n\t\t\t{\n\t\t\t\tcase LoaderEvent::unlockSucceeded:\n\t\t\t\tcase LoaderEvent::unlockFailedOther:\n\t\t\t\t\t[self transitionToState:LoaderState::loadCompleted];\n\t\t\t\t\treturn;\n\t\t\t\tcase LoaderEvent::unlockFailedPassword:\n\t\t\t\t\t[self transitionToState:LoaderState::loadInteractiveGet];\n\t\t\t\t\treturn;\n\t\t\t\tdefault:\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase LoaderState::loadCompleted:\n\t\t{\n\t\t\t// Transitional state\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\n- (void)show\n{\n//\t[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];\n\tNSView * positioningView = [_statusItem button];\n\t[_popover showRelativeToRect:NSMakeRect(0, 0, 0, 0)\n\t\t\t\t\t\t  ofView:positioningView\n\t\t\t\t   preferredEdge:NSRectEdgeMinY];\n}\n\n- (void)loadKey:(NSString*)password forFilesystem:(NSString*)filesystem\n\t\t  storeInKeychain:(bool)storeInKeychain\n{\n\tNSDictionary * opts = @{@\"filesystem\": filesystem, @\"key\": password};\n\t[_authorization loadKeyForFilesystem:opts withReply:^(NSError * error)\n\t {\n\t\tbool success = [self handleLoadKeyReply:error];\n\t\t if (success && storeInKeychain)\n\t\t {\n\t\t\t [self storePassword:password forFilesystem:filesystem];\n\t\t }\n\t }];\n}\n\n- (void)loadKeyFileForFilesystem:(NSString*)filesystem\n{\n\tNSDictionary * opts = @{@\"filesystem\": filesystem};\n\t[_authorization loadKeyForFilesystem:opts withReply:^(NSError * error)\n\t {\n\t\t[self handleLoadKeyReply:error];\n\t }];\n}\n\n- (bool)handleLoadKeyReply:(NSError*)error\n{\n\tif (error)\n\t{\n\t\tif ([error.domain isEqualToString:@\"ZFSKeyError\"])\n\t\t{\n\t\t\t[self showError:[error localizedDescription]];\n\t\t\t[self handleLoaderEvent:LoaderEvent::unlockFailedPassword];\n\t\t}\n\t\telse\n\t\t{\n\t\t\t[self notifyErrorFromHelper:error];\n\t\t\t[self handleLoaderEvent:LoaderEvent::unlockFailedOther];\n\t\t}\n\t\treturn false;\n\t}\n\telse\n\t{\n\t\t[self handleLoaderEvent:LoaderEvent::unlockSucceeded];\n\t\treturn true;\n\t}\n}\n\n- (void)showActionInProgress:(NSString*)action\n{\n\t[self showStatus:action];\n\t[_progressIndicator startAnimation:self];\n\t[_loadButton setEnabled:NO];\n\t[_skipButton setEnabled:NO];\n\t[_passwordField setEnabled:NO];\n\t[_useKeychainCheckbox setEnabled:NO];\n}\n\n- (void)requestPassword\n{\n\t[_progressIndicator stopAnimation:self];\n\t[_loadButton setEnabled:YES];\n\t[_skipButton setEnabled:YES];\n\t[_passwordField setEnabled:YES];\n\t[_useKeychainCheckbox setEnabled:YES];\n}\n\n- (void)showStatus:(NSString*)error\n{\n\t[_statusField setStringValue:error];\n\t[_statusField setTextColor:[NSColor textColor]];\n}\n\n- (void)showError:(NSString*)error\n{\n\t[_statusField setStringValue:error];\n\t[_statusField setTextColor:[NSColor systemRedColor]];\n}\n\n- (void)clearPassword\n{\n\t// The password is copied all over the place by the view, the dictionary\n\t// and the IPC, so trying to clear it is probably a waste of time.\n\t[_passwordField setStringValue:@\"\"];\n}\n\n- (void)examineFilesystem:(NSString*)filesystem\n{\n\tauto fs = libZFS.filesystem([filesystem UTF8String]);\n\tif (fs.keyLocation() == zfs::ZFileSystem::KeyLocation::uri)\n\t{\n\t\t[self transitionToState:LoaderState::loadKeyfile];\n\t}\n\telse\n\t{\n\t\t[self transitionToState:LoaderState::loadStoredKey];\n\t}\n}\n\n- (void)loadInteractivePasswordForFilesystem:(NSString*)filesystem\n{\n\tNSString * pass = [_passwordField stringValue];\n\tbool storeInKeychain = [_useKeychainCheckbox state] == NSControlStateValueOn;\n\t[self clearPassword];\n\t[self loadKey:pass forFilesystem:filesystem storeInKeychain:storeInKeychain];\n}\n\n- (void)loadStoredPasswordForFilesystem:(NSString*)filesystem\n{\n\tNSString * password = [self retrievePasswordForFilesystem:filesystem];\n\tif (password)\n\t{\n\t\t[self loadKey:password forFilesystem:filesystem storeInKeychain:false];\n\t}\n\telse\n\t{\n\t\t[self showStatus:\n\t\t NSLocalizedString(@\"No stored key found\",\n\t\t\t\t\t\t   @\"NoStoredKeyStatus\")];\n\t\t[self handleLoaderEvent:LoaderEvent::unlockFailedOther];\n\t}\n}\n\n- (NSString*)retrievePasswordForFilesystem:(NSString*)filesystem\n{\n\tvoid const * keys[] = {\n\t\tkSecClass,\n\t\tkSecAttrService,\n\t\tkSecMatchLimit,\n\t\tkSecReturnData,\n\t};\n\tvoid const * values[] = {\n\t\tkSecClassGenericPassword,\n\t\t(__bridge CFStringRef)filesystem,\n\t\tkSecMatchLimitOne,\n\t\tkCFBooleanTrue,\n\t};\n\tstatic_assert(std::extent_v<decltype(keys)> == std::extent_v<decltype(values)>);\n\tconstexpr size_t attributeCount = std::extent_v<decltype(keys)>;\n\tCFDictionaryRef attributes =  CFDictionaryCreate(nullptr,\n\t\t&keys[0], &values[0], attributeCount,\n\t\t&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);\n\tvoid const * data = nullptr;\n\tOSStatus result = SecItemCopyMatching(attributes, &data);\n\tCFRelease(attributes);\n\tif (result != errSecSuccess)\n\t{\n\t\treturn nullptr;\n\t}\n\tNSString * password = [[NSString alloc] initWithData:CFBridgingRelease((CFDataRef)data)\nencoding:NSUTF8StringEncoding];\n\treturn password;\n}\n\n- (bool)deletePasswordForFilesystem:(NSString*)filesystem\n{\n\tvoid const * keys[] = {\n\t\tkSecClass,\n\t\tkSecAttrService,\n\t\tkSecMatchLimit,\n\t};\n\tvoid const * values[] = {\n\t\tkSecClassGenericPassword,\n\t\t(__bridge CFStringRef)filesystem,\n\t\tkSecMatchLimitAll,\n\t};\n\tstatic_assert(std::extent_v<decltype(keys)> == std::extent_v<decltype(values)>);\n\tconstexpr size_t attributeCount = std::extent_v<decltype(keys)>;\n\tCFDictionaryRef attributes =  CFDictionaryCreate(nullptr,\n\t\t&keys[0], &values[0], attributeCount,\n\t\t&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);\n\tOSStatus result = SecItemDelete(attributes);\n\tCFRelease(attributes);\n\tif (result != errSecSuccess)\n\t{\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n- (bool)storePassword:(NSString*)password forFilesystem:(NSString*)filesystem\n{\n\t[self deletePasswordForFilesystem:filesystem];\n\tNSData * passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];\n\tNSString * label = [NSString stringWithFormat:@\"ZetaWatch Password for ZFS filesystem %@\", filesystem];\n\tvoid const * keys[] = {\n\t\tkSecClass,\n\t\tkSecAttrLabel,\n\t\tkSecAttrService,\n\t\tkSecValueData,\n\t};\n\tvoid const * values[] = {\n\t\tkSecClassGenericPassword,\n\t\t(__bridge CFStringRef)label,\n\t\t(__bridge CFStringRef)filesystem,\n\t\t(__bridge CFDataRef)passwordData,\n\t};\n\tstatic_assert(std::extent_v<decltype(keys)> == std::extent_v<decltype(values)>);\n\tconstexpr size_t attributeCount = std::extent_v<decltype(keys)>;\n\tCFDictionaryRef attributes =  CFDictionaryCreate(nullptr,\n\t\t&keys[0], &values[0], attributeCount,\n\t\t&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);\n\tOSStatus result = SecItemAdd(attributes, nil);\n\tCFRelease(attributes);\n\tif (result != errSecSuccess)\n\t{\n\t\tCFStringRef errorString = SecCopyErrorMessageString(result, nullptr);\n\t\tNSError * error = [NSError errorWithDomain:NSOSStatusErrorDomain\n\t\t\t\t\t\t\t\t\t\t\t  code:result userInfo:\n\t\t@{\n\t\t\tNSLocalizedDescriptionKey: CFBridgingRelease(errorString)\n\t\t}];\n\t\t[self notifyErrorFromHelper:error];\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n- (void)updateFileSystem\n{\n\tif (filesystems.empty())\n\t{\n\t\t[_queryField setStringValue:@\"\"];\n\t}\n\telse\n\t{\n\t\t[_queryField setStringValue:[NSString stringWithFormat:NSLocalizedString(@\"Enter the password for %@\", @\"Password Query\"), filesystems.front()]];\n\t\tbool useKeychain = [[NSUserDefaults standardUserDefaults] boolForKey:@\"useKeychain\"];\n\t\t[_useKeychainCheckbox setState:useKeychain ? NSControlStateValueOn : NSControlStateValueOff];\n\t}\n}\n\n- (BOOL)popoverShouldDetach:(NSPopover *)popover\n{\n\treturn YES;\n}\n\n- (BOOL)popoverShouldClose:(NSPopover *)popover\n{\n\treturn filesystems.empty();\n}\n\n- (void)popoverWillShow:(NSNotification *)notification\n{\n}\n\n- (void)popoverDidClose:(NSNotification *)notification\n{\n\t[self clearPassword];\n\t[_passwordField abortEditing];\n}\n\n- (void)newPoolDetected:(const zfs::ZPool &)pool\n{\n\tif ([[NSUserDefaults standardUserDefaults] boolForKey:@\"autoUnlock\"])\n\t{\n\t\tfor (auto & fs : pool.allFileSystems())\n\t\t{\n\t\t\tauto [encRoot, isRoot] = fs.encryptionRoot();\n\t\t\tauto keyStatus = fs.keyStatus();\n\t\t\tif (isRoot && keyStatus == zfs::ZFileSystem::KeyStatus::unavailable)\n\t\t\t{\n\t\t\t\tNSString * fsName = [NSString stringWithUTF8String:fs.name()];\n\t\t\t\t[self unlockFileSystem:fsName];\n\t\t\t}\n\t\t}\n\t}\n}\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaMainMenu.h",
    "content": "//\n//  ZetaMainMenu.h\n//  ZetaWatch\n//\n//  Created by Gerhard Röthlin on 2015.12.20.\n//  Copyright © 2015 the-color-black.net. All rights reserved.\n//\n//  Redistribution and use in source and binary forms, with or without modification, are permitted\n//  provided that the conditions of the \"3-Clause BSD\" license described in the BSD.LICENSE file are met.\n//  Additional licensing options are described in the README file.\n//\n\n#import <Cocoa/Cocoa.h>\n\n#import \"ZetaPoolWatcher.h\"\n#import \"ZetaCommanderBase.h\"\n#import \"ZetaPoolWatcher.h\"\n#import \"ZetaAutoImporter.h\"\n#import \"ZetaKeyLoader.h\"\n#import \"ZetaQueryDialog.h\"\n#import \"ZetaDictQueryDialog.h\"\n#import \"ZetaConfirmDialog.h\"\n\n@class ZetaNotificationCenter;\n\nenum ZetaMenuTags\n{\n\tZPoolAnchorMenuTag = 100,\n\tActionAnchorMenuTag = 101\n};\n\n@interface ZetaMainMenu : ZetaCommanderBase <NSMenuDelegate>\n\n@property (weak) IBOutlet ZetaPoolWatcher * poolWatcher;\n@property (weak) IBOutlet ZetaKeyLoader * zetaKeyLoader;\n@property (weak) IBOutlet ZetaQueryDialog * zetaQueryDialog;\n@property (weak) IBOutlet ZetaDictQueryDialog * zetaNewFSDialog;\n@property (weak) IBOutlet ZetaDictQueryDialog * zetaNewVolDialog;\n@property (weak) IBOutlet ZetaConfirmDialog * zetaConfirmDialog;\n@property (weak) IBOutlet ZetaNotificationCenter * notificationCenter;\n\n- (IBAction)exportPool:(id)sender;\n- (IBAction)exportPoolForce:(id)sender;\n- (IBAction)mountFilesystem:(id)sender;\n- (IBAction)mountFilesystemRecursive:(id)sender;\n- (IBAction)unmountFilesystem:(id)sender;\n- (IBAction)unmountFilesystemRecursive:(id)sender;\n- (IBAction)unmountFilesystemForce:(id)sender;\n- (IBAction)snapshotFilesystem:(id)sender;\n- (IBAction)snapshotFilesystemRecursive:(id)sender;\n- (IBAction)rollbackFilesystem:(id)sender;\n- (IBAction)rollbackFilesystemForce:(id)sender;\n- (IBAction)cloneSnapshot:(id)sender;\n- (IBAction)destroy:(id)sender;\n- (IBAction)destroyRecursive:(id)sender;\n- (IBAction)loadKey:(id)sender;\n- (IBAction)loadAllKeys:(id)sender;\n- (IBAction)unloadKey:(id)sender;\n- (IBAction)unloadAllKeys:(id)sender;\n- (IBAction)scrubPool:(id)sender;\n- (IBAction)scrubStopPool:(id)sender;\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaMainMenu.mm",
    "content": "//\n//  ZetaMainMenu.mm\n//  ZetaWatch\n//\n//  Created by Gerhard Röthlin on 2015.12.20.\n//  Copyright © 2015 the-color-black.net. All rights reserved.\n//\n//  Redistribution and use in source and binary forms, with or without modification, are permitted\n//  provided that the conditions of the \"3-Clause BSD\" license described in the BSD.LICENSE file are met.\n//  Additional licensing options are described in the README file.\n//\n\n#import \"ZetaMainMenu.h\"\n#import \"ZetaImportMenu.h\"\n#import \"ZetaPoolWatcher.h\"\n#import \"ZetaAuthorization.h\"\n#import \"ZetaSnapshotMenu.h\"\n#import \"ZetaBookmarkMenu.h\"\n#import \"ZetaFileSystemPropertyMenu.h\"\n#import \"ZetaPoolPropertyMenu.h\"\n#import \"ZetaNotificationCenter.h\"\n\n#include \"ZFSUtils.hpp\"\n#include \"ZFSStrings.hpp\"\n\n#include \"InvariantDisks/IDDiskArbitrationUtils.hpp\"\n\n#include <type_traits>\n#include <iomanip>\n#include <sstream>\n#include <chrono>\n\n@interface ZetaMainMenu ()\n{\n\tNSMutableArray * _dynamicMenus;\n\tDASessionRef _diskArbitrationSession;\n\tzfs::LibZFSHandle _zfs;\n}\n\n@end\n\n@implementation ZetaMainMenu\n\n- (id)init\n{\n\tif (self = [super init])\n\t{\n\t\t_dynamicMenus = [[NSMutableArray alloc] init];\n\t\t_diskArbitrationSession = DASessionCreate(nullptr);\n\t}\n\treturn self;\n}\n\n- (void)dealloc\n{\n\tCFRelease(_diskArbitrationSession);\n}\n\n- (void)menuNeedsUpdate:(NSMenu*)menu\n{\n\t[self clearDynamicMenu:menu];\n\t[self resetLibZFS];\n\t[self createNotificationMenu:menu];\n\t[self createPoolMenu:menu];\n\t[self createActionMenu:menu];\n}\n\n#pragma mark Formating\n\nNSString * formatErrorStat(zfs::VDevStat stat, bool emoji)\n{\n\tNSString * status = emoji ?\n\t\tzfs::emojistring_vdev_state_t(stat.state, stat.aux) :\n\t\tzfs::localized_describe_vdev_state_t(stat.state, stat.aux);\n\tNSString * errors = nil;\n\tif (stat.errorRead == 0 && stat.errorWrite == 0 && stat.errorChecksum == 0)\n\t{\n\t\terrors = NSLocalizedString(@\"No Errors\", @\"Format vdev_stat_t\");\n\t}\n\telse\n\t{\n\t\tNSString * format = NSLocalizedString(@\"%llu Read Errors, %llu Write Errors, %llu Checksum Errors\", @\"Format vdev_stat_t\");\n\t\terrors = [NSString stringWithFormat:format, stat.errorRead, stat.errorWrite, stat.errorChecksum];\n\t}\n\treturn [NSString stringWithFormat:@\"%@, %@\", status, errors];\n}\n\nstd::chrono::seconds getElapsed(zfs::ScanStat const & scanStat)\n{\n\tauto elapsed = time(0) - scanStat.passStartTime;\n\telapsed -= scanStat.passPausedSeconds;\n\telapsed = (elapsed > 0) ? elapsed : 1;\n\treturn std::chrono::seconds(elapsed);\n}\n\ninline std::string formatTimeRemaining(zfs::ScanStat const & scanStat, std::chrono::seconds const & time)\n{\n\tauto bytesRemaining = scanStat.total - scanStat.issued;\n\tauto issued = scanStat.passIssued;\n\tif (issued == 0)\n\t\tissued = 1;\n\tauto secondsRemaining = bytesRemaining * time.count() / issued;\n\tstd::stringstream ss;\n\tss << std::setfill('0');\n\tss << (secondsRemaining / (60*60*24)) << \" days \"\n\t<< std::setw(2) << ((secondsRemaining / (60*60)) % 24) << \":\"\n\t<< std::setw(2) << ((secondsRemaining / 60) % 60) << \":\"\n\t<< std::setw(2) << (secondsRemaining % 60);\n\treturn ss.str();\n}\n\n#pragma mark ZFS Inspection\n\nNSMenu * createFSMenu(zfs::ZFileSystem && fs, ZetaMainMenu * delegate)\n{\n\tNSMenu * fsMenu = [[NSMenu alloc] init];\n\t[fsMenu setAutoenablesItems:NO];\n\tNSString * fsName = [NSString stringWithUTF8String:fs.name()];\n\tauto addFSCommand = [&](NSString * title, SEL selector)\n\t{\n\t\tauto item = [fsMenu addItemWithTitle:title\n\t\t\t\t\t\t\t\t\t  action:selector keyEquivalent:@\"\"];\n\t\titem.representedObject = fsName;\n\t\titem.target = delegate;\n\t};\n\tif (fs.type() == zfs::ZFileSystem::FSType::filesystem)\n\t{\n\t\tauto [encRoot, isRoot] = fs.encryptionRoot();\n\t\tif (isRoot)\n\t\t{\n\t\t\tif (fs.keyStatus() != zfs::ZFileSystem::KeyStatus::available)\n\t\t\t{\n\t\t\t\taddFSCommand(NSLocalizedString(@\"Load Key...\", @\"Load Key\"), @selector(loadKey:));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\taddFSCommand(NSLocalizedString(@\"Unload Key\", @\"Unload Key\"), @selector(unloadKey:));\n\t\t\t}\n\t\t\t[fsMenu addItem:[NSMenuItem separatorItem]];\n\t\t}\n\t\taddFSCommand(NSLocalizedString(@\"Mount Recursively\", @\"Mount Recursively\"), @selector(mountFilesystemRecursive:));\n\t\tif (!fs.mounted() && fs.mountable())\n\t\t{\n\t\t\taddFSCommand(NSLocalizedString(@\"Mount\", @\"Mount\"), @selector(mountFilesystem:));\n\t\t}\n\t\taddFSCommand(NSLocalizedString(@\"Unmount Recursively\", @\"Unmount Recursively\"), @selector(unmountFilesystemRecursive:));\n\t\tif (fs.mounted())\n\t\t{\n\t\t\taddFSCommand(NSLocalizedString(@\"Unmount\", @\"Unmount\"), @selector(unmountFilesystem:));\n\t\t\taddFSCommand(NSLocalizedString(@\"Unmount (Force)\", @\"Unmount (Force)\"), @selector(unmountFilesystemForce:));\n\t\t}\n\t}\n\t// Snapshots\n\t[fsMenu addItem:[NSMenuItem separatorItem]];\n\taddFSCommand(NSLocalizedString(@\"Snapshot...\", @\"Snapshot\"), @selector(snapshotFilesystem:));\n\taddFSCommand(NSLocalizedString(@\"Snapshot Recursively...\", @\"Snapshot Recursively\"), @selector(snapshotFilesystemRecursive:));\n\t{\n\t\t// Snapshots submenu\n\t\tNSString * snapsTitle = NSLocalizedString(@\"Snapshots\", @\"Snapshots\");\n\t\tNSMenu * snaps = [[NSMenu alloc] initWithTitle:snapsTitle];\n\t\tZetaSnapshotMenu * sd = [[ZetaSnapshotMenu alloc] initWithFileSystem:zfs::ZFileSystem(fs) delegate:delegate];\n\t\tsnaps.delegate = sd;\n\t\tNSMenuItem * snapsItem = [[NSMenuItem alloc] initWithTitle:snapsTitle\n\t\t\taction:nullptr keyEquivalent:@\"\"];\n\t\tsnapsItem.submenu = snaps;\n\t\tsnapsItem.representedObject = sd;\n\t\t[fsMenu addItem:snapsItem];\n\t}\n\t{\n\t\t// Bookmarks Submenu\n\t\tNSString * bookmarksTitle = NSLocalizedString(@\"Bookmarks\", @\"Bookmarks\");\n\t\tNSMenu * bookmarks = [[NSMenu alloc] initWithTitle:bookmarksTitle];\n\t\tZetaBookmarkMenu * bd = [[ZetaBookmarkMenu alloc] initWithFileSystem:zfs::ZFileSystem(fs) delegate:delegate];\n\t\tbookmarks.delegate = bd;\n\t\tNSMenuItem * bookmarksItem = [[NSMenuItem alloc] initWithTitle:bookmarksTitle\n\t\t\taction:nullptr keyEquivalent:@\"\"];\n\t\tbookmarksItem.submenu = bookmarks;\n\t\tbookmarksItem.representedObject = bd;\n\t\t[fsMenu addItem:bookmarksItem];\n\t}\n\t// Create\n\t[fsMenu addItem:[NSMenuItem separatorItem]];\n\taddFSCommand(NSLocalizedString(@\"Create Filesystem...\", @\"Create Filesystem...\"),\n\t\t@selector(createFilesystem:));\n\taddFSCommand(NSLocalizedString(@\"Create Volume...\", @\"Create Volume...\"),\n\t\t@selector(createVolume:));\n\t// Destroy\n\t[fsMenu addItem:[NSMenuItem separatorItem]];\n\tif (!fs.isRoot())\n\t{\n\t\taddFSCommand(NSLocalizedString(@\"Destroy\", @\"Destroy\"), @selector(destroy:));\n\t}\n\taddFSCommand(NSLocalizedString(@\"Destroy Recursively\", @\"Destroy Recursively\"), @selector(destroyRecursive:));\n\t// Selected Properties\n\t[fsMenu addItem:[NSMenuItem separatorItem]];\n\taddMenuItem(fsMenu, delegate,\n\t\t\t\tNSLocalizedString(@\"Available:          \\t %s\", @\"FS Available Menu Entry\"),\n\t\t\t\tformatBytes(fs.available()));\n\taddMenuItem(fsMenu, delegate,\n\t\t\t\tNSLocalizedString(@\"Used:               \\t %s\", @\"FS Used Menu Entry\"),\n\t\t\t\tformatBytes(fs.used()));\n\taddMenuItem(fsMenu, delegate,\n\t\t\t\tNSLocalizedString(@\"Referenced:         \\t %s\", @\"FS Referenced Menu Entry\"),\n\t\t\t\tformatBytes(fs.referenced()));\n\taddMenuItem(fsMenu, delegate,\n\t\t\t\tNSLocalizedString(@\"Logical Used:       \\t %s\", @\"FS Logically Used Menu Entry\"),\n\t\t\t\tformatBytes(fs.logicalused()));\n\taddMenuItem(fsMenu, delegate,\n\t\t\t\tNSLocalizedString(@\"Compression Ratio:  \\t %1.2fx\", @\"FS Compression Menu Entry\"),\n\t\t\t\tfs.compressRatio());\n\taddMenuItem(fsMenu, delegate,\n\t\t\t\tNSLocalizedString(@\"Mount Point:        \\t %s\", @\"FS Mountpoint Menu Entry\"),\n\t\t\t\tfs.mountpoint());\n\t// All Properties\n\tNSString * allPropsTitle = NSLocalizedString(@\"All Properties\", @\"All Properties\");\n\tNSMenu * allProps = [[NSMenu alloc] initWithTitle:allPropsTitle];\n\tZetaFileSystemPropertyMenu * pd = [[ZetaFileSystemPropertyMenu alloc] initWithFileSystem:std::move(fs)];\n\tallProps.delegate = pd;\n\tNSMenuItem * allPropsItem = [[NSMenuItem alloc] initWithTitle:allPropsTitle\n\t\taction:nullptr keyEquivalent:@\"\"];\n\tallPropsItem.submenu = allProps;\n\tallPropsItem.representedObject = pd;\n\t[fsMenu addItem:allPropsItem];\n\treturn fsMenu;\n}\n\nNSString * formatStatus(zfs::ZFileSystem const & fs)\n{\n\tNSString * mountStatus = fs.mounted() ?\n\t\tNSLocalizedString(@\"📌\", @\"mounted status\") :\n\t\tNSLocalizedString(@\"🕳\", @\"unmounted status\");\n\tNSString * encStatus = nil;\n\tswitch (fs.keyStatus())\n\t{\n\t\tcase zfs::ZFileSystem::KeyStatus::none:\n\t\t\tencStatus = @\"\";\n\t\t\tbreak;\n\t\tcase zfs::ZFileSystem::KeyStatus::unavailable:\n\t\t\tencStatus = NSLocalizedString(@\"🔒\", @\"locked status\");\n\t\t\tbreak;\n\t\tcase zfs::ZFileSystem::KeyStatus::available:\n\t\t\tencStatus = NSLocalizedString(@\"🔑\", @\"unlocked status\");\n\t\t\tbreak;\n\t}\n\tauto [encRoot, isRoot] = fs.encryptionRoot();\n\tNSString * encRootStr = isRoot ? @\"🎁\" : @\"\";\n\tNSString * fsLine = [NSString stringWithFormat:NSLocalizedString(@\"%s (%@%@%@)\", @\"File System Menu Entry\"), fs.name(), mountStatus, encStatus, encRootStr];\n\treturn fsLine;\n}\n\nNSMenuItem * addVdev(zfs::ZPool const & pool, zfs::NVList const & device,\n\tNSMenu * menu, DASessionRef daSession, ZetaMainMenu * delegate)\n{\n\t// Menu Item\n\tauto stat = zfs::vdevStat(device);\n\tauto item = addMenuItem(menu, delegate, NSLocalizedString(@\"%s (%@)\", @\"Device Menu Entry\"),\n\t\t\t\t\t\t\tpool.vdevName(device), formatErrorStat(stat, true));\n\t// Submenu\n\t// ZFS Info\n\tNSMenu * subMenu = [[NSMenu alloc] init];\n\taddMenuItem(subMenu, delegate, formatErrorStat(stat, false));\n\taddMenuItem(subMenu, delegate,\n\t\t\t\tNSLocalizedString(@\"Space:          \\t %s used / %s total\", @\"VDev Space Menu Entry\"),\n\t\t\t\tformatBytes(stat.alloc), formatBytes(stat.space));\n\taddMenuItem(subMenu, delegate,\n\t\t\t\tNSLocalizedString(@\"Fragmentation:  \\t %llu%%\", @\"VDev Fragmentation Menu Entry\"),\n\t\t\t\tstat.fragmentation);\n\taddMenuItem(subMenu, delegate,\n\t\t\t\tNSLocalizedString(@\"VDev GUID:      \\t %llu\", @\"VDev GUID Menu Entry\"),\n\t\t\t\tzfs::vdevGUID(device));\n\tstd::string type = zfs::vdevType(device);\n\taddMenuItem(subMenu, delegate,\n\t\t\t\tNSLocalizedString(@\"Device:         \\t %s (%s)\", @\"VDev Device Menu Entry\"),\n\t\t\t\tpool.vdevDevice(device), type);\n\t// Disk Info, only if state is at least 5 or higher, (FAULTED, DEGRADED, HEALTHY)\n\tif (type == \"disk\" && stat.state >= 5)\n\t{\n\t\t[subMenu addItem:[NSMenuItem separatorItem]];\n\t\tauto devicePath = pool.vdevDevice(device);\n\t\tDADiskRef daDisk = DADiskCreateFromBSDName(nullptr, daSession, devicePath.c_str());\n\t\tauto diskInfo = ID::getDiskInformation(daDisk);\n\t\taddMenuItem(subMenu, delegate,\n\t\t\t\t\tNSLocalizedString(@\"UUID:           \\t %s\", @\"VDev MediaUUID Menu Entry\"), diskInfo.mediaUUID);\n\t\taddMenuItem(subMenu, delegate,\n\t\t\t\t\tNSLocalizedString(@\"Model:          \\t %s\", @\"VDev Model Menu Entry\"), trim(diskInfo.deviceModel));\n\t\taddMenuItem(subMenu, delegate,\n\t\t\t\t\tNSLocalizedString(@\"Serial:         \\t %s\", @\"VDev Serial Menu Entry\"), trim(diskInfo.ioSerial));\n\t\tCFRelease(daDisk);\n\t}\n\titem.submenu = subMenu;\n\treturn item;\n}\n\nvoid createScrubMenu(zfs::ZPool & pool, ZetaMainMenu * delegate, NSMenu * vdevMenu)\n{\n\t// Scrub\n\tauto scrub = pool.scanStat();\n\tauto startDate = [NSDate dateWithTimeIntervalSince1970:scrub.scanStartTime];\n\tauto endDate = [NSDate dateWithTimeIntervalSince1970:scrub.scanEndTime];\n\tauto startString = [NSDateFormatter localizedStringFromDate:startDate dateStyle:NSDateFormatterMediumStyle timeStyle:NSDateFormatterMediumStyle];\n\tauto endString = [NSDateFormatter localizedStringFromDate:endDate dateStyle:NSDateFormatterMediumStyle timeStyle:NSDateFormatterMediumStyle];\n\tNSString * scanLine0;\n\tswitch (scrub.state)\n\t{\n\t\tcase zfs::ScanStat::stateNone:\n\t\t{\n\t\t\tscanLine0 = [NSString stringWithFormat:NSLocalizedString(\n\t\t\t\t@\"Never scrubbed\", @\"Scrub None\")];\n\t\t\tbreak;\n\t\t}\n\t\tcase zfs::ScanStat::scanning:\n\t\t{\n\t\t\tscanLine0 = [NSString stringWithFormat:NSLocalizedString(\n\t\t\t\t@\"Scrub started %@ still in progress\", @\"Scrub Scanning\"),\n\t\t\t\tstartString];\n\t\t\tbreak;\n\t\t}\n\t\tcase zfs::ScanStat::finished:\n\t\t{\n\t\t\tscanLine0 = [NSString stringWithFormat:NSLocalizedString(\n\t\t\t\t@\"Scrub started %@ finished successfully at %@\", @\"Scrub Finished\"),\n\t\t\t\tstartString, endString];\n\t\t\tbreak;\n\t\t}\n\t\tcase zfs::ScanStat::canceled:\n\t\t{\n\t\t\tscanLine0 = [NSString stringWithFormat:NSLocalizedString(\n\t\t\t\t@\"Scrub started %@ was canceled at $@\", @\"Scrub Canceled\"),\n\t\t\t\tstartString, endString];\n\t\t\tbreak;\n\t\t}\n\t}\n\tauto scrubItem = [vdevMenu addItemWithTitle:scanLine0 action:nullptr keyEquivalent:@\"\"];\n\tauto scrubMenu = [[NSMenu alloc] init];\n\tscrubItem.submenu = scrubMenu;\n\tNSString * poolName = [NSString stringWithUTF8String:pool.name()];\n\tif (scrub.state == zfs::ScanStat::scanning && scrub.passPauseTime == 0)\n\t{\n\t\tauto item = [scrubMenu addItemWithTitle:\n\t\t\tNSLocalizedString(@\"Stop Scrub\", @\"Stop Scrub\")\n\t\t\taction:@selector(scrubStopPool:) keyEquivalent:@\"\"];\n\t\titem.representedObject = poolName;\n\t\titem.target = delegate;\n\t\titem = [scrubMenu addItemWithTitle:\n\t\t\tNSLocalizedString(@\"Pause Scrub\", @\"Pause Scrub\")\n\t\t\taction:@selector(scrubPausePool:) keyEquivalent:@\"\"];\n\t\titem.representedObject = poolName;\n\t\titem.target = delegate;\n\t}\n\telse\n\t{\n\t\tauto item = [scrubMenu addItemWithTitle:\n\t\t\tNSLocalizedString(@\"Start Scrub\", @\"Start Scrub\")\n\t\t\taction:@selector(scrubPool:) keyEquivalent:@\"\"];\n\t\titem.representedObject = poolName;\n\t\titem.target = delegate;\n\t}\n\tif (scrub.state == zfs::ScanStat::scanning)\n\t{\n\t\t// Scan Stats\n\t\tauto elapsed = getElapsed(scrub);\n\t\tif (scrub.passPauseTime != 0)\n\t\t{\n\t\t\tauto pauseDate = [NSDate dateWithTimeIntervalSince1970:scrub.passPauseTime];\n\t\t\tauto pauseString = [NSDateFormatter localizedStringFromDate:pauseDate dateStyle:NSDateFormatterMediumStyle timeStyle:NSDateFormatterMediumStyle];\n\t\t\tNSString * scanLinePaused = [NSString stringWithFormat:NSLocalizedString(\n\t\t\t\t@\"Scrub Paused at %@\", @\"Scrub Paused\"), pauseString];\n\t\t\tauto m = [vdevMenu addItemWithTitle:scanLinePaused action:nullptr keyEquivalent:@\"\"];\n\t\t\tm.indentationLevel = 1;\n\t\t}\n\t\tNSString * scanLine1 = [NSString stringWithFormat:NSLocalizedString(\n\t\t\t@\"%s scanned at %s, %s issued at %s\", @\"Scrub Menu Entry 1\"),\n\t\t\t\t\t\t\t\tformatBytes(scrub.scanned).c_str(),\n\t\t\t\t\t\t\t\tformatRate(scrub.passScanned, elapsed).c_str(),\n\t\t\t\t\t\t\t\tformatBytes(scrub.issued).c_str(),\n\t\t\t\t\t\t\t\tformatRate(scrub.passIssued, elapsed).c_str()];\n\t\tNSString * scanLine2 = [NSString stringWithFormat:NSLocalizedString(\n\t\t\t@\"%s total, %0.2f %% done, %s remaining, %llu errors\", @\"Scrub Menu Entry 2\"),\n\t\t\t\t\t\t\t\tformatBytes(scrub.total).c_str(),\n\t\t\t\t\t\t\t\t100.0*scrub.issued/scrub.total,\n\t\t\t\t\t\t\t\tformatTimeRemaining(scrub, elapsed).c_str(),\n\t\t\t\t\t\t\t\tscrub.errors];\n\t\tauto m1 = [vdevMenu addItemWithTitle:scanLine1 action:nullptr keyEquivalent:@\"\"];\n\t\tauto m2 = [vdevMenu addItemWithTitle:scanLine2 action:nullptr keyEquivalent:@\"\"];\n\t\tm1.indentationLevel = 1;\n\t\tm2.indentationLevel = 1;\n\t}\n}\n\nNSMenu * createVdevMenu(zfs::ZPool && pool, ZetaMainMenu * delegate, DASessionRef daSession)\n{\n\tNSMenu * vdevMenu = [[NSMenu alloc] init];\n\t[vdevMenu setAutoenablesItems:NO];\n\ttry\n\t{\n\t\tcreateScrubMenu(pool, delegate, vdevMenu);\n\t\t[vdevMenu addItem:[NSMenuItem separatorItem]];\n\t\t// VDevs\n\t\tauto vdevs = pool.vdevs();\n\t\tfor (auto && vdev: vdevs)\n\t\t{\n\t\t\t// VDev\n\t\t\taddVdev(pool, vdev, vdevMenu, daSession, delegate);\n\t\t\t// Children\n\t\t\tauto devices = zfs::vdevChildren(vdev);\n\t\t\tfor (auto && device: devices)\n\t\t\t{\n\t\t\t\tauto item = addVdev(pool, device, vdevMenu, daSession, delegate);\n\t\t\t\t[item setIndentationLevel:1];\n\t\t\t}\n\t\t}\n\t\t// Caches\n\t\tauto caches = pool.caches();\n\t\tif (caches.size() > 0)\n\t\t{\n\t\t\t[vdevMenu addItemWithTitle:@\"cache\" action:nullptr keyEquivalent:@\"\"];\n\t\t\tfor (auto && cache: caches)\n\t\t\t{\n\t\t\t\tauto item = addVdev(pool, cache, vdevMenu, daSession, delegate);\n\t\t\t\t[item setIndentationLevel:1];\n\t\t\t}\n\t\t}\n\t\t// Filesystems\n\t\t[vdevMenu addItem:[NSMenuItem separatorItem]];\n\t\tauto childFileSystems = pool.allFileSystems();\n\t\tif (childFileSystems.empty())\n\t\t{\n\t\t\t// This seems to happen when a pool is UNAVAIL\n\t\t\tNSMenuItem * item = [vdevMenu addItemWithTitle:@\"No Filesystems!\" action:nil keyEquivalent:@\"\"];\n\t\t\t[item setEnabled:NO];\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor (auto & fs : childFileSystems)\n\t\t\t{\n\t\t\t\tauto fsLine = formatStatus(fs);\n\t\t\t\tNSMenuItem * item = [vdevMenu addItemWithTitle:fsLine action:nullptr keyEquivalent:@\"\"];\n\t\t\t\titem.representedObject = [NSString stringWithUTF8String:fs.name()];\n\t\t\t\titem.submenu = createFSMenu(std::move(fs), delegate);\n\t\t\t}\n\t\t}\n\t\t// Command helper\n\t\tNSString * poolName = [NSString stringWithUTF8String:pool.name()];\n\t\tauto addRootFSCommand = [&](NSString * title, SEL selector)\n\t\t{\n\t\t\tauto item = [vdevMenu addItemWithTitle:title\n\t\t\t\taction:selector keyEquivalent:@\"\"];\n\t\t\titem.representedObject = poolName;\n\t\t\titem.target = delegate;\n\t\t};\n\t\t// Mount Recursively\n\t\t[vdevMenu addItem:[NSMenuItem separatorItem]];\n\t\taddRootFSCommand(NSLocalizedString(@\"Mount Recursively\", @\"Mount Recursively\"),\n\t\t\t\t\t\t @selector(mountFilesystemRecursive:));\n\t\taddRootFSCommand(NSLocalizedString(@\"Unmount Recursively\", @\"Unmount Recursively\"),\n\t\t\t\t\t\t @selector(unmountFilesystemRecursive:));\n\t\t// Snapshot\n\t\t[vdevMenu addItem:[NSMenuItem separatorItem]];\n\t\taddRootFSCommand(NSLocalizedString(@\"Snapshot Recursively...\", @\"Snapshot Recursively\"),\n\t\t\t\t\t\t @selector(snapshotFilesystemRecursive:));\n\t\t// Create\n\t\t[vdevMenu addItem:[NSMenuItem separatorItem]];\n\t\taddRootFSCommand(NSLocalizedString(@\"Create Filesystem...\", @\"Create Filesystem...\"),\n\t\t\t\t\t\t @selector(createFilesystem:));\n\t\taddRootFSCommand(NSLocalizedString(@\"Create Volume...\", @\"Create Volume...\"),\n\t\t\t\t\t\t @selector(createVolume:));\n\t\t// Export Actions\n\t\t[vdevMenu addItem:[NSMenuItem separatorItem]];\n\t\taddRootFSCommand(NSLocalizedString(@\"Export\", @\"Export\"),\n\t\t\t\t\t\t @selector(exportPool:));\n\t\taddRootFSCommand(NSLocalizedString(@\"Export (Force)\", @\"Export (Force)\"),\n\t\t\t\t\t\t @selector(exportPoolForce:));\n\t\t// All Properties\n\t\t[vdevMenu addItem:[NSMenuItem separatorItem]];\n\t\tNSMenu * allProps = [[NSMenu alloc] initWithTitle:@\"All Properties\"];\n\t\tZetaPoolPropertyMenu * pd = [[ZetaPoolPropertyMenu alloc] initWithPool:std::move(pool)];\n\t\tallProps.delegate = pd;\n\t\tNSMenuItem * allPropsItem = [[NSMenuItem alloc] initWithTitle:@\"All Properties\" action:nullptr keyEquivalent:@\"\"];\n\t\tallPropsItem.submenu = allProps;\n\t\tallPropsItem.representedObject = pd;\n\t\t[vdevMenu addItem:allPropsItem];\n\t}\n\tcatch (std::exception const & e)\n\t{\n\t\t[vdevMenu addItemWithTitle:NSLocalizedString(@\"Error reading pool configuration\", @\"Pool Config Error Message\")\n\t\t\t\t\t\t\taction:nullptr keyEquivalent:@\"\"];\n\t}\n\treturn vdevMenu;\n}\n\n- (void)createNotificationMenu:(NSMenu*)menu\n{\n\tif ([self.notificationCenter.inProgressActions count] > 0)\n\t{\n\t\tNSUInteger notifIdx = 0;\n\t\tfor (ZetaNotification * notification in self.notificationCenter.inProgressActions)\n\t\t{\n\t\t\tNSMenuItem * notifItem = [[NSMenuItem alloc] initWithTitle:notification.title action:nil keyEquivalent:@\"\"];\n\t\t\t[menu insertItem:notifItem atIndex:0];\n\t\t\t[_dynamicMenus addObject:notifItem];\n\t\t\t++notifIdx;\n\t\t}\n\t\tNSMenuItem * sepItem = [NSMenuItem separatorItem];\n\t\t[menu insertItem:sepItem atIndex:notifIdx];\n\t\t[_dynamicMenus addObject:sepItem];\n\t}\n}\n\n- (void)createPoolMenu:(NSMenu*)menu\n{\n\tNSInteger poolMenuIdx = [menu indexOfItemWithTag:ZPoolAnchorMenuTag];\n\tif (poolMenuIdx < 0)\n\t\treturn;\n\tNSInteger poolItemRootIdx = poolMenuIdx + 1;\n\tNSUInteger poolIdx = 0;\n\ttry\n\t{\n\t\tfor (auto && pool: _zfs.pools())\n\t\t{\n\t\t\tNSString * poolLine = [NSString stringWithFormat:NSLocalizedString(@\"%s (%@)\", @\"Pool Menu Entry\"),\n\t\t\t\t\t\t\t\t   pool.name(), zfs::emojistring_pool_status_t(pool.status())];\n\t\t\tNSMenuItem * poolItem = [[NSMenuItem alloc] initWithTitle:poolLine action:NULL keyEquivalent:@\"\"];\n\t\t\tNSMenu * vdevMenu = createVdevMenu(std::move(pool), self, _diskArbitrationSession);\n\t\t\t[poolItem setSubmenu:vdevMenu];\n\t\t\t[menu insertItem:poolItem atIndex:poolItemRootIdx + poolIdx];\n\t\t\t[_dynamicMenus addObject:poolItem];\n\t\t\t++poolIdx;\n\t\t}\n\t}\n\tcatch (std::exception const & e)\n\t{\n\t\tNSString * error = [NSString stringWithFormat:@\"Exception during pool iteration: %s\", e.what()];\n\t\tNSMenuItem * errorItem = [[NSMenuItem alloc] initWithTitle:error action:nullptr keyEquivalent:@\"\"];\n\t\t[menu insertItem:errorItem atIndex:poolItemRootIdx];\n\t\t[_dynamicMenus addObject:errorItem];\n\t}\n}\n\n- (void)createActionMenu:(NSMenu*)menu\n{\n\tNSInteger actionMenuIdx = [menu indexOfItemWithTag:ActionAnchorMenuTag];\n\tif (actionMenuIdx < 0)\n\t\treturn;\n\t// Unlock\n\tNSMenuItem * unlockItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@\"Load Keys...\", @\"Load Key Menu Entry\") action:NULL keyEquivalent:@\"\"];\n\tNSMenu * unlockMenu = [[NSMenu alloc] init];\n\t[unlockItem setSubmenu:unlockMenu];\n\tNSMutableArray<NSString*> * lockedEncryptionRoots = [NSMutableArray array];\n\tNSMenuItem * unlockAllItem = [unlockMenu addItemWithTitle:NSLocalizedString(@\"Load All Keys...\", @\"Load All Menu Entry\") action:@selector(loadAllKeys:) keyEquivalent:@\"\"];\n\tunlockAllItem.target = self;\n\tunlockAllItem.representedObject = lockedEncryptionRoots;\n\t[unlockMenu addItem:[NSMenuItem separatorItem]];\n\t// Lock\n\tNSMenuItem * lockItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@\"Unload Keys\", @\"Unload Key Menu Entry\") action:NULL keyEquivalent:@\"\"];\n\tNSMenu * lockMenu = [[NSMenu alloc] init];\n\t[lockItem setSubmenu:lockMenu];\n\tNSMutableArray<NSString*> * unlockedEncryptionRoots = [NSMutableArray array];\n\tNSMenuItem * lockAllItem = [lockMenu addItemWithTitle:NSLocalizedString(@\"Unload All Keys\", @\"Unload All Menu Entry\") action:@selector(unloadAllKeys:) keyEquivalent:@\"\"];\n\tlockAllItem.target = self;\n\tlockAllItem.representedObject = unlockedEncryptionRoots;\n\t[lockMenu addItem:[NSMenuItem separatorItem]];\n\t// Individual entries\n\ttry\n\t{\n\t\tfor (auto && pool: _zfs.pools())\n\t\t{\n\t\t\tfor (auto & fs : pool.allFileSystems())\n\t\t\t{\n\t\t\t\tauto [encRoot, isRoot] = fs.encryptionRoot();\n\t\t\t\tauto keyStatus = fs.keyStatus();\n\t\t\t\tif (isRoot)\n\t\t\t\t{\n\t\t\t\t\tNSString * fsName = [NSString stringWithUTF8String:fs.name()];\n\t\t\t\t\tif (keyStatus == zfs::ZFileSystem::KeyStatus::unavailable)\n\t\t\t\t\t{\n\t\t\t\t\t\tNSMenuItem * item = [unlockMenu addItemWithTitle:fsName\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  action:@selector(loadKey:) keyEquivalent:@\"\"];\n\t\t\t\t\t\titem.representedObject = fsName;\n\t\t\t\t\t\titem.target = self;\n\t\t\t\t\t\t[lockedEncryptionRoots addObject:fsName];\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tNSMenuItem * item = [lockMenu addItemWithTitle:fsName\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\taction:@selector(unloadKey:) keyEquivalent:@\"\"];\n\t\t\t\t\t\titem.representedObject = fsName;\n\t\t\t\t\t\titem.target = self;\n\t\t\t\t\t\t[unlockedEncryptionRoots addObject:fsName];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif ([unlockedEncryptionRoots count] > 0)\n\t\t{\n\t\t\t[menu insertItem:lockItem atIndex:actionMenuIdx + 1];\n\t\t\t[_dynamicMenus addObject:lockItem];\n\t\t}\n\t\tif ([lockedEncryptionRoots count] > 0)\n\t\t{\n\t\t\t[menu insertItem:unlockItem atIndex:actionMenuIdx + 1];\n\t\t\t[_dynamicMenus addObject:unlockItem];\n\t\t}\n\t}\n\tcatch (std::exception const & e)\n\t{\n\t\tNSString * error = [NSString stringWithFormat:@\"Exception during pool iteration: %s\", e.what()];\n\t\tNSMenuItem * errorItem = [[NSMenuItem alloc] initWithTitle:error action:nullptr keyEquivalent:@\"\"];\n\t\t[menu insertItem:errorItem atIndex:actionMenuIdx + 1];\n\t\t[_dynamicMenus addObject:lockItem];\n\t}\n}\n\n- (void)resetLibZFS\n{\n\t// Reset library to get fresh property state. This seems to be essential\n\t// for getting up-to-date altroot of pools that have been imported after\n\t// being known to the previous libzfs state. Calling zfs_refresh_properties\n\t// is insufficient for refreshing this state.\n\t// This also invalidates all filesystem and pool handles that still exist.\n\t_zfs.reset();\n}\n\n- (void)clearDynamicMenu:(NSMenu*)menu\n{\n\tfor (NSMenuItem * m in _dynamicMenus)\n\t{\n\t\t[menu removeItem:m];\n\t}\n\t[_dynamicMenus removeAllObjects];\n}\n\n- (void)handlePoolChangeReply:(NSError*)error\n{\n\tif (error)\n\t\t[self notifyErrorFromHelper:error];\n\telse\n\t\t[[self poolWatcher] checkForChanges];\n}\n\n- (void)handleFileSystemChangeReply:(NSError*)error\n{\n\tif (error)\n\t\t[self notifyErrorFromHelper:error];\n}\n\n- (void)handleMetaDataChangeReply:(NSError*)error\n{\n\tif (error)\n\t\t[self notifyErrorFromHelper:error];\n}\n\n#pragma mark ZFS Maintenance\n\n- (IBAction)exportPool:(id)sender\n{\n\tNSDictionary * opts = @{@\"pool\": [sender representedObject]};\n\t[_authorization exportPools:opts withReply:^(NSError * error)\n\t {\n\t\t if (!error)\n\t\t {\n\t\t\t NSString * title = NSLocalizedString(@\"Export succeeded\",\n\t\t\t\t\t\t\t\t\t\t\t\t  @\"Export succeeded\");\n\t\t\t NSString * text = [NSString stringWithFormat:\n\t\t\t\tNSLocalizedString(@\"%@ exported\",\n\t\t\t\t\t\t\t\t  @\"Export Success format\"),\n\t\t\t\t[sender representedObject]];\n\t\t\t [self notifySuccessWithTitle:title text:text];\n\t\t }\n\t\t [self handlePoolChangeReply:error];\n\t }];\n}\n\n- (IBAction)exportPoolForce:(id)sender\n{\n\tNSDictionary * opts = @{@\"pool\": [sender representedObject], @\"force\": @YES};\n\t[_authorization exportPools:opts withReply:^(NSError * error)\n\t {\n\t\t if (!error)\n\t\t {\n\t\t\t NSString * title = NSLocalizedString(@\"Forced export succeeded\",\n\t\t\t\t\t\t\t\t\t\t\t\t  @\"Forced export succeeded\");\n\t\t\t NSString * text = [NSString stringWithFormat:\n\t\t\t\tNSLocalizedString(@\"%@ force-exported\",\n\t\t\t\t\t\t\t\t  @\"Force-Export Successful format\"),\n\t\t\t\t[sender representedObject]];\n\t\t\t [self notifySuccessWithTitle:title text:text];\n\t\t }\n\t\t [self handlePoolChangeReply:error];\n\t }];\n}\n\n- (IBAction)mountFilesystem:(id)sender\n{\n\tNSDictionary * opts = @{@\"filesystem\": [sender representedObject]};\n\t[_authorization mountFilesystems:opts withReply:^(NSError * error)\n\t {\n\t\t if (!error)\n\t\t {\n\t\t\t NSString * title = NSLocalizedString(@\"Mount succeeded\",\n\t\t\t\t\t\t\t\t\t\t\t\t  @\"Mount succeeded\");\n\t\t\t NSString * text = [NSString stringWithFormat:\n\t\t\t\tNSLocalizedString(@\"%@ mounted\", @\"Mount Successful format\"),\n\t\t\t\t[sender representedObject]];\n\t\t\t [self notifySuccessWithTitle:title text:text];\n\t\t }\n\t\t [self handleFileSystemChangeReply:error];\n\t }];\n}\n\n- (IBAction)mountFilesystemRecursive:(id)sender\n{\n\tNSDictionary * opts = @{@\"filesystem\": [sender representedObject], @\"recursive\": @TRUE};\n\t[_authorization mountFilesystems:opts withReply:^(NSError * error)\n\t {\n\t\t if (!error)\n\t\t {\n\t\t\t NSString * title = NSLocalizedString(@\"Recursive mount succeeded\",\n\t\t\t\t\t\t\t\t\t\t\t\t  @\"Recursive mount succeeded\");\n\t\t\t NSString * text = [NSString stringWithFormat:\n\t\t\t\tNSLocalizedString(@\"%@ mounted recursively\",\n\t\t\t\t\t\t\t\t  @\"Recursive Mount Success format\"),\n\t\t\t\t[sender representedObject]];\n\t\t\t [self notifySuccessWithTitle:title text:text];\n\t\t }\n\t\t [self handleFileSystemChangeReply:error];\n\t }];\n}\n\n- (IBAction)unmountFilesystem:(id)sender\n{\n\tNSDictionary * opts = @{@\"filesystem\": [sender representedObject]};\n\t[_authorization unmountFilesystems:opts withReply:^(NSError * error)\n\t {\n\t\t if (!error)\n\t\t {\n\t\t\t NSString * title = NSLocalizedString(@\"Unmount succeeded\",\n\t\t\t\t\t\t\t\t\t\t\t\t  @\"Unmount succeeded\");\n\t\t\t NSString * text = [NSString stringWithFormat:\n\t\t\t\tNSLocalizedString(@\"%@ unmounted\",\n\t\t\t\t\t\t\t\t  @\"FS Unmount Successful format\"),\n\t\t\t\t[sender representedObject]];\n\t\t\t [self notifySuccessWithTitle:title text:text];\n\t\t }\n\t\t [self handleFileSystemChangeReply:error];\n\t }];\n}\n\n- (IBAction)unmountFilesystemRecursive:(id)sender\n{\n\tNSDictionary * opts = @{@\"filesystem\": [sender representedObject], @\"recursive\": @TRUE};\n\t[_authorization unmountFilesystems:opts withReply:^(NSError * error)\n\t {\n\t\t if (!error)\n\t\t {\n\t\t\t NSString * title = NSLocalizedString(@\"Recursive unmount succeeded\",\n\t\t\t\t\t\t\t\t\t\t\t\t  @\"Recursive unmount succeeded\");\n\t\t\t NSString * text = [NSString stringWithFormat:\n\t\t\t\tNSLocalizedString(@\"%@ unmounted recursively\",\n\t\t\t\t\t\t\t\t  @\"Recursive Unmount Success format\"),\n\t\t\t\t[sender representedObject]];\n\t\t\t [self notifySuccessWithTitle:title text:text];\n\t\t }\n\t\t [self handleFileSystemChangeReply:error];\n\t }];\n}\n\n- (IBAction)unmountFilesystemForce:(id)sender\n{\n\tNSDictionary * opts = @{@\"filesystem\": [sender representedObject], @\"force\": @YES};\n\t[_authorization unmountFilesystems:opts withReply:^(NSError * error)\n\t {\n\t\t if (!error)\n\t\t {\n\t\t\t NSString * title = NSLocalizedString(@\"Filesystem unmount (forced) succeeded\",\n\t\t\t\t\t\t\t\t\t\t\t\t  @\"Filesystem unmount (forced) succeeded\");\n\t\t\t NSString * text = [NSString stringWithFormat:\n\t\t\t\tNSLocalizedString(@\"%@ force-unmounted\",\n\t\t\t\t\t\t\t\t  @\"FS ForceUnmount Success format\"),\n\t\t\t\t[sender representedObject]];\n\t\t\t [self notifySuccessWithTitle:title text:text];\n\t\t }\n\t\t [self handleFileSystemChangeReply:error];\n\t }];\n}\n\nstatic NSString * defaultSnapshotName()\n{\n\tauto now = [NSDate date];\n\tauto formater = [[NSDateFormatter alloc] init];\n\tformater.dateFormat = @\"'ZetaSnap'-yyyy-MM-dd-HH-mm-ss\";\n\tauto nowString = [formater stringFromDate:now];\n\treturn nowString;\n}\n\n- (IBAction)snapshotFilesystem:(id)sender\n{\n\tNSString * filesystem = [sender representedObject];\n\t[_zetaQueryDialog addQuery:NSLocalizedString(@\"Enter snapshot name\", @\"Snapshot Query\")\n\t\t\t\t   withDefault:defaultSnapshotName()\n\t\t\t\t  withCallback:^(NSString * snapshot)\n\t {\n\t\t NSDictionary * opts = @{@\"filesystem\": filesystem, @\"snapshot\": snapshot};\n\t\t [self->_authorization snapshotFilesystem:opts withReply:^(NSError * error)\n\t\t  {\n\t\t\t  if (!error)\n\t\t\t  {\n\t\t\t\t  NSString * title = NSLocalizedString(@\"Snapshot succeeded\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t   @\"Snapshot succeeded\");\n\t\t\t\t  NSString * text = [NSString stringWithFormat:\n\t\t\t\t\tNSLocalizedString(@\"%@@%@ created\",\n\t\t\t\t\t\t\t\t\t  @\"Snapshot Success format\"),\n\t\t\t\t\t\t\t\t\t  filesystem, snapshot];\n\t\t\t\t  [self notifySuccessWithTitle:title text:text];\n\t\t\t  }\n\t\t\t  [self handleFileSystemChangeReply:error];\n\t\t  }];\n\t }];\n}\n\n- (IBAction)snapshotFilesystemRecursive:(id)sender\n{\n\tNSString * filesystem = [sender representedObject];\n\t[_zetaQueryDialog addQuery:NSLocalizedString(@\"Enter snapshot name\", @\"Snapshot Query\")\n\t\t\t\t   withDefault:defaultSnapshotName()\n\t\t\t\t  withCallback:^(NSString * snapshot)\n\t {\n\t\t NSDictionary * opts = @{@\"filesystem\": filesystem, @\"snapshot\": snapshot, @\"recursive\": @YES};\n\t\t [self->_authorization snapshotFilesystem:opts withReply:^(NSError * error)\n\t\t  {\n\t\t\t  if (!error)\n\t\t\t  {\n\t\t\t\t  NSString * title = NSLocalizedString(@\"Recursive snapshot succeeded\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t   @\"Recursive snapshot succeeded\");\n\t\t\t\t  NSString * text = [NSString stringWithFormat:\n\t\t\t\t\tNSLocalizedString(@\"%@@%@ created recursively\",\n\t\t\t\t\t\t\t\t\t  @\"RecursiveSnapshot Success format\"),\n\t\t\t\t\tfilesystem, snapshot];\n\t\t\t\t  [self notifySuccessWithTitle:title text:text];\n\t\t\t  }\n\t\t\t  [self handleFileSystemChangeReply:error];\n\t\t  }];\n\t }];\n}\n\nstatic NSMutableString * appendAsString(NSMutableString * fileSystemString, std::vector<zfs::ZFileSystem> const & fileSystems)\n{\n\tfor (auto const & d : fileSystems)\n\t\t[fileSystemString appendFormat:@\"%s\\n\", d.name()];\n\treturn fileSystemString;\n}\n\nstatic NSMutableString * toString(std::vector<zfs::ZFileSystem> const & fileSystems)\n{\n\tNSMutableString * fileSystemString = [NSMutableString string];\n\treturn appendAsString(fileSystemString, fileSystems);\n}\n\nstatic NSString * formatRollbackDependents(\n\tstd::vector<zfs::ZFileSystem> const & clones,\n\tstd::vector<zfs::ZFileSystem> const & snap,\n\tstd::vector<zfs::ZFileSystem> const & bookmarks)\n{\n\tNSMutableString * depString = [NSMutableString string];\n\tif (!clones.empty())\n\t{\n\t\t[depString appendString:@\"# Clones\\n\"];\n\t\tappendAsString(depString, clones);\n\t}\n\tif (!snap.empty())\n\t{\n\t\t[depString appendString:@\"# Snapshots\\n\"];\n\t\tappendAsString(depString, snap);\n\t}\n\tif (!bookmarks.empty())\n\t{\n\t\t[depString appendString:@\"# Bookmarks\\n\"];\n\t\tappendAsString(depString, bookmarks);\n\t}\n\treturn depString;\n}\n\n- (IBAction)rollbackFilesystem:(NSString*)snapNameStr Force:(bool)force\n{\n\tstd::string snapName([snapNameStr UTF8String]);\n\tstd::string baseName = snapName.substr(0, snapName.find_last_of('@'));\n\tzfs::LibZFSHandle lib;\n\tauto snap = lib.filesystem(snapName);\n\tauto fs = lib.filesystem(baseName);\n\tstd::vector<zfs::ZFileSystem> clones;\n\tauto snapshots = fs.snapshotsSince(snap);\n\tfor (auto && snap : snapshots)\n\t{\n\t\tif (snap.cloneCount() > 0)\n\t\t{\n\t\t\tauto dep = snap.dependents();\n\t\t\tstd::move(dep.begin(), dep.end(),\n\t\t\t\t\t  std::back_inserter(clones));\n\t\t}\n\t}\n\tauto bookmarks = fs.bookmarksSince(snap);\n\n\tauto rollBackBlock = ^(bool ok)\n\t{\n\t\tif (ok)\n\t\t{\n\t\t\tNSDictionary * opts = @{\n\t\t\t\t@\"snapshot\": snapNameStr,\n\t\t\t\t@\"force\": [NSNumber numberWithBool:force]\n\t\t\t};\n\t\t\t[self->_authorization rollbackFilesystem:opts withReply:^(NSError * error)\n\t\t\t {\n\t\t\t\t if (!error)\n\t\t\t\t {\n\t\t\t\t\t NSString * title = NSLocalizedString(@\"Rollback succeeded\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  @\"Rollback succeeded\");\n\t\t\t\t\t NSString * text = [NSString stringWithFormat:\n\t\t\t\t\t\tNSLocalizedString(@\"%@ rolled back\",\n\t\t\t\t\t\t\t\t\t\t  @\"Rollback Success format\"),\n\t\t\t\t\t\t\t\t\t\t snapNameStr];\n\t\t\t\t\t [self notifySuccessWithTitle:title text:text];\n\t\t\t\t }\n\t\t\t\t [self handleFileSystemChangeReply:error];\n\t\t\t }];\n\t\t}\n\t};\n\tif (!snapshots.empty() || !clones.empty() || !bookmarks.empty())\n\t{\n\t\t[_zetaConfirmDialog addQuery:NSLocalizedString(@\"The following will be destroyed by the rollback\", @\"Rollback Snapshot Query\")\n\t\t\t\t\t withInformation:formatRollbackDependents(clones, snapshots, bookmarks)\n\t\t\t\t\t\twithCallback:rollBackBlock];\n\t}\n\telse\n\t{\n\t\trollBackBlock(true);\n\t}\n}\n\n- (IBAction)rollbackFilesystem:(id)sender\n{\n\t[self rollbackFilesystem:[sender representedObject] Force:false];\n}\n\n- (IBAction)rollbackFilesystemForce:(id)sender\n{\n\t[self rollbackFilesystem:[sender representedObject] Force:true];\n}\n\n- (IBAction)cloneSnapshot:(id)sender\n{\n\tNSString * snapshot = [sender representedObject];\n\tNSString * newFileSystem = [snapshot stringByReplacingOccurrencesOfString:@\"@\" withString:@\"-\"];\n\t[_zetaQueryDialog addQuery:NSLocalizedString(@\"Enter new filesystem name\", @\"Clone Query\")\n\t\t\t\t   withDefault:newFileSystem\n\t\t\t\t  withCallback:^(NSString * newFileSystem)\n\t {\n\t\t NSDictionary * opts = @{@\"snapshot\": snapshot, @\"newFilesystem\": newFileSystem};\n\t\t [self->_authorization cloneSnapshot:opts withReply:^(NSError * error)\n\t\t  {\n\t\t\t  if (!error)\n\t\t\t  {\n\t\t\t\t  NSString * title = NSLocalizedString(@\"Clone succeeded\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t   @\"Clone succeeded\");\n\t\t\t\t  NSString * text = [NSString stringWithFormat:\n\t\t\t\t\tNSLocalizedString(@\"%@ cloned to %@\",\n\t\t\t\t\t\t\t\t\t  @\"Clone Success format\"),\n\t\t\t\t\tsnapshot, newFileSystem];\n\t\t\t\t  [self notifySuccessWithTitle:title text:text];\n\t\t\t  }\n\t\t\t  [self handleFileSystemChangeReply:error];\n\t\t  }];\n\t }];\n}\n\n- (IBAction)createFilesystem:(id)sender\n{\n\tNSString * parentFilesyStem = [sender representedObject];\n\tNSMutableDictionary * query = [NSMutableDictionary dictionary];\n\tquery[@\"filesystem\"] = [NSString stringWithFormat:@\"%@/NewFilesystem\", parentFilesyStem];\n\t[_zetaNewFSDialog addQuery:query\n\t\t\t\t  withCallback:^(NSDictionary * opts)\n\t {\n\t\t [self->_authorization createFilesystem:opts withReply:^(NSError * error)\n\t\t  {\n\t\t\t  if (!error)\n\t\t\t  {\n\t\t\t\t  NSString * title = NSLocalizedString(@\"Filesystem creation succeeded\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t   @\"Filesystem creation succeeded\");\n\t\t\t\t  NSString * text = [NSString stringWithFormat:\n\t\t\t\t\tNSLocalizedString(@\"Filesystem %@ created\",\n\t\t\t\t\t\t\t\t\t  @\"FS Create Success format\"),\n\t\t\t\t\topts[@\"filesystem\"]];\n\t\t\t\t  [self notifySuccessWithTitle:title text:text];\n\t\t\t  }\n\t\t\t  [self handleFileSystemChangeReply:error];\n\t\t  }];\n\t }];\n}\n\n- (IBAction)createVolume:(id)sender\n{\n\tNSString * parentFilesyStem = [sender representedObject];\n\tNSMutableDictionary * query = [NSMutableDictionary dictionary];\n\tquery[@\"filesystem\"] = [NSString stringWithFormat:@\"%@/NewVolume\", parentFilesyStem];\n\tquery[@\"size\"] = [NSNumber numberWithUnsignedLongLong:(1 << 30)];\n\t[_zetaNewVolDialog addQuery:query\n\t\t\t\t   withCallback:^(NSDictionary * opts)\n\t {\n\t\t [self->_authorization createVolume:opts withReply:^(NSError * error)\n\t\t  {\n\t\t\t  if (!error)\n\t\t\t  {\n\t\t\t\t  NSString * title = NSLocalizedString(@\"Volume creation succeeded\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t   @\"Volume creation succeeded\");\n\t\t\t\t  NSString * text = [NSString stringWithFormat:\n\t\t\t\t\tNSLocalizedString(@\"Volume %@ created\",\n\t\t\t\t\t\t\t\t\t  @\"Volume Create Success format\"),\n\t\t\t\t\topts[@\"filesystem\"]];\n\t\t\t\t  [self notifySuccessWithTitle:title text:text];\n\t\t\t  }\n\t\t\t  [self handleFileSystemChangeReply:error];\n\t\t  }];\n\t }];\n}\n\n- (IBAction)destroy:(id)sender\n{\n\tNSString * fsName = [sender representedObject];\n\tzfs::LibZFSHandle lib;\n\tauto fs = lib.filesystem([fsName UTF8String]);\n\tauto dependents = fs.dependents();\n\tif (!dependents.empty())\n\t{\n  // cannot destroy 'tank/nuts': filesystem has children\n\t\t[_zetaConfirmDialog addQuery:NSLocalizedString(@\"Unable to destroy, the filesystem has dependent datasets\", @\"Destroy Dep Failure\")\n\t\t\t\t\t withInformation:toString(dependents)\n\t\t\t\t\t\twithCallback:^(bool ok)\n\t\t {\n\t\t }];\n\t}\n\telse\n\t{\n\t\tNSDictionary * opts = @{@\"filesystem\": fsName};\n\t\t[_authorization destroy:opts withReply:^(NSError * error)\n\t\t {\n\t\t\t if (!error)\n\t\t\t {\n\t\t\t\t NSString * title = NSLocalizedString(@\"Destroy succeeded\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t  @\"Destroy Succeeded\");\n\t\t\t\t NSString * text = [NSString stringWithFormat:\n\t\t\t\t\tNSLocalizedString(@\"%@ destroyed\",\n\t\t\t\t\t\t\t\t\t  @\"Destroy Success format\"),\n\t\t\t\t\t[sender representedObject]];\n\t\t\t\t [self notifySuccessWithTitle:title text:text];\n\t\t\t }\n\t\t\t [self handleFileSystemChangeReply:error];\n\t\t }];\n\t}\n}\n\n- (IBAction)destroyRecursive:(id)sender\n{\n\tNSString * fsName = [sender representedObject];\n\tzfs::LibZFSHandle lib;\n\tauto fs = lib.filesystem([fsName UTF8String]);\n\tauto dependents = fs.dependents();\n\tauto destroyBlock = ^(bool ok)\n\t{\n\t\tif (ok)\n\t\t{\n\t\t\tNSDictionary * opts = @{@\"filesystem\": [sender representedObject], @\"recursive\": @TRUE};\n\t\t\t[self->_authorization destroy:opts withReply:^(NSError * error)\n\t\t\t {\n\t\t\t\t if (!error)\n\t\t\t\t {\n\t\t\t\t\t NSString * title = NSLocalizedString(@\"Recursive destroy succeeded\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  @\"Recursive destroy succeeded\");\n\t\t\t\t\t NSString * text = [NSString stringWithFormat:\n\t\t\t\t\t\tNSLocalizedString(@\"%@ destroyed recursively\",\n\t\t\t\t\t\t\t\t\t\t  @\"Destroy Recursive Success format\"),\n\t\t\t\t\t\t[sender representedObject]];\n\t\t\t\t\t [self notifySuccessWithTitle:title text:text];\n\t\t\t\t }\n\t\t\t\t [self handleFileSystemChangeReply:error];\n\t\t\t }];\n\t\t}\n\t};\n\tif (!dependents.empty())\n\t{\n\t\t[_zetaConfirmDialog addQuery:NSLocalizedString(@\"The following dependent datasets will be destroyed\", @\"Destroy Dep Query\")\n\t\t\t\t\t withInformation:toString(dependents)\n\t\t\t\t\t\twithCallback:destroyBlock];\n\t}\n\telse\n\t{\n\t\tdestroyBlock(true);\n\t}\n}\n\n- (IBAction)loadKey:(id)sender\n{\n\tNSString * fs = [sender representedObject];\n\t[_zetaKeyLoader unlockFileSystem:fs];\n}\n\n- (IBAction)loadAllKeys:(id)sender\n{\n\tNSArray<NSString*> * fss = [sender representedObject];\n\tfor (NSString * fs in fss) {\n\t\t[_zetaKeyLoader unlockFileSystem:fs];\n\t}\n}\n\n- (IBAction)unloadKey:(id)sender\n{\n\tNSDictionary * opts = @{@\"filesystem\": [sender representedObject]};\n\t[_authorization unloadKeyForFilesystem:opts withReply:^(NSError * error)\n\t {\n\t\t if (!error)\n\t\t {\n\t\t\t NSString * title = NSLocalizedString(@\"Key unloaded successfully\",\n\t\t\t\t\t\t\t\t\t\t\t\t  @\"Key unloaded successfully\");\n\t\t\t NSString * text = [NSString stringWithFormat:\n\t\t\t\tNSLocalizedString(@\"Key for %@ unloaded\",\n\t\t\t\t\t\t\t\t  @\"Key Unload Success format\"),\n\t\t\t\t[sender representedObject]];\n\t\t\t [self notifySuccessWithTitle:title text:text];\n\t\t }\n\t\t [self handleFileSystemChangeReply:error];\n\t }];\n}\n\n- (void)unloadNextKey:(NSMutableArray<NSString*>*)fileSystems\n{\n\tif ([fileSystems count] > 0)\n\t{\n\t\tNSString * fs = [fileSystems lastObject];\n\t\t[fileSystems removeLastObject];\n\t\tNSDictionary * opts = @{@\"filesystem\": fs};\n\t\t[_authorization unloadKeyForFilesystem:opts withReply:^(NSError * error)\n\t\t {\n\t\t\t if (!error)\n\t\t\t {\n\t\t\t\t NSString * title = NSLocalizedString(@\"Key unloaded successfully\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t  @\"Key unloaded successfully\");\n\t\t\t\t NSString * text = [NSString stringWithFormat:\n\t\t\t\t\tNSLocalizedString(@\"Key for %@ unloaded\",\n\t\t\t\t\t\t\t\t\t  @\"Key Unload Success format\"),\n\t\t\t\t\tfs];\n\t\t\t\t [self notifySuccessWithTitle:title text:text];\n\t\t\t }\n\t\t\t [self handleFileSystemChangeReply:error];\n\t\t\t [self unloadNextKey:fileSystems];\n\t\t }];\n\t}\n}\n\n- (IBAction)unloadAllKeys:(id)sender\n{\n\tNSMutableArray<NSString*> * fileSystems = [sender representedObject];\n\t[self unloadNextKey:fileSystems];\n}\n\n- (IBAction)scrubPool:(id)sender\n{\n\tNSDictionary * opts = @{@\"pool\": [sender representedObject]};\n\t[_authorization scrubPool:opts withReply:^(NSError * error)\n\t {\n\t\t [self handleMetaDataChangeReply:error];\n\t }];\n}\n\n- (IBAction)scrubStopPool:(id)sender\n{\n\tNSDictionary * opts = @{@\"pool\": [sender representedObject], @\"command\": @\"stop\"};\n\t[_authorization scrubPool:opts withReply:^(NSError * error)\n\t {\n\t\t [self handleMetaDataChangeReply:error];\n\t }];\n}\n\n- (IBAction)scrubPausePool:(id)sender\n{\n\tNSDictionary * opts = @{@\"pool\": [sender representedObject], @\"command\": @\"pause\"};\n\t[_authorization scrubPool:opts withReply:^(NSError * error)\n\t {\n\t\t [self handleMetaDataChangeReply:error];\n\t }];\n}\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaNotificationCenter.h",
    "content": "//\n//  ZetaNotificationCenter.h\n//  ZetaWatch\n//\n//  Created by cbreak on 19.08.25.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import \"ZetaPoolWatcher.h\"\n\n#import <Cocoa/Cocoa.h>\n\n@interface ZetaNotification : NSObject\n{\n}\n\n@property (readonly) NSString * title;\n\n@end\n\n@interface ZetaNotificationCenter : NSObject <ZetaPoolWatcherDelegate>\n{\n}\n\n- (ZetaNotification*)startAction:(NSString*)title;\n- (void)stopAction:(ZetaNotification*)notification;\n- (void)stopAction:(ZetaNotification*)notification withError:(NSError*)error;\n\n- (void)errorDetected:(std::string const &)error;\n- (void)errorDetectedInPool:(std::string const &)pool;\n\n@property (readonly) NSArray<ZetaNotification*> * inProgressActions;\n\n@property (weak) IBOutlet ZetaPoolWatcher * poolWatcher;\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaNotificationCenter.mm",
    "content": "//\n//  ZetaNotificationCenter.m\n//  ZetaWatch\n//\n//  Created by cbreak on 19.08.25.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import \"ZetaNotificationCenter.h\"\n\n#import \"ZetaPoolWatcher.h\"\n\n@implementation ZetaNotification\n{\n}\n\n- (id)initWithTitle:(NSString*)title\n{\n\tif (self = [super init])\n\t{\n\t\tself->title = title;\n\t}\n\treturn self;\n}\n\n@synthesize title;\n\n@end\n\n@implementation ZetaNotificationCenter\n{\n\tNSMutableArray<ZetaNotification*> * inProgressActions;\n}\n\n- (id)init\n{\n\tif (self = [super init])\n\t{\n\t\tinProgressActions = [[NSMutableArray alloc] init];\n\t}\n\treturn self;\n}\n\n- (void)awakeFromNib\n{\n\tif (self.poolWatcher)\n\t{\n\t\t[self.poolWatcher.delegates addObject:self];\n\t}\n}\n\n- (ZetaNotification*)startAction:(NSString*)title\n{\n\tZetaNotification * notification = [[ZetaNotification alloc] initWithTitle:title];\n\t[inProgressActions addObject:notification];\n\treturn notification;\n}\n\n- (void)stopAction:(ZetaNotification*)notification\n{\n\t[inProgressActions removeObject:notification];\n}\n\n- (void)stopAction:(ZetaNotification*)notification withError:(NSError*)error\n{\n\t[self stopAction:notification];\n}\n\n- (void)errorDetectedInPool:(std::string const &)pool\n{\n\tNSUserNotification * notification = [[NSUserNotification alloc] init];\n\tnotification.title = NSLocalizedString(@\"ZFS Pool Error\", @\"ZFS Pool Error Title\");\n\tNSString * errorFormat = NSLocalizedString(@\"ZFS detected an error on pool %s.\", @\"ZFS Pool Error Format\");\n\tnotification.informativeText = [NSString stringWithFormat:errorFormat, pool.c_str()];\n\tnotification.hasActionButton = NO;\n\t[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];\n}\n\n- (void)errorDetected:(std::string const &)error\n{\n\tNSUserNotification * notification = [[NSUserNotification alloc] init];\n\tnotification.title = NSLocalizedString(@\"ZFS Error\", @\"ZFS Error Title\");\n\tNSString * errorFormat = NSLocalizedString(@\"ZFS encountered an error: %s.\", @\"ZFS Error Format\");\n\tnotification.informativeText = [NSString stringWithFormat:errorFormat, error.c_str()];\n\tnotification.hasActionButton = NO;\n\t[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];\n}\n\n@synthesize inProgressActions;\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaPoolPropertyMenu.h",
    "content": "//\n//  ZetaPoolPropertyMenu.h\n//  ZetaWatch\n//\n//  Created by cbreak on 19.06.22.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import <Cocoa/Cocoa.h>\n\n#import \"ZetaCommanderBase.h\"\n\n#include \"ZFSUtils.hpp\"\n\n@interface ZetaPoolPropertyMenu : ZetaCommanderBase <NSMenuDelegate>\n\n- (id)initWithPool:(zfs::ZPool)pool;\n\n- (void)menuNeedsUpdate:(NSMenu*)menu;\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaPoolPropertyMenu.mm",
    "content": "//\n//  ZetaPoolPropertyMenu.mm\n//  ZetaWatch\n//\n//  Created by cbreak on 19.06.22.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import \"ZetaPoolPropertyMenu.h\"\n\n@implementation ZetaPoolPropertyMenu\n{\n\tzfs::ZPool _pool;\n}\n\n- (id)initWithPool:(zfs::ZPool)pool\n{\n\tif (self = [super init])\n\t{\n\t\t_pool = std::move(pool);\n\t}\n\treturn self;\n}\n\n- (void)menuNeedsUpdate:(NSMenu*)menu\n{\n\t[menu removeAllItems];\n\tauto props = _pool.properties();\n\tfor (auto const & p : props)\n\t{\n\t\taddMenuItem(menu, self, NSLocalizedString(@\"%-64s \\t %s\", @\"KeyValue\"),\n\t\t\t\t\t\tp.name, p.value);\n\t}\n}\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaPoolWatcher.h",
    "content": "//\n//  ZetaPoolWatcher.h\n//  ZetaWatch\n//\n//  Created by Gerhard Röthlin on 2015.12.31.\n//  Copyright © 2015 the-color-black.net. All rights reserved.\n//\n//  Redistribution and use in source and binary forms, with or without modification, are permitted\n//  provided that the conditions of the \"3-Clause BSD\" license described in the BSD.LICENSE file are met.\n//  Additional licensing options are described in the README file.\n//\n\n#import <Cocoa/Cocoa.h>\n\n#include \"ZFSUtils.hpp\"\n\n#include <string>\n\n@protocol ZetaPoolWatcherDelegate <NSObject>\n\n@optional\n- (void)newPoolDetected:(zfs::ZPool const &)pool;\n- (void)errorDetectedInPool:(std::string const &)pool;\n- (void)errorDetected:(std::string const &)error;\n\n@end\n\n@interface ZetaPoolWatcher : NSObject\n\n- (id)init;\n\n- (void)checkForChanges;\n\n- (void)keepAwake;\n- (void)stopKeepingAwake;\n\n@property (strong) NSMutableArray<id<ZetaPoolWatcherDelegate>> * delegates;\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaPoolWatcher.mm",
    "content": "//\n//  ZetaPoolWatcher.mm\n//  ZetaWatch\n//\n//  Created by Gerhard Röthlin on 2015.12.31.\n//  Copyright © 2015 the-color-black.net. All rights reserved.\n//\n//  Redistribution and use in source and binary forms, with or without modification, are permitted\n//  provided that the conditions of the \"3-Clause BSD\" license described in the BSD.LICENSE file are met.\n//  Additional licensing options are described in the README file.\n//\n\n#import \"ZetaPoolWatcher.h\"\n\n#import <IOKit/pwr_mgt/IOPMLib.h>\n\n#include <map>\n\nCFStringRef powerAssertionName = CFSTR(\"ZFSScrub\");\nCFStringRef powerAssertionReason = CFSTR(\"ZFS Scrub in progress\");\n\n@interface ZetaPoolWatcher ()\n{\n\t// ZFS\n\tstd::vector<uint64_t> _knownPools;\n\n\t// Statistics\n\tstd::map<uint64_t,zfs::VDevStat> _errorStats;\n\n\t// Sleep Prevention\n\tIOPMAssertionID assertionID;\n\tbool keptAwake;\n\n\t// Timing\n\tNSTimer * _autoUpdateTimer;\n}\n\n@end\n\nbool containsMoreErrors(zfs::VDevStat const & a, zfs::VDevStat const & b)\n{\n\treturn b.errorRead > a.errorRead\n\t\t|| b.errorWrite > a.errorWrite\n\t\t|| b.errorChecksum > a.errorChecksum;\n}\n\n@implementation ZetaPoolWatcher\n\n- (id)init\n{\n\tif (self = [super init])\n\t{\n\t\t_autoUpdateTimer = [NSTimer timerWithTimeInterval:60\n\t\t\ttarget:self selector:@selector(timedUpdate:) userInfo:nil repeats:YES];\n\t\t_autoUpdateTimer.tolerance = 8;\n\t\t[[NSRunLoop currentRunLoop] addTimer:_autoUpdateTimer forMode:NSDefaultRunLoopMode];\n\t\tdelegates = [[NSMutableArray alloc] init];\n\t}\n\treturn self;\n}\n\n- (void)dealloc\n{\n\t[_autoUpdateTimer invalidate];\n\t_autoUpdateTimer = nil;\n\t[self stopKeepingAwake];\n}\n\n- (void)timedUpdate:(NSTimer*)timer\n{\n\t[self checkForChanges];\n}\n\n- (void)checkForChanges\n{\n\ttry\n\t{\n\t\tzfs::LibZFSHandle zfs;\n\t\tauto p = zfs.pools();\n\t\t[self checkForNewPools:p];\n\t\t[self checkForNewErrors:p];\n\t\tauto scrubCounter = [self countScrubsInProgress:p];\n\t\tauto sd = [NSUserDefaults standardUserDefaults];\n\t\tif (scrubCounter > 0 && [sd boolForKey:@\"keepAwakeDuringScrub\"])\n\t\t\t[self keepAwake];\n\t\telse\n\t\t\t[self stopKeepingAwake];\n\t}\n\tcatch (std::exception const & e)\n\t{\n\t\t[self notifyError:e.what()];\n\t}\n}\n\n- (bool)checkDev:(zfs::NVList const &)dev\n{\n\tauto guid = vdevGUID(dev);\n\tauto newStat = vdevStat(dev);\n\tauto & oldStat = _errorStats[guid];\n\tbool error = containsMoreErrors(oldStat, newStat);\n\toldStat = newStat;\n\treturn error;\n}\n\n- (bool)checkForNewErrors:(std::vector<zfs::ZPool> const &)pools\n{\n\ttry\n\t{\n\t\tfor (auto && pool: pools)\n\t\t{\n\t\t\tauto vdevs = pool.vdevs();\n\t\t\tfor (auto && vdev: vdevs)\n\t\t\t{\n\t\t\t\tif ([self checkDev:vdev])\n\t\t\t\t{\n\t\t\t\t\t[self notifyErrorInPool:pool.name()];\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tauto devices = zfs::vdevChildren(vdev);\n\t\t\t\tfor (auto && device: devices)\n\t\t\t\t{\n\t\t\t\t\tif ([self checkDev:device])\n\t\t\t\t\t{\n\t\t\t\t\t\t[self notifyErrorInPool:pool.name()];\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tcatch (std::exception const & e)\n\t{\n\t\t[self notifyError:e.what()];\n\t}\n\treturn false;\n}\n\n- (void)notifyNewPoolDetected:(zfs::ZPool const &)pool\n{\n\tfor (id<ZetaPoolWatcherDelegate> d in [self delegates])\n\t{\n\t\tif ([d respondsToSelector:@selector(newPoolDetected:)])\n\t\t{\n\t\t\t[d newPoolDetected:pool];\n\t\t}\n\t}\n}\n\n- (void)notifyErrorInPool:(std::string const &)pool\n{\n\tfor (id<ZetaPoolWatcherDelegate> d in [self delegates])\n\t{\n\t\tif ([d respondsToSelector:@selector(errorDetectedInPool:)])\n\t\t{\n\t\t\t[d errorDetectedInPool:pool];\n\t\t}\n\t}\n}\n\n- (void)notifyError:(std::string const &)pool\n{\n\tfor (id<ZetaPoolWatcherDelegate> d in [self delegates])\n\t{\n\t\tif ([d respondsToSelector:@selector(errorDetected:)])\n\t\t{\n\t\t\t[d errorDetected:pool];\n\t\t}\n\t}\n}\n\nstd::vector<uint64_t> poolsToGUID(std::vector<zfs::ZPool> const & pools)\n{\n\tstd::vector<uint64_t> guids(pools.size());\n\tstd::transform(pools.begin(), pools.end(), guids.begin(),\n\t\t\t\t   [](auto const & pool) { return pool.guid(); });\n\tstd::sort(guids.begin(), guids.end());\n\treturn guids;\n}\n\n- (void)checkForNewPools:(std::vector<zfs::ZPool> const &)pools\n{\n\tfor (auto const & p : pools)\n\t{\n\t\tif (std::binary_search(_knownPools.begin(), _knownPools.end(), p.guid()))\n\t\t{\n\t\t\t// Already known pool\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// New pool\n\t\t\t[self notifyNewPoolDetected:p];\n\t\t}\n\t}\n\t_knownPools = poolsToGUID(pools);\n}\n\n- (uint64_t)countScrubsInProgress:(std::vector<zfs::ZPool> const &)pools\n{\n\tuint64_t scrubsInProgress = 0;\n\ttry\n\t{\n\t\tfor (auto && pool: pools)\n\t\t{\n\t\t\tauto vdevs = pool.vdevs();\n\t\t\tauto scan = pool.scanStat();\n\t\t\tif (scan.state == zfs::ScanStat::scanning)\n\t\t\t\t++scrubsInProgress;\n\t\t}\n\t}\n\tcatch (std::exception const & e)\n\t{\n\t\t[self notifyError:e.what()];\n\t}\n\treturn scrubsInProgress;\n}\n\n- (void)keepAwake\n{\n\tif (!keptAwake)\n\t{\n\t\tIOReturn success = IOPMAssertionCreateWithDescription(\n\t\t\tkIOPMAssertPreventUserIdleSystemSleep,\n\t\t\tpowerAssertionName, powerAssertionReason, 0, 0, 0, 0, &assertionID);\n\t\tif (success == kIOReturnSuccess)\n\t\t{\n\t\t\tkeptAwake = true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tkeptAwake = false;\n\t\t\tassertionID = 0;\n\t\t}\n\t}\n}\n\n- (void)stopKeepingAwake\n{\n\tif (keptAwake)\n\t{\n\t\tIOReturn success = IOPMAssertionRelease(assertionID);\n\t\tif (success == kIOReturnSuccess)\n\t\t{\n\t\t\tkeptAwake = false;\n\t\t\tassertionID = 0;\n\t\t}\n\t}\n}\n\n@synthesize delegates;\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaQueryDialog.h",
    "content": "//\n//  ZetaQueryDialog.h\n//  ZetaWatch\n//\n//  Created by cbreak on 19.10.06.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import <Cocoa/Cocoa.h>\n\n@interface ZetaQueryDialog : NSObject <NSPopoverDelegate>\n\n@property (weak) NSStatusItem * statusItem;\n@property (weak) IBOutlet NSPopover * popover;\n@property (weak) IBOutlet NSTextField * replyField;\n@property (weak) IBOutlet NSTextField * queryField;\n\n- (IBAction)ok:(id)sender;\n- (IBAction)cancel:(id)sender;\n\n- (BOOL)popoverShouldDetach:(NSPopover *)popover;\n\n- (void)addQuery:(NSString*)query\n\t withDefault:(NSString*)defaultReply\n\twithCallback:(void(^)(NSString*))callback;\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaQueryDialog.mm",
    "content": "//\n//  ZetaQueryDialog.mm\n//  ZetaWatch\n//\n//  Created by cbreak on 19.10.06.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import \"ZetaQueryDialog.h\"\n\n#include <deque>\n#include <type_traits>\n\nnamespace\n{\n\ttypedef void (^QueryCallback)(NSString *);\n\n\tstruct Query\n\t{\n\t\tNSString * query;\n\t\tNSString * defaultReply;\n\t\tQueryCallback reply;\n\t};\n}\n\n@interface ZetaQueryDialog ()\n{\n\tstd::deque<Query> queries;\n}\n\n@end\n\n@implementation ZetaQueryDialog\n\n- (void)addQuery:(NSString*)query\n\t withDefault:(NSString*)defaultReply\n\twithCallback:(void(^)(NSString*))callback\n{\n\tqueries.push_back({query, defaultReply, callback});\n\tif (queries.size() == 1)\n\t\t[self updateQuery];\n\tif (![_popover isShown])\n\t\t[self show];\n}\n\n- (void)show\n{\n\t[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];\n\tNSView * positioningView = [_statusItem button];\n\t[_popover showRelativeToRect:NSMakeRect(0, 0, 0, 0)\n\t\t\t\t\t\t  ofView:positioningView\n\t\t\t\t   preferredEdge:NSRectEdgeMinY];\n}\n\n- (IBAction)ok:(id)sender\n{\n\tif (!queries.empty())\n\t\tqueries.front().reply([_replyField stringValue]);\n\t[self advanceQuery];\n}\n\n- (IBAction)cancel:(id)sender\n{\n\t[self advanceQuery];\n}\n\n- (BOOL)popoverShouldDetach:(NSPopover *)popover\n{\n\treturn YES;\n}\n\n- (void)advanceQuery\n{\n\tqueries.pop_front();\n\t[self updateQuery];\n\tif (queries.empty())\n\t{\n\t\t[_popover performClose:self];\n\t}\n}\n\n- (void)updateQuery\n{\n\tif (queries.empty())\n\t{\n\t\t[_queryField setStringValue:@\"\"];\n\t\t[_replyField setStringValue:@\"\"];\n\t}\n\telse\n\t{\n\t\t[_queryField setStringValue:queries.front().query];\n\t\t[_replyField setStringValue:queries.front().defaultReply];\n\t}\n}\n\n- (BOOL)popoverShouldClose:(NSPopover *)popover\n{\n\tif (!queries.empty())\n\t{\n\t\tqueries.pop_front();\n\t\tif (queries.empty())\n\t\t\treturn YES;\n\t\t[self updateQuery];\n\t\treturn NO;\n\t}\n\telse\n\t{\n\t\treturn YES;\n\t}\n}\n\n- (void)popoverWillShow:(NSNotification *)notification\n{\n}\n\n- (void)popoverDidClose:(NSNotification *)notification\n{\n\t[_replyField abortEditing];\n}\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaSnapshotMenu.h",
    "content": "//\n//  ZetaSnapshotMenu.h\n//  ZetaWatch\n//\n//  Created by cbreak on 19.10.05.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import <Cocoa/Cocoa.h>\n\n#import \"ZetaCommanderBase.h\"\n\n#include \"ZFSUtils.hpp\"\n\nNS_ASSUME_NONNULL_BEGIN\n\n@class ZetaMainMenu;\n\n@interface ZetaSnapshotMenu : ZetaCommanderBase <NSMenuDelegate>\n\n- (id)initWithFileSystem:(zfs::ZFileSystem)fs delegate:(ZetaMainMenu*)main;\n\n- (void)menuNeedsUpdate:(NSMenu*)menu;\n\n@end\n\nNS_ASSUME_NONNULL_END\n"
  },
  {
    "path": "ZetaWatch/ZetaSnapshotMenu.mm",
    "content": "//\n//  ZetaSnapshotMenu.m\n//  ZetaWatch\n//\n//  Created by cbreak on 19.10.05.\n//  Copyright © 2019 the-color-black.net. All rights reserved.\n//\n\n#import \"ZetaSnapshotMenu.h\"\n\n#import \"ZetaMainMenu.h\"\n\n@implementation ZetaSnapshotMenu\n{\n\tzfs::ZFileSystem _fs;\n\tZetaMainMenu __weak * _delegate;\n}\n\n- (id)initWithFileSystem:(zfs::ZFileSystem)fs delegate:(ZetaMainMenu*)delegate\n{\n\tif (self = [super init])\n\t{\n\t\t_fs = std::move(fs);\n\t\t_delegate = delegate;\n\t}\n\treturn self;\n}\n\nNSMenuItem * createSnapMenu(zfs::ZFileSystem const & snap, ZetaMainMenu * delegate)\n{\n\tNSMenu * sMenu = [[NSMenu alloc] init];\n\t[sMenu setAutoenablesItems:NO];\n\tNSString * sName = [NSString stringWithUTF8String:snap.name()];\n\tauto addSnapCommand = [&](NSString * title, SEL selector)\n\t{\n\t\tauto item = [sMenu addItemWithTitle:title\n\t\t\t\t\t\t\t\t\t action:selector keyEquivalent:@\"\"];\n\t\titem.representedObject = sName;\n\t\titem.target = delegate;\n\t};\n\taddSnapCommand(NSLocalizedString(@\"Clone\", @\"Clone\"), @selector(cloneSnapshot:));\n\taddSnapCommand(NSLocalizedString(@\"Rollback\", @\"Rollback\"), @selector(rollbackFilesystem:));\n\taddSnapCommand(NSLocalizedString(@\"Rollback (Force)\", @\"Rollback (Force)\"), @selector(rollbackFilesystemForce:));\n\t[sMenu addItem:[NSMenuItem separatorItem]];\n\tif (!snap.mounted())\n\t{\n\t\taddSnapCommand(NSLocalizedString(@\"Mount\", @\"Mount\"), @selector(mountFilesystem:));\n\t}\n\telse\n\t{\n\t\taddSnapCommand(NSLocalizedString(@\"Unmount\", @\"Unmount\"), @selector(unmountFilesystem:));\n\t\taddSnapCommand(NSLocalizedString(@\"Unmount (Force)\", @\"Unmount (Force)\"), @selector(unmountFilesystemForce:));\n\t}\n\t[sMenu addItem:[NSMenuItem separatorItem]];\n\tif (snap.cloneCount() == 0)\n\t{\n\t\taddSnapCommand(NSLocalizedString(@\"Destroy\", @\"Destroy\"), @selector(destroy:));\n\t}\n\telse\n\t{\n\t\taddSnapCommand(NSLocalizedString(@\"Destroy Recursive\", @\"Destroy Recursive\"), @selector(destroyRecursive:));\n\t}\n\tauto item = [[NSMenuItem alloc] initWithTitle:sName action:nullptr keyEquivalent:@\"\"];\n\titem.representedObject = sName;\n\titem.submenu = sMenu;\n\treturn item;\n}\n\n- (void)menuNeedsUpdate:(NSMenu*)menu\n{\n\t[menu removeAllItems];\n\tauto snap = _fs.snapshots();\n\tif (!snap.empty())\n\t{\n\t\tfor (size_t i = snap.size(); i > 0; --i)\n\t\t{\n\t\t\tNSMenuItem * item = createSnapMenu(snap[i-1], _delegate);\n\t\t\t[menu addItem:item];\n\t\t}\n\t}\n\telse\n\t{\n\t\t[menu addItemWithTitle:NSLocalizedString(@\"No snapshots found\", @\"No Snapshots\")\n\t\t\t\t\t\taction:NULL keyEquivalent:@\"\"];\n\t}\n}\n\n@end\n"
  },
  {
    "path": "ZetaWatch/ZetaWatch.entitlements",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>com.apple.security.cs.disable-library-validation</key>\n\t<true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "ZetaWatch/ZetaWatchDelegate.h",
    "content": "//\n//  ZetaWatchDelegate.h\n//  ZetaWatch\n//\n//  Created by Gerhard Röthlin on 2015.12.20.\n//  Copyright © 2015 the-color-black.net. All rights reserved.\n//\n//  Redistribution and use in source and binary forms, with or without modification, are permitted\n//  provided that the conditions of the \"3-Clause BSD\" license described in the BSD.LICENSE file are met.\n//  Additional licensing options are described in the README file.\n//\n\n#import <Cocoa/Cocoa.h>\n\n@interface ZetaWatchDelegate : NSObject <NSApplicationDelegate,NSUserNotificationCenterDelegate>\n\n// NSUserNotificationCenterDelegate\n- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center\n\t shouldPresentNotification:(NSUserNotification *)notification;\n\n@end\n\n"
  },
  {
    "path": "ZetaWatch/ZetaWatchDelegate.mm",
    "content": "//\n//  ZetaWatchDelegate.mm\n//  ZetaWatch\n//\n//  Created by Gerhard Röthlin on 2015.12.20.\n//  Copyright © 2015 the-color-black.net. All rights reserved.\n//\n//  Redistribution and use in source and binary forms, with or without modification, are permitted\n//  provided that the conditions of the \"3-Clause BSD\" license described in the BSD.LICENSE file are met.\n//  Additional licensing options are described in the README file.\n//\n\n#import \"ZetaWatchDelegate.h\"\n\n#import \"ZetaAuthorization.h\"\n#import \"ZetaMainMenu.h\"\n#import \"ZetaKeyLoader.h\"\n#import \"ZetaQueryDialog.h\"\n#import \"ZetaDictQueryDialog.h\"\n#import \"ZetaConfirmDialog.h\"\n\n#import \"ZFSUtils.hpp\"\n\n#import <Sparkle/Sparkle.h>\n#import <ServiceManagement/SMLoginItem.h>\n\n@interface ZetaWatchDelegate ()\n{\n\tNSStatusItem * _statusItem;\n}\n\n@property (weak) IBOutlet NSMenu * zetaMenu;\n@property (weak) IBOutlet ZetaAuthorization * authorization;\n@property (weak) IBOutlet ZetaMainMenu * zetaMainMenu;\n@property (weak) IBOutlet ZetaKeyLoader * zetaKeyLoader;\n@property (weak) IBOutlet ZetaQueryDialog * zetaQueryDialog;\n@property (weak) IBOutlet ZetaConfirmDialog * zetaConfirmDialog;\n@property (weak) IBOutlet ZetaPoolWatcher * poolWatcher;\n@property (weak) IBOutlet SUUpdater * updater;\n@property (weak) IBOutlet NSPopover * settings;\n\n@property (strong) ZetaDictQueryDialog * zetaNewFSDialog;\n@property (strong) ZetaDictQueryDialog * zetaNewVolDialog;\n\n@end\n\n@implementation ZetaWatchDelegate\n\n- (void)applicationDidFinishLaunching:(NSNotification *)aNotification\n{\n\t// Menu Item\n\tNSStatusBar * bar = [NSStatusBar systemStatusBar];\n\t_statusItem = [bar statusItemWithLength:NSSquareStatusItemLength];\n\tNSImage * zetaImage = [NSImage imageNamed:@\"Zeta\"];\n\t[zetaImage setTemplate:YES];\n\t_statusItem.button.image = zetaImage;\n\t_statusItem.menu = _zetaMenu;\n\t_zetaKeyLoader.statusItem = _statusItem;\n\t_zetaQueryDialog.statusItem = _statusItem;\n\t_zetaConfirmDialog.statusItem = _statusItem;\n\t// Dialogs\n\t_zetaNewFSDialog = [[ZetaDictQueryDialog alloc] initWithDialog:@\"NewFS\"];\n\t_zetaNewFSDialog.statusItem = _statusItem;\n\t_zetaMainMenu.zetaNewFSDialog = _zetaNewFSDialog;\n\t_zetaNewVolDialog = [[ZetaDictQueryDialog alloc] initWithDialog:@\"NewVol\"];\n\t_zetaNewVolDialog.statusItem = _statusItem;\n\t_zetaMainMenu.zetaNewVolDialog = _zetaNewVolDialog;\n\t// Watcher\n\t[[self poolWatcher] checkForChanges];\n\t// User Notification Center Delegate\n\t[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self];\n\t// Login Item\n\t[[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@\"startAtLogin\"\n\t\t\t\t\t\t\t\t\t\t\t   options:NSKeyValueObservingOptionInitial\n\t\t\t\t\t\t\t\t\t\t\t   context:nullptr];\n}\n\n- (void)applicationWillFinishLaunching:(NSNotification *)notification\n{\n\t// User Defaults\n\t[[NSUserDefaults standardUserDefaults] registerDefaults:@{\n\t\t@\"autoUnlock\": @YES,\n\t\t@\"autoImport\": @YES,\n\t\t@\"allowHostIDMismatch\": @NO,\n\t\t@\"useKeychain\": @NO,\n\t\t@\"startAtLogin\": @YES,\n\t\t@\"keepAwakeDuringScrub\": @YES,\n\t\t@\"defaultAltroot\": @\"/Volumes\",\n\t\t@\"useAltroot\": @NO,\n\t\t@\"searchPathOverride\": @[\n\t\t\t\t@\"/var/run/disk/by-serial\",\n\t\t\t\t@\"/var/run/disk/by-id\",\n\t\t],\n\t}];\n\ttry\n\t{\n\t\t// Update Feed URL to the one matching the current ZFS version, even if\n\t\t// ZetaWatch was not compiled for it.\n\t\tauto version = zfs::LibZFSHandle::version();\n\t\tNSString * feedString = [NSString stringWithFormat:\n\t\t\t@\"https://zetawatch.the-color-black.net/download/%i.%i/appcast.xml\",\n\t\t\t\t\t\t\t\t version.major, version.minor];\n\t\tNSURL * feedURL = [NSURL URLWithString:feedString];\n\t\t[self.updater setFeedURL:feedURL];\n\t\t// TODO: Check for compatibility\n\t}\n\tcatch (std::exception const & e)\n\t{\n\t\tNSLog(@\"Error querying ZFS Version: %s\", e.what());\n\t\t// Disable auto update\n\t\t[self.updater setAutomaticallyChecksForUpdates:NO];\n\t\t[self.updater setAutomaticallyDownloadsUpdates:NO];\n\t}\n}\n\n- (void)applicationWillTerminate:(NSNotification *)aNotification\n{\n\t[[NSUserDefaults standardUserDefaults] removeObserver:self forKeyPath:@\"startAtLogin\"];\n\t[self.authorization stopHelper];\n}\n\n- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center\n\t shouldPresentNotification:(NSUserNotification *)notification\n{\n\treturn YES;\n}\n\n- (void)observeValueForKeyPath:(NSString *)keyPath\n\t\t\t\t\t  ofObject:(id)object\n\t\t\t\t\t\tchange:(NSDictionary<NSKeyValueChangeKey, id> *)change\n\t\t\t\t\t   context:(void *)context\n{\n\tif ([keyPath isEqualToString:@\"startAtLogin\"])\n\t{\n\t\tbool startAtLogin = [object boolForKey:@\"startAtLogin\"];\n\t\tSMLoginItemSetEnabled(CFSTR(\"net.the-color-black.ZetaLoginItemHelper\"), startAtLogin);\n\t}\n}\n\n- (IBAction)showSettings:(id)sender\n{\n\tNSView * positioningView = [_statusItem button];\n\t[_settings showRelativeToRect:NSMakeRect(0, 0, 0, 0)\n\t\t\t\t\t\t   ofView:positioningView preferredEdge:NSRectEdgeMinY];\n}\n\n@end\n"
  },
  {
    "path": "ZetaWatch/main.m",
    "content": "//\n//  main.m\n//  ZetaWatch\n//\n//  Created by Gerhard Röthlin on 2015.12.20.\n//  Copyright © 2015 the-color-black.net. All rights reserved.\n//\n\n#import <Cocoa/Cocoa.h>\n\nint main(int argc, const char * argv[])\n{\n\treturn NSApplicationMain(argc, argv);\n}\n"
  },
  {
    "path": "ZetaWatch.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t7006C4801C26CA1500929DAE /* ZetaWatchDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7006C47F1C26CA1500929DAE /* ZetaWatchDelegate.mm */; };\n\t\t7006C4831C26CA1500929DAE /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 7006C4821C26CA1500929DAE /* main.m */; };\n\t\t7006C4851C26CA1500929DAE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7006C4841C26CA1500929DAE /* Assets.xcassets */; };\n\t\t7006C4881C26CA1500929DAE /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7006C4861C26CA1500929DAE /* MainMenu.xib */; };\n\t\t7006C4AC1C26D3E700929DAE /* ZetaMainMenu.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7006C4AB1C26D3E700929DAE /* ZetaMainMenu.mm */; };\n\t\t70168B6622B64E48002C760A /* ZetaKeyLoader.mm in Sources */ = {isa = PBXBuildFile; fileRef = 70168B6522B64E48002C760A /* ZetaKeyLoader.mm */; };\n\t\t7018764120E7B45900BA39B8 /* ZFSUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70D85FB71C2C076E00929DAE /* ZFSUtils.cpp */; };\n\t\t7018764220E7B45B00BA39B8 /* ZFSStrings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70D85FBF1C2D9CB900929DAE /* ZFSStrings.cpp */; };\n\t\t7018764320E7B45E00BA39B8 /* ZFSNVList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70D85FC21C2EAE5A00929DAE /* ZFSNVList.cpp */; };\n\t\t7018764820E7B4A100BA39B8 /* ZFSNVList.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 70D85FC31C2EAE5A00929DAE /* ZFSNVList.hpp */; };\n\t\t7018764920E7B4A300BA39B8 /* ZFSStrings.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 70D85FC11C2D9CC900929DAE /* ZFSStrings.hpp */; };\n\t\t7018764A20E7B4A600BA39B8 /* ZFSUtils.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 70D85FB81C2C076E00929DAE /* ZFSUtils.hpp */; };\n\t\t7018764B20E7B55700BA39B8 /* libZFSWrapperStatic.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7018763D20E7B44800BA39B8 /* libZFSWrapperStatic.a */; };\n\t\t7018765120E7B6A500BA39B8 /* ZFSUtils.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 70D85FB81C2C076E00929DAE /* ZFSUtils.hpp */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t7018765220E7B6A700BA39B8 /* ZFSStrings.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 70D85FC11C2D9CC900929DAE /* ZFSStrings.hpp */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t7018765320E7B6B500BA39B8 /* ZFSNVList.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 70D85FC31C2EAE5A00929DAE /* ZFSNVList.hpp */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t7018765620E7B79E00BA39B8 /* libZFSWrapperStatic.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7018763D20E7B44800BA39B8 /* libZFSWrapperStatic.a */; };\n\t\t7023C1FB26C1C768002C760A /* ZFSStrings.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7023C1FA26C1C768002C760A /* ZFSStrings.mm */; };\n\t\t7023C1FC26C1C768002C760A /* ZFSStrings.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7023C1FA26C1C768002C760A /* ZFSStrings.mm */; };\n\t\t703811A12312A2CB002C760A /* ZetaNotificationCenter.mm in Sources */ = {isa = PBXBuildFile; fileRef = 703811A02312A2CB002C760A /* ZetaNotificationCenter.mm */; };\n\t\t703811A42312C833002C760A /* ServiceManagement.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 703811A32312C833002C760A /* ServiceManagement.framework */; };\n\t\t703B176C262C6B0F002C760A /* libnvpair.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 703B1752262C6A31002C760A /* libnvpair.3.dylib */; };\n\t\t703B176D262C6B0F002C760A /* libzfs_core.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 703B1751262C6A31002C760A /* libzfs_core.3.dylib */; };\n\t\t703B176E262C6B0F002C760A /* libzfs.4.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 703B1750262C6A31002C760A /* libzfs.4.dylib */; };\n\t\t70552BC62336AFD8002C760A /* Sparkle.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 70552BC42336AEB2002C760A /* Sparkle.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };\n\t\t70552BC82336B196002C760A /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 70552BC42336AEB2002C760A /* Sparkle.framework */; };\n\t\t7068A94623ACFB0A002C760A /* NewVol.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7068A94423ACFB0A002C760A /* NewVol.xib */; };\n\t\t7068A94823ACFBB1002C760A /* SizeTransformer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7068A94723ACFBB1002C760A /* SizeTransformer.mm */; };\n\t\t70703F3722AD7633002C760A /* DiskArbitration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 70703F3622AD7633002C760A /* DiskArbitration.framework */; };\n\t\t70703F3922AD7A17002C760A /* IDDiskArbitrationUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70703F3822AD7A16002C760A /* IDDiskArbitrationUtils.cpp */; };\n\t\t7075BE36236E09DF002C760A /* ZetaLoginItemHelper.app in CopyFiles */ = {isa = PBXBuildFile; fileRef = 70E4A21D236DF7D6002C760A /* ZetaLoginItemHelper.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };\n\t\t708112B726D993F3002C760A /* libnvpair.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 703B1752262C6A31002C760A /* libnvpair.3.dylib */; };\n\t\t708112B826D993F4002C760A /* libzfs_core.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 703B1751262C6A31002C760A /* libzfs_core.3.dylib */; };\n\t\t708112B926D993F4002C760A /* libzfs.4.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 703B1750262C6A31002C760A /* libzfs.4.dylib */; };\n\t\t708112BB26D993F4002C760A /* libzpool.5.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 708112BA26D993F4002C760A /* libzpool.5.dylib */; };\n\t\t708112C026D99413002C760A /* libnvpair.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 703B1752262C6A31002C760A /* libnvpair.3.dylib */; };\n\t\t708112C126D99413002C760A /* libzfs_core.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 703B1751262C6A31002C760A /* libzfs_core.3.dylib */; };\n\t\t708112C226D99413002C760A /* libzfs.4.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 703B1750262C6A31002C760A /* libzfs.4.dylib */; };\n\t\t708112C326D99413002C760A /* libzpool.5.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 708112BA26D993F4002C760A /* libzpool.5.dylib */; };\n\t\t708112CC26D99470002C760A /* libzpool.5.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 708112BA26D993F4002C760A /* libzpool.5.dylib */; };\n\t\t708112CD26D99473002C760A /* libnvpair.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 703B1752262C6A31002C760A /* libnvpair.3.dylib */; };\n\t\t708112CE26D99475002C760A /* libzfs_core.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 703B1751262C6A31002C760A /* libzfs_core.3.dylib */; };\n\t\t708112CF26D99479002C760A /* libzfs.4.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 703B1750262C6A31002C760A /* libzfs.4.dylib */; };\n\t\t7099FB4523A575F9002C760A /* ZetaBookmarkMenu.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7099FB4323A575F8002C760A /* ZetaBookmarkMenu.mm */; };\n\t\t709C1CAD1C354F8B00929DAE /* ZetaPoolWatcher.mm in Sources */ = {isa = PBXBuildFile; fileRef = 709C1CAC1C354F8B00929DAE /* ZetaPoolWatcher.mm */; };\n\t\t70AE5AB222A3DBAA002C760A /* ZetaImportMenu.mm in Sources */ = {isa = PBXBuildFile; fileRef = 70AE5AB122A3DBAA002C760A /* ZetaImportMenu.mm */; };\n\t\t70AE5AB522A3F7D3002C760A /* ZetaCommanderBase.mm in Sources */ = {isa = PBXBuildFile; fileRef = 70AE5AB422A3F7D3002C760A /* ZetaCommanderBase.mm */; };\n\t\t70B4E4C922F45E7C002C760A /* IDDiskArbitrationDispatcher.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70B4E4C622F45E7C002C760A /* IDDiskArbitrationDispatcher.cpp */; };\n\t\t70B4E4CC22F469FC002C760A /* ZetaAutoImporter.mm in Sources */ = {isa = PBXBuildFile; fileRef = 70B4E4CA22F469FC002C760A /* ZetaAutoImporter.mm */; };\n\t\t70BF211023539130002C760A /* ZetaConfirmDialog.mm in Sources */ = {isa = PBXBuildFile; fileRef = 70BF210F23539130002C760A /* ZetaConfirmDialog.mm */; };\n\t\t70C930D822122CBD00BA39B8 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 70C930D622122CBD00BA39B8 /* Localizable.strings */; };\n\t\t70CE283D2348B0D4002C760A /* ZetaSnapshotMenu.mm in Sources */ = {isa = PBXBuildFile; fileRef = 70CE283C2348B0D4002C760A /* ZetaSnapshotMenu.mm */; };\n\t\t70D118B72375FE28002C760A /* PathValueTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 70D118B62375FE28002C760A /* PathValueTransformer.m */; };\n\t\t70D85FEF1C316F3100929DAE /* ZFSUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70D85FB71C2C076E00929DAE /* ZFSUtils.cpp */; };\n\t\t70D85FF01C316F3100929DAE /* ZFSStrings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70D85FBF1C2D9CB900929DAE /* ZFSStrings.cpp */; };\n\t\t70D85FF11C316F3100929DAE /* ZFSNVList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70D85FC21C2EAE5A00929DAE /* ZFSNVList.cpp */; };\n\t\t70DF66B1234A2884002C760A /* ZetaQueryDialog.mm in Sources */ = {isa = PBXBuildFile; fileRef = 70DF66AF234A2884002C760A /* ZetaQueryDialog.mm */; };\n\t\t70E4A229236DF7D7002C760A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 70E4A228236DF7D7002C760A /* main.m */; };\n\t\t70EA5F5022BEC358002C760A /* ZetaFileSystemPropertyMenu.mm in Sources */ = {isa = PBXBuildFile; fileRef = 70EA5F4F22BEC358002C760A /* ZetaFileSystemPropertyMenu.mm */; };\n\t\t70EA5F5322BEC7B1002C760A /* ZetaFormatHelpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70EA5F5222BEC7B1002C760A /* ZetaFormatHelpers.cpp */; };\n\t\t70EA5F5622BED079002C760A /* ZetaPoolPropertyMenu.mm in Sources */ = {isa = PBXBuildFile; fileRef = 70EA5F5522BED079002C760A /* ZetaPoolPropertyMenu.mm */; };\n\t\t70EABDC01FF9992A00BA39B8 /* ZetaAuthorization.mm in Sources */ = {isa = PBXBuildFile; fileRef = 70EABDBF1FF9992A00BA39B8 /* ZetaAuthorization.mm */; };\n\t\t70EABDC41FF9A8D100BA39B8 /* CommonAuthorization.m in Sources */ = {isa = PBXBuildFile; fileRef = 70EABDC31FF9A8D100BA39B8 /* CommonAuthorization.m */; };\n\t\t70EABDCD1FF9ACB300BA39B8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 70EABDCC1FF9ACB300BA39B8 /* main.m */; };\n\t\t70EABDD41FF9B21C00BA39B8 /* ZetaAuthorizationHelper.mm in Sources */ = {isa = PBXBuildFile; fileRef = 70EABDD31FF9B21C00BA39B8 /* ZetaAuthorizationHelper.mm */; };\n\t\t70EABDD91FF9B6C600BA39B8 /* net.the-color-black.ZetaAuthorizationHelper in CopyFiles */ = {isa = PBXBuildFile; fileRef = 70EABDCA1FF9ACB300BA39B8 /* net.the-color-black.ZetaAuthorizationHelper */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };\n\t\t70EABDDA1FF9C05700BA39B8 /* CommonAuthorization.m in Sources */ = {isa = PBXBuildFile; fileRef = 70EABDC31FF9A8D100BA39B8 /* CommonAuthorization.m */; };\n\t\t70EABDDC1FF9C1F000BA39B8 /* CommonAuthorization.strings in Resources */ = {isa = PBXBuildFile; fileRef = 70EABDDB1FF9C11E00BA39B8 /* CommonAuthorization.strings */; };\n\t\t70F307CD23ACD917002C760A /* ZetaDictQueryDialog.mm in Sources */ = {isa = PBXBuildFile; fileRef = 70F307CC23ACD917002C760A /* ZetaDictQueryDialog.mm */; };\n\t\t70F307D023ACE415002C760A /* NewFS.xib in Resources */ = {isa = PBXBuildFile; fileRef = 70F307CE23ACE415002C760A /* NewFS.xib */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\t7018764F20E7B62400BA39B8 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 7006C4731C26CA1400929DAE /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 7018763C20E7B44800BA39B8;\n\t\t\tremoteInfo = ZFSWrapperStatic;\n\t\t};\n\t\t7018765420E7B79800BA39B8 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 7006C4731C26CA1400929DAE /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 7018763C20E7B44800BA39B8;\n\t\t\tremoteInfo = ZFSWrapperStatic;\n\t\t};\n\t\t70E4A22E236DF7FD002C760A /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 7006C4731C26CA1400929DAE /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 70E4A21C236DF7D6002C760A;\n\t\t\tremoteInfo = ZetaLoginItemHelper;\n\t\t};\n\t\t70EABDD61FF9B69000BA39B8 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 7006C4731C26CA1400929DAE /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 70EABDC91FF9ACB300BA39B8;\n\t\t\tremoteInfo = ZetaAuthorizationHelper;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXCopyFilesBuildPhase section */\n\t\t70D85FEE1C316E8F00929DAE /* Embed Frameworks */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = \"\";\n\t\t\tdstSubfolderSpec = 10;\n\t\t\tfiles = (\n\t\t\t\t70552BC62336AFD8002C760A /* Sparkle.framework in Embed Frameworks */,\n\t\t\t);\n\t\t\tname = \"Embed Frameworks\";\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t70E4A212236DF1F6002C760A /* CopyFiles */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = Contents/Library/LoginItems;\n\t\t\tdstSubfolderSpec = 1;\n\t\t\tfiles = (\n\t\t\t\t7075BE36236E09DF002C760A /* ZetaLoginItemHelper.app in CopyFiles */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t70EABDD81FF9B6A200BA39B8 /* CopyFiles */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = Contents/Library/LaunchServices;\n\t\t\tdstSubfolderSpec = 1;\n\t\t\tfiles = (\n\t\t\t\t70EABDD91FF9B6C600BA39B8 /* net.the-color-black.ZetaAuthorizationHelper in CopyFiles */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXCopyFilesBuildPhase section */\n\n/* Begin PBXFileReference section */\n\t\t7006C47B1C26CA1500929DAE /* ZetaWatch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ZetaWatch.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t7006C47E1C26CA1500929DAE /* ZetaWatchDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ZetaWatchDelegate.h; sourceTree = \"<group>\"; };\n\t\t7006C47F1C26CA1500929DAE /* ZetaWatchDelegate.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ZetaWatchDelegate.mm; sourceTree = \"<group>\"; };\n\t\t7006C4821C26CA1500929DAE /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = \"<group>\"; };\n\t\t7006C4841C26CA1500929DAE /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = \"<group>\"; };\n\t\t7006C4871C26CA1500929DAE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = \"<group>\"; };\n\t\t7006C4891C26CA1500929DAE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t7006C4AB1C26D3E700929DAE /* ZetaMainMenu.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ZetaMainMenu.mm; sourceTree = \"<group>\"; };\n\t\t7006C4AD1C26D3FA00929DAE /* ZetaMainMenu.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ZetaMainMenu.h; sourceTree = \"<group>\"; };\n\t\t70168B6422B64E48002C760A /* ZetaKeyLoader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ZetaKeyLoader.h; sourceTree = \"<group>\"; };\n\t\t70168B6522B64E48002C760A /* ZetaKeyLoader.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ZetaKeyLoader.mm; sourceTree = \"<group>\"; };\n\t\t7018763D20E7B44800BA39B8 /* libZFSWrapperStatic.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libZFSWrapperStatic.a; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t7018765A20E7DA8100BA39B8 /* libzpool.1.dylib */ = {isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.dylib\"; path = libzpool.1.dylib; sourceTree = \"<group>\"; };\n\t\t7023C1FA26C1C768002C760A /* ZFSStrings.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ZFSStrings.mm; sourceTree = \"<group>\"; };\n\t\t703811A02312A2CB002C760A /* ZetaNotificationCenter.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ZetaNotificationCenter.mm; sourceTree = \"<group>\"; };\n\t\t703811A22312A2E6002C760A /* ZetaNotificationCenter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ZetaNotificationCenter.h; sourceTree = \"<group>\"; };\n\t\t703811A32312C833002C760A /* ServiceManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ServiceManagement.framework; path = System/Library/Frameworks/ServiceManagement.framework; sourceTree = SDKROOT; };\n\t\t703B1750262C6A31002C760A /* libzfs.4.dylib */ = {isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.dylib\"; name = libzfs.4.dylib; path = ../../../../usr/local/zfs/lib/libzfs.4.dylib; sourceTree = \"<group>\"; };\n\t\t703B1751262C6A31002C760A /* libzfs_core.3.dylib */ = {isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.dylib\"; name = libzfs_core.3.dylib; path = ../../../../usr/local/zfs/lib/libzfs_core.3.dylib; sourceTree = \"<group>\"; };\n\t\t703B1752262C6A31002C760A /* libnvpair.3.dylib */ = {isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.dylib\"; name = libnvpair.3.dylib; path = ../../../../usr/local/zfs/lib/libnvpair.3.dylib; sourceTree = \"<group>\"; };\n\t\t70552BC42336AEB2002C760A /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sparkle.framework; path = ThirdParty/Sparkle/DerivedData/Sparkle/Build/Products/Release/Sparkle.framework; sourceTree = \"<group>\"; };\n\t\t7068A94523ACFB0A002C760A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/NewVol.xib; sourceTree = \"<group>\"; };\n\t\t7068A94723ACFBB1002C760A /* SizeTransformer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SizeTransformer.mm; sourceTree = \"<group>\"; };\n\t\t70703F3622AD7633002C760A /* DiskArbitration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DiskArbitration.framework; path = System/Library/Frameworks/DiskArbitration.framework; sourceTree = SDKROOT; };\n\t\t70703F3822AD7A16002C760A /* IDDiskArbitrationUtils.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = IDDiskArbitrationUtils.cpp; path = InvariantDisks/IDDiskArbitrationUtils.cpp; sourceTree = \"<group>\"; };\n\t\t7072697B22EDB2BE002C760A /* ZetaCPPUtils.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ZetaCPPUtils.hpp; sourceTree = \"<group>\"; };\n\t\t708112BA26D993F4002C760A /* libzpool.5.dylib */ = {isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.dylib\"; name = libzpool.5.dylib; path = ../../../../usr/local/zfs/lib/libzpool.5.dylib; sourceTree = \"<group>\"; };\n\t\t7099FB4323A575F8002C760A /* ZetaBookmarkMenu.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ZetaBookmarkMenu.mm; sourceTree = \"<group>\"; };\n\t\t7099FB4423A575F8002C760A /* ZetaBookmarkMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZetaBookmarkMenu.h; sourceTree = \"<group>\"; };\n\t\t709C1CAC1C354F8B00929DAE /* ZetaPoolWatcher.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ZetaPoolWatcher.mm; sourceTree = \"<group>\"; };\n\t\t709C1CAE1C354F9B00929DAE /* ZetaPoolWatcher.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ZetaPoolWatcher.h; sourceTree = \"<group>\"; };\n\t\t70A60A4622AD7A5F002C760A /* IDDiskArbitrationUtils.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = IDDiskArbitrationUtils.hpp; path = InvariantDisks/IDDiskArbitrationUtils.hpp; sourceTree = \"<group>\"; };\n\t\t70AE5AB122A3DBAA002C760A /* ZetaImportMenu.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ZetaImportMenu.mm; sourceTree = \"<group>\"; };\n\t\t70AE5AB322A3DBBF002C760A /* ZetaImportMenu.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ZetaImportMenu.h; sourceTree = \"<group>\"; };\n\t\t70AE5AB422A3F7D3002C760A /* ZetaCommanderBase.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ZetaCommanderBase.mm; sourceTree = \"<group>\"; };\n\t\t70AE5AB622A3F7E4002C760A /* ZetaCommanderBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ZetaCommanderBase.h; sourceTree = \"<group>\"; };\n\t\t70B4E4C622F45E7C002C760A /* IDDiskArbitrationDispatcher.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IDDiskArbitrationDispatcher.cpp; path = InvariantDisks/IDDiskArbitrationDispatcher.cpp; sourceTree = \"<group>\"; };\n\t\t70B4E4C722F45E7C002C760A /* IDDiskArbitrationDispatcher.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = IDDiskArbitrationDispatcher.hpp; path = InvariantDisks/IDDiskArbitrationDispatcher.hpp; sourceTree = \"<group>\"; };\n\t\t70B4E4C822F45E7C002C760A /* IDDiskArbitrationHandler.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = IDDiskArbitrationHandler.hpp; path = InvariantDisks/IDDiskArbitrationHandler.hpp; sourceTree = \"<group>\"; };\n\t\t70B4E4CA22F469FC002C760A /* ZetaAutoImporter.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ZetaAutoImporter.mm; sourceTree = \"<group>\"; };\n\t\t70B4E4CB22F469FC002C760A /* ZetaAutoImporter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ZetaAutoImporter.h; sourceTree = \"<group>\"; };\n\t\t70BF210F23539130002C760A /* ZetaConfirmDialog.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ZetaConfirmDialog.mm; sourceTree = \"<group>\"; };\n\t\t70BF21112353914F002C760A /* ZetaConfirmDialog.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ZetaConfirmDialog.h; sourceTree = \"<group>\"; };\n\t\t70C930D722122CBD00BA39B8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Localizable.strings; sourceTree = \"<group>\"; };\n\t\t70CE283B2348B0D4002C760A /* ZetaSnapshotMenu.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ZetaSnapshotMenu.h; sourceTree = \"<group>\"; };\n\t\t70CE283C2348B0D4002C760A /* ZetaSnapshotMenu.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ZetaSnapshotMenu.mm; sourceTree = \"<group>\"; };\n\t\t70D118B62375FE28002C760A /* PathValueTransformer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PathValueTransformer.m; sourceTree = \"<group>\"; };\n\t\t70D85FB71C2C076E00929DAE /* ZFSUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ZFSUtils.cpp; sourceTree = \"<group>\"; };\n\t\t70D85FB81C2C076E00929DAE /* ZFSUtils.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ZFSUtils.hpp; sourceTree = \"<group>\"; };\n\t\t70D85FBA1C2C18BE00929DAE /* libzfs_core.1.dylib */ = {isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.dylib\"; path = libzfs_core.1.dylib; sourceTree = \"<group>\"; };\n\t\t70D85FBB1C2C18BE00929DAE /* libzfs.2.dylib */ = {isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.dylib\"; path = libzfs.2.dylib; sourceTree = \"<group>\"; };\n\t\t70D85FBF1C2D9CB900929DAE /* ZFSStrings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ZFSStrings.cpp; sourceTree = \"<group>\"; };\n\t\t70D85FC11C2D9CC900929DAE /* ZFSStrings.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ZFSStrings.hpp; sourceTree = \"<group>\"; };\n\t\t70D85FC21C2EAE5A00929DAE /* ZFSNVList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ZFSNVList.cpp; sourceTree = \"<group>\"; };\n\t\t70D85FC31C2EAE5A00929DAE /* ZFSNVList.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ZFSNVList.hpp; sourceTree = \"<group>\"; };\n\t\t70D85FC51C2EBC5000929DAE /* libnvpair.1.dylib */ = {isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.dylib\"; path = libnvpair.1.dylib; sourceTree = \"<group>\"; };\n\t\t70D85FE21C316E8F00929DAE /* ZFSWrapper.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ZFSWrapper.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t70D85FE61C316E8F00929DAE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t70DF66AF234A2884002C760A /* ZetaQueryDialog.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ZetaQueryDialog.mm; sourceTree = \"<group>\"; };\n\t\t70DF66B0234A2884002C760A /* ZetaQueryDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZetaQueryDialog.h; sourceTree = \"<group>\"; };\n\t\t70E4A21D236DF7D6002C760A /* ZetaLoginItemHelper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ZetaLoginItemHelper.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t70E4A227236DF7D7002C760A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t70E4A228236DF7D7002C760A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = \"<group>\"; };\n\t\t70EA5F4E22BEC358002C760A /* ZetaFileSystemPropertyMenu.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ZetaFileSystemPropertyMenu.h; sourceTree = \"<group>\"; };\n\t\t70EA5F4F22BEC358002C760A /* ZetaFileSystemPropertyMenu.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ZetaFileSystemPropertyMenu.mm; sourceTree = \"<group>\"; };\n\t\t70EA5F5122BEC6BC002C760A /* ZetaFormatHelpers.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ZetaFormatHelpers.hpp; sourceTree = \"<group>\"; };\n\t\t70EA5F5222BEC7B1002C760A /* ZetaFormatHelpers.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ZetaFormatHelpers.cpp; sourceTree = \"<group>\"; };\n\t\t70EA5F5422BED079002C760A /* ZetaPoolPropertyMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZetaPoolPropertyMenu.h; sourceTree = \"<group>\"; };\n\t\t70EA5F5522BED079002C760A /* ZetaPoolPropertyMenu.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ZetaPoolPropertyMenu.mm; sourceTree = \"<group>\"; };\n\t\t70EABDBE1FF9992A00BA39B8 /* ZetaAuthorization.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ZetaAuthorization.h; sourceTree = \"<group>\"; };\n\t\t70EABDBF1FF9992A00BA39B8 /* ZetaAuthorization.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ZetaAuthorization.mm; sourceTree = \"<group>\"; };\n\t\t70EABDC21FF9A8D100BA39B8 /* CommonAuthorization.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CommonAuthorization.h; sourceTree = \"<group>\"; };\n\t\t70EABDC31FF9A8D100BA39B8 /* CommonAuthorization.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CommonAuthorization.m; sourceTree = \"<group>\"; };\n\t\t70EABDC51FF9AAB800BA39B8 /* ZetaAuthorizationHelperProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ZetaAuthorizationHelperProtocol.h; sourceTree = \"<group>\"; };\n\t\t70EABDCA1FF9ACB300BA39B8 /* net.the-color-black.ZetaAuthorizationHelper */ = {isa = PBXFileReference; explicitFileType = \"compiled.mach-o.executable\"; includeInIndex = 0; path = \"net.the-color-black.ZetaAuthorizationHelper\"; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t70EABDCC1FF9ACB300BA39B8 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = \"<group>\"; };\n\t\t70EABDD11FF9AE2800BA39B8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t70EABDD21FF9B21C00BA39B8 /* ZetaAuthorizationHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ZetaAuthorizationHelper.h; sourceTree = \"<group>\"; };\n\t\t70EABDD31FF9B21C00BA39B8 /* ZetaAuthorizationHelper.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ZetaAuthorizationHelper.mm; sourceTree = \"<group>\"; };\n\t\t70EABDD51FF9B40F00BA39B8 /* Launchd.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Launchd.plist; sourceTree = \"<group>\"; };\n\t\t70EABDDB1FF9C11E00BA39B8 /* CommonAuthorization.strings */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; path = CommonAuthorization.strings; sourceTree = \"<group>\"; };\n\t\t70F307CB23ACD917002C760A /* ZetaDictQueryDialog.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ZetaDictQueryDialog.h; sourceTree = \"<group>\"; };\n\t\t70F307CC23ACD917002C760A /* ZetaDictQueryDialog.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ZetaDictQueryDialog.mm; sourceTree = \"<group>\"; };\n\t\t70F307CF23ACE415002C760A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/NewFS.xib; sourceTree = \"<group>\"; };\n\t\t70F386AA22906D36002C760A /* ZetaWatch.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ZetaWatch.entitlements; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t7006C4781C26CA1400929DAE /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t703811A42312C833002C760A /* ServiceManagement.framework in Frameworks */,\n\t\t\t\t70703F3722AD7633002C760A /* DiskArbitration.framework in Frameworks */,\n\t\t\t\t7018764B20E7B55700BA39B8 /* libZFSWrapperStatic.a in Frameworks */,\n\t\t\t\t703B176C262C6B0F002C760A /* libnvpair.3.dylib in Frameworks */,\n\t\t\t\t703B176D262C6B0F002C760A /* libzfs_core.3.dylib in Frameworks */,\n\t\t\t\t703B176E262C6B0F002C760A /* libzfs.4.dylib in Frameworks */,\n\t\t\t\t70552BC82336B196002C760A /* Sparkle.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t7018763A20E7B44800BA39B8 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t708112BB26D993F4002C760A /* libzpool.5.dylib in Frameworks */,\n\t\t\t\t708112B726D993F3002C760A /* libnvpair.3.dylib in Frameworks */,\n\t\t\t\t708112B826D993F4002C760A /* libzfs_core.3.dylib in Frameworks */,\n\t\t\t\t708112B926D993F4002C760A /* libzfs.4.dylib in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t70D85FDE1C316E8F00929DAE /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t708112C026D99413002C760A /* libnvpair.3.dylib in Frameworks */,\n\t\t\t\t708112C126D99413002C760A /* libzfs_core.3.dylib in Frameworks */,\n\t\t\t\t708112C226D99413002C760A /* libzfs.4.dylib in Frameworks */,\n\t\t\t\t708112C326D99413002C760A /* libzpool.5.dylib in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t70E4A21A236DF7D6002C760A /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t70EABDC71FF9ACB300BA39B8 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t7018765620E7B79E00BA39B8 /* libZFSWrapperStatic.a in Frameworks */,\n\t\t\t\t708112CC26D99470002C760A /* libzpool.5.dylib in Frameworks */,\n\t\t\t\t708112CD26D99473002C760A /* libnvpair.3.dylib in Frameworks */,\n\t\t\t\t708112CE26D99475002C760A /* libzfs_core.3.dylib in Frameworks */,\n\t\t\t\t708112CF26D99479002C760A /* libzfs.4.dylib in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t7006C4721C26CA1400929DAE = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t7006C47D1C26CA1500929DAE /* ZetaWatch */,\n\t\t\t\t70D85FCC1C316B0900929DAE /* ZFSWrapper */,\n\t\t\t\t70EABDCB1FF9ACB300BA39B8 /* ZetaAuthorizationHelper */,\n\t\t\t\t70EABDC11FF9A81800BA39B8 /* CommonAuthorization */,\n\t\t\t\t70E4A21E236DF7D6002C760A /* ZetaLoginItemHelper */,\n\t\t\t\t7006C47C1C26CA1500929DAE /* Products */,\n\t\t\t\t70DB77B11FFAD8E300BA39B8 /* Frameworks */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t7006C47C1C26CA1500929DAE /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t7006C47B1C26CA1500929DAE /* ZetaWatch.app */,\n\t\t\t\t70D85FE21C316E8F00929DAE /* ZFSWrapper.framework */,\n\t\t\t\t70EABDCA1FF9ACB300BA39B8 /* net.the-color-black.ZetaAuthorizationHelper */,\n\t\t\t\t7018763D20E7B44800BA39B8 /* libZFSWrapperStatic.a */,\n\t\t\t\t70E4A21D236DF7D6002C760A /* ZetaLoginItemHelper.app */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t7006C47D1C26CA1500929DAE /* ZetaWatch */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t7006C47E1C26CA1500929DAE /* ZetaWatchDelegate.h */,\n\t\t\t\t7006C47F1C26CA1500929DAE /* ZetaWatchDelegate.mm */,\n\t\t\t\t70AE5AB622A3F7E4002C760A /* ZetaCommanderBase.h */,\n\t\t\t\t70AE5AB422A3F7D3002C760A /* ZetaCommanderBase.mm */,\n\t\t\t\t7006C4AD1C26D3FA00929DAE /* ZetaMainMenu.h */,\n\t\t\t\t7006C4AB1C26D3E700929DAE /* ZetaMainMenu.mm */,\n\t\t\t\t70CE283B2348B0D4002C760A /* ZetaSnapshotMenu.h */,\n\t\t\t\t70CE283C2348B0D4002C760A /* ZetaSnapshotMenu.mm */,\n\t\t\t\t70EA5F4E22BEC358002C760A /* ZetaFileSystemPropertyMenu.h */,\n\t\t\t\t70EA5F4F22BEC358002C760A /* ZetaFileSystemPropertyMenu.mm */,\n\t\t\t\t7099FB4423A575F8002C760A /* ZetaBookmarkMenu.h */,\n\t\t\t\t7099FB4323A575F8002C760A /* ZetaBookmarkMenu.mm */,\n\t\t\t\t70EA5F5422BED079002C760A /* ZetaPoolPropertyMenu.h */,\n\t\t\t\t70EA5F5522BED079002C760A /* ZetaPoolPropertyMenu.mm */,\n\t\t\t\t70AE5AB322A3DBBF002C760A /* ZetaImportMenu.h */,\n\t\t\t\t70AE5AB122A3DBAA002C760A /* ZetaImportMenu.mm */,\n\t\t\t\t70168B6422B64E48002C760A /* ZetaKeyLoader.h */,\n\t\t\t\t70168B6522B64E48002C760A /* ZetaKeyLoader.mm */,\n\t\t\t\t70DF66B0234A2884002C760A /* ZetaQueryDialog.h */,\n\t\t\t\t70DF66AF234A2884002C760A /* ZetaQueryDialog.mm */,\n\t\t\t\t70F307CB23ACD917002C760A /* ZetaDictQueryDialog.h */,\n\t\t\t\t70F307CC23ACD917002C760A /* ZetaDictQueryDialog.mm */,\n\t\t\t\t70BF21112353914F002C760A /* ZetaConfirmDialog.h */,\n\t\t\t\t70BF210F23539130002C760A /* ZetaConfirmDialog.mm */,\n\t\t\t\t709C1CAE1C354F9B00929DAE /* ZetaPoolWatcher.h */,\n\t\t\t\t709C1CAC1C354F8B00929DAE /* ZetaPoolWatcher.mm */,\n\t\t\t\t70B4E4CB22F469FC002C760A /* ZetaAutoImporter.h */,\n\t\t\t\t70B4E4CA22F469FC002C760A /* ZetaAutoImporter.mm */,\n\t\t\t\t70EABDBE1FF9992A00BA39B8 /* ZetaAuthorization.h */,\n\t\t\t\t70EABDBF1FF9992A00BA39B8 /* ZetaAuthorization.mm */,\n\t\t\t\t703811A22312A2E6002C760A /* ZetaNotificationCenter.h */,\n\t\t\t\t703811A02312A2CB002C760A /* ZetaNotificationCenter.mm */,\n\t\t\t\t70EA5F5122BEC6BC002C760A /* ZetaFormatHelpers.hpp */,\n\t\t\t\t70EA5F5222BEC7B1002C760A /* ZetaFormatHelpers.cpp */,\n\t\t\t\t70D118B62375FE28002C760A /* PathValueTransformer.m */,\n\t\t\t\t7068A94723ACFBB1002C760A /* SizeTransformer.mm */,\n\t\t\t\t70A60A4622AD7A5F002C760A /* IDDiskArbitrationUtils.hpp */,\n\t\t\t\t70703F3822AD7A16002C760A /* IDDiskArbitrationUtils.cpp */,\n\t\t\t\t70B4E4C722F45E7C002C760A /* IDDiskArbitrationDispatcher.hpp */,\n\t\t\t\t70B4E4C622F45E7C002C760A /* IDDiskArbitrationDispatcher.cpp */,\n\t\t\t\t70B4E4C822F45E7C002C760A /* IDDiskArbitrationHandler.hpp */,\n\t\t\t\t7006C4841C26CA1500929DAE /* Assets.xcassets */,\n\t\t\t\t70C930D622122CBD00BA39B8 /* Localizable.strings */,\n\t\t\t\t7006C4861C26CA1500929DAE /* MainMenu.xib */,\n\t\t\t\t70F307CE23ACE415002C760A /* NewFS.xib */,\n\t\t\t\t7068A94423ACFB0A002C760A /* NewVol.xib */,\n\t\t\t\t7006C4891C26CA1500929DAE /* Info.plist */,\n\t\t\t\t70F386AA22906D36002C760A /* ZetaWatch.entitlements */,\n\t\t\t\t7006C4811C26CA1500929DAE /* Supporting Files */,\n\t\t\t);\n\t\t\tpath = ZetaWatch;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t7006C4811C26CA1500929DAE /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t7006C4821C26CA1500929DAE /* main.m */,\n\t\t\t);\n\t\t\tname = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t7023C21926C1DF98002C760A /* include */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t70D85FB81C2C076E00929DAE /* ZFSUtils.hpp */,\n\t\t\t\t70D85FC11C2D9CC900929DAE /* ZFSStrings.hpp */,\n\t\t\t\t70D85FC31C2EAE5A00929DAE /* ZFSNVList.hpp */,\n\t\t\t);\n\t\t\tpath = include;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t7023C21A26C1DFA2002C760A /* src */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t70D85FB71C2C076E00929DAE /* ZFSUtils.cpp */,\n\t\t\t\t70D85FBF1C2D9CB900929DAE /* ZFSStrings.cpp */,\n\t\t\t\t7023C1FA26C1C768002C760A /* ZFSStrings.mm */,\n\t\t\t\t70D85FC21C2EAE5A00929DAE /* ZFSNVList.cpp */,\n\t\t\t);\n\t\t\tpath = src;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t7023C21B26C1DFB1002C760A /* misc */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t70D85FE61C316E8F00929DAE /* Info.plist */,\n\t\t\t);\n\t\t\tpath = misc;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t70D85FBE1C2C1D9100929DAE /* lib */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t70D85FC51C2EBC5000929DAE /* libnvpair.1.dylib */,\n\t\t\t\t70D85FBA1C2C18BE00929DAE /* libzfs_core.1.dylib */,\n\t\t\t\t70D85FBB1C2C18BE00929DAE /* libzfs.2.dylib */,\n\t\t\t\t7018765A20E7DA8100BA39B8 /* libzpool.1.dylib */,\n\t\t\t);\n\t\t\tname = lib;\n\t\t\tpath = /usr/local/lib;\n\t\t\tsourceTree = \"<absolute>\";\n\t\t};\n\t\t70D85FCC1C316B0900929DAE /* ZFSWrapper */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t7023C21B26C1DFB1002C760A /* misc */,\n\t\t\t\t7023C21A26C1DFA2002C760A /* src */,\n\t\t\t\t7023C21926C1DF98002C760A /* include */,\n\t\t\t\t70D85FBE1C2C1D9100929DAE /* lib */,\n\t\t\t);\n\t\t\tpath = ZFSWrapper;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t70DB77B11FFAD8E300BA39B8 /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t708112BA26D993F4002C760A /* libzpool.5.dylib */,\n\t\t\t\t703B1752262C6A31002C760A /* libnvpair.3.dylib */,\n\t\t\t\t703B1751262C6A31002C760A /* libzfs_core.3.dylib */,\n\t\t\t\t703B1750262C6A31002C760A /* libzfs.4.dylib */,\n\t\t\t\t70552BC42336AEB2002C760A /* Sparkle.framework */,\n\t\t\t\t703811A32312C833002C760A /* ServiceManagement.framework */,\n\t\t\t\t70703F3622AD7633002C760A /* DiskArbitration.framework */,\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t70E4A21E236DF7D6002C760A /* ZetaLoginItemHelper */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t70E4A227236DF7D7002C760A /* Info.plist */,\n\t\t\t\t70E4A228236DF7D7002C760A /* main.m */,\n\t\t\t);\n\t\t\tpath = ZetaLoginItemHelper;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t70EABDC11FF9A81800BA39B8 /* CommonAuthorization */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t70EABDC21FF9A8D100BA39B8 /* CommonAuthorization.h */,\n\t\t\t\t70EABDC31FF9A8D100BA39B8 /* CommonAuthorization.m */,\n\t\t\t\t70EABDDB1FF9C11E00BA39B8 /* CommonAuthorization.strings */,\n\t\t\t);\n\t\t\tpath = CommonAuthorization;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t70EABDCB1FF9ACB300BA39B8 /* ZetaAuthorizationHelper */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t70EABDC51FF9AAB800BA39B8 /* ZetaAuthorizationHelperProtocol.h */,\n\t\t\t\t70EABDD21FF9B21C00BA39B8 /* ZetaAuthorizationHelper.h */,\n\t\t\t\t70EABDD31FF9B21C00BA39B8 /* ZetaAuthorizationHelper.mm */,\n\t\t\t\t7072697B22EDB2BE002C760A /* ZetaCPPUtils.hpp */,\n\t\t\t\t70EABDCC1FF9ACB300BA39B8 /* main.m */,\n\t\t\t\t70EABDD11FF9AE2800BA39B8 /* Info.plist */,\n\t\t\t\t70EABDD51FF9B40F00BA39B8 /* Launchd.plist */,\n\t\t\t);\n\t\t\tpath = ZetaAuthorizationHelper;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXHeadersBuildPhase section */\n\t\t7018763B20E7B44800BA39B8 /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t7018764A20E7B4A600BA39B8 /* ZFSUtils.hpp in Headers */,\n\t\t\t\t7018764820E7B4A100BA39B8 /* ZFSNVList.hpp in Headers */,\n\t\t\t\t7018764920E7B4A300BA39B8 /* ZFSStrings.hpp in Headers */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t70D85FDF1C316E8F00929DAE /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t7018765120E7B6A500BA39B8 /* ZFSUtils.hpp in Headers */,\n\t\t\t\t7018765320E7B6B500BA39B8 /* ZFSNVList.hpp in Headers */,\n\t\t\t\t7018765220E7B6A700BA39B8 /* ZFSStrings.hpp in Headers */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXHeadersBuildPhase section */\n\n/* Begin PBXNativeTarget section */\n\t\t7006C47A1C26CA1400929DAE /* ZetaWatch */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 7006C4A21C26CA1500929DAE /* Build configuration list for PBXNativeTarget \"ZetaWatch\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t7006C4771C26CA1400929DAE /* Sources */,\n\t\t\t\t7006C4781C26CA1400929DAE /* Frameworks */,\n\t\t\t\t7006C4791C26CA1400929DAE /* Resources */,\n\t\t\t\t70D85FEE1C316E8F00929DAE /* Embed Frameworks */,\n\t\t\t\t70EABDD81FF9B6A200BA39B8 /* CopyFiles */,\n\t\t\t\t70E4A212236DF1F6002C760A /* CopyFiles */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t70E4A22F236DF7FD002C760A /* PBXTargetDependency */,\n\t\t\t\t7018765020E7B62400BA39B8 /* PBXTargetDependency */,\n\t\t\t\t70EABDD71FF9B69000BA39B8 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = ZetaWatch;\n\t\t\tproductName = ZetaWatch;\n\t\t\tproductReference = 7006C47B1C26CA1500929DAE /* ZetaWatch.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n\t\t7018763C20E7B44800BA39B8 /* ZFSWrapperStatic */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 7018763E20E7B44800BA39B8 /* Build configuration list for PBXNativeTarget \"ZFSWrapperStatic\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t7018763920E7B44800BA39B8 /* Sources */,\n\t\t\t\t7018763A20E7B44800BA39B8 /* Frameworks */,\n\t\t\t\t7018763B20E7B44800BA39B8 /* Headers */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = ZFSWrapperStatic;\n\t\t\tproductName = ZFSWrapperStatic;\n\t\t\tproductReference = 7018763D20E7B44800BA39B8 /* libZFSWrapperStatic.a */;\n\t\t\tproductType = \"com.apple.product-type.library.static\";\n\t\t};\n\t\t70D85FE11C316E8F00929DAE /* ZFSWrapper */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 70D85FEB1C316E8F00929DAE /* Build configuration list for PBXNativeTarget \"ZFSWrapper\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t70D85FDD1C316E8F00929DAE /* Sources */,\n\t\t\t\t70D85FDE1C316E8F00929DAE /* Frameworks */,\n\t\t\t\t70D85FDF1C316E8F00929DAE /* Headers */,\n\t\t\t\t70D85FE01C316E8F00929DAE /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = ZFSWrapper;\n\t\t\tproductName = ZFSWrapper;\n\t\t\tproductReference = 70D85FE21C316E8F00929DAE /* ZFSWrapper.framework */;\n\t\t\tproductType = \"com.apple.product-type.framework\";\n\t\t};\n\t\t70E4A21C236DF7D6002C760A /* ZetaLoginItemHelper */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 70E4A22B236DF7D7002C760A /* Build configuration list for PBXNativeTarget \"ZetaLoginItemHelper\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t70E4A219236DF7D6002C760A /* Sources */,\n\t\t\t\t70E4A21A236DF7D6002C760A /* Frameworks */,\n\t\t\t\t70E4A21B236DF7D6002C760A /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = ZetaLoginItemHelper;\n\t\t\tproductName = ZetaLoginItemHelper;\n\t\t\tproductReference = 70E4A21D236DF7D6002C760A /* ZetaLoginItemHelper.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n\t\t70EABDC91FF9ACB300BA39B8 /* ZetaAuthorizationHelper */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 70EABDCE1FF9ACB300BA39B8 /* Build configuration list for PBXNativeTarget \"ZetaAuthorizationHelper\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t70EABDC61FF9ACB300BA39B8 /* Sources */,\n\t\t\t\t70EABDC71FF9ACB300BA39B8 /* Frameworks */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t7018765520E7B79800BA39B8 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = ZetaAuthorizationHelper;\n\t\t\tproductName = ZetaAuthorizationHelper;\n\t\t\tproductReference = 70EABDCA1FF9ACB300BA39B8 /* net.the-color-black.ZetaAuthorizationHelper */;\n\t\t\tproductType = \"com.apple.product-type.tool\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t7006C4731C26CA1400929DAE /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 1130;\n\t\t\t\tORGANIZATIONNAME = \"the-color-black.net\";\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t7006C47A1C26CA1400929DAE = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.2;\n\t\t\t\t\t\tDevelopmentTeam = 8THUW5GT6P;\n\t\t\t\t\t\tProvisioningStyle = Manual;\n\t\t\t\t\t};\n\t\t\t\t\t7018763C20E7B44800BA39B8 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 9.4.1;\n\t\t\t\t\t\tDevelopmentTeam = 8THUW5GT6P;\n\t\t\t\t\t\tProvisioningStyle = Automatic;\n\t\t\t\t\t};\n\t\t\t\t\t70D85FE11C316E8F00929DAE = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.2;\n\t\t\t\t\t\tDevelopmentTeam = 8THUW5GT6P;\n\t\t\t\t\t\tProvisioningStyle = Manual;\n\t\t\t\t\t};\n\t\t\t\t\t70E4A21C236DF7D6002C760A = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 10.1;\n\t\t\t\t\t\tDevelopmentTeam = 8THUW5GT6P;\n\t\t\t\t\t\tProvisioningStyle = Manual;\n\t\t\t\t\t\tSystemCapabilities = {\n\t\t\t\t\t\t\tcom.apple.Sandbox = {\n\t\t\t\t\t\t\t\tenabled = 0;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t\t70EABDC91FF9ACB300BA39B8 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 9.2;\n\t\t\t\t\t\tDevelopmentTeam = 8THUW5GT6P;\n\t\t\t\t\t\tProvisioningStyle = Manual;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 7006C4761C26CA1400929DAE /* Build configuration list for PBXProject \"ZetaWatch\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = en;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 7006C4721C26CA1400929DAE;\n\t\t\tproductRefGroup = 7006C47C1C26CA1500929DAE /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t7006C47A1C26CA1400929DAE /* ZetaWatch */,\n\t\t\t\t70D85FE11C316E8F00929DAE /* ZFSWrapper */,\n\t\t\t\t7018763C20E7B44800BA39B8 /* ZFSWrapperStatic */,\n\t\t\t\t70EABDC91FF9ACB300BA39B8 /* ZetaAuthorizationHelper */,\n\t\t\t\t70E4A21C236DF7D6002C760A /* ZetaLoginItemHelper */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t7006C4791C26CA1400929DAE /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t70EABDDC1FF9C1F000BA39B8 /* CommonAuthorization.strings in Resources */,\n\t\t\t\t70C930D822122CBD00BA39B8 /* Localizable.strings in Resources */,\n\t\t\t\t7068A94623ACFB0A002C760A /* NewVol.xib in Resources */,\n\t\t\t\t70F307D023ACE415002C760A /* NewFS.xib in Resources */,\n\t\t\t\t7006C4851C26CA1500929DAE /* Assets.xcassets in Resources */,\n\t\t\t\t7006C4881C26CA1500929DAE /* MainMenu.xib in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t70D85FE01C316E8F00929DAE /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t70E4A21B236DF7D6002C760A /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t7006C4771C26CA1400929DAE /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t70B4E4CC22F469FC002C760A /* ZetaAutoImporter.mm in Sources */,\n\t\t\t\t70EA5F5322BEC7B1002C760A /* ZetaFormatHelpers.cpp in Sources */,\n\t\t\t\t70F307CD23ACD917002C760A /* ZetaDictQueryDialog.mm in Sources */,\n\t\t\t\t709C1CAD1C354F8B00929DAE /* ZetaPoolWatcher.mm in Sources */,\n\t\t\t\t70B4E4C922F45E7C002C760A /* IDDiskArbitrationDispatcher.cpp in Sources */,\n\t\t\t\t7068A94823ACFBB1002C760A /* SizeTransformer.mm in Sources */,\n\t\t\t\t7006C4831C26CA1500929DAE /* main.m in Sources */,\n\t\t\t\t70EA5F5622BED079002C760A /* ZetaPoolPropertyMenu.mm in Sources */,\n\t\t\t\t70D118B72375FE28002C760A /* PathValueTransformer.m in Sources */,\n\t\t\t\t7006C4801C26CA1500929DAE /* ZetaWatchDelegate.mm in Sources */,\n\t\t\t\t7006C4AC1C26D3E700929DAE /* ZetaMainMenu.mm in Sources */,\n\t\t\t\t7099FB4523A575F9002C760A /* ZetaBookmarkMenu.mm in Sources */,\n\t\t\t\t70AE5AB222A3DBAA002C760A /* ZetaImportMenu.mm in Sources */,\n\t\t\t\t70EABDC41FF9A8D100BA39B8 /* CommonAuthorization.m in Sources */,\n\t\t\t\t70168B6622B64E48002C760A /* ZetaKeyLoader.mm in Sources */,\n\t\t\t\t70EABDC01FF9992A00BA39B8 /* ZetaAuthorization.mm in Sources */,\n\t\t\t\t70DF66B1234A2884002C760A /* ZetaQueryDialog.mm in Sources */,\n\t\t\t\t70CE283D2348B0D4002C760A /* ZetaSnapshotMenu.mm in Sources */,\n\t\t\t\t70EA5F5022BEC358002C760A /* ZetaFileSystemPropertyMenu.mm in Sources */,\n\t\t\t\t70BF211023539130002C760A /* ZetaConfirmDialog.mm in Sources */,\n\t\t\t\t70AE5AB522A3F7D3002C760A /* ZetaCommanderBase.mm in Sources */,\n\t\t\t\t70703F3922AD7A17002C760A /* IDDiskArbitrationUtils.cpp in Sources */,\n\t\t\t\t703811A12312A2CB002C760A /* ZetaNotificationCenter.mm in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t7018763920E7B44800BA39B8 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t7018764120E7B45900BA39B8 /* ZFSUtils.cpp in Sources */,\n\t\t\t\t7018764220E7B45B00BA39B8 /* ZFSStrings.cpp in Sources */,\n\t\t\t\t7023C1FB26C1C768002C760A /* ZFSStrings.mm in Sources */,\n\t\t\t\t7018764320E7B45E00BA39B8 /* ZFSNVList.cpp in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t70D85FDD1C316E8F00929DAE /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t70D85FF01C316F3100929DAE /* ZFSStrings.cpp in Sources */,\n\t\t\t\t70D85FF11C316F3100929DAE /* ZFSNVList.cpp in Sources */,\n\t\t\t\t7023C1FC26C1C768002C760A /* ZFSStrings.mm in Sources */,\n\t\t\t\t70D85FEF1C316F3100929DAE /* ZFSUtils.cpp in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t70E4A219236DF7D6002C760A /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t70E4A229236DF7D7002C760A /* main.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t70EABDC61FF9ACB300BA39B8 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t70EABDCD1FF9ACB300BA39B8 /* main.m in Sources */,\n\t\t\t\t70EABDDA1FF9C05700BA39B8 /* CommonAuthorization.m in Sources */,\n\t\t\t\t70EABDD41FF9B21C00BA39B8 /* ZetaAuthorizationHelper.mm in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\t7018765020E7B62400BA39B8 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 7018763C20E7B44800BA39B8 /* ZFSWrapperStatic */;\n\t\t\ttargetProxy = 7018764F20E7B62400BA39B8 /* PBXContainerItemProxy */;\n\t\t};\n\t\t7018765520E7B79800BA39B8 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 7018763C20E7B44800BA39B8 /* ZFSWrapperStatic */;\n\t\t\ttargetProxy = 7018765420E7B79800BA39B8 /* PBXContainerItemProxy */;\n\t\t};\n\t\t70E4A22F236DF7FD002C760A /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 70E4A21C236DF7D6002C760A /* ZetaLoginItemHelper */;\n\t\t\ttargetProxy = 70E4A22E236DF7FD002C760A /* PBXContainerItemProxy */;\n\t\t};\n\t\t70EABDD71FF9B69000BA39B8 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 70EABDC91FF9ACB300BA39B8 /* ZetaAuthorizationHelper */;\n\t\t\ttargetProxy = 70EABDD61FF9B69000BA39B8 /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin PBXVariantGroup section */\n\t\t7006C4861C26CA1500929DAE /* MainMenu.xib */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t7006C4871C26CA1500929DAE /* Base */,\n\t\t\t);\n\t\t\tname = MainMenu.xib;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t7068A94423ACFB0A002C760A /* NewVol.xib */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t7068A94523ACFB0A002C760A /* Base */,\n\t\t\t);\n\t\t\tname = NewVol.xib;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t70C930D622122CBD00BA39B8 /* Localizable.strings */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t70C930D722122CBD00BA39B8 /* Base */,\n\t\t\t);\n\t\t\tname = Localizable.strings;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t70F307CE23ACE415002C760A /* NewFS.xib */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t70F307CF23ACE415002C760A /* Base */,\n\t\t\t);\n\t\t\tname = NewFS.xib;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\t7006C4A01C26CA1500929DAE /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tARCHS = x86_64;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++17\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = ZetaWatch/ZetaWatch.entitlements;\n\t\t\t\tCODE_SIGN_IDENTITY = \"Apple Development\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tDEVELOPMENT_TEAM = 8THUW5GT6P;\n\t\t\t\tENABLE_HARDENED_RUNTIME = YES;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tLIBRARY_SEARCH_PATHS = \"$(ZFS_DIR)/lib\";\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.12;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\tZETA_VERSION = 50;\n\t\t\t\tZFS_DIR = /usr/local/zfs;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t7006C4A11C26CA1500929DAE /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tARCHS = x86_64;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++17\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCODE_SIGN_ENTITLEMENTS = ZetaWatch/ZetaWatch.entitlements;\n\t\t\t\tCODE_SIGN_IDENTITY = \"Apple Development\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tDEVELOPMENT_TEAM = 8THUW5GT6P;\n\t\t\t\tENABLE_HARDENED_RUNTIME = YES;\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tLIBRARY_SEARCH_PATHS = \"$(ZFS_DIR)/lib\";\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.12;\n\t\t\t\tSDKROOT = macosx;\n\t\t\t\tZETA_VERSION = 50;\n\t\t\t\tZFS_DIR = /usr/local/zfs;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t7006C4A31C26CA1500929DAE /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCODE_SIGN_IDENTITY = \"Developer ID Application\";\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/ThirdParty/Sparkle/DerivedData/Sparkle/Build/Products/Release/\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = ZetaWatch/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/../Frameworks\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/usr/local/zfs/lib,\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"net.the-color-black.ZetaWatch\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t7006C4A41C26CA1500929DAE /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCODE_SIGN_IDENTITY = \"Developer ID Application\";\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/ThirdParty/Sparkle/DerivedData/Sparkle/Build/Products/Release/\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = ZetaWatch/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/../Frameworks\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t/usr/local/zfs/lib,\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"net.the-color-black.ZetaWatch\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t7018763F20E7B44800BA39B8 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tEXECUTABLE_PREFIX = lib;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu11;\n\t\t\t\t\"GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS[arch=*]\" = (\n\t\t\t\t\tZFSW_HAS_ZPOOL_STATUS_COMPATIBILITY_ERR,\n\t\t\t\t\tZFSW_HAS_ZPOOL_STATUS_INCOMPATIBLE_FEAT,\n\t\t\t\t);\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t\"$(ZFS_DIR)/include\",\n\t\t\t\t\t\"$(ZFS_DIR)/include/libzfs\",\n\t\t\t\t\t\"$(ZFS_DIR)/include/libspl\",\n\t\t\t\t\t\"$(ZFS_DIR)/include/libspl/os/macos\",\n\t\t\t\t);\n\t\t\t\tLIBRARY_SEARCH_PATHS = \"$(ZFS_DIR)/lib\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t7018764020E7B44800BA39B8 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tEXECUTABLE_PREFIX = lib;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu11;\n\t\t\t\t\"GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS[arch=*]\" = (\n\t\t\t\t\tZFSW_HAS_ZPOOL_STATUS_COMPATIBILITY_ERR,\n\t\t\t\t\tZFSW_HAS_ZPOOL_STATUS_INCOMPATIBLE_FEAT,\n\t\t\t\t);\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t\"$(ZFS_DIR)/include\",\n\t\t\t\t\t\"$(ZFS_DIR)/include/libzfs\",\n\t\t\t\t\t\"$(ZFS_DIR)/include/libspl\",\n\t\t\t\t\t\"$(ZFS_DIR)/include/libspl/os/macos\",\n\t\t\t\t);\n\t\t\t\tLIBRARY_SEARCH_PATHS = \"$(ZFS_DIR)/lib\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t70D85FEC1C316E8F00929DAE /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCODE_SIGN_IDENTITY = \"Developer ID Application\";\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEFINES_MODULE = YES;\n\t\t\t\tDYLIB_COMPATIBILITY_VERSION = 1;\n\t\t\t\tDYLIB_CURRENT_VERSION = 1;\n\t\t\t\tDYLIB_INSTALL_NAME_BASE = \"@rpath\";\n\t\t\t\tFRAMEWORK_VERSION = A;\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = YES;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t\"$(ZFS_DIR)/include\",\n\t\t\t\t\t\"$(ZFS_DIR)/include/libzfs\",\n\t\t\t\t\t\"$(ZFS_DIR)/include/libspl\",\n\t\t\t\t\t\"$(ZFS_DIR)/include/libspl/os/macos\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = ZFSWrapper/misc/Info.plist;\n\t\t\t\tINSTALL_PATH = \"$(LOCAL_LIBRARY_DIR)/Frameworks\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/../Frameworks @loader_path/Frameworks\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = \"$(ZFS_DIR)/lib\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"net.the-color-black.ZFSWrapper\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t\tVERSION_INFO_PREFIX = \"\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t70D85FED1C316E8F00929DAE /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCODE_SIGN_IDENTITY = \"Developer ID Application\";\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEFINES_MODULE = YES;\n\t\t\t\tDYLIB_COMPATIBILITY_VERSION = 1;\n\t\t\t\tDYLIB_CURRENT_VERSION = 1;\n\t\t\t\tDYLIB_INSTALL_NAME_BASE = \"@rpath\";\n\t\t\t\tFRAMEWORK_VERSION = A;\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = YES;\n\t\t\t\tHEADER_SEARCH_PATHS = (\n\t\t\t\t\t\"$(ZFS_DIR)/include\",\n\t\t\t\t\t\"$(ZFS_DIR)/include/libzfs\",\n\t\t\t\t\t\"$(ZFS_DIR)/include/libspl\",\n\t\t\t\t\t\"$(ZFS_DIR)/include/libspl/os/macos\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = ZFSWrapper/misc/Info.plist;\n\t\t\t\tINSTALL_PATH = \"$(LOCAL_LIBRARY_DIR)/Frameworks\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/../Frameworks @loader_path/Frameworks\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = \"$(ZFS_DIR)/lib\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"net.the-color-black.ZFSWrapper\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t\tVERSION_INFO_PREFIX = \"\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t70E4A22C236DF7D7002C760A /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCODE_SIGN_IDENTITY = \"Developer ID Application\";\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tDEVELOPMENT_TEAM = 8THUW5GT6P;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu11;\n\t\t\t\tINFOPLIST_FILE = ZetaLoginItemHelper/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/../Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"net.the-color-black.ZetaLoginItemHelper\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t70E4A22D236DF7D7002C760A /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCODE_SIGN_IDENTITY = \"Developer ID Application\";\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tDEVELOPMENT_TEAM = 8THUW5GT6P;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu11;\n\t\t\t\tINFOPLIST_FILE = ZetaLoginItemHelper/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/../Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"net.the-color-black.ZetaLoginItemHelper\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t70EABDCF1FF9ACB300BA39B8 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCODE_SIGN_IDENTITY = \"Developer ID Application\";\n\t\t\t\tCREATE_INFOPLIST_SECTION_IN_BINARY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu11;\n\t\t\t\tINFOPLIST_FILE = \"$(SRCROOT)/ZetaAuthorizationHelper/Info.plist\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = \"$(inherited)\";\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"-sectcreate\",\n\t\t\t\t\t__TEXT,\n\t\t\t\t\t__launchd_plist,\n\t\t\t\t\tZetaAuthorizationHelper/Launchd.plist,\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"net.the-color-black.ZetaAuthorizationHelper\";\n\t\t\t\tPRODUCT_NAME = \"net.the-color-black.ZetaAuthorizationHelper\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t70EABDD01FF9ACB300BA39B8 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCODE_SIGN_IDENTITY = \"Developer ID Application\";\n\t\t\t\tCREATE_INFOPLIST_SECTION_IN_BINARY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu11;\n\t\t\t\tINFOPLIST_FILE = \"$(SRCROOT)/ZetaAuthorizationHelper/Info.plist\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = \"$(inherited)\";\n\t\t\t\tOTHER_LDFLAGS = (\n\t\t\t\t\t\"-sectcreate\",\n\t\t\t\t\t__TEXT,\n\t\t\t\t\t__launchd_plist,\n\t\t\t\t\tZetaAuthorizationHelper/Launchd.plist,\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = \"net.the-color-black.ZetaAuthorizationHelper\";\n\t\t\t\tPRODUCT_NAME = \"net.the-color-black.ZetaAuthorizationHelper\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t7006C4761C26CA1400929DAE /* Build configuration list for PBXProject \"ZetaWatch\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t7006C4A01C26CA1500929DAE /* Debug */,\n\t\t\t\t7006C4A11C26CA1500929DAE /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t7006C4A21C26CA1500929DAE /* Build configuration list for PBXNativeTarget \"ZetaWatch\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t7006C4A31C26CA1500929DAE /* Debug */,\n\t\t\t\t7006C4A41C26CA1500929DAE /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t7018763E20E7B44800BA39B8 /* Build configuration list for PBXNativeTarget \"ZFSWrapperStatic\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t7018763F20E7B44800BA39B8 /* Debug */,\n\t\t\t\t7018764020E7B44800BA39B8 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t70D85FEB1C316E8F00929DAE /* Build configuration list for PBXNativeTarget \"ZFSWrapper\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t70D85FEC1C316E8F00929DAE /* Debug */,\n\t\t\t\t70D85FED1C316E8F00929DAE /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t70E4A22B236DF7D7002C760A /* Build configuration list for PBXNativeTarget \"ZetaLoginItemHelper\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t70E4A22C236DF7D7002C760A /* Debug */,\n\t\t\t\t70E4A22D236DF7D7002C760A /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t70EABDCE1FF9ACB300BA39B8 /* Build configuration list for PBXNativeTarget \"ZetaAuthorizationHelper\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t70EABDCF1FF9ACB300BA39B8 /* Debug */,\n\t\t\t\t70EABDD01FF9ACB300BA39B8 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 7006C4731C26CA1400929DAE /* Project object */;\n}\n"
  },
  {
    "path": "ZetaWatch.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:ZetaWatch.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "uninstall-helper.sh",
    "content": "#!/bin/sh\n\nlaunchctl unload /Library/LaunchDaemons/net.the-color-black.ZetaAuthorizationHelper.plist\nrm /Library/LaunchDaemons/net.the-color-black.ZetaAuthorizationHelper.plist\nrm /Library/PrivilegedHelperTools/net.the-color-black.ZetaAuthorizationHelper\n"
  }
]