├── .github ├── FUNDING.yml └── workflows │ └── swift.yml ├── .gitignore ├── .spi.yml ├── .swiftpm └── xcode │ └── package.xcworkspace │ └── contents.xcworkspacedata ├── Document ├── SKAsyncOperation.md ├── SKCrashReporter.md ├── SKDispatchFile.md ├── SKDispatchFileMonitor.md ├── SKFileLock.md ├── SKFinderExtension.md ├── SKMessagePort.md ├── SKNetworkInterface.md ├── SKNetworkMonitor.md ├── SKPermission.md ├── SKProcess.md ├── SKProcessMonitor.md ├── SKProtocol.md ├── SKSecurity.md ├── SKSignal.md ├── SKSystem.md └── SKUserDefault.md ├── LICENSE ├── ObjcSources └── Cryptor │ ├── SKSecurity.h │ └── SKSecurity.mm ├── Package.swift ├── README.md └── Sources ├── Common ├── SKData+Extension.swift ├── SKDouble+Extension.swift └── SKString+Extension.swift ├── Communication ├── SKMessagePort+Define.swift └── SKMessagePort.swift ├── Dispatch ├── SKDispatchFile.swift ├── SKDispatchFileMonitor+Define.swift ├── SKDispatchFileMonitor.swift ├── SKDispatchTimer+Define.swift └── SKDispatchTimer.swift ├── IO ├── SKIOBattery.swift ├── SKIOProcess.swift ├── SKIOResult.swift ├── SKIOReturn.swift └── SKIOSystem.swift ├── Network ├── SKNetworkInterface.swift ├── SKNetworkInterfaceDefine.swift ├── SKNetworkMonitor.swift └── SKNetworkMonitorDefine.swift ├── Permission ├── SKPermissionDefine.swift └── SKPreferencePaneDefine.swift ├── PrivacyInfo.xcprivacy ├── Process ├── SKProcess.swift ├── SKProcessMonitor.swift └── SKProcessMonitorDefine.swift ├── Protocol ├── SKClass+Protocol.swift └── SKOperation+Protocol.swift ├── SKAsyncOperation.swift ├── SKAtomicValue.swift ├── SKCrashReporter.swift ├── SKFileLock.swift ├── SKFinderExtension.swift ├── SKSignal.swift ├── SKUserDefault.swift ├── System ├── SKSystem+iOS.swift ├── SKSystem+macOS.swift ├── SKSystem.swift ├── SKSystemDefine.swift ├── SKSystemProcessResource+Additions.swift ├── SKSystemProcessResource+Define.swift ├── SKSystemProcessResource.swift ├── SKSystemResource+Additions.swift ├── SKSystemResource+Define.swift └── SKSystemResource.swift └── SystemKit.swift /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 14 | -------------------------------------------------------------------------------- /.github/workflows/swift.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Swift project 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-swift 3 | 4 | name: Swift 5 | 6 | on: 7 | push: 8 | branches: [ "main" ] 9 | pull_request: 10 | branches: [ "main" ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: macos-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v3 19 | - name: Build 20 | run: swift build -v 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/macos,swift,swiftpackagemanager,xcode,objective-c,git 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=macos,swift,swiftpackagemanager,xcode,objective-c,git 3 | 4 | ### Git ### 5 | # Created by git for backups. To disable backups in Git: 6 | # $ git config --global mergetool.keepBackup false 7 | *.orig 8 | 9 | # Created by git when using merge tools for conflicts 10 | *.BACKUP.* 11 | *.BASE.* 12 | *.LOCAL.* 13 | *.REMOTE.* 14 | *_BACKUP_*.txt 15 | *_BASE_*.txt 16 | *_LOCAL_*.txt 17 | *_REMOTE_*.txt 18 | 19 | ### macOS ### 20 | # General 21 | .DS_Store 22 | .AppleDouble 23 | .LSOverride 24 | 25 | # Icon must end with two \r 26 | Icon 27 | 28 | 29 | # Thumbnails 30 | ._* 31 | 32 | # Files that might appear in the root of a volume 33 | .DocumentRevisions-V100 34 | .fseventsd 35 | .Spotlight-V100 36 | .TemporaryItems 37 | .Trashes 38 | .VolumeIcon.icns 39 | .com.apple.timemachine.donotpresent 40 | 41 | # Directories potentially created on remote AFP share 42 | .AppleDB 43 | .AppleDesktop 44 | Network Trash Folder 45 | Temporary Items 46 | .apdisk 47 | 48 | ### macOS Patch ### 49 | # iCloud generated files 50 | *.icloud 51 | 52 | ### Objective-C ### 53 | # Xcode 54 | # 55 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 56 | 57 | ## User settings 58 | xcuserdata/ 59 | 60 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 61 | *.xcscmblueprint 62 | *.xccheckout 63 | 64 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 65 | build/ 66 | DerivedData/ 67 | *.moved-aside 68 | *.pbxuser 69 | !default.pbxuser 70 | *.mode1v3 71 | !default.mode1v3 72 | *.mode2v3 73 | !default.mode2v3 74 | *.perspectivev3 75 | !default.perspectivev3 76 | 77 | ## Obj-C/Swift specific 78 | *.hmap 79 | 80 | ## App packaging 81 | *.ipa 82 | *.dSYM.zip 83 | *.dSYM 84 | 85 | # CocoaPods 86 | # We recommend against adding the Pods directory to your .gitignore. However 87 | # you should judge for yourself, the pros and cons are mentioned at: 88 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 89 | # Pods/ 90 | # Add this line if you want to avoid checking in source code from the Xcode workspace 91 | # *.xcworkspace 92 | 93 | # Carthage 94 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 95 | # Carthage/Checkouts 96 | 97 | Carthage/Build/ 98 | 99 | # fastlane 100 | # It is recommended to not store the screenshots in the git repo. 101 | # Instead, use fastlane to re-generate the screenshots whenever they are needed. 102 | # For more information about the recommended setup visit: 103 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 104 | 105 | fastlane/report.xml 106 | fastlane/Preview.html 107 | fastlane/screenshots/**/*.png 108 | fastlane/test_output 109 | 110 | # Code Injection 111 | # After new code Injection tools there's a generated folder /iOSInjectionProject 112 | # https://github.com/johnno1962/injectionforxcode 113 | 114 | iOSInjectionProject/ 115 | 116 | ### Objective-C Patch ### 117 | 118 | ### Swift ### 119 | # Xcode 120 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 121 | 122 | 123 | 124 | 125 | 126 | 127 | ## Playgrounds 128 | timeline.xctimeline 129 | playground.xcworkspace 130 | 131 | # Swift Package Manager 132 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 133 | # Packages/ 134 | # Package.pins 135 | # Package.resolved 136 | # *.xcodeproj 137 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata 138 | # hence it is not needed unless you have added a package configuration file to your project 139 | # .swiftpm 140 | 141 | .build/ 142 | 143 | # CocoaPods 144 | # We recommend against adding the Pods directory to your .gitignore. However 145 | # you should judge for yourself, the pros and cons are mentioned at: 146 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 147 | # Pods/ 148 | # Add this line if you want to avoid checking in source code from the Xcode workspace 149 | # *.xcworkspace 150 | 151 | # Carthage 152 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 153 | # Carthage/Checkouts 154 | 155 | 156 | # Accio dependency management 157 | Dependencies/ 158 | .accio/ 159 | 160 | # fastlane 161 | # It is recommended to not store the screenshots in the git repo. 162 | # Instead, use fastlane to re-generate the screenshots whenever they are needed. 163 | # For more information about the recommended setup visit: 164 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 165 | 166 | 167 | # Code Injection 168 | # After new code Injection tools there's a generated folder /iOSInjectionProject 169 | # https://github.com/johnno1962/injectionforxcode 170 | 171 | 172 | ### SwiftPackageManager ### 173 | Packages 174 | xcuserdata 175 | *.xcodeproj 176 | 177 | 178 | ### Xcode ### 179 | 180 | ## Xcode 8 and earlier 181 | 182 | ### Xcode Patch ### 183 | *.xcodeproj/* 184 | !*.xcodeproj/project.pbxproj 185 | !*.xcodeproj/xcshareddata/ 186 | !*.xcodeproj/project.xcworkspace/ 187 | !*.xcworkspace/contents.xcworkspacedata 188 | /*.gcno 189 | **/xcshareddata/WorkspaceSettings.xcsettings 190 | 191 | # End of https://www.toptal.com/developers/gitignore/api/macos,swift,swiftpackagemanager,xcode,objective-c,git 192 | -------------------------------------------------------------------------------- /.spi.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | builder: 3 | configs: 4 | - documentation_targets: [SystemKit] 5 | metadata: 6 | authors: “ChangYeop-Yang” 7 | -------------------------------------------------------------------------------- /.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Document/SKAsyncOperation.md: -------------------------------------------------------------------------------- 1 | # 🗂 SKAsyncOperation 2 | 3 | `SKAsyncOperation`는 iOS 또는 macOS 플렛폼에서 공용적으로 사용할 수 있는 `Concurrent OperationQueue`를 효율적으로 사용할 수 있도록 기능을 제공합니다. `SKAsyncOperation`는 상속 (Inheritance)을 통해서 사용할 수 있습니다. 4 | 5 | # Example Source 6 | 7 | `SKAsyncOperation` 예제 소스코드는 아래와 같습니다. 8 | 9 | ```Swift 10 | public class CurrentOperation: SKAsyncOperation { 11 | 12 | override func start() { 13 | super.start() 14 | 15 | // 특정 작업을 수행할 수 있는 비즈니스 로직을 추가합니다. 16 | print("START") 17 | } 18 | 19 | override func cancel() { 20 | super.cancel() 21 | 22 | // 작업에 대하여 취소 작업 수행 로직을 추가합니다. 23 | print("CANCEL") 24 | } 25 | } 26 | 27 | let operation: Operation = CurrentOperation() 28 | OperationQueue().addOperation(operation) 29 | ``` 30 | 31 | # License 32 | 33 | `SystemKit` is released under the MIT license. [See LICENSE](https://github.com/ChangYeop-Yang/Apple-SystemKit/blob/main/LICENSE) for details. 34 | 35 |
36 | 37 | ```TEXT 38 | MIT License 39 | 40 | Copyright (c) 2022 Universal-SystemKit 41 | 42 | Permission is hereby granted, free of charge, to any person obtaining a copy 43 | of this software and associated documentation files (the "Software"), to deal 44 | in the Software without restriction, including without limitation the rights 45 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 46 | copies of the Software, and to permit persons to whom the Software is 47 | furnished to do so, subject to the following conditions: 48 | 49 | The above copyright notice and this permission notice shall be included in all 50 | copies or substantial portions of the Software. 51 | 52 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 53 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 54 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 55 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 56 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 57 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 58 | SOFTWARE. 59 | ``` 60 | -------------------------------------------------------------------------------- /Document/SKCrashReporter.md: -------------------------------------------------------------------------------- 1 | # 🗂 SKCrashReporter 2 | 3 | `SKCrashReporter`는 iOS 또는 macOS 플렛폼에서 구동이되는 애플리케이션이 특정한 이유로 충돌 (Crash) 발생 시 관련 내용들을 파일 저장 또는 충돌 내용을 확인할 수 있는 기능을 제공합니다. 충돌이 발생하여 애플리케이션 (Application)이 종료되는 경우에는 종료직전 입력받은 `Callback`으로 `CompletionHandler`을 받으며 애플리케이션 재시작 시 충돌 내용이 저장 된 `.plcrash` 확장자를 가진 파일이 생성됩니다. 4 | 5 | * 해당 기능을 사용하기 위해서는 `Xcode Debug executable` 환경이 아닌 `Release` 모드에서만 구동이 됩니다. 6 | 7 | * `SKCrashReporter` 기능은 [PLCrashReporter](https://github.com/microsoft/plcrashreporter) 오픈소스를 사용하여 제공하는 기능입니다. 해당 오픈소스 라이센스는 `Copyright (c) Microsoft Corporation.`를 적용받습니다. 8 | 9 | # Example Source 10 | 11 | `SKCrashReporter` 예제 소스코드는 아래와 같습니다. 12 | 13 | ```Swift 14 | // SKCrashReporter Instance를 사용하기 위해서는 충돌파일을 저장하기 위한 폴더 경로 및 파일 이름을 매개변수로 전달합니다. 15 | let crashReport = SKCrashReporter(crashReportDirectory: "DIRECTORY_REPORT", crashReportFileName: "REPORT_NAME") 16 | 17 | // typedef void (*PLCrashReporterPostCrashSignalCallback)(siginfo_t *info, ucontext_t *uap, void *context); 18 | crashReport.enable(handleSignal: PLCrashReporterPostCrashSignalCallback) 19 | 20 | // SKCrashReporter 비활성화를 수행합니다. 21 | crashReport.disable() 22 | ``` 23 | 24 | # License 25 | 26 | `SystemKit` is released under the MIT license. [See LICENSE](https://github.com/ChangYeop-Yang/Apple-SystemKit/blob/main/LICENSE) for details. 27 | 28 |
29 | 30 | ```TEXT 31 | MIT License 32 | 33 | Copyright (c) 2022 Universal-SystemKit 34 | 35 | Permission is hereby granted, free of charge, to any person obtaining a copy 36 | of this software and associated documentation files (the "Software"), to deal 37 | in the Software without restriction, including without limitation the rights 38 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 39 | copies of the Software, and to permit persons to whom the Software is 40 | furnished to do so, subject to the following conditions: 41 | 42 | The above copyright notice and this permission notice shall be included in all 43 | copies or substantial portions of the Software. 44 | 45 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 46 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 47 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 48 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 49 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 50 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 51 | SOFTWARE. 52 | ``` 53 | -------------------------------------------------------------------------------- /Document/SKDispatchFile.md: -------------------------------------------------------------------------------- 1 | # 🗂 SKDispatchFile 2 | 3 | `SKDispatchFile`는 DispatchIO를 기반으로 파일 읽기 및 쓰기 작업에 대한 기능을 제공합니다. `SKDispatchFile`는 파일 잠금(file locking) 매커니즘을 기반으로 구현이 되어있어 쓰레드 안전 (Thread Safety)합니다. 4 | 5 | * 파일 잠금 (File Locking)은 오직 특정한 시간에 한 명의 사용자나 프로세스 접근만을 허용함으로써 컴퓨터 파일에 접근을 제한하는 구조입니다. 6 | 7 | # Example Source 8 | 9 | `SKDispatchFile` 예제 소스코드는 아래와 같습니다. 10 | 11 | ```Swift 12 | let dispatch = SKDispatchFile(qualityOfService: .background) 13 | 14 | // 파일 읽기 작업 15 | dispatch.read(filePath: "/Desktop/Symbols.txt") { contents, error in 16 | print(error) 17 | } 18 | 19 | // 파일 쓰기 작업 20 | let data = "A String".data(using: .utf8) ?? Data() 21 | dispatch.write(contents: data, filePath: "/Desktop/Example.txt") { error in 22 | print(error) 23 | } 24 | ``` 25 | 26 | # License 27 | 28 | `SystemKit` is released under the MIT license. [See LICENSE](https://github.com/ChangYeop-Yang/Apple-SystemKit/blob/main/LICENSE) for details. 29 | 30 |
31 | 32 | ```TEXT 33 | MIT License 34 | 35 | Copyright (c) 2023 Universal-SystemKit 36 | 37 | Permission is hereby granted, free of charge, to any person obtaining a copy 38 | of this software and associated documentation files (the "Software"), to deal 39 | in the Software without restriction, including without limitation the rights 40 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 41 | copies of the Software, and to permit persons to whom the Software is 42 | furnished to do so, subject to the following conditions: 43 | 44 | The above copyright notice and this permission notice shall be included in all 45 | copies or substantial portions of the Software. 46 | 47 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 48 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 49 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 50 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 51 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 52 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 53 | SOFTWARE. 54 | ``` 55 | -------------------------------------------------------------------------------- /Document/SKDispatchFileMonitor.md: -------------------------------------------------------------------------------- 1 | # 🗂 SKDispatchFileMonitor 2 | 3 | `SKDispatchFileMonitor`는 iOS 또는 macOS 플렛폼에서 공용적으로 사용할 수 있는 파일에 대한 이벤트를 감시하는 기능을 제공합니다. 4 | 5 | `SKDispatchFileMonitor` provides a common interface for monitoring file events on both iOS and macOS platforms. 6 | 7 | `DispatchSource.FileSystemEvent`에 대한 설명은 아래와 같습니다. 8 | 9 | - static let all: DispatchSource.FileSystemEvent → 파일에 대하여 모든 파일 이벤트를 수신받습니다. 10 | 11 | - static let attrib: DispatchSource.FileSystemEvent → 파일 메타 데이터 변경 이벤트를 수신받습니다. 12 | 13 | - static let delete: DispatchSource.FileSystemEvent → 파일 삭제 이벤트를 수신받습니다. 14 | 15 | - static let extend: DispatchSource.FileSystemEvent → 파일 크기 변경에 대한 이벤트를 수신받습니다. 16 | 17 | - static let funlock: DispatchSource.FileSystemEvent → 파일 Unlocking 이벤트를 수신받습니다. 18 | 19 | - static let link: DispatchSource.FileSystemEvent → 파일 Link Count 변경에 대한 이벤트를 수신받습니다. 20 | 21 | - static let rename: DispatchSource.FileSystemEvent → 파일 이름 변경에 대한 이벤트를 수신받습니다. 22 | 23 | - static let revoke: DispatchSource.FileSystemEvent → 파일 접근 권한 이벤트를 수신받습니다. 24 | 25 | - static let write: DispatchSource.FileSystemEvent → 파일에 대하여 데이터 쓰기 이벤트를 수신받습니다. 26 | 27 | # Example Source 28 | 29 | `SKDispatchFileMonitor` 예제 소스코드는 아래와 같습니다. 30 | 31 | ```Swift 32 | let eventMask: DispatchSource.FileSystemEvent = [.delete, .write] 33 | let monitor = SKDispatchFileMonitor(filePath: "FILE_PATH", eventMask: eventMask) { event in 34 | print(event) 35 | } 36 | 37 | // 지정 된 파일 경로에 대하여 파일 이벤트를 탐지합니다. 38 | monitor?.start() 39 | 40 | // 지정 된 파일 경로에 대하여 파일 이벤트 탐지를 중단합니다. 41 | monitor?.stop() 42 | ``` 43 | 44 | # License 45 | 46 | `SystemKit` is released under the MIT license. [See LICENSE](https://github.com/ChangYeop-Yang/Apple-SystemKit/blob/main/LICENSE) for details. 47 | 48 |
49 | 50 | ```TEXT 51 | MIT License 52 | 53 | Copyright (c) 2024 Universal-SystemKit 54 | 55 | Permission is hereby granted, free of charge, to any person obtaining a copy 56 | of this software and associated documentation files (the "Software"), to deal 57 | in the Software without restriction, including without limitation the rights 58 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 59 | copies of the Software, and to permit persons to whom the Software is 60 | furnished to do so, subject to the following conditions: 61 | 62 | The above copyright notice and this permission notice shall be included in all 63 | copies or substantial portions of the Software. 64 | 65 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 66 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 67 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 68 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 69 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 70 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 71 | SOFTWARE. 72 | ``` 73 | -------------------------------------------------------------------------------- /Document/SKFileLock.md: -------------------------------------------------------------------------------- 1 | # 🗂 SKFileLock 2 | 3 | `SKFileLock`는 iOS 그리고 macOS 운영체제 환경에서 작동하며 오직 특정 시간에 단일 프로세스 접근만을 허용함으로써 컴퓨터 파일에 접근을 제한하는 기능을 제공합니다. `파일 읽기 (Read)`, `파일 쓰기 (Write)`, `파일 수정 (Modify)` 등의 작업을 할 수 있습니다. 4 | 5 | * [파일 잠금 (File Locking)](https://en.wikipedia.org/wiki/File_locking) → File locking is a mechanism that restricts access to a computer file, or to a region of a file, by allowing only one user or process to modify or delete it at a specific time and to prevent reading of the file while it's being modified or deleted. 6 | 7 | # Example Source 8 | 9 | `SKFileLock` 예제 소스코드는 아래와 같습니다. 10 | 11 | ```Swift 12 | // FileLockMode (.read, .write, update) 13 | let filePath = "/Users/~/Desktop/file.txt" 14 | let locker = SKFileLock(filePath: filePath, .read) 15 | 16 | // 파일 접근에 대하여 잠금 (Locking) 작업을 수행합니다. 17 | locker.lock() 18 | 19 | // 파일 접근에 대하여 잠금 해제 (UnLocking) 작업을 수행합니다. 20 | locker.unlock() 21 | ``` 22 | 23 | # License 24 | 25 | `SystemKit` is released under the MIT license. [See LICENSE](https://github.com/ChangYeop-Yang/Apple-SystemKit/blob/main/LICENSE) for details. 26 | 27 |
28 | 29 | ```TEXT 30 | MIT License 31 | 32 | Copyright (c) 2023 Universal-SystemKit 33 | 34 | Permission is hereby granted, free of charge, to any person obtaining a copy 35 | of this software and associated documentation files (the "Software"), to deal 36 | in the Software without restriction, including without limitation the rights 37 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 38 | copies of the Software, and to permit persons to whom the Software is 39 | furnished to do so, subject to the following conditions: 40 | 41 | The above copyright notice and this permission notice shall be included in all 42 | copies or substantial portions of the Software. 43 | 44 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 45 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 46 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 47 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 48 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 49 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 50 | SOFTWARE. 51 | ``` 52 | -------------------------------------------------------------------------------- /Document/SKFinderExtension.md: -------------------------------------------------------------------------------- 1 | # 🗂 SKFinderExtension 2 | 3 | `SKFinderExtension`는 macOS 운영체제 환경에서 사용되는 Finder 확장 프로그램을 추가 (Append), 활성화 (Enable), 비활성화 (Disable), 활성화 여부 (isEnable)를 실행할 수 있습니다. 4 | 5 | # Example Source 6 | 7 | `SKFinderExtension` 예제 소스코드는 아래와 같습니다. 8 | 9 | ```Swift 10 | let result: bool = SKFinderExtension.shared.isExtensionEnabled 11 | print(result) 12 | 13 | // 확장 프로그램 활성화 14 | SKFinderExtension.shared.enable(extensionPath: "extensionPath", waitUntilExit: false) 15 | 16 | // 확장 프로그램 비활성화 17 | SKFinderExtension.shared.disable(extensionPath: "extensionPath", waitUntilExit: false) 18 | 19 | // 확장 프로그램 추가 20 | SKFinderExtension.shared.append(extensionPath: "extensionPath", waitUntilExit: false) 21 | ``` 22 | 23 | # License 24 | 25 | `SystemKit` is released under the MIT license. [See LICENSE](https://github.com/ChangYeop-Yang/Apple-SystemKit/blob/main/LICENSE) for details. 26 | 27 |
28 | 29 | ```TEXT 30 | MIT License 31 | 32 | Copyright (c) 2022 Universal-SystemKit 33 | 34 | Permission is hereby granted, free of charge, to any person obtaining a copy 35 | of this software and associated documentation files (the "Software"), to deal 36 | in the Software without restriction, including without limitation the rights 37 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 38 | copies of the Software, and to permit persons to whom the Software is 39 | furnished to do so, subject to the following conditions: 40 | 41 | The above copyright notice and this permission notice shall be included in all 42 | copies or substantial portions of the Software. 43 | 44 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 45 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 46 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 47 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 48 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 49 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 50 | SOFTWARE. 51 | ``` 52 | -------------------------------------------------------------------------------- /Document/SKMessagePort.md: -------------------------------------------------------------------------------- 1 | # 🗂 SKMessagePort 2 | 3 | `SKMessagePort`는 주로 메시지 기반의 단방향 통신을 위해서 설계 되었으며 iOS 또는 macOS 플렛폼에서 로컬 장비 상에서 다중 쓰레드 및 프로세스들 간에 임의의 데이터를 전달하는 통신 채널을 제공합니다. 즉, 서로 다른 애플리케이션, 또는 애플리케이션과 프레임워크, 또는 서로 다른 프레임워크 사이의 통신을 할 수 있는 기능을 제공합니다. 4 | 5 |

6 | 7 | CFMessagePort는 아래의 주요한 메서드를 기반으로 동작합니다. 8 | 9 | * `CFMessagePortCreateLocal`: 로컬 메시지 포트를 생성합니다. 10 | * `CFMessagePortCreateRemote`: 원격 메시지 포트를 생성합니다. 11 | * `CFMessagePortSendRequest`: 원격 포트에 메시지를 전송합니다. 12 | * `CFMessagePortSetInvalidationCallBack`: 로컬 메시지 포트 또는 원격 메시지 포트가 무효화될 때 호출되는 콜백을 설정합니다. 13 | * `CFMessagePortInvalidate`: 로컬 메시지 포트 또는 원격 메시지 포트를 무효화합니다. 14 | * `CFMessagePortIsValid`: 로컬 메시지 포트 또는 원격 메시지 포트가 유효한지 확인합니다. 15 | 16 | # Example Source 17 | 18 | `SKMessagePort` 예제 소스코드는 아래와 같습니다. 19 | 20 | ```Swift 21 | // https://developer.apple.com/documentation/corefoundation/cfmessageportcallback 22 | let callback: CFMessagePortCallBack = { local, msgid, data, info -> Unmanaged? in 23 | 24 | let pointee = info?.assumingMemoryBound(to: ViewController.self).pointee 25 | 26 | /* here is processing data */ 27 | 28 | return nil 29 | } 30 | 31 | // https://developer.apple.com/documentation/corefoundation/cfmessageportinvalidationcallback 32 | let callout: CFMessagePortInvalidationCallBack = { local, info in 33 | 34 | /* here is processing invaild local port */ 35 | } 36 | 37 | let messagePort = SKMessagePort(portName: "com.message.port", callout) 38 | 39 | messagePort.listen(dispatch: .global(qos: .userInitiated), info: self, callback) 40 | 41 | messagePort.send(messageID: 777, message: "Hello World!".data(using: .utf8)!) 42 | 43 | messagePort.invalidate() 44 | ``` 45 | 46 | # License 47 | 48 | `SystemKit` is released under the MIT license. [See LICENSE](https://github.com/ChangYeop-Yang/Apple-SystemKit/blob/main/LICENSE) for details. 49 | 50 |
51 | 52 | ```TEXT 53 | MIT License 54 | 55 | Copyright (c) 2022 SystemKit 56 | 57 | Permission is hereby granted, free of charge, to any person obtaining a copy 58 | of this software and associated documentation files (the "Software"), to deal 59 | in the Software without restriction, including without limitation the rights 60 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 61 | copies of the Software, and to permit persons to whom the Software is 62 | furnished to do so, subject to the following conditions: 63 | 64 | The above copyright notice and this permission notice shall be included in all 65 | copies or substantial portions of the Software. 66 | 67 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 68 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 69 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 70 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 71 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 72 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 73 | SOFTWARE. 74 | ``` 75 | -------------------------------------------------------------------------------- /Document/SKNetworkInterface.md: -------------------------------------------------------------------------------- 1 | # 🗂 SKNetworkInterface 2 | 3 | `SKNetworkInterface`는 iOS 운영체제 또는 macOS 운영체제 환경에서 4 | 5 | # Example Source 6 | 7 | `SKNetworkInterface` 예제 소스코드는 아래와 같습니다. 8 | 9 | ```Swift 10 | ``` 11 | 12 | # License 13 | 14 | `SystemKit` is released under the MIT license. [See LICENSE](https://github.com/ChangYeop-Yang/Apple-SystemKit/blob/main/LICENSE) for details. 15 | 16 |
17 | 18 | ```TEXT 19 | MIT License 20 | 21 | Copyright (c) 2022 Universal-SystemKit 22 | 23 | Permission is hereby granted, free of charge, to any person obtaining a copy 24 | of this software and associated documentation files (the "Software"), to deal 25 | in the Software without restriction, including without limitation the rights 26 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 27 | copies of the Software, and to permit persons to whom the Software is 28 | furnished to do so, subject to the following conditions: 29 | 30 | The above copyright notice and this permission notice shall be included in all 31 | copies or substantial portions of the Software. 32 | 33 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 34 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 35 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 36 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 37 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 38 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 39 | SOFTWARE. 40 | ``` 41 | -------------------------------------------------------------------------------- /Document/SKNetworkMonitor.md: -------------------------------------------------------------------------------- 1 | # 🗂 SKNetworkMonitor 2 | 3 | `SKNetworkMonitor`는 iOS 운영체제 또는 macOS 운영체제 환경에서 네트워크 환경 (WiFi, Ethernet, Cellular, LoopBack 등)에 대한 정보를 얻을 수 있도록 기능을 제공합니다. 4 | 5 | # Example Source 6 | 7 | `SKNetworkMonitor` 예제 소스코드는 아래와 같습니다. 8 | 9 | ```Swift 10 | // 네트워크 상태에 대한 정보 수집을 종료합니다. 11 | let monitor = SKNetworkMonitor { result in 12 | 13 | // NWPath 정보를 가져옵니다. 14 | print(result.newPath) 15 | 16 | // 네트워크 상태 정보를 가져옵니다. 17 | print(result.status) 18 | 19 | // 네트워크 연결 상태를 가져옵니다. 20 | print(result.connectionType) 21 | } 22 | 23 | // 네트워크 상태에 대한 정보 수집을 시작합니다. 24 | monitor.startMonitor() 25 | 26 | // 네트워크 상태에 대한 정보 수집을 종료합니다. 27 | monitor.stopMonitor() 28 | ``` 29 | 30 | # License 31 | 32 | `SystemKit` is released under the MIT license. [See LICENSE](https://github.com/ChangYeop-Yang/Apple-SystemKit/blob/main/LICENSE) for details. 33 | 34 |
35 | 36 | ```TEXT 37 | MIT License 38 | 39 | Copyright (c) 2022 Universal-SystemKit 40 | 41 | Permission is hereby granted, free of charge, to any person obtaining a copy 42 | of this software and associated documentation files (the "Software"), to deal 43 | in the Software without restriction, including without limitation the rights 44 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 45 | copies of the Software, and to permit persons to whom the Software is 46 | furnished to do so, subject to the following conditions: 47 | 48 | The above copyright notice and this permission notice shall be included in all 49 | copies or substantial portions of the Software. 50 | 51 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 52 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 53 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 54 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 55 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 56 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 57 | SOFTWARE. 58 | ``` 59 | -------------------------------------------------------------------------------- /Document/SKPermission.md: -------------------------------------------------------------------------------- 1 | # 🗂 SKPermission 2 | 3 | `SKPermission`는 iOS 또는 macOS 운영체제에서 애플리케이션 구동에 필요 한 다양한 권한 [`파일 및 폴더 권한 (Files and Folders)`, `전체 디스크 접근 권한 (Full Disk Access)`, `사진 (Photos)`, `연락처 (AddressBook)`, `블루투스 (Bluetooth)`, `캘린더 (Calendar)`] 등을 손쉽게 관리할 수 있습니다. 4 | 5 | # Example Source 6 | 7 | `SKPermission` 예제 소스코드는 아래와 같습니다. 8 | 9 | ```Swift 10 | // 공유하기 환경설정 페이지를 표시합니다. 11 | SKSystem.shared.openPreferencePane(path: SKSharingPreferencePane.Main.rawValue) 12 | 13 | // Screentime 환경설정 페이지를 표시합니다. 14 | SKPermission.shared.openPreferencePane(path: SKDefaultPreferencePane.Screentime.rawValue) 15 | 16 | // 전체 디스크 접근 권한 (Full Disk Access) 여부를 확인합니다. 17 | let isPermission: Bool = SKPermission.shared.isFullDiskAccessPermission() 18 | print(isPermission) 19 | 20 | // com.apple.Terminal 애플리케이션 권한을 제거합니다. 21 | SKPermission.shared.managePrivacyPermission(service: .SystemPolicyDesktopFolder, bundlePath: "com.apple.Terminal") 22 | ``` 23 | 24 | # License 25 | 26 | `SystemKit` is released under the MIT license. [See LICENSE](https://github.com/ChangYeop-Yang/Apple-SystemKit/blob/main/LICENSE) for details. 27 | 28 |
29 | 30 | ```TEXT 31 | MIT License 32 | 33 | Copyright (c) 2022 Universal-SystemKit 34 | 35 | Permission is hereby granted, free of charge, to any person obtaining a copy 36 | of this software and associated documentation files (the "Software"), to deal 37 | in the Software without restriction, including without limitation the rights 38 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 39 | copies of the Software, and to permit persons to whom the Software is 40 | furnished to do so, subject to the following conditions: 41 | 42 | The above copyright notice and this permission notice shall be included in all 43 | copies or substantial portions of the Software. 44 | 45 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 46 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 47 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 48 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 49 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 50 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 51 | SOFTWARE. 52 | ``` 53 | -------------------------------------------------------------------------------- /Document/SKProcess.md: -------------------------------------------------------------------------------- 1 | # 🗂 SKProcess 2 | 3 | `SKProcess`는 macOS 운영체제 환경을 기반으로 `Process` Class를 사용하여 스크립트 (Script) 또는 응용 프로그램 (Application)을 실행할 수 있습니다. 4 | 5 | # Example Source 6 | 7 | `SKProcess` 예제 소스코드는 아래와 같습니다. 8 | 9 | ```Swift 10 | let arguments: Array = ["-e", "use", "-i", "extensionPath"] 11 | SKProcess.shared.run(launchPath: "launchPath", arguments: arguments, waitUntilExit: true) 12 | 13 | let standardError: Pipe = Pipe() 14 | let arguments: [String] = ["-a", "-vvv", "-t", "install", "atPath"] 15 | SKProcess.shared.run(launchPath: "/usr/sbin/spctl", arguments: arguments, standardError: standardError, terminationHandler: terminationHandler) 16 | ``` 17 | 18 | # License 19 | 20 | `SystemKit` is released under the MIT license. [See LICENSE](https://github.com/ChangYeop-Yang/Apple-SystemKit/blob/main/LICENSE) for details. 21 | 22 |
23 | 24 | ```TEXT 25 | MIT License 26 | 27 | Copyright (c) 2022 Universal-SystemKit 28 | 29 | Permission is hereby granted, free of charge, to any person obtaining a copy 30 | of this software and associated documentation files (the "Software"), to deal 31 | in the Software without restriction, including without limitation the rights 32 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 33 | copies of the Software, and to permit persons to whom the Software is 34 | furnished to do so, subject to the following conditions: 35 | 36 | The above copyright notice and this permission notice shall be included in all 37 | copies or substantial portions of the Software. 38 | 39 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 40 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 41 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 42 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 43 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 44 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 45 | SOFTWARE. 46 | ``` 47 | -------------------------------------------------------------------------------- /Document/SKProcessMonitor.md: -------------------------------------------------------------------------------- 1 | # 🗂 SKProcessMonitor 2 | 3 | `SKProcessMonitor`는 `macOS` 운영체제 프로세스 (Process) 상태를 추적하여 Handling 할 수 있도록 기능을 제공합니다. 4 | 5 | 프로세스 (Process) 상태를 추적할 수 있는 상태 값은 아래와 같습니다. 6 | 7 | - 실행 (exec): Process Exec'd 8 | 9 | - 종료 (exit): Process Exited 10 | 11 | - 복제 (fork): Process Forked 12 | 13 | # Example Source 14 | 15 | `SKProcessMonitor` 예제 소스코드는 아래와 같습니다. 16 | 17 | ```Swift 18 | let monitor = SKProcessMonitor(pid: 3447, fflag: .exit) { decriptor, flag, rawValue in 19 | print("Receive Process Monitor: \(decriptor), \(flag), \(rawValue)") 20 | } 21 | 22 | OperationQueue.main.addOperation(monitor) 23 | 24 | // Advises the operation object that it should stop executing its task. 25 | monitor.cancel() 26 | ``` 27 | 28 | # License 29 | 30 | `Universal SystemKit` is released under the MIT license. [See LICENSE](https://github.com/ChangYeop-Yang/Apple-SystemKit/blob/main/LICENSE) for details. 31 | 32 |
33 | 34 | ```TEXT 35 | MIT License 36 | 37 | Copyright (c) 2022 Universal-SystemKit 38 | 39 | Permission is hereby granted, free of charge, to any person obtaining a copy 40 | of this software and associated documentation files (the "Software"), to deal 41 | in the Software without restriction, including without limitation the rights 42 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 43 | copies of the Software, and to permit persons to whom the Software is 44 | furnished to do so, subject to the following conditions: 45 | 46 | The above copyright notice and this permission notice shall be included in all 47 | copies or substantial portions of the Software. 48 | 49 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 50 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 51 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 52 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 53 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 54 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 55 | SOFTWARE. 56 | ``` 57 | -------------------------------------------------------------------------------- /Document/SKProtocol.md: -------------------------------------------------------------------------------- 1 | # 🗂 SKProtocol 2 | 3 | # Example Source 4 | 5 | `SKProtocol` 예제 소스코드는 아래와 같습니다. 6 | 7 | ```Swift 8 | 9 | ``` 10 | 11 | # License 12 | 13 | `SystemKit` is released under the MIT license. [See LICENSE](https://github.com/ChangYeop-Yang/Apple-SystemKit/blob/main/LICENSE) for details. 14 | 15 |
16 | 17 | ```TEXT 18 | MIT License 19 | 20 | Copyright (c) 2022 Universal-SystemKit 21 | 22 | Permission is hereby granted, free of charge, to any person obtaining a copy 23 | of this software and associated documentation files (the "Software"), to deal 24 | in the Software without restriction, including without limitation the rights 25 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 26 | copies of the Software, and to permit persons to whom the Software is 27 | furnished to do so, subject to the following conditions: 28 | 29 | The above copyright notice and this permission notice shall be included in all 30 | copies or substantial portions of the Software. 31 | 32 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 33 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 34 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 35 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 36 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 37 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 38 | SOFTWARE. 39 | ``` 40 | -------------------------------------------------------------------------------- /Document/SKSecurity.md: -------------------------------------------------------------------------------- 1 | # 🗂 SKSecurity 2 | 3 | `SKSecurity`는 고급 암호화 표준 (Advanced Encryption Standard, AES)를 기반으로 입력받은 데이터를 `AES-128`, `AES-192`, `AES-256`들의 대칭키 (Symmetric) 크기를 바탕으로 암호화 또는 복호화 작업을 수행할 수 있습니다. 또한, CBC (Cipher Block Chaining mode) 기반으로 동작하기에 초기화 백터 값이 필요합니다. 4 | 5 |
6 | 7 | * AES (Advanced Encryption Standard) 암호화 기법에 대한 자세한 설명은 [Advanced Encryption Standard](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) 확인 부탁드립니다. 8 | 9 |
10 | 11 | 고급 암호화 표준 (Advanced Encryption Standard, AES) 키의 크기 제약 조건은 아래를 반드시 지켜야 합니다. 12 | 13 | * An AES 128-bit key can be expressed as a hexadecimal string with 32 characters. It will require 24 characters in base64. 14 | 15 | * An AES 192-bit key can be expressed as a hexadecimal string with 48 characters. It will require 32 characters in base64. 16 | 17 | * An AES 256-bit key can be expressed as a hexadecimal string with 64 characters. It will require 44 characters in base64. 18 | 19 | # Example Source 20 | 21 | `SKSecurity` 예제 소스코드는 아래와 같습니다. 22 | 23 | ```Swift 24 | // AES 암호화를 수행하기 위한 IV를 생성합니다. 25 | let iv = SKSecurity.shared().createInitializationVector() 26 | print(iv) 27 | 28 | let key = "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2" 29 | 30 | // AES 암호화를 수행하기 위한 평문을 생성합니다. 31 | if let rawData = "PASSWORD".data(using: .utf8) { 32 | 33 | // AES 암호화를 수행합니다. 34 | let encrypted = SKSecurity.shared().encrypt(key, .AES256, iv, rawData) 35 | 36 | // AES 복호화를 수행합니다. 37 | let decrypted = SKSecurity.shared().decrypt(key, .AES256, iv, encrypted) 38 | print(String(data: decrypted, encoding: .utf8)) 39 | } 40 | ``` 41 | 42 | # License 43 | 44 | `Universal SystemKit` is released under the MIT license. [See LICENSE](https://github.com/ChangYeop-Yang/Apple-SystemKit/blob/main/LICENSE) for details. 45 | 46 |
47 | 48 | ```TEXT 49 | MIT License 50 | 51 | Copyright (c) 2022 Universal-SystemKit 52 | 53 | Permission is hereby granted, free of charge, to any person obtaining a copy 54 | of this software and associated documentation files (the "Software"), to deal 55 | in the Software without restriction, including without limitation the rights 56 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 57 | copies of the Software, and to permit persons to whom the Software is 58 | furnished to do so, subject to the following conditions: 59 | 60 | The above copyright notice and this permission notice shall be included in all 61 | copies or substantial portions of the Software. 62 | 63 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 64 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 65 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 66 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 67 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 68 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 69 | SOFTWARE. 70 | ``` 71 | -------------------------------------------------------------------------------- /Document/SKSignal.md: -------------------------------------------------------------------------------- 1 | # 🗂 SKSignal 2 | 3 | `SKSignal`는 `macOS` 운영체제에서 쓰이는 제한된 형태의 프로세스 간 통신을 위해서 사용하는 `신호 (Signal)`을 손쉽게 Handling 할 수 있도록 기능을 제공합니다. `신호 (Signal)` 관련하여 추가적인 정보는 [POSIX Signal](https://en.wikipedia.org/wiki/Signal_(IPC))에서 확인할 수 있습니다. 4 | 5 | # Example Source 6 | 7 | `SKSignal` 예제 소스코드는 아래와 같습니다. 8 | 9 | ```Swift 10 | let signal = SKSignal(signal: SIGUSR1) { number in 11 | print("Receive Signal: \(number)") 12 | } 13 | 14 | OperationQueue.main.addOperation(signal) 15 | 16 | // Advises the operation object that it should stop executing its task. 17 | signal.cancel() 18 | ``` 19 | 20 | # License 21 | 22 | `Universal SystemKit` is released under the MIT license. [See LICENSE](https://github.com/ChangYeop-Yang/Apple-SystemKit/blob/main/LICENSE) for details. 23 | 24 |
25 | 26 | ```TEXT 27 | MIT License 28 | 29 | Copyright (c) 2022 Universal-SystemKit 30 | 31 | Permission is hereby granted, free of charge, to any person obtaining a copy 32 | of this software and associated documentation files (the "Software"), to deal 33 | in the Software without restriction, including without limitation the rights 34 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 35 | copies of the Software, and to permit persons to whom the Software is 36 | furnished to do so, subject to the following conditions: 37 | 38 | The above copyright notice and this permission notice shall be included in all 39 | copies or substantial portions of the Software. 40 | 41 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 42 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 43 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 44 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 45 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 46 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 47 | SOFTWARE. 48 | ``` 49 | -------------------------------------------------------------------------------- /Document/SKSystem.md: -------------------------------------------------------------------------------- 1 | # 🗂 SKSystem 2 | 3 | `SKSystem`는 iOS 또는 macOS 플렛폼에서 공용적으로 사용할 수 있도록 시스템 정보 (운영체제, 시스템, 메모리, 중앙 처리 장치, 프로젝트 버전 등)을 손쉽게 가져올 수 있습니다. 또한, 플랫폼에 구애받지 않고 공통적으로 사용할 수 있는 기능을 제공합니다. 4 | 5 | # Example Source 6 | 7 | `SKSystem` 예제 소스코드는 아래와 같습니다. 8 | 9 | ```Swift 10 | // 현재 프로세스를 실행 시킨 작업 대상이 Debug 형태로 실행이 되었는 경우를 확인합니다. 11 | let result = SKSystem.shared.getBeingDebugged(pid: pid) 12 | print(result ? "DEBUG" : "NON DEBUG") 13 | 14 | // 운영체제가 구동 중인 장비에 대한 정보를 가져옵니다. 15 | let resultA = SKSystem.shared.getMachineSystemInfo() 16 | print(resultA) 17 | 18 | // 현재 구동중인 macOS 운영체제 시스템 버전 (System Version) 정보를 가져옵니다. 19 | let resultB = SKSystem.shared.getOperatingSystemVersion() 20 | print(resultB) 21 | 22 | // 현재 구동중인 애플리케이션에 대한 `릴리즈 버전 (Release Version` 그리고 `번들 버전 (Bundle Version)` 정보를 가져옵니다. 23 | let resultC = SKSystem.shared.getApplicationVersion() 24 | print(resultC) 25 | 26 | // 현재 장비에서 사용하고 있는 `메모리 (Memory)` 정보를 가져옵니다. 27 | let resultD = SKSystem.SKSystemMemoryResult() 28 | print(resultD) 29 | 30 | // 현재 장비에서 사용하고 있는 `처리 장치 (Central/Main processor)` 정보를 가져옵니다. 31 | let resultE = SKSystem.SKSystemMainControlResult() 32 | print(resultE) 33 | 34 | // 현재 장비에서 사용하고 있는 `전지 (Battery)` 정보를 가져옵니다. 35 | let resultF = SKSystem.SKBatteryResult() 36 | print(resultF) 37 | 38 | // 현재 iPhone 디바이스가 네트워크에 연결 된 기술 타입 정보를 가져옵니다. 39 | let result = SKSystem.shared.getCurrentRadioAccessTechnology() 40 | print(result) 41 | ``` 42 | 43 | # License 44 | 45 | `SystemKit` is released under the MIT license. [See LICENSE](https://github.com/ChangYeop-Yang/Apple-SystemKit/blob/main/LICENSE) for details. 46 | 47 |
48 | 49 | ```TEXT 50 | MIT License 51 | 52 | Copyright (c) 2022 Universal-SystemKit 53 | 54 | Permission is hereby granted, free of charge, to any person obtaining a copy 55 | of this software and associated documentation files (the "Software"), to deal 56 | in the Software without restriction, including without limitation the rights 57 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 58 | copies of the Software, and to permit persons to whom the Software is 59 | furnished to do so, subject to the following conditions: 60 | 61 | The above copyright notice and this permission notice shall be included in all 62 | copies or substantial portions of the Software. 63 | 64 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 65 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 66 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 67 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 68 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 69 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 70 | SOFTWARE. 71 | ``` 72 | -------------------------------------------------------------------------------- /Document/SKUserDefault.md: -------------------------------------------------------------------------------- 1 | # 🗂 SKUserDefault 2 | 3 | `SKUserDefault`는 `@propertyWrapper` 사용하여 개발자가 보다 손쉽게 `UserDefaults` 사용할 수 있도록 개발되었습니다. 그러므로 [UserDefaults - Apple Developer Documentation](https://developer.apple.com/documentation/foundation/userdefaults)에서 사용할 수 있는 다양한 자료형을 처리할 수 있습니다. 4 | 5 | 아래의 예제 소스코드 이외에도 `Object`, `URL`, `Array`, `Dictionary`, `String`, `Data`, `Bool`, `Integer`, `Float`, `Double` 등의 자료형을 지원합니다. 6 | 7 | # Example Source 8 | 9 | `SKUserDefault` 예제 소스코드는 아래와 같습니다. 10 | 11 | ```Swift 12 | // Usage String UserDefaults 13 | @SKUserDefaults(forKey: "SKUserDefault_TEST_STRING", defaultValue: "TEST") 14 | private var defaultsString: Optional 15 | 16 | self.defaultsString = "SKUserDefault_PRINT" 17 | printf(self.defaultsString) 18 | 19 | // Usage Integer UserDefaults 20 | @SKUserDefaults(forKey: "SKUserDefault_TEST_INTEGER", defaultValue: 3540) 21 | private var defaultsInteger: Optional 22 | 23 | self.defaultsInteger = 8557 24 | printf(self.defaultsInteger) 25 | 26 | // Usage Double UserDefaults 27 | @SKUserDefaults(forKey: "SKUserDefault_TEST_DOUBLE", defaultValue: 3.14) 28 | private var defaultsDouble: Optional 29 | 30 | self.defaultsInteger = 41.3 31 | printf(self.defaultsDouble) 32 | ``` 33 | 34 | # License 35 | 36 | `SystemKit` is released under the MIT license. [See LICENSE](https://github.com/ChangYeop-Yang/Apple-SystemKit/blob/main/LICENSE) for details. 37 | 38 |
39 | 40 | ```TEXT 41 | MIT License 42 | 43 | Copyright (c) 2022 Universal-SystemKit 44 | 45 | Permission is hereby granted, free of charge, to any person obtaining a copy 46 | of this software and associated documentation files (the "Software"), to deal 47 | in the Software without restriction, including without limitation the rights 48 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 49 | copies of the Software, and to permit persons to whom the Software is 50 | furnished to do so, subject to the following conditions: 51 | 52 | The above copyright notice and this permission notice shall be included in all 53 | copies or substantial portions of the Software. 54 | 55 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 56 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 57 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 58 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 59 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 60 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 61 | SOFTWARE. 62 | ``` 63 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Universal-SystemKit 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ObjcSources/Cryptor/SKSecurity.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | #import 24 | #import 25 | 26 | NS_ASSUME_NONNULL_BEGIN 27 | 28 | #pragma mark - Define Enum 29 | typedef NS_ENUM(size_t, SKSecurityAESType) { 30 | 31 | /// AES-128의 경우 128 Bit의 대칭키를 쓰는 암호화 알고리즘 32 | AES128 = kCCKeySizeAES128, 33 | 34 | /// AES-192의 경우 192 Bit의 대칭키를 쓰는 암호화 알고리즘 35 | AES192 = kCCKeySizeAES192, 36 | 37 | /// AES-256의 경우 256 Bit의 대칭키를 쓰는 암호화 알고리 38 | AES256 = kCCKeySizeAES256 39 | }; 40 | 41 | typedef NS_ENUM(NSInteger, SKSecurityCryptType) { 42 | 43 | /// 암호화 (Encryption) 44 | Encrypt = 0, 45 | 46 | /// 복호화 47 | Decrypt = 1 48 | }; 49 | 50 | @interface SKSecurity : NSObject 51 | 52 | #pragma mark - Define Public Properties 53 | + (instancetype) shared; 54 | 55 | #pragma mark - Define Public Instance Method 56 | - (nonnull NSData *) encrypt: (nonnull NSString *) key 57 | : (const SKSecurityAESType) keyType 58 | : (nonnull NSString *) iv 59 | : (nonnull NSData *) data; 60 | 61 | - (nonnull NSData *) decrypt: (nonnull NSString *) key 62 | : (const SKSecurityAESType) keyType 63 | : (nonnull NSString *) iv 64 | : (nonnull NSData *) data; 65 | 66 | - (nonnull NSString *) createInitializationVector; 67 | 68 | @end 69 | 70 | NS_ASSUME_NONNULL_END 71 | -------------------------------------------------------------------------------- /ObjcSources/Cryptor/SKSecurity.mm: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | #import "SKSecurity.h" 24 | 25 | @interface SKSecurity() 26 | 27 | #pragma mark - Define Private Instance Method 28 | - (nonnull const char *) copyPointer: (const size_t) length 29 | : (nonnull const NSString *) target; 30 | 31 | - (nullable NSData *) getDataByStatus: (CCCryptorStatus) status 32 | : (nonnull void *) dataWithBytes 33 | : (size_t) length; 34 | 35 | - (nullable NSData *) crypt: (const NSString *) key 36 | : (const SKSecurityAESType) keySize 37 | : (const NSString *) iv 38 | : (const NSData *) data 39 | : (const CCOperation) operation; 40 | 41 | @end 42 | 43 | @implementation SKSecurity 44 | 45 | #pragma mark - Public Instance Method 46 | + (instancetype) shared { 47 | 48 | static SKSecurity * shared = nil; 49 | 50 | static dispatch_once_t onceToken; 51 | 52 | dispatch_once(&onceToken, ^{ 53 | shared = [SKSecurity new]; 54 | }); 55 | 56 | return shared; 57 | } 58 | 59 | #pragma mark - Private Instance Method 60 | - (const char *) copyPointer: (const size_t) length 61 | : (const NSString *) target { 62 | 63 | char * pointee = (char *) malloc(length); 64 | 65 | // write zeroes to a byte string 66 | bzero(pointee, length); 67 | 68 | // Converts the string to a given encoding and stores it in a buffer. 69 | [target getCString: pointee maxLength: length encoding: NSUTF8StringEncoding]; 70 | 71 | return pointee; 72 | } 73 | 74 | - (NSData *) getDataByStatus: (CCCryptorStatus) status 75 | : (void *) dataWithBytes 76 | : (size_t) length { 77 | 78 | switch (status) { 79 | 80 | case kCCSuccess: 81 | NSLog(@"[SKSecurity] Operation completed normally"); 82 | return [NSData dataWithBytes: dataWithBytes length: length]; 83 | 84 | case kCCParamError: 85 | NSLog(@"[SKSecurity] Illegal parameter value"); 86 | return NULL; 87 | 88 | case kCCBufferTooSmall: 89 | NSLog(@"[SKSecurity] Insufficent Buffer Provided for Specified Operation"); 90 | return NULL; 91 | 92 | case kCCMemoryFailure: 93 | NSLog(@"[SKSecurity] Memory allocation failure"); 94 | return NULL; 95 | 96 | case kCCDecodeError: 97 | NSLog(@"[SKSecurity] Input Size was not Aligned Properly"); 98 | return NULL; 99 | 100 | case kCCUnimplemented: 101 | NSLog(@"[SKSecurity] Function not Implemented for the Current Algorithm"); 102 | return NULL; 103 | 104 | case kCCInvalidKey: 105 | NSLog(@"[SKSecurity] Key is not valid"); 106 | return NULL; 107 | 108 | default: 109 | NSLog(@"[SKSecurity] Unknown CCCryptorStatus Error"); 110 | return NULL; 111 | } 112 | } 113 | 114 | - (NSData *) crypt: (const NSString *) key 115 | : (const SKSecurityAESType) keySize 116 | : (const NSString *) iv 117 | : (const NSData *) data 118 | : (const CCOperation) operation { 119 | 120 | @synchronized (self) { 121 | 122 | // Creating an cryption key buffer 123 | const size_t keyLength = keySize; 124 | const char * keyPointee = [self copyPointer: keyLength 125 | : key]; 126 | 127 | // Creating an initialization vector buffer 128 | const size_t ivLength = kCCBlockSizeAES128; 129 | const char * ivPointee = [self copyPointer: ivLength 130 | : iv]; 131 | 132 | const size_t blockLength = data.length + kCCBlockSizeAES128; 133 | void * block = (void *) malloc(blockLength); 134 | 135 | // Performing Encryption or Decryption Operation 136 | size_t bytesCrypted = 0; 137 | const CCCryptorStatus status = CCCrypt(operation, kCCAlgorithmAES128, kCCOptionPKCS7Padding, 138 | keyPointee, keySize, 139 | ivPointee, 140 | data.bytes, data.length, 141 | block, blockLength, 142 | &bytesCrypted); 143 | 144 | NSData * result = [self getDataByStatus: status 145 | : block 146 | : bytesCrypted]; 147 | 148 | // Deallocates or frees a memory block. 149 | free(block); 150 | block = NULL; 151 | 152 | return result; 153 | } 154 | } 155 | 156 | #pragma mark - Public Instance Method 157 | - (NSData *) encrypt: (const NSString *) key 158 | : (const SKSecurityAESType) keyType 159 | : (const NSString *) iv 160 | : (NSData *) data { 161 | 162 | @autoreleasepool { 163 | 164 | NSLog(@"[SKSecurity] Performing Encryption Operation"); 165 | 166 | return [self crypt: key 167 | : keyType 168 | : iv 169 | : data 170 | : ::Encrypt]; 171 | } 172 | } 173 | 174 | - (NSData *) decrypt: (const NSString *) key 175 | : (const SKSecurityAESType) keyType 176 | : (const NSString *) iv 177 | : (NSData *) data { 178 | 179 | @autoreleasepool { 180 | 181 | NSLog(@"[SKSecurity] Performing Decryption Operation"); 182 | 183 | return [self crypt: key 184 | : keyType 185 | : iv 186 | : data 187 | : ::Decrypt]; 188 | } 189 | } 190 | 191 | - (NSString *) createInitializationVector { 192 | 193 | @autoreleasepool { 194 | 195 | const NSArray * components = [NSUUID.UUID.UUIDString componentsSeparatedByString: @"-"]; 196 | 197 | NSMutableString * stringValue = [[NSMutableString alloc] init]; 198 | 199 | for (NSString * element in components) { 200 | [stringValue appendString: element]; 201 | } 202 | 203 | NSMutableString * result = [[NSMutableString alloc] init]; 204 | 205 | for (int index = 0; index < 16; index++) { 206 | 207 | NSUInteger characterAtIndex = arc4random() % stringValue.length; 208 | const unichar character = [stringValue characterAtIndex: characterAtIndex]; 209 | [result appendFormat: @"%C", character]; 210 | } 211 | 212 | // The IV (Initialization Vector) must have a length of 16 bytes 213 | return result; 214 | } 215 | } 216 | 217 | @end 218 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.4 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | /* 5 | * Copyright (c) 2023 Universal SystemKit. All rights reserved. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | // swiftlint:disable all 27 | import PackageDescription 28 | 29 | // The configuration of a Swift package. 30 | let package = Package( 31 | // The name of the Swift package. 32 | name: InfoPackage.PackageName, 33 | // The list of minimum versions for platforms supported by the package. 34 | platforms: [ 35 | // macOS 10.15 (Catalina) 이상의 운영체제부터 사용이 가능합니다. 36 | .macOS(SupportedPlatform.MacOSVersion.v10_15), 37 | 38 | // iOS 13 이상의 운영체제부터 사용이 가능합니다. 39 | .iOS(SupportedPlatform.IOSVersion.v13), 40 | ], 41 | // Products define the executables and libraries a package produces, and make them visible to other packages. 42 | products: [ 43 | // It is a module library related to Swift source code. 44 | .library(name: InfoPackage.PackageName, targets: [InfoPackage.PackageName]), 45 | 46 | // It is a module library related to Objective-C source code. 47 | .library(name: InfoPackage.PackageObjcName, targets: [InfoPackage.PackageObjcName]) 48 | ], 49 | // The list of package dependencies. 50 | dependencies: [ 51 | .package(url: RemotePackage.SwiftLog.path, from: RemotePackage.SwiftLog.from), 52 | .package(url: RemotePackage.SwiftHTTPTypes.path, from: RemotePackage.SwiftHTTPTypes.from), 53 | .package(url: RemotePackage.PLCrashReporter.path, from: RemotePackage.PLCrashReporter.from), 54 | ], 55 | // Targets are the basic building blocks of a package. A target can define a module or a test suite. 56 | // Targets can depend on other targets in this package, and on products in packages this package depends on. 57 | targets: [ 58 | .target(name: InfoPackage.PackageName, 59 | dependencies: [RemotePackage.SwiftLog.target, RemotePackage.SwiftHTTPTypes.target, RemotePackage.PLCrashReporter.target], 60 | path: InfoPackage.PackagePath, 61 | resources: [.process("PrivacyInfo.xcprivacy")]), 62 | .target(name: InfoPackage.PackageObjcName, 63 | path: InfoPackage.PackageObjcPath, 64 | sources: ["Cryptor/SKSecurity.mm"], 65 | publicHeadersPath: ".", 66 | cSettings: [ 67 | .headerSearchPath(".") 68 | ]) 69 | ], 70 | // The list of Swift versions with which this package is compatible. 71 | swiftLanguageVersions: [.v5] 72 | ) 73 | 74 | #if swift(>=5.6) 75 | // Add the documentation compiler plugin if possible 76 | package.dependencies.append( 77 | .package(url: RemotePackage.SwiftDocC.path, from: RemotePackage.SwiftDocC.from) 78 | ) 79 | #endif 80 | 81 | // MARK: - Struct 82 | public struct InfoPackage { 83 | 84 | // MARK: String Properties 85 | public static let PackageName: String = "SystemKit" 86 | 87 | public static let PackagePath: String = "Sources" 88 | 89 | public static let PackageObjcName: String = "SystemKit_Objc" 90 | 91 | public static let PackageObjcPath: String = "ObjcSources" 92 | 93 | public static let platforms: [PackageDescription.Platform] = [.iOS, .macOS] 94 | } 95 | 96 | // MARK: - Protocol 97 | public protocol PackageProtocol { 98 | 99 | var name: String { get } 100 | var path: String { get } 101 | var target: Target.Dependency { get } 102 | } 103 | 104 | // MARK: - Enum 105 | public enum RemotePackage: String, CaseIterable, PackageProtocol { 106 | 107 | /// 🌎 [Swift-docc-plugin - GitHub](https://github.com/apple/swift-docc-plugin) 108 | case SwiftDocC = "SwiftDocCPlugin" 109 | 110 | /// 🌎 [SwiftLog - GitHub](https://github.com/apple/swift-log) 111 | case SwiftLog = "swift-log" 112 | 113 | /// 🌎 [Swift-HTTP-Types- GitHub](https://github.com/apple/swift-http-types) 114 | case SwiftHTTPTypes = "swift-http-types" 115 | 116 | /// 🌎 [PLCrashReporter - GitHub](https://github.com/microsoft/plcrashreporter) 117 | case PLCrashReporter = "PLCrashReporter" 118 | 119 | public var path: String { 120 | 121 | switch self { 122 | case .SwiftDocC: 123 | return "https://github.com/apple/swift-docc-plugin.git" 124 | case .SwiftLog: 125 | return "https://github.com/apple/swift-log.git" 126 | case .SwiftHTTPTypes: 127 | return "https://github.com/apple/swift-http-types.git" 128 | case .PLCrashReporter: 129 | return "https://github.com/microsoft/plcrashreporter.git" 130 | } 131 | } 132 | 133 | public var from: Version { 134 | 135 | switch self { 136 | case .SwiftDocC: 137 | // https://github.com/apple/swift-docc-plugin/releases/tag/1.3.0 138 | return Version(1, 3, 0) 139 | case .SwiftLog: 140 | // https://github.com/apple/swift-log/releases/tag/1.6.1 141 | return Version(1, 6, 1) 142 | case .SwiftHTTPTypes: 143 | // https://github.com/apple/swift-http-types/releases/tag/1.3.0 144 | return Version(1, 3, 0) 145 | case .PLCrashReporter: 146 | // https://github.com/microsoft/plcrashreporter/releases/tag/1.11.2 147 | return Version(1, 11, 2) 148 | } 149 | } 150 | 151 | public var target: Target.Dependency { 152 | 153 | switch self { 154 | case .SwiftDocC: 155 | let condition = TargetDependencyCondition.when(platforms: InfoPackage.platforms) 156 | return .target(name: self.name, condition: condition) 157 | case .SwiftLog: 158 | let condition = TargetDependencyCondition.when(platforms: InfoPackage.platforms) 159 | return .product(name: "Logging", package: self.name, condition: condition) 160 | case .SwiftHTTPTypes: 161 | let condition = TargetDependencyCondition.when(platforms: InfoPackage.platforms) 162 | return .product(name: "HTTPTypes", package: self.name, condition: condition) 163 | case .PLCrashReporter: 164 | let condition = TargetDependencyCondition.when(platforms: InfoPackage.platforms) 165 | return .product(name: "CrashReporter", package: self.name, condition: condition) 166 | } 167 | } 168 | 169 | public var name: String { return self.rawValue } 170 | } 171 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Logo](https://user-images.githubusercontent.com/20036523/246614687-8c70ad56-9c85-416e-b664-7f73a1b81743.png) 2 | 3 | [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FChangYeop-Yang%2FUniversal-SystemKit%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/ChangYeop-Yang/Universal-SystemKit) 4 | [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FChangYeop-Yang%2FUniversal-SystemKit%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/ChangYeop-Yang/Universal-SystemKit) 5 | [![Tistory - Shields.io](https://img.shields.io/badge/Tistory-%40yeop9657-informational)](https://dev-dream-world.tistory.com) 6 | [![LinkedIn - Shields.io](https://img.shields.io/badge/Linked--In-창엽--양--3535ab134-informational)](https://www.linkedin.com/in/창엽-양-3535ab134/) 7 | ![Swift Package Manager - Shields.io](https://img.shields.io/badge/Swift%20Package%20Manager-Compatible-success) 8 | ![Manually - Shields.io](https://img.shields.io/badge/Manually-Compatible-success) 9 | ![Github Repository - Shields.io](https://img.shields.io/badge/Github%20Repository-Compatible-success) 10 | [![License - Shields.io](https://img.shields.io/badge/License-MIT-blueviolet)](https://github.com/ChangYeop-Yang/Universal-SystemKit/blob/main/LICENSE) 11 | 12 | The `SystemKit` open-source library can be used on Apple Platforms such as `macOS`, `iOS`. and is a common library that enables convenient and efficient use of device system functions. 13 | 14 | # Installation 15 | 16 | The installation method for Universal SystemKit can be done through the [Swift Package Manager](https://www.swift.org/package-manager) or the [Github Repository](https://docs.github.com/en/repositories), and the details are as follows. 17 | 18 | ### Manually 19 | 20 | If you prefer not to use any of the aforementioned dependency managers, you can integrate `SystemKit` into your project manually. 21 | 22 | ### Github Repository 23 | 24 | You can pull the `SystemKit` Github Repository and include the `SystemKit` to build a dynamic or static library. 25 | 26 | ### Swift Package Manager 27 | 28 | The Swift Package Manager is a tool for automating the distribution of Swift code and is integrated into the swift compiler. 29 | 30 | Once you have your Swift package set up, adding `SystemKit` as a dependency is as easy as adding it to the dependencies value of your Package.swift. 31 | 32 | 1. From the Xcode menu, click File → Swift Packages → Add Package Dependency. 33 | 34 | 2. In the dialog that appears, enter the repository URL: https://github.com/ChangYeop-Yang/Universal-SystemKit.git. 35 | 36 | 3-1. In Branch, Enter text "master". 37 | 38 | ```Swift 39 | dependencies: [ 40 | .package(url: "https://github.com/ChangYeop-Yang/Universal-SystemKit", .branch("master")) 41 | ] 42 | ``` 43 | 44 | 3-2. In Branch, Enter text "Version(2, 4, 0)". 45 | 46 | ```Swift 47 | dependencies: [ 48 | .package(url: "https://github.com/ChangYeop-Yang/Universal-SystemKit", from: Version(2, 4, 0)) 49 | ] 50 | ``` 51 | 52 | # Requirements 53 | 54 | The detailed build results for the `Universal-SystemKit` library are as follows. 55 | 56 | | Platform | Minimum Swift Version | Installation | Status | 57 | |:--------:|:---------------------:|:------------:|:------:| 58 | | iOS 13.0+ | [5.0](https://www.swift.org/blog/swift-5-released/) | [Swift Package Manager](#swift-package-manager), [Manual](#manually), [Github Repository](#github-repository) | [✅ Fully Tested](https://swiftpackageindex.com/ChangYeop-Yang/Universal-SystemKit/builds) | 59 | | macOS 10.15+ (Catalina) | [5.0](https://www.swift.org/blog/swift-5-released/) | [Swift Package Manager](#swift-package-manager), [Manual](#manually), [Github Repository](#github-repository) | [✅ Fully Tested](https://swiftpackageindex.com/ChangYeop-Yang/Universal-SystemKit/builds) | 60 | 61 | # Using SystemKit 62 | 63 | The method for using the `Universal SystemKit` open-source library is described in the guide path below. For additional related information, please inquire by creating an issue. 64 | 65 | * [SKAsyncOperation](https://dev-dream-world.tistory.com/231) 66 | 67 | * [SKUserDefault](https://dev-dream-world.tistory.com/224) 68 | 69 | * [SKMessagePort](https://dev-dream-world.tistory.com/247) 70 | 71 | * [SKNetworkMonitor](https://dev-dream-world.tistory.com/234) 72 | 73 | * [SKFinderExtension](https://dev-dream-world.tistory.com/226?category=1294828) 74 | 75 | * [SKPermission](https://dev-dream-world.tistory.com/227?category=1294828) 76 | 77 | * [SKProcess](https://dev-dream-world.tistory.com/225?category=1294828) 78 | 79 | * [SKProcessMonitor](https://dev-dream-world.tistory.com/230?category=1294828) 80 | 81 | * [SKSignal](https://dev-dream-world.tistory.com/229?category=1294828) 82 | 83 | * [SKCrashReporter](https://dev-dream-world.tistory.com/236) 84 | 85 | * [SKFileLock](https://dev-dream-world.tistory.com/244) 86 | 87 | * [SKDispatchFile](https://dev-dream-world.tistory.com/246) 88 | 89 | * [SKSecurity](https://dev-dream-world.tistory.com/262) 90 | 91 | * [SKDispatchFileMonitor](https://dev-dream-world.tistory.com/275) → `SKDispatchFileMonitor` provides a common interface for monitoring file events on both iOS and macOS platforms. 92 | 93 | # License 94 | 95 | `SystemKit` is released under the MIT license. [See LICENSE](https://github.com/ChangYeop-Yang/Apple-SystemKit/blob/main/LICENSE) for details. 96 | 97 |
98 | 99 | ```TEXT 100 | MIT License 101 | 102 | Copyright (c) 2022 Universal-SystemKit 103 | 104 | Permission is hereby granted, free of charge, to any person obtaining a copy 105 | of this software and associated documentation files (the "Software"), to deal 106 | in the Software without restriction, including without limitation the rights 107 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 108 | copies of the Software, and to permit persons to whom the Software is 109 | furnished to do so, subject to the following conditions: 110 | 111 | The above copyright notice and this permission notice shall be included in all 112 | copies or substantial portions of the Software. 113 | 114 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 115 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 116 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 117 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 118 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 119 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 120 | SOFTWARE. 121 | ``` 122 | -------------------------------------------------------------------------------- /Sources/Common/SKData+Extension.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | import Foundation 24 | 25 | // MARK: - Public Extension Data 26 | public extension Data { 27 | 28 | var base64DecodedString: String? { 29 | 30 | return String(data: self, encoding: .utf8)?.base64DecodedString 31 | } 32 | 33 | var base64DecodedData: Data? { 34 | 35 | return String(data: self, encoding: .utf8)?.base64DecodedData 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Sources/Common/SKDouble+Extension.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | import Foundation 24 | 25 | // MARK: - Extension Double 26 | extension Double { 27 | 28 | public var round2dp: Double { return (10.0 * self).rounded() / 10.0 } 29 | } 30 | -------------------------------------------------------------------------------- /Sources/Common/SKString+Extension.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | import Foundation 24 | 25 | // MARK: - Public Extension String 26 | public extension String { 27 | 28 | var kCFString: CFString { return self as CFString } 29 | 30 | var kCString: UnsafePointer? { return (self as NSString).cString(using: String.Encoding.utf8.rawValue) } 31 | 32 | var base64EncodedString: String? { return self.data(using: .utf8)?.base64EncodedString() } 33 | 34 | var base64EncodedData: Data? { return self.data(using: .utf8)?.base64EncodedData() } 35 | 36 | var base64DecodedString: String? { 37 | 38 | guard let rawData = Data(base64Encoded: self) else { return nil } 39 | 40 | return String(data: rawData, encoding: .utf8) 41 | } 42 | 43 | var base64DecodedData: Data? { return Data(base64Encoded: self) } 44 | 45 | var kNSNotificationName: NSNotification.Name { return NSNotification.Name(self) } 46 | 47 | var kNotificationName: Notification.Name { return Notification.Name(self) } 48 | } 49 | -------------------------------------------------------------------------------- /Sources/Communication/SKMessagePort+Define.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | import Foundation 24 | import CoreFoundation 25 | 26 | // MARK: - Typealias 27 | public typealias SKMessageLocalPort = (messagePort: CFMessagePort, instance: UnsafeMutablePointer) 28 | public typealias SKMessagePortRequestResult = Result 29 | 30 | // MARK: - Enum 31 | public enum SKMessagePortSendRequestErrorCode: Error { 32 | 33 | // https://developer.apple.com/documentation/corefoundation/cfmessageport/1561514-cfmessageportsendrequest_error_c 34 | 35 | /// The message was successfully sent and, if a reply was expected, a reply was received. 36 | case success 37 | 38 | /// The message could not be sent before the send timeout. 39 | case timeoutSend 40 | 41 | /// No reply was received before the receive timeout. 42 | case timeoutReceive 43 | 44 | /// The message could not be sent because the message port is invalid. 45 | case invalid 46 | 47 | /// An error occurred trying to send the message. 48 | case transportError 49 | 50 | /// The message port was invalidated. 51 | case BecameInvalidError 52 | 53 | // MARK: Enum Computed Properties 54 | public var errorCode: Int32 { 55 | 56 | // Error codes for CFMessagePortSendRequest. 57 | switch self { 58 | case .success: 59 | return kCFMessagePortSuccess 60 | case .timeoutSend: 61 | return kCFMessagePortSendTimeout 62 | case .timeoutReceive: 63 | return kCFMessagePortReceiveTimeout 64 | case .invalid: 65 | return kCFMessagePortIsInvalid 66 | case .transportError: 67 | return kCFMessagePortTransportError 68 | case .BecameInvalidError: 69 | return kCFMessagePortBecameInvalidError 70 | } 71 | } 72 | 73 | // MARK: Enum Method 74 | public static func getMessagePortRequestError(_ errorCode: Int32) -> SKMessagePortRequestResult { 75 | 76 | switch errorCode { 77 | case kCFMessagePortSuccess: 78 | return .success(SKMessagePortSendRequestErrorCode.success.errorCode) 79 | case kCFMessagePortSendTimeout: 80 | return .failure(SKMessagePortSendRequestErrorCode.timeoutSend) 81 | case kCFMessagePortReceiveTimeout: 82 | return .failure(SKMessagePortSendRequestErrorCode.timeoutReceive) 83 | case kCFMessagePortIsInvalid: 84 | return .failure(SKMessagePortSendRequestErrorCode.invalid) 85 | case kCFMessagePortTransportError: 86 | return .failure(SKMessagePortSendRequestErrorCode.transportError) 87 | case kCFMessagePortBecameInvalidError: 88 | return .failure(SKMessagePortSendRequestErrorCode.BecameInvalidError) 89 | default: 90 | fatalError("The value of CFMessagePortSendRequest Error Codes is invalid.") 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Sources/Communication/SKMessagePort.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | import Foundation 24 | import CoreFoundation 25 | 26 | public class SKMessagePort: SKClass { 27 | 28 | // MARK: - Object Properties 29 | public static var label: String = "com.SystemKit.SKMessagePort" 30 | public static var identifier: String = "368027F0-C77F-4F81-B352-F92B7B0370DB" 31 | 32 | private var portName: CFString 33 | private var portAttribute: Optional 34 | private var invalidateCallBack: CFMessagePortInvalidationCallBack 35 | 36 | // MARK: - Initalize 37 | public init(portName: String, _ invalidateCallBack: @escaping CFMessagePortInvalidationCallBack) { 38 | self.portName = portName as CFString 39 | self.portAttribute = nil 40 | self.invalidateCallBack = invalidateCallBack 41 | } 42 | } 43 | 44 | // MARK: - Private Extension SKMessagePort 45 | private extension SKMessagePort { 46 | 47 | final func createMutablePointer(instance: T) -> UnsafeMutablePointer { 48 | 49 | let pointer = UnsafeMutablePointer.allocate(capacity: 1) 50 | 51 | pointer.initialize(to: instance) 52 | 53 | return pointer 54 | } 55 | 56 | /// Returns a local CFMessagePort object. 57 | final func createLocalMessagePort(instance: AnyObject, 58 | _ callback: @escaping CFMessagePortCallBack) -> Optional { 59 | 60 | let pointer = createMutablePointer(instance: instance) 61 | 62 | var context = CFMessagePortContext(version: CFIndex.zero, info: pointer, 63 | retain: nil, release: nil, copyDescription: nil) 64 | 65 | var shouldFreeInfo: DarwinBoolean = false 66 | 67 | // 동일한 프로세스 내에서 메시지를 보낼 때 사용하는 로컬 메시지 포트를 생성합니다. 68 | guard let localPort = CFMessagePortCreateLocal(kCFAllocatorDefault, 69 | self.portName, callback, &context, &shouldFreeInfo) else { 70 | logger.error("[SKMessagePort] Failed to create a CFMessageLocalPort object.") 71 | return nil 72 | } 73 | 74 | // Sets the callback function invoked when a CFMessagePort object is invalidated. 75 | CFMessagePortSetInvalidationCallBack(localPort, self.invalidateCallBack) 76 | 77 | // The flag is set to true on failure or if a local port named name already exists, false otherwise. 78 | switch shouldFreeInfo.boolValue { 79 | case true: 80 | logger.error("[SKMessagePort] Could not create CFMessageLocalPort as it already exists.") 81 | return nil 82 | 83 | case false: 84 | logger.info("[SKMessagePort] CFMessageLocalPort has been created.") 85 | return SKMessageLocalPort(localPort, pointer) 86 | } 87 | } 88 | 89 | /// Returns a CFMessagePort object connected to a remote port. 90 | final func createRemoteMessagePort() -> Optional { 91 | 92 | // 다른 프로세스로 메시지를 보낼 때 사용하는 원격 메시지 포트를 생성합니다. 93 | guard let remotePort = CFMessagePortCreateRemote(kCFAllocatorDefault, self.portName) else { 94 | logger.error("[SKMessagePort] Failed to create a CFMessageRemotePort object.") 95 | return nil 96 | } 97 | 98 | // Sets the callback function invoked when a CFMessagePort object is invalidated. 99 | CFMessagePortSetInvalidationCallBack(remotePort, self.invalidateCallBack) 100 | 101 | logger.info("[SKMessagePort] CFMessageRemotePort has been created.") 102 | 103 | return remotePort 104 | } 105 | 106 | /// Invalidates a CFMessagePort object, stopping it from receiving or sending any more messages. 107 | final func invalidate(_ messagePort: CFMessagePort) { 108 | 109 | logger.info("[SKMessagePort] Performing invalidate on the CFMessagePort.") 110 | 111 | CFMessagePortInvalidate(messagePort) 112 | } 113 | } 114 | 115 | // MARK: - Public Extension SKMessagePort 116 | public extension SKMessagePort { 117 | 118 | final func invalidate() { 119 | 120 | // CFMessagePort 초기화 작업 대상 존재 여부를 확인합니다. 121 | guard let attribuate = self.portAttribute else { 122 | logger.error("[SKMessagePort] There are no targets to perform the invalidation.") 123 | return 124 | } 125 | 126 | // Deallocates the memory block previously allocated at this pointer. 127 | attribuate.instance.deallocate() 128 | 129 | // Invalidates a CFMessagePort object, stopping it from receiving or sending any more messages. 130 | invalidate(attribuate.messagePort) 131 | } 132 | 133 | @discardableResult 134 | final func listen(dispatch: DispatchQueue, 135 | info: AnyObject, _ callback: @escaping CFMessagePortCallBack) -> Bool { 136 | 137 | guard let attribute = createLocalMessagePort(instance: info, callback) else { return false } 138 | 139 | // CFMessagePort가 활성화 상태가 유지되도록 전역 변수에 저장합니다. 140 | self.portAttribute = attribute 141 | 142 | // Schedules callbacks for the specified message port on the specified dispatch queue. 143 | CFMessagePortSetDispatchQueue(attribute.messagePort, dispatch) 144 | 145 | logger.info("[SKMessagePort] Performing the listen on the CFMessagePort by DispatchQueue.") 146 | 147 | return CFMessagePortIsValid(attribute.messagePort) 148 | } 149 | 150 | @discardableResult 151 | final func send(messageID: Int32, message: Data, 152 | sendTimeout: CFTimeInterval = CFTimeInterval.zero, 153 | recvTimeout: CFTimeInterval = CFTimeInterval.zero) -> SKMessagePortRequestResult { 154 | 155 | // 데이터 전송을 위하여 CFMessageRemotePort를 생성합니다. 156 | guard let remotePort = createRemoteMessagePort() else { 157 | return .failure(SKMessagePortSendRequestErrorCode.invalid) 158 | } 159 | 160 | // 데이터 전송 후 CFMessageRemotePort 소멸작업을 수행합니다. 161 | defer { invalidate(remotePort) } 162 | 163 | // 전송하고자 하는 데이터가 비어있는 경우에는 전송하지 않습니다. 164 | if message.isEmpty { 165 | logger.error("[SKMessagePort] The data to be transferred is empty.") 166 | return .failure(SKMessagePortSendRequestErrorCode.transportError) 167 | } 168 | 169 | // Sends a message to a remote CFMessagePort object. 170 | let error = CFMessagePortSendRequest(remotePort, messageID, message as CFData, sendTimeout, recvTimeout, nil, nil) 171 | 172 | switch SKMessagePortSendRequestErrorCode.getMessagePortRequestError(error) { 173 | case .success: 174 | logger.info("[SKMessagePort] \(message.count) Bytes of data has been transferred.") 175 | return .success(kCFMessagePortSuccess) 176 | 177 | case .failure(let error): 178 | logger.error("[SKMessagePort] Error occur: \(error.localizedDescription)") 179 | return .failure(error) 180 | } 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /Sources/Dispatch/SKDispatchFile.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | import Darwin 24 | import Dispatch 25 | import Foundation 26 | 27 | @objc public class SKDispatchFile: NSObject, SKClass { 28 | 29 | // MARK: - Typealias 30 | public typealias FileIOReadCompletion = (Data, Int32) -> Swift.Void 31 | public typealias FileIOWriteCompletion = (Int32) -> Swift.Void 32 | 33 | // MARK: - Object Properties 34 | public static var label: String = "com.SystemKit.SKDispatchFile" 35 | public static var identifier: String = "870EBBA7-3167-4147-BE3A-82E0C4A108A2" 36 | 37 | private let mode: mode_t 38 | private let implementQueue: DispatchQueue 39 | 40 | // MARK: - Initalize 41 | public init(qualityOfService qos: DispatchQoS = .default, mode: mode_t = 0o777) { 42 | 43 | // 파일이나 디렉토리 권한에 관련된 정보를 저장하는 변수입니다. 44 | self.mode = mode 45 | self.implementQueue = DispatchQueue(label: SKDispatchFile.label, qos: qos, attributes: .concurrent) 46 | } 47 | } 48 | 49 | // MARK: - Private Extension SKDispatchFile 50 | private extension SKDispatchFile { 51 | 52 | static func closeChannel(channel: DispatchIO, filePath: String, error: Int32) { 53 | 54 | let result: Int32 = flock(channel.fileDescriptor, LOCK_UN) 55 | logger.info("[SKDispatchFile][\(filePath)][error: \(result)] Unlock FileDescriptor") 56 | 57 | channel.close(flags: DispatchIO.CloseFlags.stop) 58 | logger.info("[SKDispatchFile][\(filePath)][error: \(error)] Close DispatchIO Operation") 59 | } 60 | 61 | final func createFileChannel(filePath: String, _ oflag: Int32) -> Optional { 62 | 63 | let fileDescriptor = open(filePath, oflag, self.mode) 64 | 65 | if fileDescriptor == EOF { 66 | logger.error("[SKDispatchFile][\(filePath)] Could't create file descriptor") 67 | return nil 68 | } 69 | 70 | // 파일 작업을 수행하기 전에 다른 프로세스 및 쓰레드에 대하여 원자성을 보장하기 위하여 파일 잠금을 수행합니다. 71 | flock(fileDescriptor, LOCK_EX) 72 | 73 | let channel = DispatchIO(type: .stream, fileDescriptor: fileDescriptor, queue: self.implementQueue) { error in 74 | 75 | // The handler to execute once the channel is closed. 76 | logger.info("[SKDispatchFile][\(filePath)][error: \(error)] DispatchIO Cleanup") 77 | } 78 | 79 | return channel 80 | } 81 | } 82 | 83 | // MARK: - Public Extension SKDispatchFile 84 | public extension SKDispatchFile { 85 | 86 | /** 87 | 파일에 대하여 쓰기 작업을 수행합니다. 88 | Perform a write operation on the file. 89 | 90 | - Version: `1.0.0` 91 | - Authors: `ChangYeop-Yang` 92 | - NOTE: `스레드 안전 (Thread Safety)` 93 | - Parameters: 94 | - contents: 파일에 쓰기 작업을 수행하기 위한 `Data`를 입력받는 매개변수 95 | - filePath: 쓰기 작업을 수행 할 파일 경로를 입력받는 매개변수 96 | - completion: 쓰기 작업을 통한 `(Int32) -> Swift.Void` 형태의 결과물을 전달하는 매개변수 97 | */ 98 | final func write(contents: Data, filePath: String, _ completion: @escaping FileIOWriteCompletion) { 99 | 100 | // 쓰기 작업을 수행하기 위한 DispatchIO 생성합니다. 101 | guard let channel = self.createFileChannel(filePath: filePath, O_WRONLY | O_CREAT) else { return } 102 | 103 | let body: (UnsafeRawBufferPointer) throws -> Swift.Void = { pointer in 104 | 105 | // If the baseAddress of this buffer is nil, the count is zero. 106 | guard let baseAddress = pointer.baseAddress else { 107 | SKDispatchFile.closeChannel(channel: channel, filePath: filePath, error: EOF) 108 | return 109 | } 110 | 111 | let bytes = UnsafeRawBufferPointer(start: baseAddress, count: contents.count) 112 | 113 | let data = DispatchData(bytes: bytes) 114 | 115 | channel.write(offset: off_t.zero, data: data, queue: self.implementQueue) { done, data, error in 116 | 117 | // 파일 쓰기 작업에 오류가 발생한 경우에는 읽기 작업을 종료합니다. 118 | guard error == Int32.zero else { 119 | SKDispatchFile.closeChannel(channel: channel, filePath: filePath, error: error) 120 | return 121 | } 122 | 123 | // 정상적으로 파일 쓰기 작업이 완료 된 경우에 파일 내용을 전달합니다. 124 | if done { 125 | // 쓰기 작업에 수행 한 모든 파일 내용을 전달합니다. 126 | completion(error) 127 | 128 | // 파일 쓰기 작업을 위해서 생성 한 DispatchIO을 닫습니다. 129 | SKDispatchFile.closeChannel(channel: channel, filePath: filePath, error: error) 130 | } 131 | } 132 | } 133 | 134 | do { try contents.withUnsafeBytes(body) } 135 | catch let error as NSError { 136 | let errcode: Int32 = Int32(error.code) 137 | SKDispatchFile.closeChannel(channel: channel, filePath: filePath, error: errcode) 138 | return 139 | } 140 | } 141 | 142 | /** 143 | 파일에 대하여 읽기 작업을 수행합니다. 144 | Perform a read operation on the file. 145 | 146 | - Version: `1.0.0` 147 | - Authors: `ChangYeop-Yang` 148 | - NOTE: `스레드 안전 (Thread Safety)` 149 | - Parameters: 150 | - filePath: 읽기 작업을 수행하는 파일 경로를 입력받는 매개변수 151 | - completion: 읽기 작업을 통한 `(Data, Int32) -> Swift.Void` 형태의 결과물을 전달하는 매개변수 152 | */ 153 | final func read(filePath: String, _ completion: @escaping FileIOReadCompletion) { 154 | 155 | // 파일 읽기 작업을 수행하기 전에 해당 파일이 실제로 존재하는지 확인합니다. 156 | guard FileManager.default.fileExists(atPath: filePath) else { 157 | logger.error("[SKDispatchFile][\(filePath)] The file does not exist at the specified path") 158 | return 159 | } 160 | 161 | // 읽기 작업을 수행하기 위한 DispatchIO 생성합니다. 162 | guard let channel = createFileChannel(filePath: filePath, O_RDONLY) else { return } 163 | 164 | var rawData = Data() 165 | 166 | channel.read(offset: off_t.zero, length: Int.max, queue: self.implementQueue) { done, data, error in 167 | 168 | // 파일 읽기 작업에 오류가 발생한 경우에는 읽기 작업을 종료합니다. 169 | guard error == Int32.zero else { 170 | SKDispatchFile.closeChannel(channel: channel, filePath: filePath, error: error) 171 | return 172 | } 173 | 174 | // 정상적으로 파일로부터 데이터를 읽어들이는 경우 175 | if let contentsOf = data { rawData.append(contentsOf: contentsOf) } 176 | 177 | // 정상적으로 파일 읽기 작업이 완료 된 경우에 파일 내용을 전달합니다. 178 | if done { 179 | // 읽어들인 모든 파일 내용을 전달합니다. 180 | completion(rawData, error) 181 | 182 | // 파일 읽기 작업을 위해서 생성 한 DispatchIO을 닫습니다. 183 | SKDispatchFile.closeChannel(channel: channel, filePath: filePath, error: error) 184 | } 185 | } 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /Sources/Dispatch/SKDispatchFileMonitor+Define.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | import Foundation 24 | 25 | // MARK: - Typealias 26 | public typealias SKFileEventHandler = (DispatchSource.FileSystemEvent) -> Swift.Void 27 | -------------------------------------------------------------------------------- /Sources/Dispatch/SKDispatchFileMonitor.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2024 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | import Dispatch 24 | import Foundation 25 | 26 | @objc public class SKDispatchFileMonitor: NSObject, SKClass { 27 | 28 | // MARK: - Object Properties 29 | public static let label: String = "com.SystemKit.SKDispatchFileMonitor" 30 | public static let identifier: String = "A2BC9AF4-45B0-4C49-8D6B-1B0BAB8AC3FA" 31 | public static let name = Notification.Name(SKDispatchFileMonitor.label) 32 | 33 | private let source: DispatchSourceFileSystemObject 34 | private var handler: Optional 35 | 36 | // MARK: - Initalize 37 | public init?(filePath: String, eventMask: DispatchSource.FileSystemEvent, handler: Optional = nil) { 38 | 39 | // Creating a FileHandle 40 | guard let fileDescriptor = SKDispatchFileMonitor.makeFileDescriptor(filePath: filePath) else { return nil } 41 | 42 | // Creating a DispatchSourceFileSystemObject 43 | guard let source = SKDispatchFileMonitor.makeFileSystemObjectSource(fileDescriptor: fileDescriptor, 44 | eventMask: eventMask) else { return nil } 45 | 46 | self.source = source 47 | self.handler = handler 48 | } 49 | 50 | // MARK: - Deinitalize 51 | deinit { stop() } 52 | } 53 | 54 | // MARK: - Private Extension SKDispatchFileMonitor 55 | private extension SKDispatchFileMonitor { 56 | 57 | static func makeFileDescriptor(filePath: String) -> Optional { 58 | 59 | // Creating a FileDescriptor 60 | let fileDescriptor = open(filePath, O_EVTONLY | F_NOCACHE) 61 | 62 | // Failed to create FileDescriptor 63 | if fileDescriptor < Int32.zero { return nil } 64 | 65 | return fileDescriptor 66 | } 67 | 68 | static func makeFileSystemObjectSource(fileDescriptor: Int32, 69 | eventMask: DispatchSource.FileSystemEvent) -> Optional { 70 | 71 | let queue = DispatchQueue(label: SKDispatchFileMonitor.label, qos: .background, attributes: .concurrent) 72 | 73 | return DispatchSource.makeFileSystemObjectSource(fileDescriptor: fileDescriptor, eventMask: eventMask, queue: queue) 74 | } 75 | 76 | final func occurEventHandler() { 77 | 78 | logger.info("[SKDispatchFileMonitor] Setting up an EventHandler for FileSystem") 79 | 80 | self.handler?(self.source.data) 81 | 82 | NotificationCenter.default.post(name: SKDispatchFileMonitor.name, object: self.source.data) 83 | } 84 | 85 | final func occurCancelHandler() { 86 | 87 | logger.info("[SKDispatchFileMonitor] Setting up an CancelEventHandler for FileSystem") 88 | 89 | // Cleaning up objects used in FileSystemEvent 90 | self.handler = nil 91 | close(self.source.handle) 92 | 93 | NotificationCenter.default.post(name: SKDispatchFileMonitor.name, object: nil) 94 | } 95 | } 96 | 97 | // MARK: - Public Extension SKDispatchFileMonitor 98 | public extension SKDispatchFileMonitor { 99 | 100 | final func start() { 101 | 102 | // Setting up an EventHandler for DispatchSourceFileSystem 103 | self.source.setEventHandler { [unowned self] in self.occurEventHandler() } 104 | 105 | // Setting up an CancelEventHandler for DispatchSourceFileSystem 106 | self.source.setCancelHandler { [unowned self] in self.occurCancelHandler() } 107 | 108 | // Resumes the DispatchSourceFileSystem 109 | self.source.resume() 110 | } 111 | 112 | final func stop() { 113 | 114 | logger.info("[SKDispatchFileMonitor] Stopping FileSystemEvent monitoring") 115 | 116 | // cancel the DispatchSourceFileSystem 117 | self.source.cancel() 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /Sources/Dispatch/SKDispatchTimer+Define.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | // MARK: - Enum 24 | public enum SKDispatchTimerState { case resumed, suspended, canceled, activated } 25 | -------------------------------------------------------------------------------- /Sources/Dispatch/SKDispatchTimer.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | import Dispatch 24 | import Foundation 25 | 26 | @objc public class SKDispatchTimer: NSObject, SKClass { 27 | 28 | // MARK: - Typealias 29 | public typealias SKDispatchTimerHandler = () -> Swift.Void 30 | 31 | // MARK: - Object Properties 32 | public static var label: String = "com.SystemKit.SKDispatchTimer" 33 | public static var identifier: String = "A42D0B47-D7B3-4A23-8F30-B3E51555471E" 34 | 35 | private var interval = TimeInterval.zero 36 | private let implementQueue = DispatchQueue(label: SKDispatchFile.label) 37 | private var state = SKDispatchTimerState.suspended 38 | private var handler: Optional = nil 39 | private lazy var timer: Optional = nil 40 | 41 | // MARK: - Initalize 42 | @objc public init(interval: TimeInterval, _ handler: SKDispatchTimerHandler? = nil) { 43 | super.init() 44 | 45 | self.handler = handler 46 | self.interval = interval 47 | 48 | self.timer = makeTimerSource() 49 | } 50 | 51 | // MARK: - Deinitalize 52 | deinit { deinitalize() } 53 | } 54 | 55 | // MARK: - Private Extension SKDispatchTimer 56 | private extension SKDispatchTimer { 57 | 58 | final func makeTimerSource(flags: DispatchSource.TimerFlags = .strict) -> DispatchSourceTimer { 59 | 60 | let timer = DispatchSource.makeTimerSource(flags: flags, queue: self.implementQueue) 61 | timer.schedule(deadline: DispatchTime.now(), repeating: self.interval) 62 | timer.setEventHandler { self.handler?() } 63 | 64 | return timer 65 | } 66 | 67 | final func deinitalize() { 68 | 69 | self.timer?.setEventHandler(handler: nil) 70 | 71 | // if the DispatchSourceTimer state is Cancelled, the cancel will not be performed 72 | if self.timer?.isCancelled == false { self.timer?.cancel() } 73 | 74 | self.handler = nil 75 | } 76 | 77 | final func withLock(_ handler: @escaping SKDispatchTimerHandler) { 78 | 79 | self.implementQueue.async(flags: .barrier) { handler() } 80 | } 81 | } 82 | 83 | // MARK: - Public Extension SKDispatchTimer 84 | public extension SKDispatchTimer { 85 | 86 | @objc final func resume() { 87 | 88 | withLock { 89 | 90 | // If the DispatchSourceTimer state is currently Resume, the Resume will not be performed 91 | if self.state == .resumed || self.state == .activated { return } 92 | 93 | self.state = .resumed 94 | self.timer?.resume() 95 | } 96 | } 97 | 98 | @objc final func suspend() { 99 | 100 | withLock { 101 | 102 | // If the DispatchSourceTimer state is currently Suspend, the Suspend will not be performed 103 | if self.state == .suspended { return } 104 | 105 | // Suspend the DispatchSourceTimer 106 | self.state = .suspended 107 | self.timer?.suspend() 108 | } 109 | } 110 | 111 | @objc final func reschedule(interval: TimeInterval, _ handler: SKDispatchTimerHandler? = nil) { 112 | 113 | withLock { 114 | 115 | // Rescheduling the DispatchSourceTimer's TimeInterval 116 | self.interval = interval 117 | self.timer?.schedule(deadline: DispatchTime.now(), repeating: self.interval) 118 | 119 | // Rescheduling the DispatchSourceTimer's EventHandler 120 | self.handler = handler 121 | self.timer?.setEventHandler { self.handler?() } 122 | } 123 | } 124 | 125 | @objc final func cancel() { 126 | 127 | withLock { 128 | 129 | // If the DispatchSourceTimer state is currently Cancel, the Cancel will not be performed 130 | if self.state == .canceled || self.timer?.isCancelled == true { return } 131 | 132 | // Cancel the DispatchSourceTimer 133 | self.state = .canceled 134 | self.timer?.cancel() 135 | } 136 | } 137 | 138 | @objc final func activate() { 139 | 140 | withLock { 141 | 142 | self.state = .activated 143 | self.timer?.activate() 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /Sources/IO/SKIOProcess.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Universal SystemKit. All rights reserved. 3 | * Copyright (C) 2014-2017 beltex 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | * THE SOFTWARE. 22 | */ 23 | 24 | #if os(macOS) 25 | import Darwin 26 | import Foundation 27 | 28 | /// Assuming this is interpreted as unknown for now 29 | public let CPU_TYPE_ANY: cpu_type_t = -1 30 | public let CPU_TYPE_X86: cpu_type_t = 7 31 | public let CPU_TYPE_I386: cpu_type_t = CPU_TYPE_X86 // For compatibility 32 | public let CPU_TYPE_X86_64: cpu_type_t = CPU_TYPE_X86 | CPU_ARCH_ABI64 33 | public let CPU_TYPE_ARM: cpu_type_t = 12 34 | public let CPU_TYPE_ARM64: cpu_type_t = CPU_TYPE_ARM | CPU_ARCH_ABI64 35 | public let CPU_TYPE_POWERPC: cpu_type_t = 18 36 | public let CPU_TYPE_POWERPC64: cpu_type_t = CPU_TYPE_POWERPC | CPU_ARCH_ABI64 37 | 38 | // MARK: - Enum 39 | 40 | /// Process information 41 | public struct SKIOProcessInfo { 42 | 43 | public let pid: Int 44 | public let ppid: Int 45 | public let pgid: Int 46 | public let uid: Int 47 | public let command: String 48 | public let arch: cpu_type_t 49 | public var status: Int32 // sys/proc.h - SIDL, SRUN, SSLEEP, SSTOP, SZOMB 50 | } 51 | 52 | /// Process API 53 | public struct SKIOProcessAPI { 54 | 55 | fileprivate static let machHost = mach_host_self() 56 | 57 | // MARK: Initalize 58 | public init() { NSLog("[SKIOProcessAPI] Initalize") } 59 | } 60 | 61 | // MARK: - Private Extension SKIOProcessAPI 62 | private extension SKIOProcessAPI { 63 | 64 | static func arch(_ pid: pid_t) -> cpu_type_t { 65 | 66 | var arch = CPU_TYPE_ANY 67 | 68 | var mib = [Int32](repeating: 0, count: Int(CTL_MAXNAME)) 69 | var mibLength = size_t(CTL_MAXNAME) 70 | 71 | var result = sysctlnametomib("sysctl.proc_cputype", &mib, &mibLength) 72 | 73 | if result != Int32.zero { 74 | #if DEBUG 75 | print("ERROR - \(#file):\(#function):\(#line) - " + "\(result)") 76 | #endif 77 | 78 | return arch 79 | } 80 | 81 | mib[Int(mibLength)] = pid 82 | var size = MemoryLayout.size 83 | 84 | result = sysctl(&mib, u_int(mibLength + 1), &arch, &size, nil, Int.zero) 85 | 86 | if result != Int32.zero { 87 | #if DEBUG 88 | print("ERROR - \(#file):\(#function):\(#line) - " + "\(result)") 89 | #endif 90 | 91 | arch = CPU_TYPE_ANY 92 | } 93 | 94 | return arch 95 | } 96 | } 97 | 98 | // MARK: - Public Extension SKIOProcessAPI 99 | public extension SKIOProcessAPI { 100 | 101 | static func list() -> [SKIOProcessInfo] { 102 | 103 | var list = [SKIOProcessInfo]() 104 | var psets: processor_set_name_array_t? = processor_set_name_array_t.allocate(capacity: 1) 105 | var pcnt: mach_msg_type_number_t = mach_msg_type_number_t.zero 106 | 107 | // Need root 108 | var result = host_processor_sets(machHost, &psets, &pcnt) 109 | if result != KERN_SUCCESS { 110 | #if DEBUG 111 | print("ERROR - \(#file):\(#function) - Need root - " + "kern_return_t: \(result)") 112 | #endif 113 | 114 | return list 115 | } 116 | 117 | // For each CPU set 118 | for i in Int.zero...stride 154 | var mib: [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_PID, pid] 155 | 156 | // TODO: Error check 157 | sysctl(&mib, u_int(mib.count), &kinfo, &size, nil, Int.zero) 158 | 159 | let command = withUnsafePointer(to: &kinfo.kp_proc.p_comm) { 160 | String(cString: UnsafeRawPointer($0).assumingMemoryBound(to: CChar.self)) 161 | } 162 | 163 | list.append(SKIOProcessInfo(pid: Int(pid), ppid: Int(kinfo.kp_eproc.e_ppid), 164 | pgid: Int(kinfo.kp_eproc.e_pgid), uid: Int(kinfo.kp_eproc.e_ucred.cr_uid), 165 | command: command, arch: arch(pid), status: Int32(kinfo.kp_proc.p_stat))) 166 | 167 | mach_port_deallocate(mach_task_self_, task) 168 | } 169 | 170 | // TODO: Missing deallocate for tasks 171 | mach_port_deallocate(mach_task_self_, pset) 172 | mach_port_deallocate(mach_task_self_, psets![i]) 173 | } 174 | 175 | return list 176 | } 177 | } 178 | #endif 179 | -------------------------------------------------------------------------------- /Sources/IO/SKIOReturn.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Universal SystemKit. All rights reserved. 3 | * Copyright (C) 2014-2017 beltex 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | * THE SOFTWARE. 22 | */ 23 | 24 | #if os(macOS) 25 | import IOKit 26 | 27 | /* 28 | I/O Kit common error codes - as defined in 29 | 30 | Swift can't import complex macros, thus we have to manually add them here. 31 | Most of these are not relevant to us, but for the sake of completeness. See 32 | "Accessing Hardware From Applications -> Handling Errors" Apple document for 33 | more information. 34 | 35 | NOTE: kIOReturnSuccess is the only return code already defined in IOKit module 36 | for us. 37 | 38 | https://developer.apple.com/library/mac/qa/qa1075/_index.html 39 | */ 40 | 41 | /// General error 42 | public let kIOReturnError = iokit_common_err(0x2bc) 43 | /// Can't allocate memory 44 | public let kIOReturnNoMemory = iokit_common_err(0x2bd) 45 | /// Resource shortage 46 | public let kIOReturnNoResources = iokit_common_err(0x2be) 47 | /// Error during IPC 48 | public let kIOReturnIPCError = iokit_common_err(0x2bf) 49 | /// No such device 50 | public let kIOReturnNoDevice = iokit_common_err(0x2c0) 51 | /// Privilege violation 52 | //public let kIOReturnNotPrivileged = iokit_common_err(0x2c1) 53 | /// Invalid argument 54 | public let kIOReturnBadArgument = iokit_common_err(0x2c2) 55 | /// Device read locked 56 | public let kIOReturnLockedRead = iokit_common_err(0x2c3) 57 | /// Exclusive access and device already open 58 | public let kIOReturnExclusiveAccess = iokit_common_err(0x2c5) 59 | /// Sent/received messages had different msg_id 60 | public let kIOReturnBadMessageID = iokit_common_err(0x2c6) 61 | /// Unsupported function 62 | public let kIOReturnUnsupported = iokit_common_err(0x2c7) 63 | /// Misc. VM failure 64 | public let kIOReturnVMError = iokit_common_err(0x2c8) 65 | /// Internal error 66 | public let kIOReturnInternalError = iokit_common_err(0x2c9) 67 | /// General I/O error 68 | public let kIOReturnIOError = iokit_common_err(0x2ca) 69 | /// Can't acquire lock 70 | public let kIOReturnCannotLock = iokit_common_err(0x2cc) 71 | /// Device not open 72 | public let kIOReturnNotOpen = iokit_common_err(0x2cd) 73 | /// Read not supported 74 | public let kIOReturnNotReadable = iokit_common_err(0x2ce) 75 | /// Write not supported 76 | public let kIOReturnNotWritable = iokit_common_err(0x2cf) 77 | /// Alignment error 78 | public let kIOReturnNotAligned = iokit_common_err(0x2d0) 79 | /// Media Error 80 | public let kIOReturnBadMedia = iokit_common_err(0x2d1) 81 | /// Device(s) still open 82 | public let kIOReturnStillOpen = iokit_common_err(0x2d2) 83 | /// RLD failure 84 | public let kIOReturnRLDError = iokit_common_err(0x2d3) 85 | /// DMA failure 86 | public let kIOReturnDMAError = iokit_common_err(0x2d4) 87 | /// Device Busy 88 | public let kIOReturnBusy = iokit_common_err(0x2d5) 89 | /// I/O Timeout 90 | public let kIOReturnTimeout = iokit_common_err(0x2d6) 91 | /// Device offline 92 | public let kIOReturnOffline = iokit_common_err(0x2d7) 93 | /// Not ready 94 | public let kIOReturnNotReady = iokit_common_err(0x2d8) 95 | /// Device not attached 96 | public let kIOReturnNotAttached = iokit_common_err(0x2d9) 97 | /// No DMA channels left 98 | public let kIOReturnNoChannels = iokit_common_err(0x2da) 99 | /// No space for data 100 | public let kIOReturnNoSpace = iokit_common_err(0x2db) 101 | /// Port already exists 102 | public let kIOReturnPortExists = iokit_common_err(0x2dd) 103 | /// Can't wire down physical memory 104 | public let kIOReturnCannotWire = iokit_common_err(0x2de) 105 | /// No interrupt attached 106 | public let kIOReturnNoInterrupt = iokit_common_err(0x2df) 107 | /// No DMA frames enqueued 108 | public let kIOReturnNoFrames = iokit_common_err(0x2e0) 109 | /// Oversized msg received on interrupt port 110 | public let kIOReturnMessageTooLarge = iokit_common_err(0x2e1) 111 | /// Not permitted 112 | public let kIOReturnNotPermitted = iokit_common_err(0x2e2) 113 | /// No power to device 114 | public let kIOReturnNoPower = iokit_common_err(0x2e3) 115 | /// Media not present 116 | public let kIOReturnNoMedia = iokit_common_err(0x2e4) 117 | /// Media not formatted 118 | public let kIOReturnUnformattedMedia = iokit_common_err(0x2e5) 119 | /// No such mode 120 | public let kIOReturnUnsupportedMode = iokit_common_err(0x2e6) 121 | /// Data underrun 122 | public let kIOReturnUnderrun = iokit_common_err(0x2e7) 123 | /// Data overrun 124 | public let kIOReturnOverrun = iokit_common_err(0x2e8) 125 | /// The device is not working properly! 126 | public let kIOReturnDeviceError = iokit_common_err(0x2e9) 127 | /// A completion routine is required 128 | public let kIOReturnNoCompletion = iokit_common_err(0x2ea) 129 | /// Operation aborted 130 | public let kIOReturnAborted = iokit_common_err(0x2eb) 131 | /// Bus bandwidth would be exceeded 132 | public let kIOReturnNoBandwidth = iokit_common_err(0x2ec) 133 | /// Device not responding 134 | public let kIOReturnNotResponding = iokit_common_err(0x2ed) 135 | /// Isochronous I/O request for distant past! 136 | public let kIOReturnIsoTooOld = iokit_common_err(0x2ee) 137 | /// Isochronous I/O request for distant future 138 | public let kIOReturnIsoTooNew = iokit_common_err(0x2ef) 139 | /// Data was not found 140 | public let kIOReturnNotFound = iokit_common_err(0x2f0) 141 | /// Should never be seen 142 | public let kIOReturnInvalid = iokit_common_err(0x1) 143 | 144 | /** 145 | I/O Kit system code is 0x38. First 6 bits of error code. Passed to err_system() 146 | macro as defined in . 147 | */ 148 | private let SYS_IOKIT: UInt32 = (0x38 & 0x3f) << 26 149 | 150 | /** 151 | I/O Kit subsystem code is 0. Middle 12 bits of error code. Passed to err_sub() 152 | macro as defined in . 153 | */ 154 | private let SUB_IOKIT_COMMON: UInt32 = (0 & 0xfff) << 14 155 | 156 | /** 157 | Based on macro of the same name in ``. 158 | Generates the error code. 159 | 160 | - Parameters: 161 | - code: The specific I/O Kit error code. Last 14 bits. 162 | - Returns Full 32 bit error code. 163 | */ 164 | private func iokit_common_err(_ code: UInt32) -> kern_return_t { 165 | return Int32(bitPattern: SYS_IOKIT | SUB_IOKIT_COMMON | code) 166 | } 167 | #endif 168 | -------------------------------------------------------------------------------- /Sources/Network/SKNetworkInterfaceDefine.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | // swiftlint:disable all 24 | #if os(iOS) || os(macOS) 25 | import Darwin 26 | import Foundation 27 | 28 | // MARK: - Enum 29 | 30 | /// The network interface family (IPv4 or IPv6). 31 | public enum SKFamily: Int { 32 | 33 | /// [IPv4](https://en.wikipedia.org/wiki/Internet_Protocol_version_4) 34 | case ipv4 35 | 36 | /// [IPv6](https://en.wikipedia.org/wiki/IPv6) 37 | case ipv6 38 | 39 | /// Used in case of errors. 40 | case other 41 | 42 | // MARK: Enum Computed Properties 43 | public var toString: String { 44 | 45 | // String representation of the address family. 46 | switch self { 47 | case .ipv4: 48 | return "IPv4" 49 | case .ipv6: 50 | return "IPv6" 51 | case .other: 52 | return "Other" 53 | } 54 | } 55 | } 56 | 57 | // MARK: - Struct 58 | public struct SKInterface: Identifiable, Codable { 59 | 60 | public var id: String = UUID().uuidString 61 | 62 | /// Extracted from `sysctl` based on `if_nametoindex`. 63 | public let macAddress: Optional 64 | 65 | /// Extracted from `ifaddrs->ifa_netmask`, supports both IPv4 and IPv6. 66 | public let netmask: Optional 67 | 68 | /// Extracted from `ifaddrs->ifa_addr`, supports both IPv4 and IPv6. 69 | public let ipAddress: Optional 70 | 71 | /// Extracted from `ifaddrs->ifa_dstaddr`. Not applicable for IPv6. 72 | public let broadcastAddress: Optional 73 | 74 | /// Field `ifaddrs->ifa_name`. 75 | public let interfaceName: String 76 | 77 | /// Field `ifaddrs->ifa_addr->sa_family`. 78 | public let interfaceFamily: String 79 | 80 | /// `IFF_UP` flag of `ifaddrs->ifa_flags`. 81 | public let up: Bool 82 | 83 | /// `IFF_RUNNING` flag of `ifaddrs->ifa_flags`. 84 | public let running: Bool 85 | 86 | /// `IFF_LOOPBACK` flag of `ifaddrs->ifa_flags`. 87 | public let loopBack: Bool 88 | 89 | /// `IFF_MULTICAST` flag of `ifaddrs->ifa_flags`. 90 | public let multicastSupported: Bool 91 | 92 | /// `IFF_BROADCAST` flag of `ifaddrs->ifa_flags`. 93 | public let broadcastSupported: Bool 94 | 95 | // MARK: Initalize 96 | public init(ipAddress: Optional, macAddress: Optional, 97 | broadcastAddress: Optional, netmask: Optional, 98 | interfaceName: String, interfaceFamily: String, ifaFlags: Int32) { 99 | 100 | self.netmask = netmask 101 | self.ipAddress = ipAddress 102 | self.macAddress = macAddress 103 | self.broadcastAddress = broadcastAddress 104 | 105 | self.interfaceName = interfaceName 106 | self.interfaceFamily = interfaceFamily 107 | 108 | self.up = (ifaFlags & IFF_UP) == IFF_UP 109 | self.running = (ifaFlags & IFF_RUNNING) == IFF_RUNNING 110 | self.loopBack = (ifaFlags & IFF_LOOPBACK) == IFF_LOOPBACK 111 | self.multicastSupported = (ifaFlags & IFF_MULTICAST) == IFF_MULTICAST 112 | self.broadcastSupported = (ifaFlags & IFF_BROADCAST) == IFF_BROADCAST 113 | } 114 | } 115 | #endif 116 | -------------------------------------------------------------------------------- /Sources/Network/SKNetworkMonitor.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | // swiftlint:disable all 24 | #if os(iOS) || os(macOS) 25 | import Network 26 | import Foundation 27 | 28 | @available(iOS 12.0, macOS 10.14, *) 29 | public class SKNetworkMonitor: SKClass { 30 | 31 | // MARK: - Typealias 32 | public typealias SKNetworkStatus = (isConnected: Bool, image: SKNetworkStatusSymbols) 33 | public typealias SKNetworkStatusUpdateHandler = (SKNetworkMonitorStatus) -> Swift.Void 34 | 35 | // MARK: - Object Properties 36 | public static var label: String = "com.SystemKit.SKNetworkMonitor" 37 | public static var identifier: String = "5C6F96D5-C21E-4A48-9AED-15794E19A4E9" 38 | 39 | private let monitor: NWPathMonitor = NWPathMonitor() 40 | private let pathUpdateHandler: SKNetworkStatusUpdateHandler 41 | private let implementQueue: DispatchQueue = DispatchQueue(label: SKNetworkMonitor.label, 42 | qos: DispatchQoS.background, 43 | attributes: DispatchQueue.Attributes.concurrent) 44 | 45 | // MARK: - Initalize 46 | public init(pathUpdateHandler: @escaping SKNetworkStatusUpdateHandler) { 47 | self.pathUpdateHandler = pathUpdateHandler 48 | } 49 | } 50 | 51 | // MARK: - Public Extension SKNetworkMonitor 52 | @available(iOS 12.0, macOS 10.14, *) 53 | public extension SKNetworkMonitor { 54 | 55 | final func startMonitor() { 56 | 57 | #if DEBUG 58 | NSLog("[%@][%@] Action, Start NWPathMonitor", SKNetworkMonitor.label, SKNetworkMonitor.identifier) 59 | #endif 60 | 61 | self.monitor.pathUpdateHandler = { newPath in 62 | 63 | #if DEBUG 64 | NSLog("[%@][%@] \(newPath)", SKNetworkMonitor.label, SKNetworkMonitor.identifier) 65 | #endif 66 | 67 | let result: SKNetworkMonitorStatus = SKNetworkMonitorStatus(newPath) 68 | self.pathUpdateHandler(result) 69 | } 70 | 71 | self.monitor.start(queue: self.implementQueue) 72 | } 73 | 74 | final func stopMonitor() { 75 | 76 | #if DEBUG 77 | NSLog("[%@][%@] Action, Cancel NWPathMonitor", SKNetworkMonitor.label, SKNetworkMonitor.identifier) 78 | #endif 79 | 80 | self.monitor.cancel() 81 | } 82 | } 83 | #endif 84 | -------------------------------------------------------------------------------- /Sources/Network/SKNetworkMonitorDefine.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | #if os(iOS) || os(macOS) 24 | import Network 25 | import Foundation 26 | 27 | // MARK: - Enum 28 | @available(iOS 12, macOS 10.14, *) 29 | public enum SKNetworkStatusSymbols: String { 30 | 31 | case satisfied = "wifi" 32 | case unsatisfied = "wifi.slash" 33 | case requiresConnection = "wifi.exclamationmark" 34 | } 35 | 36 | @available(iOS 12, macOS 10.14, *) 37 | public enum SKNetworkConnectionType: String { 38 | 39 | case unknown = "unknown" 40 | 41 | /// [Wi-Fi - Wikipedia](https://en.wikipedia.org/wiki/Wi-Fi) 42 | case wifi = "wifi" 43 | 44 | /// [Ethernet - Wikipedia](https://en.wikipedia.org/wiki/Ethernet) 45 | case ethernet = "ethernet" 46 | 47 | /// [Cellular - Wikipedia](https://en.wikipedia.org/wiki/Cellular_network) 48 | case cellular = "cellular" 49 | 50 | /// [Loopback - Wikipedia](https://en.wikipedia.org/wiki/Loopback) 51 | case loopback = "loopback" 52 | } 53 | 54 | // MARK: - Struct 55 | @available(iOS 12, macOS 10.14, *) 56 | public struct SKNetworkMonitorStatus { 57 | 58 | // MARK: Object Properties 59 | public let newPath: NWPath 60 | 61 | // MARK: - Initalize 62 | public init(_ newPath: NWPath) { 63 | self.newPath = newPath 64 | } 65 | 66 | // MARK: - Computed Properties 67 | 68 | /// - NOTE: [NWPath.Status](https://developer.apple.com/documentation/network/nwpath/status) 69 | public var status: SKNetworkMonitor.SKNetworkStatus { 70 | 71 | // 현재 디바이스에 대한 네트워크 연결 상태를 확인합니다. 72 | switch self.newPath.status { 73 | 74 | // The path is not currently available, but establishing a new connection may activate the path. 75 | case .requiresConnection: 76 | return SKNetworkMonitor.SKNetworkStatus(false, SKNetworkStatusSymbols.requiresConnection) 77 | 78 | // The path is not available for use. 79 | case .unsatisfied: 80 | return SKNetworkMonitor.SKNetworkStatus(false, SKNetworkStatusSymbols.unsatisfied) 81 | 82 | // The path is available to establish connections and send data. 83 | case .satisfied: 84 | return SKNetworkMonitor.SKNetworkStatus(true, SKNetworkStatusSymbols.satisfied) 85 | 86 | @unknown default: 87 | NSLog("[%@][%@] Error, Invaild NWPath.Status", SKNetworkMonitor.label, SKNetworkMonitor.identifier) 88 | return SKNetworkMonitor.SKNetworkStatus(false, SKNetworkStatusSymbols.unsatisfied) 89 | } 90 | } 91 | 92 | /// - NOTE: [NWInterface.InterfaceType](https://developer.apple.com/documentation/network/nwinterface/interfacetype) 93 | public var connectionType: SKNetworkConnectionType { 94 | 95 | // The network interface type used for communication over Wi-Fi networks. 96 | if self.newPath.usesInterfaceType(NWInterface.InterfaceType.wifi) { 97 | return SKNetworkConnectionType.wifi 98 | } 99 | 100 | // The network interface type used for communication over cellular networks. 101 | if self.newPath.usesInterfaceType(NWInterface.InterfaceType.cellular) { 102 | return SKNetworkConnectionType.cellular 103 | } 104 | 105 | // The network interface type used for communication over local loopback networks. 106 | if self.newPath.usesInterfaceType(NWInterface.InterfaceType.loopback) { 107 | return SKNetworkConnectionType.loopback 108 | } 109 | 110 | // The network interface type used for communication over wired Ethernet networks. 111 | if self.newPath.usesInterfaceType(NWInterface.InterfaceType.wiredEthernet) { 112 | return SKNetworkConnectionType.ethernet 113 | } 114 | 115 | // The network interface type used for communication over virtual networks or networks of unknown types. 116 | return SKNetworkConnectionType.unknown 117 | } 118 | } 119 | #endif 120 | -------------------------------------------------------------------------------- /Sources/Permission/SKPermissionDefine.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | #if os(iOS) || os(macOS) 24 | import Foundation 25 | 26 | // MARK: - Enum 27 | public enum SKPermissionServiceName: String, CaseIterable { 28 | 29 | case All = "All" 30 | 31 | case AddressBook = "kTCCServiceAddressBook" 32 | case AppleEvents = "kTCCServiceAppleEvents" 33 | case Bluetooth = "kTCCServiceBluetoothAlways" 34 | case Calendar = "kTCCServiceCalendar" 35 | case Camera = "kTCCServiceCamera" 36 | case ContactsFull = "kTCCServiceContactsFull" 37 | case ContactsLimited = "kTCCServiceContactsLimited" 38 | case FileProviderDomain = "kTCCServiceFileProviderDomain" 39 | case FileProviderPresence = "kTCCServiceFileProviderPresence" 40 | case Location = "kTCCServiceLocation" 41 | case MediaLibrary = "kTCCServiceMediaLibrary" 42 | case Microphone = "kTCCServiceMicrophone" 43 | case Motion = "kTCCServiceMotion" 44 | case Photos = "kTCCServicePhotos" 45 | case PhotosAdd = "kTCCServicePhotosAdd" 46 | case Prototype3Rights = "kTCCServicePrototype3Rights" 47 | case Prototype4Rights = "kTCCServicePrototype4Rights" 48 | case Reminders = "kTCCServiceReminders" 49 | case ScreenCapture = "kTCCServiceScreenCapture" 50 | case Siri = "kTCCServiceSiri" 51 | case SpeechRecognition = "kTCCServiceSpeechRecognition" 52 | case Willow = "kTCCServiceWillow" 53 | case Accessibility = "kTCCServiceAccessibility" 54 | case PostEvent = "kTCCServicePostEvent" 55 | case ListenEvent = "kTCCServiceListenEvent" 56 | case DeveloperTool = "kTCCServiceDeveloperTool" 57 | case HomeKit = "kTCCServiceHomeKit" 58 | case SocialService = "kTCCServiceSocial" 59 | case TVProvider = "kTCCServiceTVProvider" 60 | 61 | /* These seem to be carry-overs from macOS */ 62 | case SystemPolicyFullDiskAccess = "kTCCServiceSystemPolicyAllFiles" 63 | case SystemPolicyDeveloperFiles = "kTCCServiceSystemPolicyDeveloperFiles" 64 | case SystemPolicyRemovableVolumes = "kTCCServiceSystemPolicyRemovableVolumes" 65 | case SystemPolicyNetworkVolumes = "kTCCServiceSystemPolicyNetworkVolumes" 66 | case SystemPolicyDesktopFolder = "kTCCServiceSystemPolicyDesktopFolder" 67 | case SystemPolicyDownloadsFolder = "kTCCServiceSystemPolicyDownloadsFolder" 68 | case SystemPolicyDocumentsFolder = "kTCCServiceSystemPolicyDocumentsFolder" 69 | case SystemPolicySysAdminFiles = "kTCCServiceSystemPolicySysAdminFiles" 70 | 71 | /* These seem to be carry-overs from iOS */ 72 | case LiverPool = "kTCCServiceLiverpool" 73 | case Ubiquity = "kTCCServiceUbiquity" 74 | case ShareKit = "kTCCServiceShareKit" 75 | case LinkedIn = "kTCCServiceLinkedIn" 76 | case Twitter = "kTCCServiceTwitter" 77 | case FaceBook = "kTCCServiceFacebook" 78 | case SinaWeibo = "kTCCServiceSinaWeibo" 79 | case TencentWeibo = "kTCCServiceTencentWeibo" 80 | 81 | // MARK: Enum Computed Properties 82 | public var name: String { self.rawValue } 83 | } 84 | #endif 85 | -------------------------------------------------------------------------------- /Sources/Permission/SKPreferencePaneDefine.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | #if os(macOS) 24 | import Foundation 25 | 26 | public enum SKDefaultPreferencePane: String, CaseIterable { 27 | 28 | case Battery = "x-apple.systempreferences:com.apple.preference.battery" 29 | case Password = "x-apple.systempreferences:com.apple.preferences.password" 30 | case Notifications = "x-apple.systempreferences:com.apple.preference.notifications" 31 | case SoftwareUpdate = "x-apple.systempreferences:com.apple.preferences.softwareupdate?client=softwareupdateapp" 32 | case FamilySharingPrefPane = "x-apple.systempreferences:com.apple.preferences.FamilySharingPrefPane" 33 | case AppleID = "x-apple.systempreferences:com.apple.preferences.AppleIDPrefPane" 34 | case Wallet = "x-apple.systempreferences:com.apple.preferences.wallet" 35 | case Profile = "x-apple.systempreferences:com.apple.preferences.configurationprofiles" 36 | case Screentime = "x-apple.systempreferences:com.apple.preference.screentime" 37 | 38 | // MARK: macOS Ventura (Version 13.*) 39 | case LoginItems = "x-apple.systempreferences:com.apple.LoginItems-Settings.extension" 40 | case DesktopScreenEffect = "x-apple.systempreferences:com.apple.preference.desktopscreeneffect" 41 | } 42 | 43 | public enum SKAccessibilityPreferencePane: String, CaseIterable { 44 | 45 | case Display = "x-apple.systempreferences:com.apple.preference.universalaccess?Seeing_Display" 46 | case Zoom = "x-apple.systempreferences:com.apple.preference.universalaccess?Seeing_Zoom" 47 | case VoiceOver = "x-apple.systempreferences:com.apple.preference.universalaccess?Seeing_VoiceOver" 48 | case Descriptions = "x-apple.systempreferences:com.apple.preference.universalaccess?Media_Descriptions" 49 | case Captions = "x-apple.systempreferences:com.apple.preference.universalaccess?Captioning" 50 | case Audio = "x-apple.systempreferences:com.apple.preference.universalaccess?Hearing" 51 | case Keyboard = "x-apple.systempreferences:com.apple.preference.universalaccess?Keyboard" 52 | case Mouse = "x-apple.systempreferences:com.apple.preference.universalaccess?Mouse" 53 | case Switch = "x-apple.systempreferences:com.apple.preference.universalaccess?Switch" 54 | case Dictation = "x-apple.systempreferences:com.apple.preference.universalaccess?SpeakableItems" 55 | } 56 | 57 | public enum SKSharingPreferencePane: String, CaseIterable { 58 | 59 | case Main = "x-apple.systempreferences:com.apple.preferences.sharing" 60 | 61 | case ShareScreen = "x-apple.systempreferences:com.apple.preferences.sharing?Services_ScreenSharing" 62 | case SharePrint = "x-apple.systempreferences:com.apple.preferences.sharing?Services_PrinterSharing" 63 | case ShareFile = "x-apple.systempreferences:com.apple.preferences.sharing?Services_PersonalFileSharing" 64 | case ShareInternet = "x-apple.systempreferences:com.apple.preferences.sharing?Internet" 65 | case ShareBluetooth = "x-apple.systempreferences:com.apple.preferences.sharing?Services_BluetoothSharing" 66 | 67 | case RemoteLogin = "x-apple.systempreferences:com.apple.preferences.sharing?Services_RemoteLogin" 68 | case RemoteAppleEvents = "x-apple.systempreferences:com.apple.preferences.sharing?Services_RemoteAppleEvent" 69 | case RemoteManagement = "x-apple.systempreferences:com.apple.preferences.sharing?Services_ARDService" 70 | } 71 | 72 | public enum SKDictationSpeechPreferencePane: String, CaseIterable { 73 | 74 | case Dictation = "x-apple.systempreferences:com.apple.preference.speech?Dictation" 75 | case TextToSpeech = "x-apple.systempreferences:com.apple.preference.speech?TTS" 76 | } 77 | 78 | public enum SKSecurityPrivacyPreferencePane: String, CaseIterable { 79 | 80 | case Main = "x-apple.systempreferences:com.apple.preference.security" 81 | 82 | case General = "x-apple.systempreferences:com.apple.preference.security?General" 83 | case FileVault = "x-apple.systempreferences:com.apple.preference.security?FDE" 84 | case Firewall = "x-apple.systempreferences:com.apple.preference.security?Firewall" 85 | case Advanced = "x-apple.systempreferences:com.apple.preference.security?Advanced" 86 | case Privacy = "x-apple.systempreferences:com.apple.preference.security?Privacy" 87 | 88 | case PrivacyAccessibility = "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility" 89 | case PrivacyAssistive = "x-apple.systempreferences:com.apple.preference.security?Privacy_Assistive" 90 | case PrivacyLocationServices = "x-apple.systempreferences:com.apple.preference.security?Privacy_LocationServices" 91 | case PrivacyContacts = "x-apple.systempreferences:com.apple.preference.security?Privacy_Contacts" 92 | case PrivacyDiagnosticsUsage = "x-apple.systempreferences:com.apple.preference.security?Privacy_Diagnostics" 93 | case PrivacyCalendars = "x-apple.systempreferences:com.apple.preference.security?Privacy_Calendars" 94 | case PrivacyReminders = "x-apple.systempreferences:com.apple.preference.security?Privacy_Reminders" 95 | case PrivacyTencentWeibo = "x-apple.systempreferences:com.apple.preference.security?Privacy_TencentWeibo" 96 | case PrivacyAutomation = "x-apple.systempreferences:com.apple.preference.security?Privacy_Automation" 97 | case PrivacyAdvertising = "x-apple.systempreferences:com.apple.preference.security?Privacy_Advertising" 98 | 99 | case PrivacyFacebook = "x-apple.systempreferences:com.apple.preference.security?Privacy_Facebook" 100 | case PrivacyLinkedIn = "x-apple.systempreferences:com.apple.preference.security?Privacy_LinkedIn" 101 | case PrivacyTwitter = "x-apple.systempreferences:com.apple.preference.security?Privacy_Twitter" 102 | case PrivacyWeibo = "x-apple.systempreferences:com.apple.preference.security?Privacy_Weibo" 103 | 104 | case PrivacyFullDiskAccess = "x-apple.systempreferences:com.apple.preference.security?Privacy_AllFiles" 105 | 106 | // MARK: macOS Catalina (Version: 10.15) 107 | case PrivacyDevTools = "x-apple.systempreferences:com.apple.preference.security?Privacy_DevTools" 108 | case PrivacyDesktopFolder = "x-apple.systempreferences:com.apple.preference.security?Privacy_DesktopFolder" 109 | case PrivacyDocumentsFolder = "x-apple.systempreferences:com.apple.preference.security?Privacy_DocumentsFolder" 110 | case PrivacyDownloadsFolder = "x-apple.systempreferences:com.apple.preference.security?Privacy_DownloadsFolder" 111 | case PrivacyNetworkVolume = "x-apple.systempreferences:com.apple.preference.security?Privacy_NetworkVolume" 112 | case PrivacyRemovableVolume = "x-apple.systempreferences:com.apple.preference.security?Privacy_RemovableVolume" 113 | case PrivacyInputMonitoring = "x-apple.systempreferences:com.apple.preference.security?Privacy_ListenEvent" 114 | case PrivacyScreenCapture = "x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture" 115 | } 116 | #endif 117 | -------------------------------------------------------------------------------- /Sources/PrivacyInfo.xcprivacy: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrivacyTracking 6 | 7 | NSPrivacyAccessedAPITypes 8 | 9 | 10 | NSPrivacyAccessedAPIType 11 | NSPrivacyAccessedAPICategoryFileTimestamp 12 | NSPrivacyAccessedAPITypeReasons 13 | 14 | 0A2A.1 15 | 16 | 17 | 18 | NSPrivacyAccessedAPIType 19 | NSPrivacyAccessedAPICategoryUserDefaults 20 | NSPrivacyAccessedAPITypeReasons 21 | 22 | C56D.1 23 | 24 | 25 | 26 | NSPrivacyAccessedAPIType 27 | NSPrivacyAccessedAPICategoryDiskSpace 28 | NSPrivacyAccessedAPITypeReasons 29 | 30 | 85F4.1 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Sources/Process/SKProcess.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | #if os(macOS) 24 | import Foundation 25 | 26 | @available(macOS 10.12, *) 27 | public class SKProcess: NSObject, SKClass { 28 | 29 | // MARK: - Typealias 30 | public typealias SKProcessErrorResult = (NSError, Process) -> Swift.Void 31 | public typealias SKProcessTerminationHandler = (Process) -> Swift.Void 32 | 33 | // MARK: - Object Properties 34 | public static let shared: SKProcess = SKProcess() 35 | public static let label: String = "com.SystemKit.SKProcess" 36 | public static let identifier: String = "B275BF0C-3E1B-4897-B6CB-CA3DC7FFD3EB" 37 | 38 | // MARK: - Initalize 39 | private override init() { super.init() } 40 | } 41 | 42 | // MARK: - Private Extension SKProcess 43 | @available(macOS 10.12, *) 44 | private extension SKProcess { 45 | 46 | final func launch(process: Process) throws { 47 | 48 | // macOS 10.13 미만의 운영체제에서는 launch() 함수를 통하여 실행합니다. 49 | guard #available(macOS 10.13, *) else { 50 | process.launch() 51 | return 52 | } 53 | 54 | // macOS 10.13 이상의 운영체제에서는 run() 함수를 통하여 실행합니다. 55 | try process.run() 56 | } 57 | 58 | final func closePipe(_ pipe: Optional) { 59 | 60 | // If the PIPE is not used, the close operation is not performed 61 | guard let target = pipe else { return } 62 | 63 | // The writing file handle close 64 | try? target.fileHandleForWriting.close() 65 | 66 | // The reading file handle close 67 | try? target.fileHandleForReading.close() 68 | } 69 | } 70 | 71 | // MARK: - Public Extension SKProcess 72 | @available(macOS 10.12, *) 73 | public extension SKProcess { 74 | 75 | @discardableResult 76 | final func run(launchPath: String, 77 | arguments: Array, 78 | standardInput: Optional = nil, 79 | standardOutput: Optional = nil, 80 | standardError: Optional = nil, 81 | waitUntilExit: Bool = false, 82 | qualityOfService: QualityOfService = .default, 83 | terminationHandler: Optional = nil, 84 | errorCompletionHandler: Optional = nil) -> Int32 { 85 | 86 | let process = Process() 87 | process.launchPath = launchPath 88 | process.arguments = arguments 89 | process.terminationHandler = terminationHandler 90 | process.standardInput = standardInput 91 | process.standardOutput = standardOutput 92 | process.standardError = standardError 93 | process.qualityOfService = qualityOfService 94 | 95 | do { 96 | try launch(process: process) 97 | 98 | if waitUntilExit { process.waitUntilExit() } 99 | 100 | // Closing the PIPE used in the operation 101 | [standardInput, standardOutput, standardError].forEach(closePipe) 102 | 103 | } catch let error as NSError { 104 | errorCompletionHandler?(error, process) 105 | return EOF 106 | } 107 | 108 | return process.processIdentifier 109 | } 110 | } 111 | #endif 112 | -------------------------------------------------------------------------------- /Sources/Process/SKProcessMonitor.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | #if os(macOS) 24 | import Darwin 25 | import Foundation 26 | import CoreFoundation 27 | 28 | public class SKProcessMonitor: SKAsyncOperation { 29 | 30 | // MARK: - Object Properties 31 | public static var label: String = "com.SystemKit.SKProcessMonitor" 32 | public static var identifier: String = "A4031B25-241F-4457-9DF4-B711D022C4EA" 33 | 34 | private var info: ProcessMonitorInfo 35 | 36 | // MARK: - Initalize 37 | public init(name: Optional = SKProcessMonitor.label, 38 | qualityOfService: QualityOfService = .default, 39 | queuePriority: Operation.QueuePriority = .normal, 40 | pid ident: pid_t, 41 | runLoop: CFRunLoop = CFRunLoopGetCurrent(), 42 | fflag: SKProcessMonitorFilterFlag, 43 | handler callback: @escaping CFFileDescriptorCallBack) { 44 | 45 | self.info = ProcessMonitorInfo(pid: ident, runLoop: runLoop, fflag: fflag, handler: callback) 46 | 47 | super.init() 48 | 49 | self.name = name 50 | self.queuePriority = queuePriority 51 | self.qualityOfService = qualityOfService 52 | } 53 | } 54 | 55 | // MARK: - Private Extension SKProcessMonitor 56 | public extension SKProcessMonitor { 57 | 58 | final func enableMonitorProcess() { 59 | 60 | // 현재 작업이 취소가 된 상태인 경우에는 아래의 작업을 수행하지 않습니다. 61 | if self.isCancelled { return } 62 | 63 | let kqueue: Int32 = kqueue() 64 | var processEvent = kevent(ident: UInt(self.info.pid), filter: Int16(EVFILT_PROC), 65 | flags: UInt16(EV_ADD | EV_RECEIPT), fflags: self.info.fflag.define, 66 | data: Int.zero, udata: nil) 67 | kevent(kqueue, &processEvent, 1, nil, 1, nil) 68 | 69 | var context: CFFileDescriptorContext = CFFileDescriptorContext() 70 | self.info.descriptor = CFFileDescriptorCreate(nil, kqueue, true, self.info.handler, &context) 71 | 72 | let source: CFRunLoopSource = CFFileDescriptorCreateRunLoopSource(nil, self.info.descriptor, CFIndex.zero) 73 | CFRunLoopAddSource(self.info.runLoop, source, CFRunLoopMode.defaultMode) 74 | 75 | CFFileDescriptorEnableCallBacks(self.info.descriptor, kCFFileDescriptorReadCallBack) 76 | } 77 | 78 | final func disableMonitorProcess() { 79 | 80 | // 현재 작업이 활성화 상태인 경우에는 아래의 작업을 수행하지 않습니다. 81 | guard self.isCancelled else { return } 82 | 83 | CFRunLoopStop(self.info.runLoop) 84 | CFFileDescriptorDisableCallBacks(self.info.descriptor, kCFFileDescriptorReadCallBack) 85 | } 86 | } 87 | 88 | // MARK: - Public Extension SKProcessMonitor 89 | public extension SKProcessMonitor { 90 | 91 | override func start() { 92 | super.start() 93 | 94 | enableMonitorProcess() 95 | } 96 | 97 | override func cancel() { 98 | super.cancel() 99 | 100 | disableMonitorProcess() 101 | } 102 | } 103 | #endif 104 | -------------------------------------------------------------------------------- /Sources/Process/SKProcessMonitorDefine.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | #if os(macOS) 24 | import Darwin 25 | import Foundation 26 | 27 | // MARK: - Struct 28 | internal struct ProcessMonitorInfo { 29 | 30 | internal let pid: pid_t 31 | internal let runLoop: CFRunLoop 32 | internal let fflag: SKProcessMonitorFilterFlag 33 | internal let handler: CFFileDescriptorCallBack 34 | 35 | internal var descriptor: Optional = nil 36 | } 37 | 38 | // MARK: - Enum 39 | public enum SKProcessMonitorFilterFlag { 40 | 41 | /// - NOTE: [exit - System Call](https://en.wikipedia.org/wiki/Exit_(system_call)) 42 | case exit 43 | 44 | /// - NOTE: [fork - System Call](https://en.wikipedia.org/wiki/Fork_(system_call)) 45 | case fork 46 | 47 | /// - NOTE: [exec - System Call](https://en.wikipedia.org/wiki/Exec_(system_call)) 48 | case exec 49 | 50 | // MARK: Enum Properties 51 | public var define: UInt32 { 52 | 53 | switch self { 54 | /// process exec'd: `0x20000000` 55 | case .exec: 56 | return UInt32(NOTE_EXEC) 57 | 58 | /// Process Exited: `0x80000000` 59 | case .exit: 60 | return NOTE_EXIT 61 | 62 | /// process forked: `0x40000000` 63 | case .fork: 64 | return UInt32(NOTE_FORK) 65 | } 66 | } 67 | } 68 | #endif 69 | -------------------------------------------------------------------------------- /Sources/Protocol/SKClass+Protocol.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | // swiftlint:disable all 24 | #if os(iOS) || os(macOS) || os(Linux) 25 | import Foundation 26 | 27 | @objc public protocol SKClass: AnyObject { 28 | 29 | // MARK: Required Protocol Properties 30 | static var label: String { get } 31 | static var identifier: String { get } 32 | 33 | // MARK: Optaionl Protocol Method 34 | @objc optional var implementQueue: DispatchQueue { get set } 35 | @objc optional var operationQueue: OperationQueue { get set } 36 | } 37 | #endif 38 | -------------------------------------------------------------------------------- /Sources/Protocol/SKOperation+Protocol.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | // swiftlint:disable all 24 | #if os(iOS) || os(macOS) || os(Linux) 25 | import Dispatch 26 | import Foundation 27 | 28 | @objc public protocol SKOperation: SKClass { 29 | 30 | // MARK: Optional Protocol Properties 31 | @objc optional var payload: Optional { get set } 32 | @objc optional var timer: Optional { get set } 33 | 34 | // MARK: Required Initalize 35 | init(name: Optional, qualityOfService: QualityOfService) 36 | } 37 | #endif 38 | -------------------------------------------------------------------------------- /Sources/SKAsyncOperation.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | #if os(iOS) || os(macOS) || os(Linux) 24 | import Foundation 25 | 26 | open class SKAsyncOperation: Operation { 27 | 28 | // MARK: - Enum 29 | public enum State: String { 30 | 31 | case ready = "Ready" 32 | case executing = "Executing" 33 | case finished = "Finished" 34 | 35 | // KVO notifications을 위한 keyPath설정 36 | fileprivate var keyPath: String { 37 | return String(format: "is%@", rawValue.capitalized) 38 | } 39 | } 40 | 41 | // MARK: - Object Properties 42 | public var state = State.ready { 43 | 44 | // 직접적으로 Operation 작업 상태를 관리하기 위한 Status Variable 생성 45 | willSet { 46 | willChangeValue(forKey: newValue.keyPath) 47 | willChangeValue(forKey: state.keyPath) 48 | } 49 | 50 | didSet { 51 | didChangeValue(forKey: oldValue.keyPath) 52 | didChangeValue(forKey: state.keyPath) 53 | } 54 | } 55 | } 56 | 57 | // MARK: - Open Extension AsyncOperation With Properties 58 | extension SKAsyncOperation { 59 | 60 | open override var isReady: Bool { return super.isReady && self.state == State.ready } 61 | 62 | open override var isExecuting: Bool { return self.state == State.executing } 63 | 64 | open override var isFinished: Bool { return self.state == State.finished } 65 | 66 | open override var isAsynchronous: Bool { return true } 67 | } 68 | 69 | // MARK: - Open Extension AsyncOperation With Method 70 | extension SKAsyncOperation { 71 | 72 | open override func start() { 73 | 74 | if self.isCancelled { 75 | self.state = State.finished 76 | return 77 | } 78 | 79 | self.main() 80 | 81 | #if DEBUG 82 | NSLog("[SKAsyncOperation] Action, Operation Start: %@", self.state.keyPath) 83 | #endif 84 | 85 | self.state = State.executing 86 | } 87 | 88 | open override func cancel() { 89 | super.cancel() 90 | 91 | #if DEBUG 92 | NSLog("[SKAsyncOperation] Action, Operation Cancel: %@", self.state.keyPath) 93 | #endif 94 | 95 | self.state = State.finished 96 | } 97 | } 98 | #endif 99 | -------------------------------------------------------------------------------- /Sources/SKAtomicValue.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | #if os(iOS) || os(macOS) || os(Linux) 24 | import Foundation 25 | 26 | @propertyWrapper 27 | public class SKAtomicValue { 28 | 29 | // MARK: - Object Properties 30 | private let dispatch = DispatchQueue(label: "com.SystemKit.SKAtomicValue") 31 | private var value: Value 32 | 33 | // MARK: - Computed Properties 34 | public var wrappedValue: Value { 35 | 36 | get { 37 | return self.dispatch.sync { return self.value } 38 | } 39 | 40 | set { 41 | self.dispatch.sync { self.value = newValue } 42 | } 43 | } 44 | 45 | // MARK: - Initalize 46 | public init(wrappedValue: Value) { self.value = wrappedValue } 47 | } 48 | 49 | // MARK: - Public Extension SKAtomicValue 50 | public extension SKAtomicValue { 51 | 52 | typealias SKMutateHandler = (inout Value) -> Swift.Void 53 | final func mutate(_ mutating: SKMutateHandler) { 54 | 55 | return self.dispatch.sync { mutating(&self.value) } 56 | } 57 | } 58 | #endif 59 | -------------------------------------------------------------------------------- /Sources/SKFileLock.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | // swiftlint:disable all 24 | #if os(iOS) || os(macOS) || os(Linux) 25 | import Darwin 26 | import Foundation 27 | 28 | /** 29 | - Date: `2023.05.01.` 30 | - Version: `1.0.0` 31 | - Authors: `ChangYeop-Yang` 32 | */ 33 | public class SKFileLock: SKClass { 34 | 35 | // MARK: - Enum 36 | public enum FileLockMode: Int { 37 | case read 38 | case write 39 | case update 40 | } 41 | 42 | // MARK: - Object Properties 43 | public static var label = "com.SystemKit.SKFileLock" 44 | public static var identifier = "7777529A-98A3-4E43-A3AA-AAFBE437BC3F" 45 | 46 | private let filePath: String 47 | private let fileHandle: Optional 48 | 49 | // MARK: - Initalize 50 | public init(filePath: String, _ mode: FileLockMode) { 51 | logger.info("[SKFileLock] init(filePath: String, mode: FileLockMode)") 52 | 53 | self.filePath = filePath 54 | self.fileHandle = SKFileLock.createFileHandle(filePath: filePath, mode) 55 | } 56 | 57 | public init(fileDescriptor: Int32) { 58 | logger.info("[SKFileLock] init(fileDescriptor: Int32)") 59 | 60 | self.filePath = SKFileLock.getFilePath(fileDescriptor: fileDescriptor) ?? String.init() 61 | self.fileHandle = FileHandle(fileDescriptor: fileDescriptor) 62 | } 63 | } 64 | 65 | // MARK: - Private Extension SKFileLock 66 | private extension SKFileLock { 67 | 68 | static func createFileHandle(filePath: String, _ mode: FileLockMode) -> Optional { 69 | 70 | switch mode { 71 | case .read: 72 | return FileHandle(forReadingAtPath: filePath) 73 | case .write: 74 | return FileHandle(forWritingAtPath: filePath) 75 | case .update: 76 | return FileHandle(forUpdatingAtPath: filePath) 77 | } 78 | } 79 | 80 | static func getFilePath(fileDescriptor: Int32) -> Optional { 81 | 82 | let maxPathSize = Int(PATH_MAX) 83 | var filePath = [CChar](repeating: CChar.zero, count: maxPathSize) 84 | 85 | guard fcntl(fileDescriptor, F_GETPATH, &filePath) == Int32.zero else { return nil } 86 | 87 | return String(cString: filePath) 88 | } 89 | } 90 | 91 | // MARK: - Public Extension SKFileLock 92 | public extension SKFileLock { 93 | 94 | /** 95 | 파일에 대하여 `파일 잠금 (File Locking)`을(를) 수행합니다. 96 | 97 | - Version: `1.0.0` 98 | - Returns: `Bool` 99 | */ 100 | @discardableResult 101 | final func lock() -> Bool { 102 | 103 | logger.info("[SKFileLock] Perform a file lock on the file located at the \(self.filePath) path.") 104 | 105 | guard let fileDescriptor = self.fileHandle?.fileDescriptor else { return false } 106 | 107 | // 파일 잠금 (File Locking) 작업 수행 여부를 확인합니다. 108 | guard flock(fileDescriptor, LOCK_EX | LOCK_NB) == Int32.zero else { return false } 109 | 110 | return true 111 | } 112 | 113 | /** 114 | 파일에 대하여 `파일 잠금 해제 (File UnLocking)`을(를) 수행합니다. 115 | 116 | - Version: `1.0.0` 117 | - Returns: `Bool` 118 | */ 119 | @discardableResult 120 | final func unlock() -> Bool { 121 | 122 | logger.info("[SKFileLock] Perform a file unlock on the file located at the \(self.filePath) path.") 123 | 124 | guard let fileDescriptor = self.fileHandle?.fileDescriptor else { return false } 125 | 126 | // 파일 잠금 해제 (File UnLocking) 작업 수행 여부를 확인합니다. 127 | guard flock(fileDescriptor, LOCK_UN) == Int32.zero else { return false } 128 | 129 | return true 130 | } 131 | } 132 | #endif 133 | -------------------------------------------------------------------------------- /Sources/SKFinderExtension.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | #if os(macOS) 24 | import Foundation 25 | import FinderSync 26 | 27 | /** 28 | - Version: `1.0.0` 29 | - Authors: `ChangYeop-Yang` 30 | */ 31 | public class SKFinderExtension: NSObject, SKClass { 32 | 33 | // MARK: - Object Properties 34 | public static let shared: SKFinderExtension = SKFinderExtension() 35 | public static let label: String = "com.SystemKit.SKFinderExtension" 36 | public static let identifier: String = "18EF2C59-D9A8-4908-8898-1E64C6E116BF" 37 | 38 | private let launchPath: String = "/usr/bin/pluginkit" 39 | 40 | // MARK: - Initalize 41 | private override init() { super.init() } 42 | } 43 | 44 | // MARK: - Public Extension SKFinderExtension With Properties 45 | public extension SKFinderExtension { 46 | 47 | @available(macOS 10.14, *) 48 | var isExtensionEnabled: Bool { FIFinderSyncController.isExtensionEnabled } 49 | } 50 | 51 | // MARK: - Public Extension SKFinderExtension With Method 52 | public extension SKFinderExtension { 53 | 54 | @available(macOS 10.12, *) 55 | final func append(extensionPath: String, waitUntilExit: Bool) { 56 | 57 | #if DEBUG 58 | NSLog("[%@][%@] Action, Append Application Finder Extension", SKFinderExtension.label, SKFinderExtension.identifier) 59 | #endif 60 | 61 | let arguments: Array = ["-a", extensionPath] 62 | SKProcess.shared.run(launchPath: self.launchPath, arguments: arguments, waitUntilExit: waitUntilExit) 63 | } 64 | 65 | @available(macOS 10.12, *) 66 | final func enable(extensionPath: String, waitUntilExit: Bool) { 67 | 68 | #if DEBUG 69 | NSLog("[%@][%@] Action, Enable Application Finder Extension", SKFinderExtension.label, SKFinderExtension.identifier) 70 | #endif 71 | 72 | let arguments: Array = ["-e", "use", "-i", extensionPath] 73 | SKProcess.shared.run(launchPath: self.launchPath, arguments: arguments, waitUntilExit: waitUntilExit) 74 | } 75 | 76 | @available(macOS 10.12, *) 77 | final func disable(extensionPath: String, waitUntilExit: Bool) { 78 | 79 | #if DEBUG 80 | NSLog("[%@][%@] Action, Disable Application Finder Extension", SKFinderExtension.label, SKFinderExtension.identifier) 81 | #endif 82 | 83 | let arguments: Array = ["-e", "ignore", "-i", extensionPath] 84 | SKProcess.shared.run(launchPath: self.launchPath, arguments: arguments, waitUntilExit: waitUntilExit) 85 | } 86 | } 87 | #endif 88 | -------------------------------------------------------------------------------- /Sources/SKSignal.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | #if os(macOS) 24 | import Darwin 25 | import Dispatch 26 | import Foundation 27 | 28 | /** 29 | - Date: `2022.11.10.` 30 | - Version: `1.0.0` 31 | - Authors: `ChangYeop-Yang` 32 | */ 33 | public class SKSignal: SKAsyncOperation { 34 | 35 | // MARK: - Typealias 36 | public typealias SKSignalHandler = @convention(c) (Int32) -> Swift.Void 37 | private typealias SKSignalResult = (signal: Int32, handler: SKSignalHandler) 38 | 39 | // MARK: - Object Properties 40 | public static var label: String = "com.SystemKit.SKSignal" 41 | public static var identifier: String = "45F971FC-B05F-4CF5-9927-AD793F461718" 42 | 43 | private let result: SKSignalResult 44 | private var source: Optional = nil 45 | 46 | // MARK: - Initalize 47 | public init(signal number: Int32, handler: @escaping SKSignalHandler) { 48 | self.result = SKSignalResult(number, handler) 49 | } 50 | } 51 | 52 | // MARK: - Private Extension SKSignal 53 | private extension SKSignal { 54 | 55 | final func observeSignal(signal number: Int32, handler: @escaping SKSignalHandler) { 56 | 57 | // 현재 작업이 취소 상태인 경우에는 아래의 등록 작업을 하지 않습니다. 58 | if self.isCancelled { return } 59 | 60 | // SIGNAL 등록 작업을 수행하기 전에 기존의 SIGNAL 이벤트를 거부 작업을 수행합니다. 61 | signal(number, SIG_IGN) 62 | 63 | self.source = DispatchSource.makeSignalSource(signal: number) 64 | self.source?.setEventHandler { handler(number) } 65 | self.source?.resume() 66 | } 67 | 68 | final func removeObserveSignal() { 69 | 70 | // 현재 작업이 취소 상태가 아닌 경우에는 아래의 취소작업을 하지 않습니다. 71 | guard self.isCancelled else { return } 72 | 73 | #if DEBUG 74 | NSLog("[%@][%@] Action, Remove Signal Observe: %@", SKSignal.label, SKSignal.identifier, self.result.signal) 75 | #endif 76 | 77 | self.source?.cancel() 78 | self.source = nil 79 | } 80 | } 81 | 82 | // MARK: - Public Extension SKSignal 83 | public extension SKSignal { 84 | 85 | override func start() { 86 | super.start() 87 | 88 | // Signal Handler 등록 작업을 수행합니다. 89 | observeSignal(signal: self.result.signal, handler: self.result.handler) 90 | } 91 | 92 | override func cancel() { 93 | super.cancel() 94 | 95 | // Signal handler 등록 해제 작업을 수행합니다. 96 | removeObserveSignal() 97 | } 98 | } 99 | #endif 100 | -------------------------------------------------------------------------------- /Sources/SKUserDefault.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | // swiftlint:disable all 24 | #if os(iOS) || os(macOS) || os(Linux) 25 | import Foundation 26 | 27 | @propertyWrapper 28 | public struct SKUserDefaults { 29 | 30 | // MARK: - Struct Properties 31 | private let forKey: String 32 | private let defaultValue: Optional 33 | 34 | // Property Wrapper 필수 구현 Property 35 | public var wrappedValue: Optional { 36 | get { UserDefaults.standard.object(forKey: self.forKey) as? Value ?? self.defaultValue } 37 | set { UserDefaults.standard.setValue(newValue, forKey: self.forKey) } 38 | } 39 | 40 | // MARK: - Initalize 41 | public init(forKey: String, defaultValue: Optional = nil) { 42 | self.forKey = forKey 43 | self.defaultValue = defaultValue 44 | } 45 | } 46 | #endif 47 | -------------------------------------------------------------------------------- /Sources/System/SKSystem.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | #if os(macOS) || os(iOS) 24 | import Darwin 25 | import Foundation 26 | import SystemConfiguration 27 | 28 | public class SKSystem: NSObject, SKClass { 29 | 30 | // MARK: - Object Properties 31 | public static let shared: SKSystem = SKSystem() 32 | public static let label: String = "com.SystemKit.SKSystem" 33 | public static let identifier: String = "1735CFB1-19CC-4581-8CB7-F2DC3E16C678" 34 | } 35 | 36 | // MARK: - Public Extension SKSystem With Universal Platform 37 | public extension SKSystem { 38 | 39 | /** 40 | 현재 구동중인 애플리케이션에 대한 `릴리즈 버전 (Release Version` 그리고 `번들 버전 (Bundle Version)` 정보를 가져오는 함수입니다. 41 | 42 | - Version: `1.0.0` 43 | - Authors: `ChangYeop-Yang` 44 | - Returns: `Optional` 45 | */ 46 | final func getApplicationVersion() -> Optional { 47 | 48 | guard let infoDictionary = Bundle.main.infoDictionary else { return nil } 49 | 50 | guard let releaseVersion = infoDictionary["CFBundleShortVersionString"] as? String, 51 | let bundleVersion = infoDictionary["CFBundleVersion"] as? String else { return nil } 52 | 53 | return SKSystemApplicationVersionResult(release: releaseVersion, bundle: bundleVersion) 54 | } 55 | 56 | /** 57 | 현재 장비에서 사용중인 메모리 사용률 그리고 전체 메모리 값을 가져오는 함수입니다. 58 | 59 | - Version: `1.0.0` 60 | - Authors: `ChangYeop-Yang` 61 | - NOTE: Units of measurement `Megabyte (MB)` 62 | - Returns: `SKSystemMachineUsageMemeoryResult` 63 | */ 64 | final func getMachineUsageMemory() -> SKSystemMachineUsageMemeoryResult { 65 | 66 | var usageMegaBytes: Float = Float.zero 67 | let totalMegaBytes: Float = Float(ProcessInfo.processInfo.physicalMemory) / 1024.0 / 1024.0 68 | 69 | var info: mach_task_basic_info = mach_task_basic_info() 70 | var count: UInt32 = mach_msg_type_number_t(MemoryLayout.size) / 4 71 | 72 | let result: kern_return_t = withUnsafeMutablePointer(to: &info) { 73 | $0.withMemoryRebound(to: integer_t.self, capacity: 1) { 74 | task_info( mach_task_self_, task_flavor_t(MACH_TASK_BASIC_INFO), $0, &count) 75 | } 76 | } 77 | 78 | if result == KERN_SUCCESS { 79 | usageMegaBytes = Float(info.resident_size) / 1024.0 / 1024.0 80 | } 81 | 82 | return SKSystemMachineUsageMemeoryResult(usage: usageMegaBytes, total: totalMegaBytes) 83 | } 84 | 85 | /** 86 | 현재 사용중인 장비 모델 명칭을 가져오는 함수입니다. 87 | 88 | - SeeAlso: [Apple Device Database](https://appledb.dev) 89 | - Version: `1.0.0` 90 | - Authors: `ChangYeop-Yang` 91 | - NOTE: 장비 모델 명칭을 가져오고 실제 제품을 판매하기 위한 제품명을 가져오기 위해서는 `getMachineSystemInfo` 함수를 사용하여야합니다. 92 | - Returns: `String` 93 | */ 94 | final func getDeviceModelName() -> String { 95 | 96 | var mib: Array = [CTL_HW, HW_MODEL] 97 | var size: Int = MemoryLayout.size 98 | let pointee = UnsafeMutablePointer.allocate(capacity: 1) 99 | 100 | let result = sysctl(&mib, u_int(mib.count), pointee, &size, nil, Int.zero) 101 | 102 | #if DEBUG 103 | NSLog("[%@][%@] Action, Get Device Model: %d", SystemKit.label, SKSystem.identifier, result) 104 | #endif 105 | 106 | let cString: UnsafePointer = UnsafeRawPointer(pointee).assumingMemoryBound(to: CChar.self) 107 | 108 | return String(cString: cString, encoding: String.Encoding.utf8) ?? String.init() 109 | } 110 | 111 | /** 112 | 현재 사용중인 제품에 대한 제품 정보를 가져오는 함수입니다. 113 | 114 | - SeeAlso: [Apple Device Database](https://appledb.dev) 115 | - Version: `1.0.0` 116 | - Authors: `ChangYeop-Yang` 117 | - Returns: `Optional` 118 | */ 119 | final func getMachineSystemInfo() -> Optional { 120 | 121 | let toString: (UnsafeRawBufferPointer) -> Optional = { raw in 122 | 123 | guard let cString = raw.baseAddress?.assumingMemoryBound(to: CChar.self) else { return nil } 124 | 125 | return String(cString: cString, encoding: String.Encoding.utf8) 126 | } 127 | 128 | var names: utsname = utsname() 129 | guard Foundation.uname(&names) == Int32.zero else { return nil } 130 | 131 | let sysname = withUnsafeBytes(of: &names.sysname, toString) ?? String.init() 132 | let nodename = withUnsafeBytes(of: &names.nodename, toString) ?? String.init() 133 | let release = withUnsafeBytes(of: &names.release, toString) ?? String.init() 134 | let version = withUnsafeBytes(of: &names.version, toString) ?? String.init() 135 | let machine = withUnsafeBytes(of: &names.machine, toString) ?? String.init() 136 | 137 | return SKSystemMachineSystemResult(operatingSystemName: sysname, 138 | operatingSystemRelease: release, operatingSystemVersion: version, 139 | machineNetworkNodeName: nodename, machineHardwarePlatform: machine) 140 | } 141 | } 142 | #endif 143 | -------------------------------------------------------------------------------- /Sources/System/SKSystemDefine.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | import Foundation 24 | 25 | #if os(macOS) || os(iOS) 26 | 27 | // MARK: Enum With Universal Platform 28 | public enum SKResourceDataUnit: Double { 29 | 30 | case byte = 1 // 1 Byte 31 | case kiloByte = 1024 // 1024 Byte 32 | case megaByte = 1_048_576 // 1024 * 1024 Byte 33 | case gigaByte = 1_073_741_824 // 1024 * 1024 * 1024 Byte 34 | case teraBtye = 1_099_511_627_776 // 1024 * 1024 * 1024 * 1024 Byte 35 | } 36 | 37 | // MARK: - Struct With Universal Platform 38 | public struct SKSystemMachineUsageMemeoryResult: Codable { 39 | 40 | // MARK: Float Proeprties 41 | 42 | public let usage: Float 43 | 44 | public let total: Float 45 | } 46 | 47 | public struct SKSystemApplicationVersionResult: Codable { 48 | 49 | // MARK: String Properties 50 | 51 | public let release: String 52 | 53 | public let bundle: String 54 | } 55 | 56 | public struct SKSystemMachineSystemResult: Codable { 57 | 58 | // MARK: String Proeprties 59 | 60 | /// Name of the operating system implementation 61 | public let operatingSystemName: String 62 | 63 | /// Release level of the operating system 64 | public let operatingSystemRelease: String 65 | 66 | /// Version level of the operating system. 67 | public let operatingSystemVersion: String 68 | 69 | /// Network name of this machine 70 | public let machineNetworkNodeName: String 71 | 72 | /// Machine hardware platform 73 | public let machineHardwarePlatform: String 74 | } 75 | #endif 76 | 77 | #if os(macOS) 78 | // MARK: - Enum With macOS Platform 79 | public enum SKTranslatedRosettaResult: Int32 { 80 | 81 | /// Error Occurs 82 | case error = -1 83 | 84 | /// Native Process 85 | case native = 0 86 | 87 | /// Translated Process 88 | case translated = 1 89 | } 90 | 91 | @available(macOS 10.12, *) 92 | public enum macOSSystemVersion: String { 93 | 94 | /// macOS 10.12 (Sierra) 95 | case Sierra = "Sierra" 96 | 97 | /// macOS 10.13 (High Sierra) 98 | case HighSierra = "High Sierra" 99 | 100 | /// macOS 10.14 (Mojave) 101 | case Mojave = "Mojave" 102 | 103 | /// macOS 10.15 (Catalina) 104 | case Catalina = "Catalina" 105 | 106 | /// macOS 11 (BigSur) 107 | case BigSur = "BigSur" 108 | 109 | /// macOS 12 (Monterey) 110 | case Monterey = "Monterey" 111 | 112 | /// macOS 13 (Ventura) 113 | case Ventura = "Ventura" 114 | 115 | /// macOS 14 (Sonoma) 116 | case Sonoma = "Sonoma" 117 | 118 | /// macOS 15 (Sequoia) 119 | case Sequoia = "Sequoia" 120 | 121 | // MARK: Enum Computed Properties 122 | public var name: String { return String(format: "macOS %@", self.rawValue) } 123 | } 124 | 125 | // MARK: - Struct With macOS Platform 126 | public struct SKDisplayOutputUnitResult: Codable { 127 | 128 | // MARK: Integer Properties 129 | 130 | /// The window number of the window’s window device. 131 | public let windowNumber: Int 132 | 133 | /// the bit depth of the window’s raster image (2-bit, 8-bit, and so forth) 134 | public var bitsPerSample: Optional = nil 135 | 136 | // MARK: Double Properties 137 | 138 | /// A screen resolution width value. 139 | public var frameWidth: Optional = nil 140 | 141 | /// A screen resolution height value. 142 | public var frameHeight: Optional = nil 143 | 144 | /// A raster screen resolution width value. 145 | public var rasterWidth: Optional = nil 146 | 147 | /// A raster screen resolution height value. 148 | public var rasterHeight: Optional = nil 149 | 150 | // MARK: String Properties 151 | 152 | /// The name of the window’s color space. 153 | public var colorSpaceName: Optional = nil 154 | 155 | // MARK: Bool Properties 156 | 157 | /// The display device is a screen. 158 | public var isScreen: Optional = nil 159 | 160 | /// The display device is a printer. 161 | public var isPrinter: Optional = nil 162 | } 163 | #endif 164 | -------------------------------------------------------------------------------- /Sources/System/SKSystemProcessResource+Additions.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | #if os(macOS) 24 | import Darwin 25 | import Foundation 26 | 27 | // MARK: - Public Extension SKSystemProcessResource 28 | public extension SKSystemProcessResource { 29 | 30 | final func getProcessName(pid: pid_t) -> String { 31 | 32 | // The maximum bytes of argument to execve 33 | var mib: [Int32] = [CTL_KERN, KERN_ARGMAX] 34 | 35 | var buffersize = UInt32.zero 36 | var size = MemoryLayout.size(ofValue: buffersize) 37 | 38 | if sysctl(&mib, UInt32(mib.count), &buffersize, &size, nil, Int.zero) < Int32.zero { 39 | logger.error("[SKSystemProcessResource] Failed to retrieve KERN_ARGMAX buffer size") 40 | return String.init() 41 | } 42 | 43 | let count = Int(buffersize) 44 | var cString = [CChar](repeating: CChar.zero, count: count) 45 | 46 | // Retrieves the process name 47 | if proc_name(pid, &cString, buffersize) < Int32.zero { 48 | logger.error("[SKSystemProcessResource] Failed to retrieve process name") 49 | return String.init() 50 | } 51 | 52 | return String(cString: cString) 53 | } 54 | 55 | final func getProcessInfoList() -> Array { 56 | 57 | var mib: [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_ALL] 58 | 59 | // Retrieves information about all processes running on the operating system 60 | var length = size_t.zero 61 | if sysctl(&mib, UInt32(mib.count), nil, &length, nil, Int.zero) < Int32.zero { 62 | logger.error("[SKSystemProcessResource] Failed to retrieve process information") 63 | return Array.init() 64 | } 65 | 66 | // Allocating memory to UnsafeMutablePointer 67 | let capacity = Int(length) 68 | let info = UnsafeMutablePointer.allocate(capacity: capacity) 69 | 70 | // Deallocating memory from UnsafeMutablePointer 71 | defer { info.deallocate() } 72 | 73 | // Retrieves detailed information about processes 74 | if sysctl(&mib, UInt32(mib.count), info, &length, nil, Int.zero) < Int32.zero { 75 | logger.error("[SKSystemProcessResource] Failed to retrieve detailed process information using kinfo_proc") 76 | return Array.init() 77 | } 78 | 79 | var result = Array.init() 80 | 81 | let count = Int(length / MemoryLayout.size) 82 | for index in Int.zero...size) 92 | if proc_pidinfo(pid, PROC_PIDTASKINFO, UInt64.zero, &taskInfo, buffersize) < Int32.zero { continue } 93 | 94 | // Retrieves the process name 95 | let name = getProcessName(pid: pid) 96 | 97 | let newElement = SKProcessResourceInfo(pid: pid, name: name, info: taskInfo) 98 | result.append(newElement) 99 | } 100 | 101 | return result 102 | } 103 | } 104 | #endif 105 | -------------------------------------------------------------------------------- /Sources/System/SKSystemProcessResource+Define.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | #if os(macOS) 24 | import Darwin 25 | import Foundation 26 | 27 | // MARK: - Struct 28 | public struct SKProcessResourceInfo: Codable { 29 | 30 | public let pid: pid_t 31 | 32 | public let name: String 33 | 34 | /// Virtual memory size (Bytes) 35 | public let virtualMemSize: UInt64 36 | 37 | /// Resident memory size (Bytes) 38 | public let residentMemSize: UInt64 39 | 40 | /// Task priority 41 | public let priority: Int32 42 | 43 | /// Number of running threads 44 | public let runningThreads: Int32 45 | 46 | /// Number of threads in the task 47 | public let totalThreads: Int32 48 | 49 | /// Number of context switches 50 | public let contextSwitch: Int32 51 | 52 | /// Total time `[User]` 53 | public let totalUserTime: UInt64 54 | 55 | /// Total Time `[System]` 56 | public let totalSystemTime: UInt64 57 | 58 | /// Number of page faults 59 | public let totalPageFaults: Int32 60 | 61 | /// Number of copy-on-write faults 62 | public let onCopyWritePageFaluts: Int32 63 | 64 | // MARK: Initalize 65 | public init(pid: pid_t, name: String, info: proc_taskinfo) { 66 | 67 | self.pid = pid 68 | self.name = name 69 | self.onCopyWritePageFaluts = info.pti_cow_faults 70 | self.totalPageFaults = info.pti_faults 71 | self.totalUserTime = info.pti_total_user 72 | self.totalSystemTime = info.pti_total_system 73 | self.priority = info.pti_priority 74 | self.contextSwitch = info.pti_csw 75 | self.totalThreads = info.pti_threadnum 76 | self.runningThreads = info.pti_numrunning 77 | self.virtualMemSize = info.pti_virtual_size 78 | self.residentMemSize = info.pti_resident_size 79 | } 80 | } 81 | #endif 82 | -------------------------------------------------------------------------------- /Sources/System/SKSystemProcessResource.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | #if os(macOS) 24 | import Foundation 25 | 26 | public class SKSystemProcessResource: SKClass { 27 | 28 | // MARK: - Object Properties 29 | public static let label: String = "com.SystemKit.SKSystemResource" 30 | public static let identifier: String = "D6217410-E762-478B-A97F-D5E8EC05D0CA" 31 | public static let shared: SKSystemProcessResource = SKSystemProcessResource() 32 | 33 | // MARK: - Initalize 34 | private init() { /* Initalize */ } 35 | } 36 | #endif 37 | -------------------------------------------------------------------------------- /Sources/System/SKSystemResource+Additions.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | #if os(macOS) 24 | import Darwin 25 | import Foundation 26 | 27 | // MARK: - Private Extension SKSystemResource 28 | private extension SKSystemResource { 29 | 30 | final func getHostStatisticsWithCPU() -> host_cpu_load_info { 31 | 32 | var size = mach_msg_type_number_t(MemoryLayout.size / MemoryLayout.size) 33 | 34 | let capacity = Int(size) 35 | 36 | let hostInfo = host_cpu_load_info_t.allocate(capacity: 1) 37 | let _ = hostInfo.withMemoryRebound(to: integer_t.self, capacity: capacity) { (pointer) -> kern_return_t in 38 | return host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, pointer, &size) 39 | } 40 | 41 | let data = hostInfo.move() 42 | hostInfo.deallocate() 43 | 44 | return data 45 | } 46 | 47 | final func getStatisticsWithMemory() -> vm_statistics64 { 48 | 49 | var size = mach_msg_type_number_t(MemoryLayout.size / MemoryLayout.size) 50 | 51 | let capacity = Int(size) 52 | 53 | let hostInfo = vm_statistics64_t.allocate(capacity: 1) 54 | let _ = hostInfo.withMemoryRebound(to: integer_t.self, capacity: capacity) { (pointer) -> kern_return_t in 55 | return host_statistics64(mach_host_self(), HOST_VM_INFO64, pointer, &size) 56 | } 57 | 58 | let data = hostInfo.move() 59 | hostInfo.deallocate() 60 | 61 | return data 62 | } 63 | } 64 | 65 | // MARK: - Public Extension SKSystemResource 66 | public extension SKSystemResource { 67 | 68 | final func getSystemVolumeDiskSpace() -> Optional { 69 | 70 | do { 71 | 72 | let forPath = NSHomeDirectory() 73 | 74 | let attributes = try FileManager.default.attributesOfFileSystem(forPath: forPath) 75 | 76 | guard let totalSpace = attributes[FileAttributeKey.systemSize] as? NSNumber else { return nil } 77 | 78 | guard let freeSpace = attributes[FileAttributeKey.systemFreeSize] as? NSNumber else { return nil } 79 | 80 | let totalSpaceGB = ByteCountFormatter.string(fromByteCount: totalSpace.int64Value, 81 | countStyle: .decimal) 82 | let freeSpaceGB = ByteCountFormatter.string(fromByteCount: freeSpace.int64Value, 83 | countStyle: .decimal) 84 | let usedSpaceGB = ByteCountFormatter.string(fromByteCount: totalSpace.int64Value - freeSpace.int64Value, 85 | countStyle: .decimal) 86 | 87 | return SKDiskSpaceResult(totalSpace: totalSpace.int64Value, 88 | freeSpace: freeSpace.int64Value, 89 | usedSpace: totalSpace.int64Value - freeSpace.int64Value) 90 | 91 | } catch let error as NSError { 92 | logger.error("[SKSystemResource] retrieving file system info: \(error.description)") 93 | return nil 94 | } 95 | } 96 | 97 | final func getSystemCPUResource(type: SKResourceDataUnit = .gigaByte) -> SKCPUResourceInfo { 98 | 99 | let load = getHostStatisticsWithCPU() 100 | 101 | let userDiff = Double(load.cpu_ticks.0 - self.previousSystemResource.cpu_ticks.0) 102 | let sysDiff = Double(load.cpu_ticks.1 - self.previousSystemResource.cpu_ticks.1) 103 | let idleDiff = Double(load.cpu_ticks.2 - self.previousSystemResource.cpu_ticks.2) 104 | let niceDiff = Double(load.cpu_ticks.3 - self.previousSystemResource.cpu_ticks.3) 105 | 106 | self.previousSystemResource = load 107 | 108 | let totalTicks = sysDiff + userDiff + idleDiff + niceDiff 109 | let sys = (100.0 * sysDiff / totalTicks) 110 | let user = (100.0 * userDiff / totalTicks) 111 | let idle = (100.0 * idleDiff / totalTicks) 112 | 113 | return SKCPUResourceInfo(value: min(99.9, (sys + user).round2dp), 114 | systemValue: sys.round2dp, 115 | userValue: user.round2dp, 116 | idleValue: idle.round2dp) 117 | } 118 | 119 | final func getSystemMemoryResource(type: SKResourceDataUnit = .gigaByte) -> SKMemoryResourceInfo { 120 | 121 | let maximumMemory = Double(ProcessInfo.processInfo.physicalMemory) / type.rawValue 122 | 123 | let load = getStatisticsWithMemory() 124 | let unit = Double(vm_kernel_page_size) / type.rawValue 125 | 126 | let active = Double(load.active_count) * unit 127 | let speculative = Double(load.speculative_count) * unit 128 | let inactive = Double(load.inactive_count) * unit 129 | let wired = Double(load.wire_count) * unit 130 | let compressed = Double(load.compressor_page_count) * unit 131 | let purgeable = Double(load.purgeable_count) * unit 132 | let external = Double(load.external_page_count) * unit 133 | let using = active + inactive + speculative + wired + compressed - purgeable - external 134 | 135 | return SKMemoryResourceInfo(value: min(99.9, (100.0 * using / maximumMemory).round2dp), 136 | pressureValue: (100.0 * (wired + compressed) / maximumMemory).round2dp, 137 | appValue: (using - wired - compressed).round2dp, 138 | wiredValue: wired.round2dp, 139 | compressedValue: compressed.round2dp) 140 | } 141 | } 142 | #endif 143 | -------------------------------------------------------------------------------- /Sources/System/SKSystemResource+Define.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | #if os(macOS) 24 | import Foundation 25 | 26 | // MARK: - Struct 27 | public struct SKMemoryResourceInfo: Codable { 28 | 29 | /// Using Total RAM `[% Percentage]` 30 | public let value: Double 31 | 32 | /// Efficiently your memory is serving your processing needs `[% Percentage]` 33 | public let pressureValue: Double 34 | 35 | /// The amount of memory being used by apps 36 | public let appValue: Double 37 | 38 | /// Memory required by the system to operate. This memory can’t be cached and must stay in RAM, so it’s not available to other apps 39 | public let wiredValue: Double 40 | 41 | /// The amount of memory that has been compressed to make more RAM available 42 | public let compressedValue: Double 43 | } 44 | 45 | public struct SKCPUResourceInfo: Codable { 46 | 47 | /// Using Total CPU `[% Percentage]` 48 | public let value: Double 49 | 50 | /// The percentage of CPU capability that’s being used by processes that belong to macOS. `[% Percentage]` 51 | public let systemValue: Double 52 | 53 | /// The percentage of CPU capability that’s being used by apps you opened, or by the processes opened by those apps. `[% Percentage]` 54 | public let userValue: Double 55 | 56 | /// The percentage of CPU capability that’s not being used. `[% Percentage]` 57 | public let idleValue: Double 58 | } 59 | 60 | public struct SKDiskSpaceResult: Codable { 61 | 62 | public let totalSpace: Int64 63 | 64 | public let freeSpace: Int64 65 | 66 | public let usedSpace: Int64 67 | } 68 | #endif 69 | -------------------------------------------------------------------------------- /Sources/System/SKSystemResource.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | #if os(macOS) 24 | import Darwin 25 | import Foundation 26 | 27 | public class SKSystemResource: SKClass { 28 | 29 | // MARK: - Object Properties 30 | public static let label: String = "com.SystemKit.SKSystemResource" 31 | public static let identifier: String = "0DEE36A9-02C6-4CEE-9FA7-A8CB6A4093A6" 32 | public static let shared: SKSystemResource = SKSystemResource() 33 | 34 | public var previousSystemResource: host_cpu_load_info = host_cpu_load_info() 35 | 36 | // MARK: - Initalize 37 | private init() { /* Initalize */ } 38 | } 39 | #endif 40 | -------------------------------------------------------------------------------- /Sources/SystemKit.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Universal-SystemKit. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | 23 | // swiftlint:disable all 24 | import Foundation 25 | 26 | import Logging 27 | 28 | // MARK: - Global Properties 29 | public let logger: Logger = Logger(label: SystemKit.label) 30 | 31 | public struct SystemKit { 32 | 33 | // MARK: - Object Properties 34 | public static let label: String = "com.SystemKit" 35 | public static let version: String = "2.3.2" 36 | } 37 | --------------------------------------------------------------------------------