├── .circleci └── config.yml ├── .gitignore ├── LICENSE ├── README.md ├── attach.go ├── cmd └── go-hdiutil │ └── main.go ├── convert.go ├── create.go ├── detach.go ├── doc.go ├── flag.go ├── hdiutil.go ├── hdiutil_darwin.go ├── makehybrid.go └── verify.go /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | jobs: 4 | build-macos: 5 | macos: 6 | xcode: "10.0.0" 7 | environment: 8 | PATH: /Users/distiller/go/bin:/usr/local/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin 9 | GOPATH: /Users/distiller/go 10 | HOMEBREW_NO_AUTO_UPDATE: "1" 11 | working_directory: ~/go/src/go-darwin.dev/hdiutil 12 | shell: /bin/bash --login -eux -o pipefail 13 | steps: 14 | - checkout 15 | - run: 16 | name: Install latest go via Homebrew 17 | command: | 18 | brew install https://github.com/Homebrew/homebrew-core/raw/master/Formula/go.rb || true 19 | - run: 20 | name: Show versions 21 | command: | 22 | uname -a 23 | sw_vers 24 | xcodebuild -version 25 | system_profiler SPHardwareDataType 26 | go version 27 | - run: 28 | name: Install go dependencies tools 29 | command: | 30 | go get -u golang.org/x/lint/golint 31 | - run: 32 | name: Run linters 33 | command: | 34 | test -z "$(gofmt -e -s -l $(find . -not -iwholename '*vendor*' -and -name '*.go' -print) | tee /dev/stderr)" 35 | golint -set_exit_status $(go list ./...) 36 | go vet $(go list ./...) 37 | - run: 38 | name: Take a coverage 39 | command: | 40 | go test -v -race -cover -covermode=atomic -coverprofile=coverage.txt . 41 | - run: 42 | name: Send coverage reports to codecov.io 43 | command: | 44 | bash <(curl -s https://codecov.io/bash) -Z 45 | 46 | reviewdog: 47 | docker: 48 | - image: golang:1.11.0-stretch 49 | working_directory: /go/src/github.com/go-darwin/hdiutil 50 | steps: 51 | - checkout 52 | - run: 53 | name: Run reviewdog 54 | command: | 55 | go get -u github.com/haya14busa/reviewdog/cmd/reviewdog 56 | reviewdog -reporter="github-pr-review" 57 | 58 | workflows: 59 | version: 2 60 | build-workflow: 61 | jobs: 62 | - build-macos: 63 | context: org-global 64 | - reviewdog: 65 | context: org-global 66 | filters: 67 | branches: 68 | ignore: master 69 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # hdiutil project generated files to ignore 2 | # if you want to ignore files created by your editor/tools, 3 | # please consider a global .gitignore https://help.github.com/articles/ignoring-files 4 | # please do not open a pull request to add something created by your editor or tools 5 | # 6 | # github/gitignore/Go.gitignore 7 | # Binaries for programs and plugins 8 | *.exe 9 | *.dll 10 | *.so 11 | *.dylib 12 | 13 | # Test binary, build with `go test -c` 14 | *.test 15 | 16 | # Output of the go coverage tool, specifically when used with LiteIDE 17 | *.out 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2017, The go-darwin Authors. 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # hdiutil 2 | 3 | A package hdiutil implements a macOS hdiutil command wrapper. 4 | 5 | | **CI (darwin)** | **godoc.org** | **codecov.io** | 6 | |:-------------------------------------------:|:-----------------------------------:|:---------------------------------------:| 7 | | [![circleci.com][circleci-badge]][circleci] | [![godoc.org][godoc-badge]][godoc] | [![codecov.io][codecov-badge]][codecov] | 8 | 9 | 10 | [![Analytics][ga-badge]][ga] 11 | 12 | ## Support commands 13 | 14 | - [x] **attach** 15 | - [ ] burn 16 | - [ ] checksum 17 | - [ ] chpass 18 | - [ ] compact 19 | - [x] **convert** 20 | - [x] **create** 21 | - [x] **detach** 22 | - [ ] eject 23 | - [ ] erasekeys 24 | - [ ] flatten 25 | - [ ] imageinfo 26 | - [ ] info 27 | - [ ] internet-enable 28 | - [ ] isencrypted 29 | - [x] **makehybrid** 30 | - [ ] mount 31 | - [ ] mountvol 32 | - [ ] plugins 33 | - [ ] pmap 34 | - [ ] resize 35 | - [ ] segment 36 | - [ ] udifderez 37 | - [ ] udifrez 38 | - [ ] unflatten 39 | - [ ] unmount 40 | - [x] **verify** 41 | 42 | 43 | [circleci]: https://circleci.com/gh/go-darwin/hdiutil 44 | [godoc]: https://godoc.org/go-darwin.dev/hdiutil 45 | [codecov]: https://codecov.io/gh/go-darwin/hdiutil 46 | [ga]: https://github.com/zchee 47 | 48 | [circleci-badge]: https://img.shields.io/circleci/project/github/go-darwin/hdiutil.svg?style=flat-square&label=%20%20CircleCI&logoWidth=16&logo=data%3Aimage%2Fsvg%2Bxml%3Bcharset%3Dutf-8%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MCIgdmlld0JveD0iMCAwIDIwMCAyMDAiPjxwYXRoIGZpbGw9IiNEREQiIGQ9Ik03NC43IDEwMGMwLTEzLjIgMTAuNy0yMy44IDIzLjgtMjMuOCAxMy4xIDAgMjMuOCAxMC43IDIzLjggMjMuOCAwIDEzLjEtMTAuNyAyMy44LTIzLjggMjMuOC0xMy4xIDAtMjMuOC0xMC43LTIzLjgtMjMuOHpNOTguNSAwQzUxLjggMCAxMi43IDMyIDEuNiA3NS4yYy0uMS4zLS4xLjYtLjEgMSAwIDIuNiAyLjEgNC44IDQuOCA0LjhoNDAuM2MxLjkgMCAzLjYtMS4xIDQuMy0yLjggOC4zLTE4IDI2LjUtMzAuNiA0Ny42LTMwLjYgMjguOSAwIDUyLjQgMjMuNSA1Mi40IDUyLjRzLTIzLjUgNTIuNC01Mi40IDUyLjRjLTIxLjEgMC0zOS4zLTEyLjUtNDcuNi0zMC42LS44LTEuNi0yLjQtMi44LTQuMy0yLjhINi4zYy0yLjYgMC00LjggMi4xLTQuOCA0LjggMCAuMy4xLjYuMSAxQzEyLjYgMTY4IDUxLjggMjAwIDk4LjUgMjAwYzU1LjIgMCAxMDAtNDQuOCAxMDAtMTAwUzE1My43IDAgOTguNSAweiIvPjwvc3ZnPg%3D%3D 49 | [godoc-badge]: https://img.shields.io/badge/godoc-reference-4F73B3.svg?style=flat-square&label=%20godoc.org 50 | [codecov-badge]: https://img.shields.io/codecov/c/github/go-darwin/hdiutil.svg?style=flat-square&label=%20%20Codecov%2Eio&logo=data%3Aimage%2Fsvg%2Bxml%3Bcharset%3Dutf-8%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgdmlld0JveD0iMCAwIDI1NiAyODEiPjxwYXRoIGZpbGw9IiNFRUUiIGQ9Ik0yMTguNTUxIDM3LjQxOUMxOTQuNDE2IDEzLjI4OSAxNjIuMzMgMCAxMjguMDk3IDAgNTcuNTM3LjA0Ny4wOTEgNTcuNTI3LjA0IDEyOC4xMjFMMCAxNDkuODEzbDE2Ljg1OS0xMS40OWMxMS40NjgtNy44MTQgMjQuNzUtMTEuOTQ0IDM4LjQxNy0xMS45NDQgNC4wNzkgMCA4LjE5OC4zNzMgMTIuMjQgMS4xMSAxMi43NDIgMi4zMiAyNC4xNjUgOC4wODkgMzMuNDE0IDE2Ljc1OCAyLjEyLTQuNjcgNC42MTQtOS4yMDkgNy41Ni0xMy41MzZhODguMDgxIDg4LjA4MSAwIDAgMSAzLjgwNS01LjE1Yy0xMS42NTItOS44NC0yNS42NDktMTYuNDYzLTQwLjkyNi0xOS4yNDVhOTAuMzUgOTAuMzUgMCAwIDAtMTYuMTItMS40NTkgODguMzc3IDg4LjM3NyAwIDAgMC0zMi4yOSA2LjA3YzguMzYtNTEuMjIyIDUyLjg1LTg5LjM3IDEwNS4yMy04OS40MDggMjguMzkyIDAgNTUuMDc4IDExLjA1MyA3NS4xNDkgMzEuMTE3IDE2LjAxMSAxNi4wMSAyNi4yNTQgMzYuMDMzIDI5Ljc4OCA1OC4xMTctMTAuMzI5LTQuMDM1LTIxLjIxMi02LjEtMzIuNDAzLTYuMTQ0bC0xLjU2OC0uMDA3YTkwLjk1NyA5MC45NTcgMCAwIDAtMy40MDEuMTExYy0xLjk1NS4xLTMuODk4LjI3Ny01LjgyMS41LS41NzQuMDYzLTEuMTM5LjE1My0xLjcwNy4yMzEtMS4zNzguMTg2LTIuNzUuMzk1LTQuMTA5LjYzOS0uNjAzLjExLTEuMjAzLjIzMS0xLjguMzUxYTkwLjUxNyA5MC41MTcgMCAwIDAtNC4xMTQuOTM3Yy0uNDkyLjEyNi0uOTgzLjI0My0xLjQ3LjM3NGE5MC4xODMgOTAuMTgzIDAgMCAwLTUuMDkgMS41MzhjLS4xLjAzNS0uMjA0LjA2My0uMzA0LjA5NmE4Ny41MzIgODcuNTMyIDAgMCAwLTExLjA1NyA0LjY0OWMtLjA5Ny4wNS0uMTkzLjEwMS0uMjkzLjE1MWE4Ni43IDg2LjcgMCAwIDAtNC45MTIgMi43MDFsLS4zOTguMjM4YTg2LjA5IDg2LjA5IDAgMCAwLTIyLjMwMiAxOS4yNTNjLS4yNjIuMzE4LS41MjQuNjM1LS43ODQuOTU4LTEuMzc2IDEuNzI1LTIuNzE4IDMuNDktMy45NzYgNS4zMzZhOTEuNDEyIDkxLjQxMiAwIDAgMC0zLjY3MiA1LjkxMyA5MC4yMzUgOTAuMjM1IDAgMCAwLTIuNDk2IDQuNjM4Yy0uMDQ0LjA5LS4wODkuMTc1LS4xMzMuMjY1YTg4Ljc4NiA4OC43ODYgMCAwIDAtNC42MzcgMTEuMjcybC0uMDAyLjAwOXYuMDA0YTg4LjAwNiA4OC4wMDYgMCAwIDAtNC41MDkgMjkuMzEzYy4wMDUuMzk3LjAwNS43OTQuMDE5IDEuMTkyLjAyMS43NzcuMDYgMS41NTcuMTA0IDIuMzM4YTk4LjY2IDk4LjY2IDAgMCAwIC4yODkgMy44MzRjLjA3OC44MDQuMTc0IDEuNjA2LjI3NSAyLjQxLjA2My41MTIuMTE5IDEuMDI2LjE5NSAxLjUzNGE5MC4xMSA5MC4xMSAwIDAgMCAuNjU4IDQuMDFjNC4zMzkgMjIuOTM4IDE3LjI2MSA0Mi45MzcgMzYuMzkgNTYuMzE2bDIuNDQ2IDEuNTY0LjAyLS4wNDhhODguNTcyIDg4LjU3MiAwIDAgMCAzNi4yMzIgMTMuNDVsMS43NDYuMjM2IDEyLjk3NC0yMC44MjItNC42NjQtLjEyN2MtMzUuODk4LS45ODUtNjUuMS0zMS4wMDMtNjUuMS02Ni45MTcgMC0zNS4zNDggMjcuNjI0LTY0LjcwMiA2Mi44NzYtNjYuODI5bDIuMjMtLjA4NWMxNC4yOTItLjM2MiAyOC4zNzIgMy44NTkgNDAuMzI1IDExLjk5N2wxNi43ODEgMTEuNDIxLjAzNi0yMS41OGMuMDI3LTM0LjIxOS0xMy4yNzItNjYuMzc5LTM3LjQ0OS05MC41NTQiLz48L3N2Zz4= 51 | [ga-badge]: https://ga-beacon.appspot.com/UA-89201129-1/go-darwin/hdiutil?flat&useReferer&pixel 52 | -------------------------------------------------------------------------------- /attach.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The go-darwin Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package hdiutil 6 | 7 | import ( 8 | "fmt" 9 | "os/exec" 10 | "regexp" 11 | "strconv" 12 | ) 13 | 14 | // attachFlag implements a hdiutil attach command flag interface. 15 | type attachFlag interface { 16 | attachFlag() []string 17 | } 18 | 19 | type attachRWType int 20 | 21 | const ( 22 | readonly attachRWType = 1 << iota 23 | readwrite 24 | ) 25 | 26 | func (a attachRWType) attachFlag() string { 27 | switch a { 28 | case readonly: 29 | return "-readonly" 30 | case readwrite: 31 | return "-readwrite" 32 | default: 33 | return "" 34 | } 35 | } 36 | 37 | type attachKernel bool 38 | 39 | func (a attachKernel) attachFlag() []string { return boolNoFlag("kernel", bool(a)) } 40 | 41 | type attachNotRemovable bool 42 | 43 | func (a attachNotRemovable) attachFlag() []string { return boolFlag("notremovable", bool(a)) } 44 | 45 | type attachMount string 46 | 47 | func (a attachMount) attachFlag() []string { return stringFlag("mount", string(a)) } 48 | 49 | type attachNoMount bool 50 | 51 | func (a attachNoMount) attachFlag() []string { return boolFlag("nomount", bool(a)) } 52 | 53 | // AttachMountRoot mount volumes on subdirectories of path instead of under /Volumes. path must exist. 54 | // 55 | // Full mount point paths must be less than MNAMELEN characters (increased from 90 to 1024 in Mac OS X 10.6). 56 | type AttachMountRoot string 57 | 58 | func (a AttachMountRoot) attachFlag() []string { return stringFlag("mountroot", string(a)) } 59 | 60 | // AttachMountRandom like AttachMountRoot, but mount point directory names are randomized with mkdtemp(3). 61 | type AttachMountRandom string 62 | 63 | func (a AttachMountRandom) attachFlag() []string { return stringFlag("mountrandom", string(a)) } 64 | 65 | // AttachMountPoint assuming only one volume, mount it at path instead of in /Volumes. 66 | // 67 | // See fstab(5) for ways a system administrator can make particular volumes automatically mount in particular filesystem locations by editing the file /etc/fstab. 68 | type AttachMountPoint string 69 | 70 | func (a AttachMountPoint) attachFlag() []string { return stringFlag("mountpoint", string(a)) } 71 | 72 | type attachNoBrowse bool 73 | 74 | func (a attachNoBrowse) attachFlag() []string { return boolFlag("nobrowse", bool(a)) } 75 | 76 | type attachOwners string 77 | 78 | const ( 79 | ownersOn attachOwners = "on" 80 | ownersOff attachOwners = "off" 81 | ) 82 | 83 | func (a attachOwners) attachFlag() []string { return stringFlag("owners", string(a)) } 84 | 85 | // AttachDrivekey specify a key/value pair to be set on the device in the IOKit registry. 86 | type AttachDrivekey [2]string 87 | 88 | func (a AttachDrivekey) attachFlag() []string { 89 | return stringFlag(a[0]+"="+a[1], "drivekey") 90 | } 91 | 92 | // AttachSection attach a subsection of a disk image. 93 | // subspec is any of , , or in 0-based sectors. 94 | // Ranges are inclusive. 95 | type AttachSection [2]int 96 | 97 | func (a AttachSection) attachFlag() []string { 98 | var arg string 99 | for v := range a { 100 | arg = arg + strconv.Itoa(v) 101 | } 102 | return stringFlag(arg, "section") 103 | } 104 | 105 | type attachVerify bool 106 | 107 | func (a attachVerify) attachFlag() []string { return boolNoFlag("verify", bool(a)) } 108 | 109 | type attachIgnoreBadChecksums bool 110 | 111 | func (a attachIgnoreBadChecksums) attachFlag() []string { 112 | return boolNoFlag("ignoreBadChecksums", bool(a)) 113 | } 114 | 115 | type attachIdme bool 116 | 117 | func (a attachIdme) attachFlag() []string { return boolNoFlag("idme", bool(a)) } 118 | 119 | type atachIdmeReveal bool 120 | 121 | func (a atachIdmeReveal) attachFlag() []string { return boolNoFlag("idmereveal", bool(a)) } 122 | 123 | type attachIdmeTrash bool 124 | 125 | func (a attachIdmeTrash) attachFlag() []string { return boolNoFlag("idmetrash", bool(a)) } 126 | 127 | type attachAutoOpen bool 128 | 129 | func (a attachAutoOpen) attachFlag() []string { return boolNoFlag("autoopen", bool(a)) } 130 | 131 | type attachAutoOpenRO bool 132 | 133 | func (a attachAutoOpenRO) attachFlag() []string { return boolNoFlag("autoopenro", bool(a)) } 134 | 135 | type attachAutoOpenRW bool 136 | 137 | func (a attachAutoOpenRW) attachFlag() []string { return boolNoFlag("autoopenrw", bool(a)) } 138 | 139 | type attachAutoFsck bool 140 | 141 | func (a attachAutoFsck) attachFlag() []string { return boolNoFlag("autofsck", bool(a)) } 142 | 143 | const ( 144 | // AttachReadonly force the resulting device to be read-only. 145 | AttachReadonly attachRWType = readonly 146 | 147 | // AttachReadWrite attempt to override the DiskImages framework's decision to attach a particular image read-only. 148 | // 149 | // For example, AttachReadWrite can be used to modify the HFS+ filesystem on a HFS+/ISO hybrid CD image. 150 | AttachReadWrite attachRWType = readwrite 151 | 152 | // AttachKernel attempt to attach this image without a helper process; fail if unsupported. 153 | // 154 | // Only UDRW, UDRO, UDZO, ULFO, and UDSP images are supported in-kernel. Encryption and HTTP are supported by the kernel driver. 155 | AttachKernel attachKernel = true 156 | 157 | // AttachNoKernel attach with a helper process. This is (again) the default as of Mac OS X 10.5. 158 | AttachNoKernel attachKernel = false 159 | 160 | // AttachNotRemovable prevent this image from being detached. Only root can use this option. 161 | // 162 | // A reboot is necessary to cleanly detach an image attached with AttachNotRemovable. 163 | AttachNotRemovable attachNotRemovable = true 164 | 165 | // AttachMountRequired indicate to mount required. 166 | AttachMountRequired attachMount = "required" 167 | 168 | // AttachMountOptional indicate to mount optional. 169 | AttachMountOptional attachMount = "optional" 170 | 171 | // AttachMountSuppressed indicate to mount suppressed. 172 | AttachMountSuppressed attachMount = "suppressed" 173 | 174 | // AttachNoMount identical to AttachMountSuppressed. 175 | AttachNoMount attachNoMount = true 176 | 177 | // AttachNoBrowse render any volumes invisible in applications such as the macOS Finder. 178 | AttachNoBrowse attachNoBrowse = true 179 | 180 | // AttachOwnersOn owners on any filesystems be honored. 181 | AttachOwnersOn attachOwners = ownersOn 182 | 183 | // AttachOwnersOff owners on any filesystems be not honored. 184 | AttachOwnersOff attachOwners = ownersOff 185 | 186 | // AttachVerify do verify the image. 187 | AttachVerify attachVerify = true 188 | 189 | // AttachNoVerify do not verify the image. 190 | AttachNoVerify attachVerify = false 191 | 192 | // AttachIgnoreBadChecksums bad checksums should be ignored. 193 | AttachIgnoreBadChecksums attachIgnoreBadChecksums = true 194 | 195 | // AttachNoIgnoreBadChecksums bad checksums should be not ignored. 196 | AttachNoIgnoreBadChecksums attachIgnoreBadChecksums = false 197 | 198 | // AttachIdme do perform IDME actions on IDME images. 199 | AttachIdme attachIdme = true 200 | 201 | // AttachNoIdme do not perform IDME actions on IDME images. 202 | AttachNoIdme attachIdme = false 203 | 204 | // AttachIdmeReveal do reveal (in the Finder) the results of IDME processing. 205 | AttachIdmeReveal atachIdmeReveal = true 206 | 207 | // AttachNoIdmeReveal do not reveal (in the Finder) the results of IDME processing. 208 | AttachNoIdmeReveal atachIdmeReveal = false 209 | 210 | // AttachIdmeTrash do put IDME images in the trash after processing. 211 | AttachIdmeTrash attachIdmeTrash = true 212 | 213 | // AttachNoIdmeTrash do not put IDME images in the trash after processing. 214 | AttachNoIdmeTrash attachIdmeTrash = false 215 | 216 | // AttachAutoOpen do not auto-open volumes (in the Finder) after attaching an image. 217 | AttachAutoOpen attachAutoOpen = true 218 | 219 | // AttachNoAutoOpen do not auto-open volumes (in the Finder) after attaching an image. 220 | AttachNoAutoOpen attachAutoOpen = false 221 | 222 | // AttachAutoOpenRO do auto-open read-only volumes. 223 | AttachAutoOpenRO attachAutoOpenRO = true 224 | 225 | // AttachNoAutoOpenRO do not auto-open read-only volumes. 226 | AttachNoAutoOpenRO attachAutoOpenRO = false 227 | 228 | // AttachAutoOpenRW do auto-open read/write volumes. 229 | AttachAutoOpenRW attachAutoOpenRW = true 230 | 231 | // AttachNoAutoOpenRW do not auto-open read/write volumes. 232 | AttachNoAutoOpenRW attachAutoOpenRW = false 233 | 234 | // AttachAutoFsck do force automatic file system checking before mounting a disk image. 235 | AttachAutoFsck attachAutoFsck = true 236 | 237 | // AttachNoAutoFsck do not force automatic file system checking before mounting a disk image. 238 | AttachNoAutoFsck attachAutoFsck = false 239 | ) 240 | 241 | var attachRe = regexp.MustCompile(`/dev/disk[\d]+`) 242 | 243 | // Attach attach the image file. The returns device node path and error. 244 | func Attach(image string, flags ...attachFlag) (string, error) { 245 | cmd := exec.Command(hdiutilPath, "attach", image) 246 | 247 | if len(flags) > 0 { 248 | for _, f := range flags { 249 | cmd.Args = append(cmd.Args, f.attachFlag()...) 250 | } 251 | } 252 | 253 | out, err := cmd.CombinedOutput() 254 | if err != nil { 255 | return "", fmt.Errorf("%v: %s", err, out) 256 | } 257 | 258 | return string(attachRe.Find(out)), nil 259 | } 260 | -------------------------------------------------------------------------------- /cmd/go-hdiutil/main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The go-darwin Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package main 6 | 7 | import ( 8 | "log" 9 | "os" 10 | 11 | "github.com/go-darwin/hdiutil" 12 | ) 13 | 14 | func main() { 15 | image := "test.sparsebundle" 16 | 17 | if err := hdiutil.Create("test", hdiutil.CreateMegabytes(20), hdiutil.CreateHFSPlus, hdiutil.CreateSPARSEBUNDLE); err != nil { 18 | log.Fatal(err) 19 | } 20 | if _, err := os.Stat(image); err != nil { 21 | log.Fatal(err) 22 | } 23 | defer os.RemoveAll(image) 24 | 25 | deviceNode, err := hdiutil.Attach(image, hdiutil.AttachMountPoint("./test"), hdiutil.AttachNoVerify, hdiutil.AttachNoAutoFsck) 26 | if err != nil { 27 | log.Fatal(err) 28 | } 29 | 30 | log.Println(hdiutil.RawDeviceNode(deviceNode)) 31 | log.Println(hdiutil.DeviceNumber(deviceNode)) 32 | 33 | if err := hdiutil.Detach(deviceNode); err != nil { 34 | log.Fatal(err) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /convert.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The go-darwin Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package hdiutil 6 | 7 | import "os/exec" 8 | 9 | // formatFlag implements a hdiutil convert command format flag interface. 10 | type formatFlag interface { 11 | formatFlag() []string 12 | } 13 | 14 | type convertFormot int 15 | 16 | const ( 17 | // ConvertUDRW UDIF read/write image. 18 | ConvertUDRW convertFormot = 1 << iota 19 | // ConvertUDRO UDIF read-only image. 20 | ConvertUDRO 21 | // ConvertUDCO UDIF ADC-compressed image. 22 | ConvertUDCO 23 | // ConvertUDZO UDIF zlib-compressed image. 24 | ConvertUDZO 25 | // ConvertULFO UDIF lzfse-compressed image (OS X 10.11+ only). 26 | ConvertULFO 27 | // ConvertUDBZ UDIF bzip2-compressed image (Mac OS X 10.4+ only). 28 | ConvertUDBZ 29 | // ConvertUDTO DVD/CD-R master for export. 30 | ConvertUDTO 31 | // ConvertUDSP SPARSE (grows with content). 32 | ConvertUDSP 33 | // ConvertUDSB SPARSEBUNDLE (grows with content; bundle-backed). 34 | ConvertUDSB 35 | // ConvertUFBI UDIF entire image with MD5 checksum. 36 | ConvertUFBI 37 | // ConvertUDRo UDIF read-only (obsolete format). 38 | ConvertUDRo 39 | // ConvertUDCo UDIF compressed (obsolete format). 40 | ConvertUDCo 41 | // ConvertRdWr NDIF read/write image (deprecated). 42 | ConvertRdWr 43 | // ConvertRdxx NDIF read-only image (Disk Copy 6.3.3 format; deprecated). 44 | ConvertRdxx 45 | // ConvertROCo NDIF compressed image (deprecated). 46 | ConvertROCo 47 | // ConvertRken NDIF compressed (obsolete format). 48 | ConvertRken 49 | // ConvertDC42 Disk Copy 4.2 image (obsolete format). 50 | ConvertDC42 51 | ) 52 | 53 | // convertFlag implements a hdiutil convert command flag interface. 54 | type convertFlag interface { 55 | convertFlag() []string 56 | } 57 | 58 | // ConvertAlign default is 4 (2K). 59 | type ConvertAlign int 60 | 61 | func (c ConvertAlign) convertFlag() []string { return intFlag("align", int(c)) } 62 | 63 | type convertPmap bool 64 | 65 | func (c convertPmap) convertFlag() []string { return boolFlag("pmap", bool(c)) } 66 | 67 | // ConvertSegmentSize specify segmentation into size_spec-sized segments as outfile is being written. 68 | // 69 | // The default size_spec when ConvertSegmentSize is specified alone is 2*1024*1024 (1 GB worth of sectors) for UDTO images and 4*1024*1024 (2 GB segments) for all other image types. 70 | // 71 | // size_spec(string) can also be specified ??b|??k|??m|??g|??t|??p|??e like create's CreateSize flag. 72 | type ConvertSegmentSize string 73 | 74 | func (c ConvertSegmentSize) convertFlag() []string { return stringFlag("segmentSize", string(c)) } 75 | 76 | // ConvertTasks when converting an image into a compressed format, specify the number of threads to use for the compression operation. 77 | // 78 | // The default is the number of processors active in the current system. 79 | type ConvertTasks int 80 | 81 | func (c ConvertTasks) convertFlag() []string { return intFlag("tasks", int(c)) } 82 | 83 | const ( 84 | // ConvertPmap add partition map. 85 | ConvertPmap convertPmap = true 86 | ) 87 | 88 | // Convert convert image to type format and write the result to outfile. 89 | func Convert(image string, format formatFlag, outfile string, flags ...convertFlag) error { 90 | cmd := exec.Command(hdiutilPath, "convert", image) 91 | cmd.Args = append(cmd.Args, format.formatFlag()...) 92 | cmd.Args = append(cmd.Args, outfile) 93 | if len(flags) > 0 { 94 | for _, flag := range flags { 95 | cmd.Args = append(cmd.Args, flag.convertFlag()...) 96 | } 97 | } 98 | 99 | err := cmd.Run() 100 | if err != nil { 101 | return err 102 | } 103 | 104 | return nil 105 | } 106 | -------------------------------------------------------------------------------- /create.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The go-darwin Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package hdiutil 6 | 7 | import "os/exec" 8 | 9 | // sizeFlag implements a hdiutil create command size flag interface. 10 | type sizeFlag interface { 11 | sizeFlag() []string 12 | } 13 | 14 | // CreateSize specify the size of the image in the style of mkfile(8) with the addition of tera-, peta-, and exa-bytes sizes. 15 | // 16 | // The larger sizes are useful for large sparse images. 17 | type CreateSize string 18 | 19 | func (c CreateSize) sizeFlag() []string { return stringFlag("size", string(c)) } 20 | 21 | // CreateSectors specify the size of the image file in 512-byte sectors. 22 | type CreateSectors int 23 | 24 | func (c CreateSectors) sizeFlag() []string { return intFlag("sectors", int(c)) } 25 | 26 | // CreateMegabytes specify the size of the image file in megabytes (1024*1024 bytes). 27 | type CreateMegabytes int 28 | 29 | func (c CreateMegabytes) sizeFlag() []string { return intFlag("megabytes", int(c)) } 30 | 31 | // CreateSrcfolder copies file-by-file the contents of source into image, creating a fresh (theoretically defragmented) filesystem on the destination. 32 | // 33 | // The resulting image is thus recommended for use with asr(8) since it will have a minimal amount of unused space. 34 | // Its size will be that of the source data plus some padding for filesystem overhead. The filesystem type of the image volume will match that of the source as closely as possible unless overridden with -fs. 35 | // 36 | // Other size specifiers, such as CreateSize, will override the default size calculation based on the source content, allowing for more or less free space in the resulting filesystem. 37 | // CreateSrcfolder can be specified more than once, in which case the image volume will be populated at the top level with a copy of each specified filesystem object. 38 | type CreateSrcfolder string 39 | 40 | func (c CreateSrcfolder) sizeFlag() []string { return stringFlag("srcfolder", string(c)) } 41 | 42 | // CreateSrcdir is a synonym to CreateSrcfolder. 43 | type CreateSrcdir CreateSrcfolder 44 | 45 | func (c CreateSrcdir) sizeFlag() []string { return stringFlag("srcdir", string(c)) } 46 | 47 | // CreateSrcdevice specifies that the blocks of device should be used to create a new image. 48 | // 49 | // The image size will match the size of device. resize can be used to adjust the size of resizable filesystems and writable images. 50 | // Both CreateSrcdevice and CreateSrcfolder can run into errors if there are bad blocks on a disk. 51 | // One way around this problem is to write over the files in question in the hopes that the drive will remap the bad blocks. 52 | // Data will be lost, but the image creation operation will subsequently succeed. 53 | // 54 | // Filesystem options (like createFS, CreateVolname, CreateStretch, or CreateSize) are invalid and ignored when using CreateSrcdevice. 55 | type CreateSrcdevice string 56 | 57 | func (c CreateSrcdevice) sizeFlag() []string { return stringFlag("srcdevice", string(c)) } 58 | 59 | // createFlag implements a hdiutil create command flag interface. 60 | type createFlag interface { 61 | createFlag() []string 62 | } 63 | 64 | // CreateAlign specifies a size to which the final data partition will be aligned. The default is 4K. 65 | type CreateAlign int 66 | 67 | func (c CreateAlign) createFlag() []string { return intFlag("align", int(c)) } 68 | 69 | type createType int 70 | 71 | const ( 72 | // CreateUDIF is the default type. If specified, a UDRW of the specified size will be created. 73 | CreateUDIF createType = 1 << iota 74 | // CreateSPARSE creates a UDSP, a read/write single-file image which expands as is is filled with data. 75 | CreateSPARSE 76 | // CreateSPARSEBUNDLE creates a UDSB, a read/write image backed by a directory bundle. 77 | CreateSPARSEBUNDLE 78 | ) 79 | 80 | func (c createType) String() string { 81 | switch c { 82 | case CreateUDIF: 83 | return "UDIF" 84 | case CreateSPARSE: 85 | return "SPARSE" 86 | case CreateSPARSEBUNDLE: 87 | return "SPARSEBUNDLE" 88 | default: 89 | return "" 90 | } 91 | } 92 | 93 | func (c createType) createFlag() []string { return stringFlag("type", c.String()) } 94 | 95 | type createFS int 96 | 97 | const ( 98 | // CreateHFSPlus provides the HFS+. 99 | CreateHFSPlus createFS = 1 << iota 100 | // CreateHFSPlusJ provides the HFS+J. 101 | CreateHFSPlusJ 102 | // CreateJHFSPlus provides the JHFS+. 103 | CreateJHFSPlus 104 | // CreateHFSX provides the HFSX. 105 | CreateHFSX 106 | // CreateJHFSPlusX provides the JHFS+X. 107 | CreateJHFSPlusX 108 | // CreateAPFS provides the APFS. 109 | CreateAPFS 110 | // CreateFAT32 provides the FAT32. 111 | CreateFAT32 112 | // CreateExFAT provides the ExFAT. 113 | CreateExFAT 114 | // CreateUDF provides the UDF. 115 | CreateUDF 116 | ) 117 | 118 | func (c createFS) String() string { 119 | switch c { 120 | case CreateHFSPlus: 121 | return "HFS+" 122 | case CreateHFSPlusJ: 123 | return "HFS+J" 124 | case CreateJHFSPlus: 125 | return "JHFS+" 126 | case CreateHFSX: 127 | return "HFSX" 128 | case CreateJHFSPlusX: 129 | return "JHFS+X" 130 | case CreateAPFS: 131 | return "APFS" 132 | case CreateFAT32: 133 | return "FAT32" 134 | case CreateExFAT: 135 | return "ExFAT" 136 | case CreateUDF: 137 | return "UDF" 138 | default: 139 | return "" 140 | } 141 | } 142 | 143 | func (c createFS) createFlag() []string { return stringFlag("fs", c.String()) } 144 | 145 | // CreateVolname the newly-created filesystem will be named volname. 146 | // 147 | // The default depends the filesystem being used, The default volume name in both HFS+ and APFS is `untitled'. 148 | // 149 | // CreateVolname is invalid and ignored when using CreateSrcdevice. 150 | type CreateVolname string 151 | 152 | func (c CreateVolname) createFlag() []string { return stringFlag("volname", string(c)) } 153 | 154 | // CreateUID the root of the newly-created volume will be owned by the given numeric user id. 99 maps to the magic 'unknown' user. 155 | type CreateUID int 156 | 157 | func (c CreateUID) createFlag() []string { return intFlag("uid", int(c)) } 158 | 159 | // CreateGID the root of the newly-created volume will be owned by the given numeric group id. 99 maps to 'unknown'. 160 | type CreateGID int 161 | 162 | func (c CreateGID) createFlag() []string { return intFlag("gid", int(c)) } 163 | 164 | // CreateMode the root of the newly-created volume will have mode (in octal) mode. 165 | // 166 | // The default mode is determined by the filesystem's newfs unless CreateSrcfolder is specified, in which case the default mode is derived from the specified filesystem object. 167 | type CreateMode string 168 | 169 | func (c CreateMode) createFlag() []string { return stringFlag("mode", string(c)) } 170 | 171 | type createAutostretch bool 172 | 173 | func (c createAutostretch) createFlag() []string { return boolNoFlag("autostretch", bool(c)) } 174 | 175 | // CreateStretch initializes HFS+ filesystem data such that it can later be stretched on older systems (which could only stretch within predefined limits) using hdiutil resize or by asr(8). max_stretch(int) is specified like CreateSize. 176 | // 177 | // CreateStretch is invalid and ignored when using CreateSrcdevice. 178 | type CreateStretch int 179 | 180 | func (c CreateStretch) createFlag() []string { return intFlag("stretch", int(c)) } 181 | 182 | // CreateFSArgs additional arguments to pass to whichever newfs program is implied by createFS. 183 | // 184 | // As an example with HFS+, newfs_hfs(8) has a number of options that can control the amount of space used by the filesystem's data structures. 185 | type CreateFSArgs []string 186 | 187 | func (c CreateFSArgs) createFlag() []string { return stringSliceFlag("fsargs", c) } 188 | 189 | // CreateLayout specify the partition layout of the image. 190 | // 191 | // layout can be anything supported by MediaKit.framework. 192 | // NONE creates an image with no partition map.When such an image is attached, a single /dev entry will be created (e.g. /dev/disk1). 193 | // 194 | // 'SPUD' causes a DDM and an Apple Partition Scheme partition map with a single entry to be written. 'GPTSPUD' creates a similar image but with a GUID Partition Scheme map instead. 195 | // When attached, multiple /dev entries will be created, with either slice 1 (GPT) or slice 2 (APM) as the data partition. (e.g. /dev/disk1, /dev/disk1s1, /dev/disk1s2). 196 | // 197 | // Unless overridden by createFS, the default layout is 'GPTSPUD' (PPC systems used 'SPUD' prior to Mac OS X 10.6). Other layouts include 'MBRSPUD' and 'ISOCD'. create -help lists all supported layouts. 198 | type CreateLayout string 199 | 200 | func (c CreateLayout) createFlag() []string { return stringFlag("layout", string(c)) } 201 | 202 | // CreateLibrary specify an alternate layout library. The default is MediaKit's MKDrivers.bundle. 203 | type CreateLibrary string 204 | 205 | func (c CreateLibrary) createFlag() []string { return stringFlag("library", string(c)) } 206 | 207 | // CreatePartitionType change the type of partition in a single-partition disk image. The default is Apple_HFS unless createFS implies otherwise. 208 | type CreatePartitionType string 209 | 210 | func (c CreatePartitionType) createFlag() []string { return stringFlag("partitionType", string(c)) } 211 | 212 | type createOV bool 213 | 214 | func (c createOV) createFlag() []string { return boolFlag("ov", bool(c)) } 215 | 216 | type createAttach bool 217 | 218 | func (c createAttach) createFlag() []string { return boolFlag("attach", bool(c)) } 219 | 220 | // CreateFormat specify the final image format. The default when a source is specified is UDZO. CreateFormat can be any of the format parameters used by convert. 221 | type CreateFormat string 222 | 223 | func (c CreateFormat) createFlag() []string { return stringFlag("format", string(c)) } 224 | 225 | // CreateSegmentSize specify that the image should be written in segments no bigger than size_spec (which follows CreateSize conventions). 226 | type CreateSegmentSize int 227 | 228 | func (c CreateSegmentSize) createFlag() []string { return intFlag("segmentSize", int(c)) } 229 | 230 | type createCrossdev bool 231 | 232 | func (c createCrossdev) createFlag() []string { return boolNoFlag("crossdev", bool(c)) } 233 | 234 | type createScrub bool 235 | 236 | func (c createScrub) createFlag() []string { return boolNoFlag("scrub", bool(c)) } 237 | 238 | type createAnyowners bool 239 | 240 | func (c createAnyowners) createFlag() []string { return boolNoFlag("anyowners", bool(c)) } 241 | 242 | type createSkipunreadable bool 243 | 244 | func (c createSkipunreadable) createFlag() []string { return boolFlag("skipunreadable", bool(c)) } 245 | 246 | type createAtomic bool 247 | 248 | func (c createAtomic) createFlag() []string { return boolFlag("atomic", bool(c)) } 249 | 250 | // CreateCopyuid perform the copy as the given user. Requires root privilege. 251 | // If user can't read or create files with the needed owners, CreateAnyowners or CreateSkipunreadable must be used to prevent the operation from failing. 252 | type CreateCopyuid string 253 | 254 | func (c CreateCopyuid) createFlag() []string { return stringFlag("copyuid", string(c)) } 255 | 256 | const ( 257 | // CreateAutostretch do suppress automatically making backwards-compatible stretchable volumes when the volume size crosses the auto-stretch-size threshold (default: 256 MB). See also asr(8). 258 | CreateAutostretch createAutostretch = true 259 | 260 | // CreateNoAutostretch do not suppress automatically making backwards-compatible stretchable volumes when the volume size crosses the auto-stretch-size threshold (default: 256 MB). See also asr(8). 261 | CreateNoAutostretch createAutostretch = false 262 | 263 | // CreateOV overwrite an existing file. The default is not to overwrite existing files. 264 | CreateOV createOV = true 265 | 266 | // CreateAttach the image after creating it. If no filesystem is specified via createFS, the attach will fail per the default attach createMount required behavior. 267 | CreateAttach createAttach = true 268 | 269 | // CreateCrossdev do cross device boundaries on the source filesystem. 270 | CreateCrossdev createCrossdev = true 271 | 272 | // CreateNoCrossdev do not cross device boundaries on the source filesystem. 273 | CreateNoCrossdev createCrossdev = false 274 | 275 | // CreateScrub do cross device boundaries on the source filesystem. 276 | CreateScrub createScrub = true 277 | 278 | // CreateNoScrub do not cross device boundaries on the source filesystem. 279 | CreateNoScrub createScrub = false 280 | 281 | // CreateAnyowners do fail if the user invoking hdiutil can't ensure correct file ownership for the files in the image. 282 | CreateAnyowners createAnyowners = true 283 | 284 | // CreateNoAnyowners do not fail if the user invoking hdiutil can't ensure correct file ownership for the files in the image. 285 | CreateNoAnyowners createAnyowners = false 286 | 287 | // CreeteSkipunreadable skip files that can't be read by the copying user and don't authenticate. 288 | CreeteSkipunreadable createSkipunreadable = false 289 | 290 | // CreateAtomic do copy files to a temporary location and then rename them to their destination. Atomic copies are the default. Non-atomic copying may be slightly faster. 291 | CreateAtomic createAtomic = true 292 | 293 | // CreateNoAtomic do not copy files to a temporary location and then rename them to their destination. Atomic copies are the default. Non-atomic copying may be slightly faster. 294 | CreateNoAtomic createAtomic = false 295 | ) 296 | 297 | // Create create a new image of the given size or from the provided data. 298 | func Create(image string, sizeSpec sizeFlag, flags ...createFlag) error { 299 | cmd := exec.Command(hdiutilPath, "create") 300 | cmd.Args = append(cmd.Args, sizeSpec.sizeFlag()...) 301 | cmd.Args = append(cmd.Args, image) 302 | if len(flags) > 0 { 303 | for _, flag := range flags { 304 | cmd.Args = append(cmd.Args, flag.createFlag()...) 305 | } 306 | } 307 | 308 | err := cmd.Run() 309 | if err != nil { 310 | return err 311 | } 312 | 313 | return nil 314 | } 315 | -------------------------------------------------------------------------------- /detach.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The go-darwin Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package hdiutil 6 | 7 | import "os/exec" 8 | 9 | // detachFlag implements a hdiutil detach command flag interface. 10 | type detachFlag interface { 11 | detachFlag() []string 12 | } 13 | 14 | type detachForce bool 15 | 16 | func (d detachForce) detachFlag() []string { return boolFlag("force", bool(d)) } 17 | 18 | const ( 19 | // DetachForce ignore open files on mounted volumes, etc. 20 | DetachForce detachForce = true 21 | ) 22 | 23 | // Detach detach a disk image and terminate any associated process. 24 | func Detach(deviceNode string, flags ...detachFlag) error { 25 | cmd := exec.Command(hdiutilPath, "detach", deviceNode) 26 | if len(flags) > 0 { 27 | for _, flag := range flags { 28 | cmd.Args = append(cmd.Args, flag.detachFlag()...) 29 | } 30 | } 31 | 32 | err := cmd.Run() 33 | if err != nil { 34 | return err 35 | } 36 | 37 | return nil 38 | } 39 | -------------------------------------------------------------------------------- /doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The darwinutil Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package hdiutil implements a macOS hdiutil command wrapper. 6 | // 7 | // HDIUTIL(1) BSD General Commands Manual HDIUTIL(1) 8 | // NAME 9 | // hdiutil -- manipulate disk images (attach, verify, create, etc) 10 | // 11 | // SYNOPSIS 12 | // hdiutil verb [options] 13 | // 14 | // DESCRIPTION 15 | // hdiutil uses the DiskImages framework to manipulate disk images. 16 | // Common verbs include attach, detach, verify, create, convert, and 17 | // compact. 18 | // 19 | // The rest of the verbs are currently: help, info, burn, checksum, 20 | // chpass, erasekeys, unflatten, flatten, imageinfo, isencrypted, 21 | // mountvol, unmount, plugins, udifrez, udifderez, internet-enable, 22 | // resize, segment, makehybrid, and pmap. 23 | // 24 | // BACKGROUND 25 | // Disk images are data containers that emulate disks. Like disks, they 26 | // can be partitioned and formatted. Many common uses of disk images 27 | // blur the distinction between the disk image container and its content, 28 | // but this distinction is critical to understanding how disk images 29 | // work. 30 | // The terms "attach" and "detach" are used to distinguish the way disk 31 | // images are connected to and disconnected from a system. 32 | // "Mount" and "unmount" are the parallel filesystems options. 33 | // 34 | // For example, when you double-click a disk image in the macOS Finder, 35 | // two separate things happen. 36 | // First, the image is "attached" to the system just like an external 37 | // drive. 38 | // Then, the kernel and Disk Arbitration probe the new device for 39 | // recognized file structures. 40 | // If any are discovered that should be mounted, the associated volumes 41 | // will mount and appear on the desktop. 42 | // 43 | // When using disk images, always consider whether an operation applies 44 | // to the blocks of the disk image container or to the 45 | // (often file-oriented) content of the image. 46 | // For example, hdiutil verify verifies that the blocks stored in a 47 | // read-only disk image have not changed since it was created. 48 | // It does not check whether the filesystem stored within the image is 49 | // self-consistent (as diskutil verifyVolume would). 50 | // On the other hand, hdiutil create -srcfolder creates a disk image 51 | // container, puts a filesystem in it, and then copies the specified 52 | // files to the new filesystem. 53 | package hdiutil // import "go-darwin.dev/hdiutil" 54 | -------------------------------------------------------------------------------- /flag.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The go-darwin Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package hdiutil 6 | 7 | import "strconv" 8 | 9 | func boolFlag(name string, b bool) []string { 10 | if b { 11 | return []string{"-" + name} 12 | } 13 | return nil 14 | } 15 | 16 | func boolNoFlag(name string, b bool) []string { 17 | if b { 18 | return []string{"-" + name} 19 | } 20 | return []string{"-no" + name} 21 | } 22 | 23 | func stringFlag(name, s string) []string { 24 | return []string{"-" + name, s} 25 | } 26 | 27 | func stringSliceFlag(name string, s []string) []string { 28 | a := []string{"-" + name} 29 | a = append(a, s...) 30 | return a 31 | } 32 | 33 | func intFlag(name string, i int) []string { 34 | return []string{"-" + name, strconv.Itoa(i)} 35 | } 36 | -------------------------------------------------------------------------------- /hdiutil.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The go-darwin Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package hdiutil 6 | 7 | import ( 8 | "fmt" 9 | "strconv" 10 | "strings" 11 | ) 12 | 13 | // Usage: hdiutil 14 | // is one of the following: 15 | // help flatten 16 | // attach imageinfo 17 | // detach internet-enable 18 | // eject isencrypted 19 | // verify makehybrid 20 | // create mount 21 | // compact mountvol 22 | // convert unmount 23 | // burn plugins 24 | // info resize 25 | // checksum segment 26 | // chpass pmap 27 | // erasekeys udifderez 28 | // unflatten udifrez 29 | // help display more detailed help 30 | 31 | // EncryptionType specify a particular type of encryption. 32 | type EncryptionType int 33 | 34 | const ( 35 | // AES128 use AES cipher running in CBC mode on 512-byte blocks with a 128-bit key (recommended). 36 | AES128 EncryptionType = 1 << iota 37 | // AES256 use AES cipher running in CBC mode on 512-byte blocks with a 256-bit key (more secure, but slower). 38 | AES256 39 | ) 40 | 41 | func (e EncryptionType) String() string { 42 | switch e { 43 | case AES128: 44 | return "AES-128" 45 | case AES256: 46 | return "AES-256" 47 | } 48 | return fmt.Sprintf("EncryptionType(%d)", e) 49 | } 50 | 51 | func (e EncryptionType) attachFlag() []string { return stringFlag("encryption", e.String()) } 52 | func (e EncryptionType) convertFlag() []string { return stringFlag("encryption", e.String()) } 53 | func (e EncryptionType) makehybridFlag() []string { return stringFlag("encryption", e.String()) } 54 | func (e EncryptionType) verifyFlag() []string { return stringFlag("encryption", e.String()) } 55 | 56 | type plist bool 57 | 58 | func (p plist) attachFlag() []string { return boolFlag("plist", bool(p)) } 59 | func (p plist) convertFlag() []string { return boolFlag("plist", bool(p)) } 60 | func (p plist) verifyFlag() []string { return boolFlag("plist", bool(p)) } 61 | 62 | type puppetstrings bool 63 | 64 | func (p puppetstrings) attachFlag() []string { return boolFlag("puppetstrings", bool(p)) } 65 | func (p puppetstrings) convertFlag() []string { return boolFlag("puppetstrings", bool(p)) } 66 | func (p puppetstrings) makehybridFlag() []string { return boolFlag("puppetstrings", bool(p)) } 67 | func (p puppetstrings) verifyFlag() []string { return boolFlag("puppetstrings", bool(p)) } 68 | 69 | // Srcimagekey specify a key/value pair for the disk image recognition system. (-imagekey is normally a synonym) 70 | type Srcimagekey map[string]string 71 | 72 | func (s Srcimagekey) commonFlag() []string { 73 | var arg string 74 | for k, v := range s { 75 | arg = k + "=" + v 76 | } 77 | return stringFlag("srcimagekey", arg) 78 | } 79 | func (s Srcimagekey) attachFlag() []string { return s.commonFlag() } 80 | func (s Srcimagekey) convertFlag() []string { return s.commonFlag() } 81 | func (s Srcimagekey) createFlag() []string { return s.commonFlag() } 82 | func (s Srcimagekey) makehybridFlag() []string { return s.commonFlag() } 83 | 84 | // Tgtimagekey specify a key/value pair for any image created. (-imagekey is only a synonym if there is no input image). 85 | type Tgtimagekey map[string]string 86 | 87 | func (t Tgtimagekey) commonFlag() []string { 88 | var arg string 89 | for k, v := range t { 90 | arg = k + "=" + v 91 | } 92 | return stringFlag("tgtimagekey", arg) 93 | } 94 | func (t Tgtimagekey) attachFlag() []string { return t.commonFlag() } 95 | func (t Tgtimagekey) convertFlag() []string { return t.commonFlag() } 96 | func (t Tgtimagekey) createFlag() []string { return t.commonFlag() } 97 | 98 | // Imagekey is normally a synonym to Srcimagekey, only a synonym Tgtimagekey if there is no input image. 99 | type Imagekey map[string]string 100 | 101 | func (i Imagekey) commonFlag() []string { 102 | var arg string 103 | for k, v := range i { 104 | arg = k + "=" + v 105 | } 106 | return stringFlag("imagekey", arg) 107 | } 108 | func (i Imagekey) attachFlag() []string { return i.commonFlag() } 109 | func (i Imagekey) createFlag() []string { return i.commonFlag() } 110 | 111 | // Encryption specify a particular type of encryption or, if not specified, the default encryption algorithm. 112 | // 113 | // As of OS X 10.7, the default algorithm is the AES cipher running in CBC mode on 512-byte blocks with a 128-bit key. 114 | type Encryption EncryptionType 115 | 116 | type stdinpass bool 117 | 118 | func (s stdinpass) attachFlag() []string { return boolFlag("stdinpass", bool(s)) } 119 | func (s stdinpass) convertFlag() []string { return boolFlag("stdinpass", bool(s)) } 120 | func (s stdinpass) makehybridFlag() []string { return boolFlag("stdinpass", bool(s)) } 121 | func (s stdinpass) verifyFlag() []string { return boolFlag("stdinpass", bool(s)) } 122 | 123 | type agentpass bool 124 | 125 | // Recover specify a keychain containing the secret corresponding to the certificate specified with -certificate when the image was created. 126 | type Recover string 127 | 128 | func (r Recover) attachFlag() []string { return stringFlag("recover", string(r)) } 129 | 130 | // Certificate specify a secondary access certificate for an encrypted image. 131 | // cert_file must be DER-encoded certificate data, which can be created by Keychain Access or openssl(1). 132 | type Certificate string 133 | 134 | func (c Certificate) convertFlag() []string { return stringFlag("certificate", string(c)) } 135 | 136 | // Pubkey specify a list of public keys, identified by their hexadecimal hashes, to be used to protect the encrypted image being created. 137 | type Pubkey []string 138 | 139 | // Cacert specify a certificate authority certificate. 140 | // cert can be either a PEM file or a directory of certificates processed by c_rehash(1). 141 | // 142 | // See also --capath and --cacert in curl(1). 143 | type Cacert string 144 | 145 | type insecurehttp bool 146 | 147 | // Shadow use a shadow file in conjunction with the data in the primary image file. 148 | // This option prevents modification of the original image and allows read-only images to be attached read/write. 149 | // 150 | // When blocks are being read from the image, blocks present in the shadow file override blocks in the base image. 151 | // All data written to an attached device will be redirected to the shadow file. 152 | // If not specified, shadowfile defaults to image.shadow. 153 | // If the shadow file does not exist, it is created. 154 | // 155 | // hdiutil verbs taking images as input accept -shadow, -cacert, and -insecurehttp. 156 | type Shadow string 157 | 158 | func (s Shadow) attachFlag() []string { return stringFlag("shadow", string(s)) } 159 | func (s Shadow) convertFlag() []string { return stringFlag("shadow", string(s)) } 160 | func (s Shadow) makehybridFlag() []string { return stringFlag("shadow", string(s)) } 161 | 162 | type verbose bool 163 | 164 | func (v verbose) attachFlag() []string { return boolFlag("verbose", bool(v)) } 165 | func (v verbose) convertFlag() []string { return boolFlag("verbose", bool(v)) } 166 | func (v verbose) createFlag() []string { return boolFlag("verbose", bool(v)) } 167 | func (v verbose) detachFlag() []string { return boolFlag("verbose", bool(v)) } 168 | func (v verbose) makehybridFlag() []string { return boolFlag("verbose", bool(v)) } 169 | 170 | type quiet bool 171 | 172 | func (q quiet) attachFlag() []string { return boolFlag("quiet", bool(q)) } 173 | func (q quiet) createFlag() []string { return boolFlag("quiet", bool(q)) } 174 | func (q quiet) detachFlag() []string { return boolFlag("quiet", bool(q)) } 175 | func (q quiet) makehybridFlag() []string { return boolFlag("quiet", bool(q)) } 176 | 177 | type debug bool 178 | 179 | func (d debug) attachFlag() []string { return boolFlag("debug", bool(d)) } 180 | func (d debug) convertFlag() []string { return boolFlag("debug", bool(d)) } 181 | func (d debug) createFlag() []string { return boolFlag("debug", bool(d)) } 182 | func (d debug) detachFlag() []string { return boolFlag("debug", bool(d)) } 183 | func (d debug) makehybridFlag() []string { return boolFlag("debug", bool(d)) } 184 | 185 | const ( 186 | // Plist provide result output in plist format. 187 | // Other programs invoking hdiutil are expected to use -plist rather than try to parse the human-readable output. 188 | // 189 | // The usual output is consistent but generally unstructured. 190 | Plist plist = true 191 | 192 | // Puppetstrings provide progress output that is easy for another program to parse. 193 | // PERCENTAGE outputs can include the value -1 which means hdiutil is performing an operation that will take an indeterminate amount of time to complete. 194 | // 195 | // Any program trying to interpret hdiutil's progress should use -puppetstrings. 196 | Puppetstrings puppetstrings = true 197 | 198 | // Stdinpass read a null-terminated passphrase from standard input. 199 | // If the standard input is a tty, the passphrase will be read with readpassphrase(3). 200 | // Otherwise, the password is read from stdin. 201 | // 202 | // -stdinpass replaces -passphrase which has been deprecated. 203 | // -passphrase is insecure because its argument appears in the output of ps(1) where it is visible to other users and processes on the system. 204 | Stdinpass stdinpass = true 205 | 206 | // Agentpass force the default behavior of prompting for a passphrase. 207 | // 208 | // Useful with -pubkey to create an image protected by both a passphrase and a public key. 209 | Agentpass agentpass = true 210 | 211 | // Insecurehttp ignore SSL host validation failures. 212 | // Useful for self-signed servers for which the appropriate certificates are unavailable or if access to a server is desired when the server name doesn't match what is in the certificate. 213 | Insecurehttp insecurehttp = true 214 | 215 | // Verbose be verbose: produce extra progress output and error diagnostics. 216 | // 217 | // This option can help the user decipher why a particular operation failed. 218 | // At a minimum, the probing of any specified images will be detailed. 219 | // BUG(zchee): not exit hdiutil command if set. 220 | Verbose verbose = true 221 | 222 | // Quiet close stdout and stderr, leaving only hdiutil's exit status to indicate success or failure. 223 | // No /dev entries or mount points will be printed. 224 | // 225 | // -debug and -verbose disable -quiet. 226 | // BUG(zchee): not get the command result such as device node path when attach. 227 | Quiet quiet = true 228 | 229 | // Debug be very verbose. 230 | // 231 | // This option is good if a large amount of progress information is needed. 232 | // As of Mac OS X 10.6, -debug enables -verbose. 233 | // BUG(zchee): not exit hdiutil command if set. 234 | Debug debug = true 235 | ) 236 | 237 | // RawDeviceNode return the raw device node from the deviceNode. 238 | func RawDeviceNode(deviceNode string) string { 239 | return strings.Replace(deviceNode, "disk", "rdisk", 1) 240 | } 241 | 242 | // DeviceNumber return the device number from the deviceNode. 243 | func DeviceNumber(deviceNode string) int { 244 | n, err := strconv.Atoi(strings.TrimPrefix(deviceNode, "/dev/disk")) 245 | if err != nil { 246 | return 0 247 | } 248 | return n 249 | } 250 | -------------------------------------------------------------------------------- /hdiutil_darwin.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The go-darwin Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package hdiutil 6 | 7 | const hdiutilPath = "/usr/bin/hdiutil" 8 | -------------------------------------------------------------------------------- /makehybrid.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The go-darwin Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package hdiutil 6 | 7 | import "os/exec" 8 | 9 | // makehybridFlag implements a hdiutil makehybrid command flag interface. 10 | type makehybridFlag interface { 11 | makehybridFlag() []string 12 | } 13 | 14 | type makehybridHFS bool 15 | 16 | func (m makehybridHFS) makehybridFlag() []string { return boolFlag("hfs", bool(m)) } 17 | 18 | type makehybridISO bool 19 | 20 | func (m makehybridISO) makehybridFlag() []string { return boolFlag("iso", bool(m)) } 21 | 22 | type makehybridJoliet bool 23 | 24 | func (m makehybridJoliet) makehybridFlag() []string { return boolFlag("joliet", bool(m)) } 25 | 26 | type makehybridUDF bool 27 | 28 | func (m makehybridUDF) makehybridFlag() []string { return boolFlag("udf", bool(m)) } 29 | 30 | type makehybridHFSBlessedDirectory bool 31 | 32 | func (m makehybridHFSBlessedDirectory) makehybridFlag() []string { 33 | return boolFlag("hfs-blessed-directory", bool(m)) 34 | } 35 | 36 | type makehybridHFSOpenfolder bool 37 | 38 | func (m makehybridHFSOpenfolder) makehybridFlag() []string { return boolFlag("hfs-openfolder", bool(m)) } 39 | 40 | type makehybridHFSStartupfileSize bool 41 | 42 | func (m makehybridHFSStartupfileSize) makehybridFlag() []string { 43 | return boolFlag("hfs-startupfile-size", bool(m)) 44 | } 45 | 46 | type makehybridAbstractFile bool 47 | 48 | func (m makehybridAbstractFile) makehybridFlag() []string { return boolFlag("abstract-file", bool(m)) } 49 | 50 | type makehybridBibliographyFile bool 51 | 52 | func (m makehybridBibliographyFile) makehybridFlag() []string { 53 | return boolFlag("bibliography-file", bool(m)) 54 | } 55 | 56 | type makehybridCopyrightFile bool 57 | 58 | func (m makehybridCopyrightFile) makehybridFlag() []string { return boolFlag("copyright-file", bool(m)) } 59 | 60 | type makehybridApplication bool 61 | 62 | func (m makehybridApplication) makehybridFlag() []string { return boolFlag("application", bool(m)) } 63 | 64 | type makehybridPreparer bool 65 | 66 | func (m makehybridPreparer) makehybridFlag() []string { return boolFlag("preparer", bool(m)) } 67 | 68 | type makehybridPublisher bool 69 | 70 | func (m makehybridPublisher) makehybridFlag() []string { return boolFlag("publisher", bool(m)) } 71 | 72 | type makehybridSystemID bool 73 | 74 | func (m makehybridSystemID) makehybridFlag() []string { return boolFlag("system-id", bool(m)) } 75 | 76 | type makehybridKeepMacSpecific bool 77 | 78 | func (m makehybridKeepMacSpecific) makehybridFlag() []string { 79 | return boolFlag("keep-mac-specific", bool(m)) 80 | } 81 | 82 | type makehybridEltoritoBoot bool 83 | 84 | func (m makehybridEltoritoBoot) makehybridFlag() []string { return boolFlag("eltorito-boot", bool(m)) } 85 | 86 | type makehybridHardDiskBoot bool 87 | 88 | func (m makehybridHardDiskBoot) makehybridFlag() []string { return boolFlag("hard-disk-boot", bool(m)) } 89 | 90 | type makehybridNoEmulBoot bool 91 | 92 | func (m makehybridNoEmulBoot) makehybridFlag() []string { return boolFlag("no-emul-boot", bool(m)) } 93 | 94 | type makehybridNoBoot bool 95 | 96 | func (m makehybridNoBoot) makehybridFlag() []string { return boolFlag("no-boot", bool(m)) } 97 | 98 | type makehybridBootLoadSeg bool 99 | 100 | func (m makehybridBootLoadSeg) makehybridFlag() []string { return boolFlag("boot-load-seg", bool(m)) } 101 | 102 | type makehybridBootLoadSize bool 103 | 104 | func (m makehybridBootLoadSize) makehybridFlag() []string { return boolFlag("boot-load-seg", bool(m)) } 105 | 106 | type makehybridEltoritoPlatform bool 107 | 108 | func (m makehybridEltoritoPlatform) makehybridFlag() []string { 109 | return boolFlag("eltorito-platform", bool(m)) 110 | } 111 | 112 | type makehybridEltoritoSpecification bool 113 | 114 | func (m makehybridEltoritoSpecification) makehybridFlag() []string { 115 | return boolFlag("eltorito-specification", bool(m)) 116 | } 117 | 118 | type makehybridUDFVersion bool 119 | 120 | func (m makehybridUDFVersion) makehybridFlag() []string { return boolFlag("udf-version", bool(m)) } 121 | 122 | type makehybridDefaultVolumeName bool 123 | 124 | func (m makehybridDefaultVolumeName) makehybridFlag() []string { 125 | return boolFlag("default-volume-name", bool(m)) 126 | } 127 | 128 | type makehybridHFSVolumeName bool 129 | 130 | func (m makehybridHFSVolumeName) makehybridFlag() []string { 131 | return boolFlag("hfs-volume-name", bool(m)) 132 | } 133 | 134 | type makehybridISOVolumeName bool 135 | 136 | func (m makehybridISOVolumeName) makehybridFlag() []string { 137 | return boolFlag("iso-volume-name", bool(m)) 138 | } 139 | 140 | type makehybridJolietVolumeName bool 141 | 142 | func (m makehybridJolietVolumeName) makehybridFlag() []string { 143 | return boolFlag("joliet-volume-name", bool(m)) 144 | } 145 | 146 | type makehybridUDFVolumeName bool 147 | 148 | func (m makehybridUDFVolumeName) makehybridFlag() []string { 149 | return boolFlag("udf-volume-name", bool(m)) 150 | } 151 | 152 | type makehybridHideAll bool 153 | 154 | func (m makehybridHideAll) makehybridFlag() []string { return boolFlag("hide-all", bool(m)) } 155 | 156 | type makehybridHideHFS bool 157 | 158 | func (m makehybridHideHFS) makehybridFlag() []string { return boolFlag("hide-hfs", bool(m)) } 159 | 160 | type makehybridHideISO bool 161 | 162 | func (m makehybridHideISO) makehybridFlag() []string { return boolFlag("hide-iso", bool(m)) } 163 | 164 | type makehybridHideJoliet bool 165 | 166 | func (m makehybridHideJoliet) makehybridFlag() []string { return boolFlag("hide-joliet", bool(m)) } 167 | 168 | type makehybridHideUDF bool 169 | 170 | func (m makehybridHideUDF) makehybridFlag() []string { return boolFlag("hide-udf", bool(m)) } 171 | 172 | type makehybridOnlyUDF bool 173 | 174 | func (m makehybridOnlyUDF) makehybridFlag() []string { return boolFlag("only-udf", bool(m)) } 175 | 176 | type makehybridOnlyISO bool 177 | 178 | func (m makehybridOnlyISO) makehybridFlag() []string { return boolFlag("only-iso", bool(m)) } 179 | 180 | type makehybridOnlyJoliet bool 181 | 182 | func (m makehybridOnlyJoliet) makehybridFlag() []string { return boolFlag("only-joliet", bool(m)) } 183 | 184 | type makehybridPrintSize bool 185 | 186 | func (m makehybridPrintSize) makehybridFlag() []string { return boolFlag("print-size", bool(m)) } 187 | 188 | type makehybridPlistin bool 189 | 190 | func (m makehybridPlistin) makehybridFlag() []string { return boolFlag("plistin", bool(m)) } 191 | 192 | const ( 193 | // MakehybridHFS generate an HFS+ filesystem. 194 | // 195 | // This filesystem can be present on an image simultaneously with an ISO9660 or Joliet or UDF filesystem. 196 | // On operating systems that understand HFS+ as well as ISO9660 and UDF, like Mac OS 9 or OS X, HFS+ is usually the preferred filesystem for hybrid images. 197 | MakehybridHFS makehybridHFS = true 198 | 199 | // MakehybridISO generate an ISO9660 Level 2 filesystem with Rock Ridge extensions. 200 | // 201 | // This filesystem can be present on an image simultaneously with an HFS+ or Joliet or UDF filesystem. 202 | // ISO9660 is the standard cross-platform interchange format for CDs and some DVDs, and is understood by virtually all operating systems. 203 | // 204 | // If an ISO9660 or Joliet filesystem is present on a disk image or CD, but not HFS+, OS X will use the ISO9660 (or Joliet) filesystem. 205 | MakehybridISO makehybridISO = true 206 | 207 | // MakeHybridJoliet generate joliet extensions to ISO9660. 208 | // 209 | // This view of the filesystem can be present on an image simultaneously with HFS+, and requires the presence of an ISO9660 filesystem. 210 | // Joliet supports Unicode filenames, but is only supported on some operating systems. 211 | // 212 | // If both an ISO9660 and Joliet filesystem are present on a disk image or CD, but not HFS+, OS X will prefer the Joliet filesystem. 213 | MakeHybridJoliet makehybridJoliet = true 214 | 215 | // MakeHybridUDF generate a UDF filesystem. 216 | // 217 | // This filesystem can be present on an image simultaneously with HFS+, ISO9660, and Joliet. 218 | // UDF is the standard interchange format for DVDs, although operating system support varies based on OS version and UDF version. 219 | MakeHybridUDF makehybridUDF = true 220 | 221 | // MakehybridHFSBlessedDirectory path to directory which should be "blessed" for OS X booting on the generated filesystem. 222 | // 223 | // This assumes the directory has been otherwise prepared, for example with bless -bootinfo to create a valid BootX file. (HFS+ only). 224 | MakehybridHFSBlessedDirectory makehybridHFSBlessedDirectory = true 225 | 226 | // MakehybridHFSOpenfolder path to a directory that will be opened by the Finder automatically. See also the -openfolder option in bless(8) (HFS+ only). 227 | MakehybridHFSOpenfolder makehybridHFSOpenfolder = true 228 | 229 | // MakehybridHFSStartupfileSize allocate an empty HFS+ Startup File of the specified size, in bytes (HFS+ only). 230 | MakehybridHFSStartupfileSize makehybridHFSStartupfileSize = true 231 | 232 | // MakehybridAbstractFile path to a file in the source directory (and thus the root of the generated filesystem) for use as the ISO9660/Joliet Abstract file (ISO9660/Joliet). 233 | MakehybridAbstractFile makehybridAbstractFile = true 234 | 235 | // MakehybridBibliographyFile path to a file in the source directory (and thus the root of the generated filesystem) for use as the ISO9660/Joliet Bibliography file (ISO9660/Joliet). 236 | MakehybridBibliographyFile makehybridBibliographyFile = true 237 | 238 | // MakehybridCopyrightFile path to a file in the source directory (and thus the root of the generated filesystem) for use as the ISO9660/Joliet Copyright file (ISO9660/Joliet). 239 | MakehybridCopyrightFile makehybridCopyrightFile = true 240 | 241 | // MakehybridApplication Application string (ISO9660/Joliet). 242 | MakehybridApplication makehybridApplication = true 243 | 244 | // MakehybridPreparer preparer string (ISO9660/Joliet). 245 | MakehybridPreparer makehybridPreparer = true 246 | 247 | // MakehybridPublisher publisher string (ISO9660/Joliet). 248 | MakehybridPublisher makehybridPublisher = true 249 | 250 | // MakehybridSystemID system Identification string (ISO9660/Joliet). 251 | MakehybridSystemID makehybridSystemID = true 252 | 253 | // MakehybridKeepMacSpecific Expose Macintosh-specific files (such as .DS_Store) in non-HFS+ filesystems (ISO9660/Joliet). 254 | MakehybridKeepMacSpecific makehybridKeepMacSpecific = true 255 | 256 | // MakehybridEltoritoBoot path to an El Torito boot image within the source directory. By default, floppy drive emulation is used, so the image must be one of 1200KB, 1440KB, or 2880KB. If the image has a different size, either -no-emul-boot or 257 | // -hard-disk-boot must be used to enable "No Emulation" or "Hard Disk Emulation" mode, respectively (ISO9660/Joliet). 258 | MakehybridEltoritoBoot makehybridEltoritoBoot = true 259 | 260 | // MakehybridHardDiskBoot use El Torito Hard Disk Emulation mode. The image must represent a virtual device with an MBR partition map and a single partition. 261 | MakehybridHardDiskBoot makehybridHardDiskBoot = true 262 | 263 | // MakehybridNoEmulBoot use El Torito No Emulation mode. The system firmware will load the number of sectors specified by -boot-load-size and execute it, without emulating any devices (ISO9660/Joliet). 264 | MakehybridNoEmulBoot makehybridNoEmulBoot = true 265 | 266 | // MakehybridNoBoot mark the El Torito image as non-bootable. The system firmware may still create a virtual device backed by this data. This option is not recommended (ISO9660/Joliet). 267 | MakehybridNoBoot makehybridNoBoot = true 268 | 269 | // MakehybridBootLoadSeg for a No Emulation boot image, load the data at the specified segment address. This options is not recommended, so that the system firmware can use its default address (ISO9660/Joliet) 270 | MakehybridBootLoadSeg makehybridBootLoadSeg = true 271 | 272 | // MakehybridBootLoadSize for a No Emulation boot image, load the specified number of 512-byte emulated sectors into memory and execute it. By default, 4 sectors (2KB) will be loaded (ISO9660/Joliet). 273 | MakehybridBootLoadSize makehybridBootLoadSize = true 274 | 275 | // MakehybridEltoritoPlatform use the specified numeric platform ID in the El Torito Boot Catalog Validation Entry or Section Header. Defaults to 0 to identify x86 hardware (ISO/Joliet). 276 | MakehybridEltoritoPlatform makehybridEltoritoPlatform = true 277 | 278 | // MakehybridEltoritoSpecification for complex layouts involving multiple boot images, a plist-formatted string can be provided, using either OpenStep-style syntax or XML syntax, representing an array of dictionaries. 279 | // 280 | // Any of the El Torito options can be set in the sub-dictionaries and will apply to that boot image only. 281 | // If -eltorito-specification is provided in addition to the normal El Torito command-line options, the specification will be used to populate secondary non-default boot entries. 282 | MakehybridEltoritoSpecification makehybridEltoritoSpecification = true 283 | 284 | // MakehybridUDFVersion version of UDF filesystem to generate. This can be either "1.02" or "1.50". If not specified, it defaults to "1.50" (UDF). 285 | MakehybridUDFVersion makehybridUDFVersion = true 286 | 287 | // MakehybridDefaultVolumeName default volume name for all filesystems, unless overridden. 288 | // 289 | // If not specified, defaults to the last path component of source. 290 | MakehybridDefaultVolumeName makehybridDefaultVolumeName = true 291 | 292 | // MakehybridHFSVolumeName volume name for just the HFS+ filesystem if it should be different (HFS+ only). 293 | MakehybridHFSVolumeName makehybridHFSVolumeName = true 294 | 295 | // MakehybridISOVolumeName volume name for just the ISO9660 filesystem if it should be different (ISO9660 only). 296 | MakehybridISOVolumeName makehybridISOVolumeName = true 297 | 298 | // MakehybridJolietVolumeName volume name for just the Joliet filesystem if it should be different (Joliet only). 299 | MakehybridJolietVolumeName makehybridJolietVolumeName = true 300 | 301 | // MakehybridUDFVolumeName volume name for just the UDF filesystem if it should be different (UDF only). 302 | MakehybridUDFVolumeName makehybridUDFVolumeName = true 303 | 304 | // MakehybridHideAll a glob expression of files and directories that should not be exposed in the generated filesystems. 305 | // 306 | // The string may need to be quoted to avoid shell expansion, and will be passed to glob(3) for evaluation. 307 | // Although this option can not be used multiple times, an arbitrarily complex glob expression can be used. 308 | MakehybridHideAll makehybridHideAll = true 309 | 310 | // MakehybridHideHFS a glob expression of files and directories that should not be exposed via the HFS+ filesystem, although the data may still be present for use by other filesystems (HFS+ only). 311 | MakehybridHideHFS makehybridHideHFS = true 312 | 313 | // MakehybridHideISO a glob expression of files and directories that should not be exposed via the ISO filesystem, although the data may still be present for use by other filesystems (ISO9660 only). 314 | // 315 | // Per above, the Joliet hierarchy will supersede the ISO hierarchy when the hybrid is mounted as an ISO 9660 filesystem on OS X. 316 | // Therefore, if Joliet is being generated (the default) -hide-joliet will also be needed to hide the file from mount_cd9660(8). 317 | MakehybridHideISO makehybridHideISO = true 318 | 319 | // MakehybridHideJoliet a glob expression of files and directories that should not be exposed via the Joliet filesystem, although the data may still be present for use by other filesystems (Joliet only). 320 | // 321 | // Because OS X's ISO 9660 filesystem uses the Joliet catalog if it is available, -hide-joliet effectively supersedes -hide-iso when the resulting filesystem is mounted as ISO on OS X. 322 | MakehybridHideJoliet makehybridHideJoliet = true 323 | 324 | // MakehybridHideUDF a glob expression of files and directories that should not be exposed via the UDF filesystem, although the data may still be present for use by other filesystems (UDF only). 325 | MakehybridHideUDF makehybridHideUDF = true 326 | 327 | // MakehybridOnlyUDF a glob expression of objects that should only be exposed in UDF. 328 | MakehybridOnlyUDF makehybridOnlyUDF = true 329 | 330 | // MakehybridOnlyISO a glob expression of objects that should only be exposed in ISO. 331 | MakehybridOnlyISO makehybridOnlyISO = true 332 | 333 | // MakehybridOnlyJoliet a glob expression of objects that should only be exposed in Joleit. 334 | MakehybridOnlyJoliet makehybridOnlyJoliet = true 335 | 336 | // MakehybridPrintSize preflight the data and calculate an upper bound on the size of the image. The actual size of the generated image is guaranteed to be less than or equal to this estimate. 337 | MakehybridPrintSize makehybridPrintSize = true 338 | 339 | // MakehybridPlistin instead of using command-line parameters, use a standard plist from standard input to specific the parameters of the hybrid image generation. 340 | // 341 | // Each command-line option should be a key in the dictionary, without the leading "-", and the value should be a string for path and string arguments, a number for number arguments, and a boolean for toggle options. 342 | // The source argument should use a key of "source" and the image should use a key of "output". 343 | MakehybridPlistin makehybridPlistin = true 344 | ) 345 | 346 | // Makehybrid generate a potentially-hybrid filesystem in a read-only disk image using the DiscRecording framework's content creation system. 347 | func Makehybrid(image, source string, flags ...makehybridFlag) error { 348 | cmd := exec.Command(hdiutilPath, "makehybrid", image, source) 349 | if len(flags) > 0 { 350 | for _, flag := range flags { 351 | cmd.Args = append(cmd.Args, flag.makehybridFlag()...) 352 | } 353 | } 354 | 355 | err := cmd.Run() 356 | if err != nil { 357 | return err 358 | } 359 | 360 | return nil 361 | } 362 | -------------------------------------------------------------------------------- /verify.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The go-darwin Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package hdiutil 6 | 7 | import "os/exec" 8 | 9 | // verifyFlag implements a hdiutil verify command flag interface. 10 | type verifyFlag interface { 11 | verifyFlag() []string 12 | } 13 | 14 | type verifyCache bool 15 | 16 | func (v verifyCache) verifyFlag() []string { return boolFlag("cache", bool(v)) } 17 | 18 | const ( 19 | // VerifyCache do cache checksum-verification. 20 | VerifyCache verifyCache = true 21 | 22 | // VerifyNoCache do not cache checksum-verification cache. 23 | VerifyNoCache verifyCache = false 24 | ) 25 | 26 | // Verify compute the checksum of a "read-only" or "compressed" image and verify it against the value stored in the image. 27 | func Verify(image string, flags ...verifyFlag) error { 28 | cmd := exec.Command(hdiutilPath, "verify", image) 29 | if len(flags) > 0 { 30 | for _, flag := range flags { 31 | cmd.Args = append(cmd.Args, flag.verifyFlag()...) 32 | } 33 | } 34 | 35 | err := cmd.Run() 36 | if err != nil { 37 | return err 38 | } 39 | 40 | return nil 41 | } 42 | --------------------------------------------------------------------------------